diff --git a/core/forms.py b/core/forms.py index 53ed0a6..accd5e6 100644 --- a/core/forms.py +++ b/core/forms.py @@ -89,7 +89,6 @@ class AccountForm(RestrictedFormMixin, ModelForm): "exchange", "api_key", "api_secret", - "risk_model", "initial_balance", "sandbox", "enabled", @@ -101,7 +100,6 @@ class AccountForm(RestrictedFormMixin, ModelForm): "api_secret": "The API secret or password/token for the account.", "sandbox": "Whether to use the sandbox/demo or not.", "enabled": "Whether the account is enabled.", - "risk_model": "The risk model to use for this account.", "initial_balance": "The initial balance of the account.", } @@ -125,6 +123,7 @@ class StrategyForm(RestrictedFormMixin, ModelForm): "description", "account", "asset_group", + "risk_model", "trading_times", "order_type", "time_in_force", @@ -135,8 +134,6 @@ class StrategyForm(RestrictedFormMixin, ModelForm): "take_profit_percent", "stop_loss_percent", "trailing_stop_loss_percent", - "price_slippage_percent", - "callback_price_deviation_percent", "trade_size_percent", ) @@ -145,6 +142,7 @@ class StrategyForm(RestrictedFormMixin, ModelForm): "description": "Description of the strategy. Informational only.", "account": "The account to use for this strategy.", "asset_group": "Asset groups determine which pairs can be traded.", + "risk_model": "The risk model to use for this strategy. Highly recommended.", "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.", @@ -155,8 +153,6 @@ class StrategyForm(RestrictedFormMixin, ModelForm): "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.", "trailing_stop_loss_percent": "The trailing stop loss will be set at this percentage above/below the entry price. A trailing stop loss will follow the price as it moves in your favor.", - "price_slippage_percent": "The price slippage is the maximum percent the price can move against you before the trade is cancelled. Limit orders will be set at this percentage against your favour. Market orders will have a price bound set if this is supported.", - "callback_price_deviation_percent": "The callback price deviation is the maximum percent the price can change between receiving the callback and acting on it. This protects against rogue or delayed callbacks. Keep it low.", "trade_size_percent": "Percentage of the account balance to use for each trade.", } @@ -297,6 +293,8 @@ class RiskModelForm(RestrictedFormMixin, ModelForm): "max_risk_percent", "max_open_trades", "max_open_trades_per_symbol", + "price_slippage_percent", + "callback_price_deviation_percent", ) help_texts = { "name": "Name of the risk model. Informational only.", @@ -305,6 +303,8 @@ class RiskModelForm(RestrictedFormMixin, ModelForm): "max_risk_percent": "The maximum percent of the account balance that can be risked on all open trades.", "max_open_trades": "The maximum number of open trades.", "max_open_trades_per_symbol": "The maximum number of open trades per symbol.", + "price_slippage_percent": "The price slippage is the maximum percent the price can move against you before the trade is cancelled. Limit orders will be set at this percentage against your favour. Market orders will have a price bound set if this is supported.", + "callback_price_deviation_percent": "The callback price deviation is the maximum percent the price can change between receiving the callback and acting on it. This protects against rogue or delayed callbacks. Keep it low.", } diff --git a/core/migrations/0066_remove_account_risk_model_and_more.py b/core/migrations/0066_remove_account_risk_model_and_more.py new file mode 100644 index 0000000..cde5d97 --- /dev/null +++ b/core/migrations/0066_remove_account_risk_model_and_more.py @@ -0,0 +1,81 @@ +# Generated by Django 4.1.6 on 2023-02-15 18:11 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0065_assetgroup_when_bearish_assetgroup_when_bullish_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='account', + name='risk_model', + ), + migrations.RemoveField( + model_name='strategy', + name='callback_price_deviation_percent', + ), + migrations.RemoveField( + model_name='strategy', + name='price_slippage_percent', + ), + migrations.AddField( + model_name='riskmodel', + name='callback_price_deviation_percent', + field=models.FloatField(default=0.5), + ), + migrations.AddField( + model_name='riskmodel', + name='price_slippage_percent', + field=models.FloatField(default=2.5), + ), + migrations.AddField( + model_name='strategy', + name='risk_model', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='core.riskmodel'), + ), + migrations.AlterField( + model_name='assetgroup', + name='when_bearish', + field=models.IntegerField(choices=[(6, 'Always allow'), (7, 'Always deny'), (2, 'Bullish'), (3, 'Bearish')], default=3), + ), + migrations.AlterField( + model_name='assetgroup', + name='when_bullish', + field=models.IntegerField(choices=[(6, 'Always allow'), (7, 'Always deny'), (2, 'Bullish'), (3, 'Bearish')], default=2), + ), + migrations.AlterField( + model_name='assetgroup', + name='when_no_aggregation', + field=models.IntegerField(choices=[(6, 'Always allow'), (7, 'Always deny'), (2, 'Bullish'), (3, 'Bearish')], default=6), + ), + migrations.AlterField( + model_name='assetgroup', + name='when_no_data', + field=models.IntegerField(choices=[(6, 'Always allow'), (7, 'Always deny'), (2, 'Bullish'), (3, 'Bearish')], default=7), + ), + migrations.AlterField( + model_name='assetgroup', + name='when_no_match', + field=models.IntegerField(choices=[(6, 'Always allow'), (7, 'Always deny'), (2, 'Bullish'), (3, 'Bearish')], default=6), + ), + migrations.AlterField( + model_name='assetgroup', + name='when_not_in_bounds', + field=models.IntegerField(choices=[(6, 'Always allow'), (7, 'Always deny'), (2, 'Bullish'), (3, 'Bearish')], default=6), + ), + migrations.AlterField( + model_name='assetrule', + name='original_status', + field=models.IntegerField(choices=[(0, 'No data'), (1, 'No match'), (2, 'Bullish'), (3, 'Bearish'), (4, 'No aggregation'), (5, 'Not in bounds'), (6, 'Always allow'), (7, 'Always deny')], default=0), + ), + migrations.AlterField( + model_name='assetrule', + name='status', + field=models.IntegerField(choices=[(0, 'No data'), (1, 'No match'), (2, 'Bullish'), (3, 'Bearish'), (4, 'No aggregation'), (5, 'Not in bounds'), (6, 'Always allow'), (7, 'Always deny')], default=0), + ), + ] diff --git a/core/models.py b/core/models.py index 901d737..a2bc74c 100644 --- a/core/models.py +++ b/core/models.py @@ -136,9 +136,9 @@ class Account(models.Model): supported_symbols = models.JSONField(default=list) instruments = models.JSONField(default=list) currency = models.CharField(max_length=255, null=True, blank=True) - risk_model = models.ForeignKey( - "core.RiskModel", on_delete=models.SET_NULL, null=True, blank=True - ) + # risk_model = models.ForeignKey( + # "core.RiskModel", on_delete=models.SET_NULL, null=True, blank=True + # ) initial_balance = models.FloatField(default=0) def __str__(self): @@ -386,14 +386,17 @@ class Strategy(models.Model): take_profit_percent = models.FloatField(default=1.5) stop_loss_percent = models.FloatField(default=1.0) trailing_stop_loss_percent = models.FloatField(default=1.0, null=True, blank=True) - price_slippage_percent = models.FloatField(default=2.5) - callback_price_deviation_percent = models.FloatField(default=0.5) + # 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) asset_group = models.ForeignKey( "core.AssetGroup", on_delete=models.PROTECT, null=True, blank=True ) + risk_model = models.ForeignKey( + "core.RiskModel", on_delete=models.PROTECT, null=True, blank=True + ) class Meta: verbose_name_plural = "strategies" @@ -424,6 +427,9 @@ class RiskModel(models.Model): # Maximum number of trades per symbol max_open_trades_per_symbol = models.IntegerField(default=2) + price_slippage_percent = models.FloatField(default=2.5) + callback_price_deviation_percent = models.FloatField(default=0.5) + def __str__(self): return self.name diff --git a/core/templates/partials/risk-list.html b/core/templates/partials/risk-list.html index 5369ab2..b97eaff 100644 --- a/core/templates/partials/risk-list.html +++ b/core/templates/partials/risk-list.html @@ -19,6 +19,8 @@ max risk percent max open trades max open trades per symbol + max price slippage percent + max callback price deviation percent actions {% for item in object_list %} @@ -31,6 +33,8 @@ {{ item.max_risk_percent }} {{ item.max_open_trades }} {{ item.max_open_trades_per_symbol }} + {{ item.price_slippage_percent }} + {{ item.callback_price_deviation_percent }}