Skip to content

Commit

Permalink
[Dca][DailyTrading] adapt order fees for last order only
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeDSM committed Jan 30, 2025
1 parent 3df16bf commit 724b767
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 5 deletions.
7 changes: 5 additions & 2 deletions Trading/Mode/daily_trading_mode/daily_trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,8 @@ async def _create_order(
local_take_profits_details = [
OrderDetails(decimal.Decimal("nan"), current_order.origin_quantity)
]
for take_profits_detail in local_take_profits_details:
for index, take_profits_detail in enumerate(local_take_profits_details):
is_last = index == len(local_take_profits_details) - 1
take_profit_price = trading_personal_data.decimal_adapt_price(
symbol_market,
current_order.origin_price * (
Expand All @@ -540,7 +541,9 @@ async def _create_order(
)
param_update, chained_order = await self.register_chained_order(
current_order, take_profit_price, order_type, exit_side,
quantity=take_profits_detail.quantity, tag=tag, reduce_only=reduce_only_chained_orders
quantity=take_profits_detail.quantity, tag=tag, reduce_only=reduce_only_chained_orders,
# only the last order is to take trigger fees into account
update_with_triggering_order_fees=is_last and not self.exchange_manager.is_future
)
params.update(param_update)
chained_orders.append(chained_order)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,7 @@ async def test_chained_multiple_take_profit_orders(tools):
tp_prices = [decimal.Decimal("100000"), decimal.Decimal("110000"), decimal.Decimal("120000")]
assert len(buy_order.chained_orders) == len(tp_prices)
for i, take_profit_order in enumerate(buy_order.chained_orders):
is_last = i == len(buy_order.chained_orders) - 1
assert isinstance(take_profit_order, trading_personal_data.SellLimitOrder)
assert take_profit_order.origin_quantity == (
decimal.Decimal("0.01")
Expand All @@ -1085,6 +1086,7 @@ async def test_chained_multiple_take_profit_orders(tools):
assert take_profit_order.associated_entry_ids == [buy_order.order_id]
assert not take_profit_order.is_open()
assert not take_profit_order.is_created()
assert take_profit_order.update_with_triggering_order_fees == is_last

# only 2 additional (2 in total)
data = {
Expand All @@ -1096,6 +1098,7 @@ async def test_chained_multiple_take_profit_orders(tools):
tp_prices = [decimal.Decimal("110000"), decimal.Decimal("120000")]
assert len(buy_order.chained_orders) == len(tp_prices)
for i, take_profit_order in enumerate(buy_order.chained_orders):
is_last = i == len(buy_order.chained_orders) - 1
assert isinstance(take_profit_order, trading_personal_data.SellLimitOrder)
assert take_profit_order.origin_quantity == (
decimal.Decimal("0.01")
Expand All @@ -1106,6 +1109,7 @@ async def test_chained_multiple_take_profit_orders(tools):
assert take_profit_order.associated_entry_ids == [buy_order.order_id]
assert not take_profit_order.is_open()
assert not take_profit_order.is_created()
assert take_profit_order.update_with_triggering_order_fees == is_last

# stop loss and 1 take profit and 5 additional (6 TP in total)
tp_prices = [
Expand All @@ -1129,8 +1133,10 @@ async def test_chained_multiple_take_profit_orders(tools):
assert stop_order.origin_price == decimal.Decimal("123")
assert stop_order.is_waiting_for_chained_trigger
assert stop_order.associated_entry_ids == [buy_order.order_id]
assert stop_order.update_with_triggering_order_fees is True
assert len(buy_order.chained_orders[1:]) == len(tp_prices)
for i, take_profit_order in enumerate(buy_order.chained_orders[1:]):
is_last = i == len(buy_order.chained_orders[1:]) - 1
assert isinstance(take_profit_order, trading_personal_data.SellLimitOrder)
assert take_profit_order.origin_quantity == (
decimal.Decimal("0.01")
Expand All @@ -1143,6 +1149,7 @@ async def test_chained_multiple_take_profit_orders(tools):
assert not take_profit_order.is_created()
assert isinstance(stop_order.order_group, trading_personal_data.BalancedTakeProfitAndStopOrderGroup)
assert take_profit_order.order_group is stop_order.order_group
assert take_profit_order.update_with_triggering_order_fees == is_last


async def test_create_stop_loss_orders(tools):
Expand All @@ -1168,6 +1175,7 @@ async def test_create_stop_loss_orders(tools):
assert stop_order.origin_price == decimal.Decimal("10")
assert stop_order.side is trading_enums.TradeOrderSide.SELL
assert stop_order.is_waiting_for_chained_trigger is False
assert stop_order.update_with_triggering_order_fees is False # not chained order
assert stop_order.tag is None
assert stop_order.is_open()

Expand Down
9 changes: 7 additions & 2 deletions Trading/Mode/dca_trading_mode/dca_trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,14 +370,17 @@ async def _create_entry_with_chained_exit_orders(self, entry_order, entry_price,
can_bundle_exit_orders = len(exit_quantities) == 1
reduce_only_chained_orders = self.exchange_manager.is_future
for i, exit_quantity in exit_quantities:
is_last = i == len(exit_quantities)
order_couple = []
# stop loss
if self.trading_mode.use_stop_loss:
stop_price = trading_personal_data.decimal_adapt_price(symbol_market, stop_price)
param_update, chained_order = await self.register_chained_order(
entry_order, stop_price, trading_enums.TraderOrderType.STOP_LOSS, exit_side,
quantity=exit_quantity, allow_bundling=can_bundle_exit_orders,
reduce_only=reduce_only_chained_orders
reduce_only=reduce_only_chained_orders,
# only the last order is to take trigger fees into account
update_with_triggering_order_fees=is_last and not self.exchange_manager.is_future
)
params.update(param_update)
order_couple.append(chained_order)
Expand All @@ -403,7 +406,9 @@ async def _create_entry_with_chained_exit_orders(self, entry_order, entry_price,
param_update, chained_order = await self.register_chained_order(
entry_order, take_profit_price, take_profit_order_type, None,
quantity=exit_quantity, allow_bundling=can_bundle_exit_orders,
reduce_only=reduce_only_chained_orders
reduce_only=reduce_only_chained_orders,
# only the last order is to take trigger fees into account
update_with_triggering_order_fees=is_last and not self.exchange_manager.is_future
)
params.update(param_update)
order_couple.append(chained_order)
Expand Down
10 changes: 9 additions & 1 deletion Trading/Mode/dca_trading_mode/tests/test_dca_trading_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ async def test_create_entry_with_chained_exit_orders(tools):
assert stop_loss.triggered_by is entry_order
assert stop_loss.order_group is None
assert stop_loss.reduce_only is False
assert stop_loss.update_with_triggering_order_fees is True
# reset values
create_order_mock.reset_mock()
entry_order.chained_orders = []
Expand All @@ -458,6 +459,7 @@ async def test_create_entry_with_chained_exit_orders(tools):
assert take_profit.triggered_by is entry_order
assert take_profit.order_group is None
assert take_profit.reduce_only is False
assert take_profit.update_with_triggering_order_fees is True
# reset values
create_order_mock.reset_mock()
entry_order.chained_orders = []
Expand All @@ -480,6 +482,7 @@ async def test_create_entry_with_chained_exit_orders(tools):
assert isinstance(take_profit.state, trading_personal_data.PendingCreationChainedOrderState)
assert take_profit.order_group is stop_loss.order_group
assert isinstance(take_profit.order_group, trading_personal_data.OneCancelsTheOtherOrderGroup)
assert take_profit.update_with_triggering_order_fees is True
# reset values
create_order_mock.reset_mock()
entry_order.chained_orders = []
Expand Down Expand Up @@ -510,7 +513,8 @@ async def test_create_entry_with_chained_exit_orders(tools):
total_tp_quantity = trading_constants.ZERO
previous_stop_price = entry_price
previous_tp_price = trading_constants.ZERO
for (stop_loss, take_profit) in zip(stop_losses, take_profits):
for i, (stop_loss, take_profit) in enumerate(zip(stop_losses, take_profits)):
is_last = i == len(stop_losses) - 1
assert isinstance(stop_loss.state, trading_personal_data.PendingCreationChainedOrderState)
assert isinstance(take_profit.state, trading_personal_data.PendingCreationChainedOrderState)
total_tp_quantity += take_profit.origin_quantity
Expand All @@ -526,6 +530,8 @@ async def test_create_entry_with_chained_exit_orders(tools):
# ensure orders are grouped together
assert take_profit.order_group is stop_loss.order_group
assert isinstance(take_profit.order_group, trading_personal_data.OneCancelsTheOtherOrderGroup)
assert stop_loss.update_with_triggering_order_fees is is_last
assert take_profit.update_with_triggering_order_fees is is_last
# ensure selling the total entry quantity
assert total_stop_quantity == entry_order.origin_quantity
assert total_tp_quantity == entry_order.origin_quantity
Expand Down Expand Up @@ -560,6 +566,8 @@ async def test_create_entry_with_chained_exit_orders(tools):
assert len(take_profits) == 1
assert all(order.reduce_only is True for order in entry_order.chained_orders) # futures: use reduce only
assert stop_losses[0].origin_quantity == take_profits[0].origin_quantity == entry_order.origin_quantity
# update_with_triggering_order_fees is false because we are trading futures
assert stop_losses[0].update_with_triggering_order_fees == take_profits[0].update_with_triggering_order_fees == False


async def test_create_entry_order(tools):
Expand Down

0 comments on commit 724b767

Please sign in to comment.