Implement trend signals
This commit is contained in:
parent
242c9fbaed
commit
3b3faecdf1
|
@ -122,6 +122,7 @@ class StrategyForm(RestrictedFormMixin, ModelForm):
|
|||
"time_in_force",
|
||||
"entry_signals",
|
||||
"exit_signals",
|
||||
"trend_signals",
|
||||
"enabled",
|
||||
"take_profit_percent",
|
||||
"stop_loss_percent",
|
||||
|
@ -138,8 +139,9 @@ class StrategyForm(RestrictedFormMixin, ModelForm):
|
|||
"trading_times": "When the strategy will place new trades.",
|
||||
"order_type": "Market: Buy/Sell at the current market price. Limit: Buy/Sell at a specified price. Limits protect you more against market slippage.",
|
||||
"time_in_force": "The time in force controls how the order is executed.",
|
||||
"entry_signals": "The entry signals to attach to this strategy. Callbacks received to these signals will trigger a trade.",
|
||||
"exit_signals": "The exit signals to attach to this strategy. Callbacks received to these signals will close all trades for the symbol on the account.",
|
||||
"entry_signals": "Callbacks received to these signals will trigger a trade.",
|
||||
"exit_signals": "Callbacks received to these signals will close all trades for the symbol on the account.",
|
||||
"trend_signals": "Callbacks received to these signals will limit the trading direction of the given symbol to the callback direction until further notice.",
|
||||
"enabled": "Whether the strategy is enabled.",
|
||||
"take_profit_percent": "The take profit will be set at this percentage above/below the entry price.",
|
||||
"stop_loss_percent": "The stop loss will be set at this percentage above/below the entry price.",
|
||||
|
@ -161,6 +163,12 @@ class StrategyForm(RestrictedFormMixin, ModelForm):
|
|||
help_text=Meta.help_texts["exit_signals"],
|
||||
required=False,
|
||||
)
|
||||
trend_signals = forms.ModelMultipleChoiceField(
|
||||
queryset=Signal.objects.all(),
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
help_text=Meta.help_texts["trend_signals"],
|
||||
required=False,
|
||||
)
|
||||
trading_times = forms.ModelMultipleChoiceField(
|
||||
queryset=TradingTime.objects.all(), widget=forms.CheckboxSelectMultiple
|
||||
)
|
||||
|
|
|
@ -296,7 +296,7 @@ def execute_strategy(callback, strategy, func):
|
|||
:param strategy: Strategy object
|
||||
"""
|
||||
|
||||
# Only check times for entries. We can always exit trades.
|
||||
# Only check times for entries. We can always exit trades and set trends.
|
||||
if func == "entry":
|
||||
# Check if we can trade now!
|
||||
now_utc = datetime.utcnow()
|
||||
|
@ -380,6 +380,31 @@ def execute_strategy(callback, strategy, func):
|
|||
response = account.client.close_position(side, symbol)
|
||||
log.debug(f"Close position response: {response}")
|
||||
return
|
||||
|
||||
# Set the trend
|
||||
elif func == "trend":
|
||||
if strategy.trends is None:
|
||||
strategy.trends = {}
|
||||
strategy.trends[symbol] = direction
|
||||
strategy.save()
|
||||
log.debug(f"Set trend for {symbol}: {direction}")
|
||||
return
|
||||
|
||||
# Check if we are trading against the trend
|
||||
if strategy.trend_signals is not None:
|
||||
if strategy.trends is None:
|
||||
log.debug("Refusing to trade with no trend signals received")
|
||||
return
|
||||
if symbol not in strategy.trends:
|
||||
log.debug("Refusing to trade asset without established trend")
|
||||
return
|
||||
else:
|
||||
if strategy.trends[symbol] != direction:
|
||||
log.debug("Refusing to trade against the trend")
|
||||
return
|
||||
else:
|
||||
log.debug(f"Trend check passed for {symbol} - {direction}")
|
||||
|
||||
type = strategy.order_type
|
||||
|
||||
# Get the account's balance in the native account currency
|
||||
|
@ -443,6 +468,17 @@ def execute_strategy(callback, strategy, func):
|
|||
def process_callback(callback):
|
||||
log.info(f"Received callback for {callback.hook} - {callback.signal}")
|
||||
|
||||
# Scan for trend
|
||||
log.debug("Scanning for trend strategies...")
|
||||
strategies = Strategy.objects.filter(trend_signals=callback.signal, enabled=True)
|
||||
log.debug(f"Matched strategies: {strategies}")
|
||||
for strategy in strategies:
|
||||
log.debug(f"Executing strategy {strategy}")
|
||||
if callback.hook.user != strategy.user:
|
||||
log.error("Ownership differs between callback and strategy.")
|
||||
continue
|
||||
execute_strategy(callback, strategy, func="trend")
|
||||
|
||||
# Scan for entry
|
||||
log.debug("Scanning for entry strategies...")
|
||||
strategies = Strategy.objects.filter(entry_signals=callback.signal, enabled=True)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.1.3 on 2022-12-06 19:24
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0042_trade_information'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='strategy',
|
||||
name='trend_signals',
|
||||
field=models.ManyToManyField(blank=True, related_name='trend_strategies', to='core.signal'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.1.3 on 2022-12-06 19:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0043_strategy_trend_signals'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='strategy',
|
||||
name='trends',
|
||||
field=models.JSONField(blank=True, null=True),
|
||||
),
|
||||
]
|
|
@ -334,6 +334,9 @@ class Strategy(models.Model):
|
|||
exit_signals = models.ManyToManyField(
|
||||
Signal, related_name="exit_strategies", blank=True
|
||||
)
|
||||
trend_signals = models.ManyToManyField(
|
||||
Signal, related_name="trend_strategies", blank=True
|
||||
)
|
||||
enabled = models.BooleanField(default=False)
|
||||
take_profit_percent = models.FloatField(default=1.5)
|
||||
stop_loss_percent = models.FloatField(default=1.0)
|
||||
|
@ -341,6 +344,7 @@ class Strategy(models.Model):
|
|||
price_slippage_percent = models.FloatField(default=2.5)
|
||||
callback_price_deviation_percent = models.FloatField(default=0.5)
|
||||
trade_size_percent = models.FloatField(default=0.5)
|
||||
trends = models.JSONField(null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = "strategies"
|
||||
|
|
Loading…
Reference in New Issue