Add example calculation
This commit is contained in:
parent
2cacb3767f
commit
04d4f15dff
@ -629,7 +629,7 @@ class AwesomeStrategy(IStrategy):
|
|||||||
|
|
||||||
The `position_adjustment_enable` strategy property enables the usage of `adjust_trade_position()` callback in the strategy.
|
The `position_adjustment_enable` strategy property enables the usage of `adjust_trade_position()` callback in the strategy.
|
||||||
For performance reasons, it's disabled by default and freqtrade will show a warning message on startup if enabled.
|
For performance reasons, it's disabled by default and freqtrade will show a warning message on startup if enabled.
|
||||||
`adjust_trade_position()` can be used to perform additional orders, for example to manage risk with DCA (Dollar Cost Averaging) or to increase or decrease winning positions.
|
`adjust_trade_position()` can be used to perform additional orders, for example to manage risk with DCA (Dollar Cost Averaging) or to increase or decrease positions.
|
||||||
|
|
||||||
`max_entry_position_adjustment` property is used to limit the number of additional buys per trade (on top of the first buy) that the bot can execute. By default, the value is -1 which means the bot have no limit on number of adjustment buys.
|
`max_entry_position_adjustment` property is used to limit the number of additional buys per trade (on top of the first buy) that the bot can execute. By default, the value is -1 which means the bot have no limit on number of adjustment buys.
|
||||||
|
|
||||||
@ -652,12 +652,12 @@ Position adjustments will always be applied in the direction of the trade, so a
|
|||||||
|
|
||||||
!!! Warning
|
!!! Warning
|
||||||
Stoploss is still calculated from the initial opening price, not averaged price.
|
Stoploss is still calculated from the initial opening price, not averaged price.
|
||||||
|
Regular stoploss rules still apply (cannot move down).
|
||||||
|
|
||||||
!!! Warning "/stopbuy"
|
|
||||||
While `/stopbuy` command stops the bot from entering new trades, the position adjustment feature will continue buying new orders on existing trades.
|
While `/stopbuy` command stops the bot from entering new trades, the position adjustment feature will continue buying new orders on existing trades.
|
||||||
|
|
||||||
!!! Warning "Backtesting"
|
!!! Warning "Backtesting"
|
||||||
During backtesting this callback is called for each candle in `timeframe` or `timeframe_detail`, so performance will be affected.
|
During backtesting this callback is called for each candle in `timeframe` or `timeframe_detail`, so run-time performance will be affected.
|
||||||
|
|
||||||
``` python
|
``` python
|
||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
@ -757,6 +757,25 @@ def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: f
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Position adjust calculations
|
||||||
|
|
||||||
|
* Entry rates are calculated using weighted averages.
|
||||||
|
* Exits will not influence the average entry rate.
|
||||||
|
* Partial exit relative profit is relative to the average entry price at this point.
|
||||||
|
* Final exit relative profit is calculated based on the total invested capital. (See example below)
|
||||||
|
|
||||||
|
??? example "Calculation example"
|
||||||
|
*This example assumes 0 fees for simplicity, and a long position on an imaginary coin.*
|
||||||
|
|
||||||
|
* Buy 100@8\$
|
||||||
|
* Buy 100@9\$ -> Avg price: 8.5\$
|
||||||
|
* Sell 100@10\$ -> Avg price: 8.5\$, realized profit 150\$, 17.65%
|
||||||
|
* Buy 150@11\$ -> Avg price: 10\$, realized profit 150\$, 17.65%
|
||||||
|
* Sell 100@12\$ -> Avg price: 10\$, total realized profit 350\$, 20%
|
||||||
|
* Sell 150@14\$ -> Avg price: 10\$, total realized profit 950\$, 40%
|
||||||
|
|
||||||
|
The total profit for this trade was 950$ on a 3350$ investment (`100@8$ + 100@9$ + 150@11$`). As such - the final relative profit is 28.35% (`950 / 3350`).
|
||||||
|
|
||||||
## Adjust Entry Price
|
## Adjust Entry Price
|
||||||
|
|
||||||
The `adjust_entry_price()` callback may be used by strategy developer to refresh/replace limit orders upon arrival of new candles.
|
The `adjust_entry_price()` callback may be used by strategy developer to refresh/replace limit orders upon arrival of new candles.
|
||||||
|
@ -485,6 +485,7 @@ class Telegram(RPCHandler):
|
|||||||
sumA += amount * filled_orders[y]["safe_price"]
|
sumA += amount * filled_orders[y]["safe_price"]
|
||||||
sumB += amount
|
sumB += amount
|
||||||
prev_avg_price = sumA / sumB
|
prev_avg_price = sumA / sumB
|
||||||
|
# TODO: This calculation ignores fees.
|
||||||
price_to_1st_entry = ((cur_entry_average - first_avg) / first_avg)
|
price_to_1st_entry = ((cur_entry_average - first_avg) / first_avg)
|
||||||
minus_on_entry = 0
|
minus_on_entry = 0
|
||||||
if prev_avg_price:
|
if prev_avg_price:
|
||||||
|
@ -2835,7 +2835,7 @@ def test_order_to_ccxt(limit_buy_order_open):
|
|||||||
(('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)),
|
(('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)),
|
||||||
(('sell', 50, 12), (150.0, 12.5, 1875.0, -25.0, -25.0, -0.04)),
|
(('sell', 50, 12), (150.0, 12.5, 1875.0, -25.0, -25.0, -0.04)),
|
||||||
(('sell', 100, 20), (50.0, 12.5, 625.0, 725.0, 750.0, 0.60)),
|
(('sell', 100, 20), (50.0, 12.5, 625.0, 725.0, 750.0, 0.60)),
|
||||||
(('sell', 50, 5), (50.0, 12.5, 625.0, 725.0, -375.0, -0.60)),
|
(('sell', 50, 5), (50.0, 12.5, 625.0, 350.0, -375.0, -0.60)),
|
||||||
],
|
],
|
||||||
'end_profit': 350.0,
|
'end_profit': 350.0,
|
||||||
'end_profit_ratio': 0.14,
|
'end_profit_ratio': 0.14,
|
||||||
@ -2847,7 +2847,7 @@ def test_order_to_ccxt(limit_buy_order_open):
|
|||||||
(('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)),
|
(('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)),
|
||||||
(('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625, -0.044788)),
|
(('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625, -0.044788)),
|
||||||
(('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875, 0.59201995)),
|
(('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875, 0.59201995)),
|
||||||
(('sell', 50, 5), (50.0, 12.5, 625.0, 713.8125, -377.1875, -0.60199501)),
|
(('sell', 50, 5), (50.0, 12.5, 625.0, 336.625, -377.1875, -0.60199501)),
|
||||||
],
|
],
|
||||||
'end_profit': 336.625,
|
'end_profit': 336.625,
|
||||||
'end_profit_ratio': 0.1343142,
|
'end_profit_ratio': 0.1343142,
|
||||||
@ -2860,7 +2860,7 @@ def test_order_to_ccxt(limit_buy_order_open):
|
|||||||
(('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0, 1.189027)),
|
(('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0, 1.189027)),
|
||||||
(('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0, 1.189027)),
|
(('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0, 1.189027)),
|
||||||
(('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5, 0.7186579)),
|
(('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5, 0.7186579)),
|
||||||
(('sell', 150, 23), (150.0, 11.0, 1650.0, 1388.5, 1787.25, 1.08048062)),
|
(('sell', 150, 23), (150.0, 11.0, 1650.0, 3175.75, 1787.25, 1.08048062)),
|
||||||
],
|
],
|
||||||
'end_profit': 3175.75,
|
'end_profit': 3175.75,
|
||||||
'end_profit_ratio': 0.9747170,
|
'end_profit_ratio': 0.9747170,
|
||||||
@ -2874,11 +2874,24 @@ def test_order_to_ccxt(limit_buy_order_open):
|
|||||||
(('sell', 100, 11), (100.0, 5.0, 500.0, 600.0, 600.0, 1.2)),
|
(('sell', 100, 11), (100.0, 5.0, 500.0, 600.0, 600.0, 1.2)),
|
||||||
(('buy', 150, 15), (250.0, 11.0, 2750.0, 600.0, 600.0, 1.2)),
|
(('buy', 150, 15), (250.0, 11.0, 2750.0, 600.0, 600.0, 1.2)),
|
||||||
(('sell', 100, 19), (150.0, 11.0, 1650.0, 1400.0, 800.0, 0.72727273)),
|
(('sell', 100, 19), (150.0, 11.0, 1650.0, 1400.0, 800.0, 0.72727273)),
|
||||||
(('sell', 150, 23), (150.0, 11.0, 1650.0, 1400.0, 1800.0, 1.09090909)),
|
(('sell', 150, 23), (150.0, 11.0, 1650.0, 3200.0, 1800.0, 1.09090909)),
|
||||||
],
|
],
|
||||||
'end_profit': 3200.0,
|
'end_profit': 3200.0,
|
||||||
'fee': 0.0,
|
|
||||||
'end_profit_ratio': 0.98461538,
|
'end_profit_ratio': 0.98461538,
|
||||||
|
'fee': 0.0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'orders': [
|
||||||
|
(('buy', 100, 8), (100.0, 8.0, 800.0, 0.0, None, None)),
|
||||||
|
(('buy', 100, 9), (200.0, 8.5, 1700.0, 0.0, None, None)),
|
||||||
|
(('sell', 100, 10), (100.0, 8.5, 850.0, 150.0, 150.0, 0.17647059)),
|
||||||
|
(('buy', 150, 11), (250.0, 10, 2500.0, 150.0, 150.0, 0.17647059)),
|
||||||
|
(('sell', 100, 12), (150.0, 10.0, 1500.0, 350.0, 350.0, 0.2)),
|
||||||
|
(('sell', 150, 14), (150.0, 10.0, 1500.0, 950.0, 950.0, 0.40)),
|
||||||
|
],
|
||||||
|
'end_profit': 950.0,
|
||||||
|
'end_profit_ratio': 0.283582,
|
||||||
|
'fee': 0.0,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
def test_recalc_trade_from_orders_dca(data) -> None:
|
def test_recalc_trade_from_orders_dca(data) -> None:
|
||||||
@ -2940,7 +2953,7 @@ def test_recalc_trade_from_orders_dca(data) -> None:
|
|||||||
assert trade.open_rate == result[1]
|
assert trade.open_rate == result[1]
|
||||||
assert trade.stake_amount == result[2]
|
assert trade.stake_amount == result[2]
|
||||||
# TODO: enable the below.
|
# TODO: enable the below.
|
||||||
# assert pytest.approx(trade.realized_profit) == result[3]
|
assert pytest.approx(trade.realized_profit) == result[3]
|
||||||
# assert pytest.approx(trade.close_profit_abs) == result[4]
|
# assert pytest.approx(trade.close_profit_abs) == result[4]
|
||||||
assert pytest.approx(trade.close_profit) == result[5]
|
assert pytest.approx(trade.close_profit) == result[5]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user