You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.7 KiB
Python
122 lines
3.7 KiB
Python
from core.models import AssetRule
|
|
|
|
|
|
def get_allowed(group, base, quote, side):
|
|
"""
|
|
Determine whether the trade is allowed according to the group.
|
|
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 side: The direction of the trade
|
|
"""
|
|
|
|
# If our base has allowed == False, we can only short it, or long the quote
|
|
base_rule = AssetRule.objects.filter(group=group, asset=base).first()
|
|
quote_rule = AssetRule.objects.filter(group=group, asset=quote).first()
|
|
|
|
if all([x is None for x in [base_rule, quote_rule]]):
|
|
# Neither side has data, we can't check any group statuses
|
|
if group.when_no_data == 7:
|
|
# Always deny
|
|
return False
|
|
elif group.when_no_data == 6:
|
|
# Always allow
|
|
return True
|
|
|
|
# Translate statuses, depending on the group's definitions
|
|
if base_rule:
|
|
base_mapped_status = update_status_from_mappings(base_rule.status, group)
|
|
if quote_rule:
|
|
quote_mapped_status = update_status_from_mappings(quote_rule.status, group)
|
|
|
|
# Check for deny first
|
|
if base_rule:
|
|
if base_mapped_status == 7:
|
|
# Always deny
|
|
return False
|
|
elif base_mapped_status == 3:
|
|
if side == "long":
|
|
return False
|
|
elif base_mapped_status == 2:
|
|
if side == "short":
|
|
return False
|
|
|
|
if quote_rule:
|
|
if quote_mapped_status == 7:
|
|
# Always deny
|
|
return False
|
|
elif quote_mapped_status == 3:
|
|
if side == "short":
|
|
return False
|
|
elif quote_mapped_status == 2:
|
|
if side == "long":
|
|
return False
|
|
|
|
# Only one side does not have data
|
|
if any([x is None for x in [base_rule, quote_rule]]):
|
|
if group.when_no_data == 7:
|
|
# Always deny
|
|
return False
|
|
elif group.when_no_data == 6:
|
|
# Always allow
|
|
return True
|
|
|
|
# Check for explicit allow
|
|
if base_rule:
|
|
if base_mapped_status == 6:
|
|
# Always allow
|
|
return True
|
|
|
|
if quote_rule:
|
|
if quote_mapped_status == 6:
|
|
# Always allow
|
|
return True
|
|
|
|
return True
|
|
|
|
|
|
def check_asset_aggregation(value, trigger_above, trigger_below):
|
|
"""
|
|
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 trigger_below is not None:
|
|
if value < trigger_below:
|
|
# Prohibited
|
|
return 3
|
|
if trigger_above is not None:
|
|
if value > trigger_above:
|
|
# Permitted
|
|
return 2
|
|
# Neither is defined, so we match
|
|
if not any(x is not None for x in [trigger_above, trigger_below]):
|
|
# No aggregation
|
|
return 4
|
|
# Not in bounds
|
|
return 5
|
|
|
|
|
|
def update_status_from_mappings(status, asset_group):
|
|
if status == 0:
|
|
if asset_group.when_no_data > -1:
|
|
return asset_group.when_no_data
|
|
elif status == 1:
|
|
if asset_group.when_no_match > -1:
|
|
return asset_group.when_no_match
|
|
elif status == 2:
|
|
if asset_group.when_bullish > -1:
|
|
return asset_group.when_bullish
|
|
elif status == 3:
|
|
if asset_group.when_bearish > -1:
|
|
return asset_group.when_bearish
|
|
elif status == 4:
|
|
if asset_group.when_no_aggregation > -1:
|
|
return asset_group.when_no_aggregation
|
|
elif status == 5:
|
|
if asset_group.when_not_in_bounds > -1:
|
|
return asset_group.when_not_in_bounds
|
|
return status
|