Implement checking direction with assetfilter
This commit is contained in:
parent
dcfb963be6
commit
0321aff9d5
|
@ -16,16 +16,55 @@ class AssetfilterTestCase(TestCase):
|
||||||
description="Test group",
|
description="Test group",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_allowed(self):
|
def test_get_allowed_negative(self):
|
||||||
"""
|
"""
|
||||||
Test that the asset filter works.
|
Test that the asset filter works on negative aggregations.
|
||||||
"""
|
"""
|
||||||
self.group.allowed = {"EUR_USD": True, "EUR_GBP": False}
|
# We have negative news about EUR
|
||||||
self.assertTrue(assetfilter.get_allowed(self.group, "EUR_USD", "buy"))
|
self.group.allowed = {"EUR": False}
|
||||||
self.assertFalse(assetfilter.get_allowed(self.group, "EUR_GBP", "sell"))
|
self.group.save()
|
||||||
|
|
||||||
# Default true
|
# This means that:
|
||||||
self.assertTrue(assetfilter.get_allowed(self.group, "nonexistent", "sell"))
|
# * base == EUR: long is not allowed, short is allowed
|
||||||
|
# * quote == EUR: long is allowed, short is not allowed
|
||||||
|
# We are betting on it going down, so we short base, and long quote.
|
||||||
|
|
||||||
|
# Test that short on base of EUR is allowed
|
||||||
|
self.assertTrue(assetfilter.get_allowed(self.group, "EUR", "USD", "short"))
|
||||||
|
|
||||||
|
# Test that long on quote of EUR is allowed
|
||||||
|
self.assertTrue(assetfilter.get_allowed(self.group, "USD", "EUR", "long"))
|
||||||
|
|
||||||
|
# Test that long on base of EUR is not allowed
|
||||||
|
self.assertFalse(assetfilter.get_allowed(self.group, "EUR", "USD", "long"))
|
||||||
|
|
||||||
|
# Test that short on quote of EUR is not allowed
|
||||||
|
self.assertFalse(assetfilter.get_allowed(self.group, "USD", "EUR", "short"))
|
||||||
|
|
||||||
|
def test_get_allowed_positive(self):
|
||||||
|
"""
|
||||||
|
Test that the asset filter works on positive aggregations.
|
||||||
|
"""
|
||||||
|
# We have positive news about EUR
|
||||||
|
self.group.allowed = {"EUR": True}
|
||||||
|
self.group.save()
|
||||||
|
|
||||||
|
# This means that:
|
||||||
|
# * base == EUR: long is allowed, short is not allowed
|
||||||
|
# * quote == EUR: long is not allowed, short is allowed
|
||||||
|
# We are betting on it going up, so we long base, and short quote.
|
||||||
|
|
||||||
|
# Test that long on base of EUR is allowed
|
||||||
|
self.assertTrue(assetfilter.get_allowed(self.group, "EUR", "USD", "long"))
|
||||||
|
|
||||||
|
# Test that short on quote of EUR is allowed
|
||||||
|
self.assertTrue(assetfilter.get_allowed(self.group, "USD", "EUR", "short"))
|
||||||
|
|
||||||
|
# Test that short on base of EUR is not allowed
|
||||||
|
self.assertFalse(assetfilter.get_allowed(self.group, "EUR", "USD", "short"))
|
||||||
|
|
||||||
|
# Test that long on quote of EUR is not allowed
|
||||||
|
self.assertFalse(assetfilter.get_allowed(self.group, "USD", "EUR", "long"))
|
||||||
|
|
||||||
def test_check_asset_aggregation(self):
|
def test_check_asset_aggregation(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,22 +1,44 @@
|
||||||
def get_allowed(group, symbol, direction):
|
def get_allowed(group, base, quote, direction):
|
||||||
"""
|
"""
|
||||||
Determine whether the trade is allowed according to the Asset Groups
|
Determine whether the trade is allowed according to the group.
|
||||||
linked to the strategy.
|
See tests for examples. The logic requires trading knowledge.
|
||||||
|
:param group: The group to check
|
||||||
|
:param base: The base currency
|
||||||
|
:param quote: The quote currency
|
||||||
|
:param direction: The direction of the trade
|
||||||
"""
|
"""
|
||||||
# TODO: figure out what to do with direction
|
|
||||||
|
|
||||||
allowed = group.allowed
|
allowed = group.allowed
|
||||||
if not isinstance(allowed, dict):
|
if not isinstance(allowed, dict):
|
||||||
return False
|
return False
|
||||||
if symbol not in allowed:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return allowed[symbol]
|
# If our base has allowed == False, we can only short it, or long the quote
|
||||||
|
if base in allowed:
|
||||||
|
if not allowed[base]:
|
||||||
|
if direction == "long":
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
if direction == "short":
|
||||||
|
return False
|
||||||
|
|
||||||
|
# If our quote has allowed == False, we can only long it, or short the base
|
||||||
|
if quote in allowed:
|
||||||
|
if not allowed[quote]:
|
||||||
|
if direction == "short":
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
if direction == "long":
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def check_asset_aggregation(value, trigger_above, trigger_below):
|
def check_asset_aggregation(value, trigger_above, trigger_below):
|
||||||
"""
|
"""
|
||||||
Check if the value is within the bounds of the aggregation
|
Check if the value is within the bounds of the aggregation.
|
||||||
|
:param value: The value to check
|
||||||
|
:param trigger_above: Only trigger if the value is above this
|
||||||
|
:param trigger_below: Only trigger if the value is below this
|
||||||
"""
|
"""
|
||||||
# If both are defined
|
# If both are defined
|
||||||
if trigger_above is not None and trigger_below is not None:
|
if trigger_above is not None and trigger_below is not None:
|
||||||
|
|
|
@ -63,6 +63,22 @@ def check_conflicting_position(
|
||||||
new_symbol: str,
|
new_symbol: str,
|
||||||
trade_side_opposite: str,
|
trade_side_opposite: str,
|
||||||
):
|
):
|
||||||
|
"""
|
||||||
|
Determine if we have a conflicting position open.
|
||||||
|
:param func: Whether we are checking entries, exits or trends
|
||||||
|
:param position: Position dict
|
||||||
|
:param open_base: Base currency of the open position
|
||||||
|
:param open_quote: Quote currency of the open position
|
||||||
|
:param open_side: Side of the open position
|
||||||
|
:param open_symbol: Symbol of the open position
|
||||||
|
:param open_units: Units of the open position
|
||||||
|
:param new_base: Base currency of the new position
|
||||||
|
:param new_quote: Quote currency of the new position
|
||||||
|
:param new_side: Side of the new position
|
||||||
|
:param new_symbol: Symbol of the new position
|
||||||
|
:param trade_side_opposite: Opposite side of the trade
|
||||||
|
:return: dict of action and opposing position, or None
|
||||||
|
"""
|
||||||
if open_base == new_quote or open_quote == new_base:
|
if open_base == new_quote or open_quote == new_base:
|
||||||
# If we have a long on GBP/AUD, we can only place shorts on XAU/GBP.
|
# If we have a long on GBP/AUD, we can only place shorts on XAU/GBP.
|
||||||
if open_side != trade_side_opposite:
|
if open_side != trade_side_opposite:
|
||||||
|
@ -85,10 +101,10 @@ def crossfilter(account, new_symbol, new_direction, func):
|
||||||
Checks open positions for the account, rejecting the trade if there is one
|
Checks open positions for the account, rejecting the trade if there is one
|
||||||
with an opposite direction to this one.
|
with an opposite direction to this one.
|
||||||
:param account: Account object
|
:param account: Account object
|
||||||
:param symbol: Symbol
|
:param new_symbol: Symbol of the new position
|
||||||
:param direction: Direction of the trade
|
:param new_direction: Direction of the new position
|
||||||
:param func: Whether we are checking entries or exits
|
:param func: Whether we are checking entries, exits or trends
|
||||||
:return: dict of action and opposing position, or False
|
:return: dict of action and opposing position, False or None
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# Only get the data we need
|
# Only get the data we need
|
||||||
|
|
|
@ -329,7 +329,7 @@ def execute_strategy(callback, strategy, func):
|
||||||
|
|
||||||
# Check against the asset groups
|
# Check against the asset groups
|
||||||
if func == "entry" and strategy.assetgroup is not None:
|
if func == "entry" and strategy.assetgroup is not None:
|
||||||
allowed = assetfilter.get_allowed(strategy, symbol, direction)
|
allowed = assetfilter.get_allowed(strategy, base, quote, direction)
|
||||||
if not allowed:
|
if not allowed:
|
||||||
log.debug(
|
log.debug(
|
||||||
f"Denied trading {symbol} due to asset filter {strategy.assetgroup}"
|
f"Denied trading {symbol} due to asset filter {strategy.assetgroup}"
|
||||||
|
|
Loading…
Reference in New Issue