wbportfolio 1.54.13__py2.py3-none-any.whl → 1.54.15__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wbportfolio might be problematic. Click here for more details.

Files changed (86) hide show
  1. wbportfolio/admin/__init__.py +2 -0
  2. wbportfolio/admin/orders/__init__.py +2 -0
  3. wbportfolio/admin/orders/order_proposals.py +14 -0
  4. wbportfolio/admin/orders/orders.py +30 -0
  5. wbportfolio/admin/{transactions/rebalancing.py → rebalancing.py} +1 -1
  6. wbportfolio/admin/transactions/__init__.py +0 -1
  7. wbportfolio/admin/transactions/trades.py +2 -17
  8. wbportfolio/contrib/company_portfolio/tests/conftest.py +2 -2
  9. wbportfolio/factories/__init__.py +2 -1
  10. wbportfolio/factories/orders/__init__.py +2 -0
  11. wbportfolio/factories/orders/order_proposals.py +17 -0
  12. wbportfolio/factories/orders/orders.py +21 -0
  13. wbportfolio/factories/rebalancing.py +1 -1
  14. wbportfolio/factories/trades.py +2 -13
  15. wbportfolio/filters/orders/__init__.py +1 -0
  16. wbportfolio/filters/orders/orders.py +11 -0
  17. wbportfolio/import_export/handlers/trade.py +20 -20
  18. wbportfolio/import_export/resources/trades.py +2 -2
  19. wbportfolio/migrations/0082_remove_tradeproposal_creator_and_more.py +93 -0
  20. wbportfolio/migrations/0083_order_alter_trade_options_and_more.py +181 -0
  21. wbportfolio/models/__init__.py +2 -0
  22. wbportfolio/models/orders/__init__.py +2 -0
  23. wbportfolio/models/{transactions/trade_proposals.py → orders/order_proposals.py} +289 -245
  24. wbportfolio/models/orders/orders.py +243 -0
  25. wbportfolio/models/portfolio.py +17 -20
  26. wbportfolio/models/{transactions/rebalancing.py → rebalancing.py} +18 -18
  27. wbportfolio/models/transactions/__init__.py +0 -2
  28. wbportfolio/models/transactions/trades.py +10 -450
  29. wbportfolio/pms/analytics/portfolio.py +10 -6
  30. wbportfolio/pms/analytics/utils.py +9 -0
  31. wbportfolio/pms/trading/handler.py +6 -4
  32. wbportfolio/pms/typing.py +18 -7
  33. wbportfolio/rebalancing/decorators.py +1 -1
  34. wbportfolio/rebalancing/models/composite.py +3 -7
  35. wbportfolio/rebalancing/models/market_capitalization_weighted.py +3 -1
  36. wbportfolio/serializers/__init__.py +1 -0
  37. wbportfolio/serializers/orders/__init__.py +2 -0
  38. wbportfolio/serializers/{transactions/trade_proposals.py → orders/order_proposals.py} +23 -15
  39. wbportfolio/serializers/orders/orders.py +187 -0
  40. wbportfolio/serializers/portfolios.py +7 -7
  41. wbportfolio/serializers/rebalancing.py +1 -1
  42. wbportfolio/serializers/transactions/__init__.py +1 -5
  43. wbportfolio/serializers/transactions/trades.py +1 -182
  44. wbportfolio/tests/conftest.py +4 -2
  45. wbportfolio/tests/models/orders/__init__.py +0 -0
  46. wbportfolio/tests/models/{transactions/test_trade_proposals.py → orders/test_order_proposals.py} +218 -246
  47. wbportfolio/tests/models/test_portfolios.py +11 -10
  48. wbportfolio/tests/models/transactions/test_rebalancing.py +5 -5
  49. wbportfolio/tests/models/transactions/test_trades.py +0 -20
  50. wbportfolio/tests/rebalancing/test_models.py +24 -28
  51. wbportfolio/tests/signals.py +10 -10
  52. wbportfolio/tests/tests.py +1 -1
  53. wbportfolio/urls.py +7 -7
  54. wbportfolio/viewsets/__init__.py +2 -0
  55. wbportfolio/viewsets/configs/buttons/__init__.py +2 -3
  56. wbportfolio/viewsets/configs/buttons/trades.py +0 -8
  57. wbportfolio/viewsets/configs/display/__init__.py +0 -2
  58. wbportfolio/viewsets/configs/display/portfolios.py +5 -5
  59. wbportfolio/viewsets/configs/display/rebalancing.py +2 -2
  60. wbportfolio/viewsets/configs/display/trades.py +1 -225
  61. wbportfolio/viewsets/configs/endpoints/__init__.py +0 -3
  62. wbportfolio/viewsets/configs/endpoints/trades.py +0 -41
  63. wbportfolio/viewsets/orders/__init__.py +6 -0
  64. wbportfolio/viewsets/orders/configs/__init__.py +4 -0
  65. wbportfolio/viewsets/orders/configs/buttons/__init__.py +2 -0
  66. wbportfolio/viewsets/{configs/buttons/trade_proposals.py → orders/configs/buttons/order_proposals.py} +22 -21
  67. wbportfolio/viewsets/orders/configs/buttons/orders.py +9 -0
  68. wbportfolio/viewsets/orders/configs/displays/__init__.py +2 -0
  69. wbportfolio/viewsets/{configs/display/trade_proposals.py → orders/configs/displays/order_proposals.py} +21 -21
  70. wbportfolio/viewsets/orders/configs/displays/orders.py +180 -0
  71. wbportfolio/viewsets/orders/configs/endpoints/__init__.py +2 -0
  72. wbportfolio/viewsets/orders/configs/endpoints/order_proposals.py +21 -0
  73. wbportfolio/viewsets/orders/configs/endpoints/orders.py +26 -0
  74. wbportfolio/viewsets/orders/configs/titles/__init__.py +0 -0
  75. wbportfolio/viewsets/orders/configs/titles/orders.py +0 -0
  76. wbportfolio/viewsets/{transactions/trade_proposals.py → orders/order_proposals.py} +46 -45
  77. wbportfolio/viewsets/orders/orders.py +219 -0
  78. wbportfolio/viewsets/portfolios.py +12 -12
  79. wbportfolio/viewsets/{transactions/rebalancing.py → rebalancing.py} +2 -2
  80. wbportfolio/viewsets/transactions/__init__.py +1 -7
  81. wbportfolio/viewsets/transactions/trades.py +1 -199
  82. {wbportfolio-1.54.13.dist-info → wbportfolio-1.54.15.dist-info}/METADATA +1 -1
  83. {wbportfolio-1.54.13.dist-info → wbportfolio-1.54.15.dist-info}/RECORD +85 -58
  84. wbportfolio/viewsets/configs/endpoints/trade_proposals.py +0 -18
  85. {wbportfolio-1.54.13.dist-info → wbportfolio-1.54.15.dist-info}/WHEEL +0 -0
  86. {wbportfolio-1.54.13.dist-info → wbportfolio-1.54.15.dist-info}/licenses/LICENSE +0 -0
@@ -7,7 +7,7 @@ import pytest
7
7
  from faker import Faker
8
8
  from pandas._libs.tslibs.offsets import BDay, BusinessMonthEnd
9
9
 
10
- from wbportfolio.models import Portfolio, RebalancingModel, Trade, TradeProposal
10
+ from wbportfolio.models import Order, OrderProposal, Portfolio, RebalancingModel
11
11
  from wbportfolio.pms.typing import Portfolio as PortfolioDTO
12
12
  from wbportfolio.pms.typing import Position
13
13
 
@@ -16,54 +16,55 @@ fake = Faker()
16
16
 
17
17
  # Mark tests to use Django's database
18
18
  @pytest.mark.django_db
19
- class TestTradeProposal:
19
+ class TestOrderProposal:
20
+ def test_init(self, order_proposal):
21
+ assert order_proposal.id is not None
22
+
20
23
  # Test that the checked object is correctly set to the portfolio
21
- def test_checked_object(self, trade_proposal):
24
+ def test_checked_object(self, order_proposal):
22
25
  """
23
- Verify that the checked object is the portfolio associated with the trade proposal.
26
+ Verify that the checked object is the portfolio associated with the order proposal.
24
27
  """
25
- assert trade_proposal.checked_object == trade_proposal.portfolio
28
+ assert order_proposal.checked_object == order_proposal.portfolio
26
29
 
27
30
  # Test that the evaluation date matches the trade date
28
- def test_check_evaluation_date(self, trade_proposal):
31
+ def test_check_evaluation_date(self, order_proposal):
29
32
  """
30
33
  Ensure the evaluation date is the same as the trade date.
31
34
  """
32
- assert trade_proposal.check_evaluation_date == trade_proposal.trade_date
35
+ assert order_proposal.check_evaluation_date == order_proposal.trade_date
33
36
 
34
37
  # Test the validated trading service functionality
35
- def test_validated_trading_service(self, trade_proposal, asset_position_factory, trade_factory):
38
+ def test_validated_trading_service(self, order_proposal, asset_position_factory, order_factory):
36
39
  """
37
40
  Validate that the effective and target portfolios are correctly calculated.
38
41
  """
39
- effective_date = (trade_proposal.trade_date - BDay(1)).date()
42
+ effective_date = (order_proposal.trade_date - BDay(1)).date()
40
43
 
41
44
  # Create asset positions for testing
42
45
  a1 = asset_position_factory.create(
43
- portfolio=trade_proposal.portfolio, date=effective_date, weighting=Decimal("0.3")
46
+ portfolio=order_proposal.portfolio, date=effective_date, weighting=Decimal("0.3")
44
47
  )
45
48
  a2 = asset_position_factory.create(
46
- portfolio=trade_proposal.portfolio, date=effective_date, weighting=Decimal("0.7")
49
+ portfolio=order_proposal.portfolio, date=effective_date, weighting=Decimal("0.7")
47
50
  )
48
51
 
49
- # Create trades for testing
50
- t1 = trade_factory.create(
51
- trade_proposal=trade_proposal,
52
+ # Create orders for testing
53
+ t1 = order_factory.create(
54
+ order_proposal=order_proposal,
52
55
  weighting=Decimal("0.05"),
53
- portfolio=trade_proposal.portfolio,
54
- transaction_date=trade_proposal.trade_date,
56
+ portfolio=order_proposal.portfolio,
55
57
  underlying_instrument=a1.underlying_quote,
56
58
  )
57
- t2 = trade_factory.create(
58
- trade_proposal=trade_proposal,
59
+ t2 = order_factory.create(
60
+ order_proposal=order_proposal,
59
61
  weighting=Decimal("-0.05"),
60
- portfolio=trade_proposal.portfolio,
61
- transaction_date=trade_proposal.trade_date,
62
+ portfolio=order_proposal.portfolio,
62
63
  underlying_instrument=a2.underlying_quote,
63
64
  )
64
65
 
65
66
  # Get the validated trading service
66
- validated_trading_service = trade_proposal.validated_trading_service
67
+ validated_trading_service = order_proposal.validated_trading_service
67
68
 
68
69
  # Assert effective and target portfolios are as expected
69
70
  assert validated_trading_service._effective_portfolio.to_dict() == {
@@ -76,116 +77,116 @@ class TestTradeProposal:
76
77
  }
77
78
 
78
79
  # Test the calculation of the last effective date
79
- def test_last_effective_date(self, trade_proposal, asset_position_factory):
80
+ def test_last_effective_date(self, order_proposal, asset_position_factory):
80
81
  """
81
82
  Verify the last effective date is correctly determined based on asset positions.
82
83
  """
83
84
  # Without any positions, it should be the day before the trade date
84
85
  assert (
85
- trade_proposal.last_effective_date == (trade_proposal.trade_date - BDay(1)).date()
86
+ order_proposal.last_effective_date == (order_proposal.trade_date - BDay(1)).date()
86
87
  ), "Last effective date without position should be t-1"
87
88
 
88
89
  # Create an asset position before the trade date
89
90
  a1 = asset_position_factory.create(
90
- portfolio=trade_proposal.portfolio, date=(trade_proposal.trade_date - BDay(5)).date()
91
+ portfolio=order_proposal.portfolio, date=(order_proposal.trade_date - BDay(5)).date()
91
92
  )
92
- a_noise = asset_position_factory.create(portfolio=trade_proposal.portfolio, date=trade_proposal.trade_date) # noqa
93
+ a_noise = asset_position_factory.create(portfolio=order_proposal.portfolio, date=order_proposal.trade_date) # noqa
93
94
 
94
95
  # The last effective date should still be the day before the trade date due to caching
95
96
  assert (
96
- trade_proposal.last_effective_date == (trade_proposal.trade_date - BDay(1)).date()
97
+ order_proposal.last_effective_date == (order_proposal.trade_date - BDay(1)).date()
97
98
  ), "last effective date is cached, so it won't change as is"
98
99
 
99
100
  # Reset the cache property to recalculate
100
- del trade_proposal.last_effective_date
101
+ del order_proposal.last_effective_date
101
102
 
102
103
  # Now it should be the date of the latest position before the trade date
103
104
  assert (
104
- trade_proposal.last_effective_date == a1.date
105
+ order_proposal.last_effective_date == a1.date
105
106
  ), "last effective date is the latest position strictly lower than trade date"
106
107
 
107
- # Test finding the previous trade proposal
108
- def test_previous_trade_proposal(self, trade_proposal_factory):
108
+ # Test finding the previous order proposal
109
+ def test_previous_order_proposal(self, order_proposal_factory):
109
110
  """
110
- Ensure the previous trade proposal is correctly identified as the last approved proposal before the current one.
111
+ Ensure the previous order proposal is correctly identified as the last approved proposal before the current one.
111
112
  """
112
- tp = trade_proposal_factory.create()
113
- tp_previous_submit = trade_proposal_factory.create( # noqa
114
- portfolio=tp.portfolio, status=TradeProposal.Status.SUBMIT, trade_date=(tp.trade_date - BDay(1)).date()
113
+ tp = order_proposal_factory.create()
114
+ tp_previous_submit = order_proposal_factory.create( # noqa
115
+ portfolio=tp.portfolio, status=OrderProposal.Status.SUBMIT, trade_date=(tp.trade_date - BDay(1)).date()
115
116
  )
116
- tp_previous_approve = trade_proposal_factory.create(
117
- portfolio=tp.portfolio, status=TradeProposal.Status.APPROVED, trade_date=(tp.trade_date - BDay(2)).date()
117
+ tp_previous_approve = order_proposal_factory.create(
118
+ portfolio=tp.portfolio, status=OrderProposal.Status.APPROVED, trade_date=(tp.trade_date - BDay(2)).date()
118
119
  )
119
- tp_next_approve = trade_proposal_factory.create( # noqa
120
- portfolio=tp.portfolio, status=TradeProposal.Status.APPROVED, trade_date=(tp.trade_date + BDay(1)).date()
120
+ tp_next_approve = order_proposal_factory.create( # noqa
121
+ portfolio=tp.portfolio, status=OrderProposal.Status.APPROVED, trade_date=(tp.trade_date + BDay(1)).date()
121
122
  )
122
123
 
123
- # The previous valid trade proposal should be the approved one strictly before the current proposal
124
+ # The previous valid order proposal should be the approved one strictly before the current proposal
124
125
  assert (
125
- tp.previous_trade_proposal == tp_previous_approve
126
- ), "the previous valid trade proposal is the strictly before and approved trade proposal"
126
+ tp.previous_order_proposal == tp_previous_approve
127
+ ), "the previous valid order proposal is the strictly before and approved order proposal"
127
128
 
128
- # Test finding the next trade proposal
129
- def test_next_trade_proposal(self, trade_proposal_factory):
129
+ # Test finding the next order proposal
130
+ def test_next_order_proposal(self, order_proposal_factory):
130
131
  """
131
- Verify the next trade proposal is correctly identified as the first approved proposal after the current one.
132
+ Verify the next order proposal is correctly identified as the first approved proposal after the current one.
132
133
  """
133
- tp = trade_proposal_factory.create()
134
- tp_previous_approve = trade_proposal_factory.create( # noqa
135
- portfolio=tp.portfolio, status=TradeProposal.Status.APPROVED, trade_date=(tp.trade_date - BDay(1)).date()
134
+ tp = order_proposal_factory.create()
135
+ tp_previous_approve = order_proposal_factory.create( # noqa
136
+ portfolio=tp.portfolio, status=OrderProposal.Status.APPROVED, trade_date=(tp.trade_date - BDay(1)).date()
136
137
  )
137
- tp_next_submit = trade_proposal_factory.create( # noqa
138
- portfolio=tp.portfolio, status=TradeProposal.Status.SUBMIT, trade_date=(tp.trade_date + BDay(1)).date()
138
+ tp_next_submit = order_proposal_factory.create( # noqa
139
+ portfolio=tp.portfolio, status=OrderProposal.Status.SUBMIT, trade_date=(tp.trade_date + BDay(1)).date()
139
140
  )
140
- tp_next_approve = trade_proposal_factory.create(
141
- portfolio=tp.portfolio, status=TradeProposal.Status.APPROVED, trade_date=(tp.trade_date + BDay(2)).date()
141
+ tp_next_approve = order_proposal_factory.create(
142
+ portfolio=tp.portfolio, status=OrderProposal.Status.APPROVED, trade_date=(tp.trade_date + BDay(2)).date()
142
143
  )
143
144
 
144
- # The next valid trade proposal should be the approved one strictly after the current proposal
145
+ # The next valid order proposal should be the approved one strictly after the current proposal
145
146
  assert (
146
- tp.next_trade_proposal == tp_next_approve
147
- ), "the next valid trade proposal is the strictly after and approved trade proposal"
147
+ tp.next_order_proposal == tp_next_approve
148
+ ), "the next valid order proposal is the strictly after and approved order proposal"
148
149
 
149
150
  # Test getting the default target portfolio
150
- def test__get_default_target_portfolio(self, trade_proposal, asset_position_factory):
151
+ def test__get_default_target_portfolio(self, order_proposal, asset_position_factory):
151
152
  """
152
153
  Ensure the default target portfolio is set to the effective portfolio from the day before the trade date.
153
154
  """
154
- effective_date = (trade_proposal.trade_date - BDay(1)).date()
155
+ effective_date = (order_proposal.trade_date - BDay(1)).date()
155
156
 
156
157
  # Create asset positions for testing
157
158
  a1 = asset_position_factory.create(
158
- portfolio=trade_proposal.portfolio, date=effective_date, weighting=Decimal("0.3")
159
+ portfolio=order_proposal.portfolio, date=effective_date, weighting=Decimal("0.3")
159
160
  )
160
161
  a2 = asset_position_factory.create(
161
- portfolio=trade_proposal.portfolio, date=effective_date, weighting=Decimal("0.7")
162
+ portfolio=order_proposal.portfolio, date=effective_date, weighting=Decimal("0.7")
162
163
  )
163
- asset_position_factory.create(portfolio=trade_proposal.portfolio, date=trade_proposal.trade_date) # noise
164
+ asset_position_factory.create(portfolio=order_proposal.portfolio, date=order_proposal.trade_date) # noise
164
165
 
165
166
  # The default target portfolio should match the effective portfolio
166
- assert trade_proposal._get_default_target_portfolio().to_dict() == {
167
+ assert order_proposal._get_default_target_portfolio().to_dict() == {
167
168
  a1.underlying_quote.id: a1.weighting,
168
169
  a2.underlying_quote.id: a2.weighting,
169
170
  }
170
171
 
171
172
  # Test getting the default target portfolio with a rebalancing model
172
173
  @patch.object(RebalancingModel, "get_target_portfolio")
173
- def test__get_default_target_portfolio_with_rebalancer_model(self, mock_fct, trade_proposal, rebalancer_factory):
174
+ def test__get_default_target_portfolio_with_rebalancer_model(self, mock_fct, order_proposal, rebalancer_factory):
174
175
  """
175
176
  Verify that the target portfolio is correctly obtained from a rebalancing model.
176
177
  """
177
178
  # Expected target portfolio from the rebalancing model
178
179
  expected_target_portfolio = PortfolioDTO(
179
- positions=(Position(underlying_instrument=1, weighting=Decimal(1), date=trade_proposal.trade_date),)
180
+ positions=(Position(underlying_instrument=1, weighting=Decimal(1), date=order_proposal.trade_date),)
180
181
  )
181
182
  mock_fct.return_value = expected_target_portfolio
182
183
 
183
184
  # Create a rebalancer for testing
184
185
  rebalancer = rebalancer_factory.create(
185
- portfolio=trade_proposal.portfolio, parameters={"rebalancer_parameter": "A"}
186
+ portfolio=order_proposal.portfolio, parameters={"rebalancer_parameter": "A"}
186
187
  )
187
- trade_proposal.rebalancing_model = rebalancer.rebalancing_model
188
- trade_proposal.save()
188
+ order_proposal.rebalancing_model = rebalancer.rebalancing_model
189
+ order_proposal.save()
189
190
 
190
191
  # Additional keyword arguments for the rebalancing model
191
192
  extra_kwargs = {"test": "test"}
@@ -196,41 +197,38 @@ class TestTradeProposal:
196
197
 
197
198
  # Assert the target portfolio matches the expected output from the rebalancing model
198
199
  assert (
199
- trade_proposal._get_default_target_portfolio(**extra_kwargs) == expected_target_portfolio
200
+ order_proposal._get_default_target_portfolio(**extra_kwargs) == expected_target_portfolio
200
201
  ), "We expect the target portfolio to be whatever is returned by the rebalancer model"
201
202
  mock_fct.assert_called_once_with(
202
- trade_proposal.portfolio, trade_proposal.trade_date, trade_proposal.last_effective_date, **expected_kwargs
203
+ order_proposal.portfolio, order_proposal.trade_date, order_proposal.last_effective_date, **expected_kwargs
203
204
  )
204
205
 
205
- # Test normalizing trades
206
- def test_normalize_trades(self, trade_proposal, trade_factory):
206
+ # Test normalizing orders
207
+ def test_normalize_orders(self, order_proposal, order_factory):
207
208
  """
208
- Ensure trades are normalized to sum up to 1, handling quantization errors.
209
+ Ensure orders are normalized to sum up to 1, handling quantization errors.
209
210
  """
210
- # Create trades for testing
211
- t1 = trade_factory.create(
212
- trade_proposal=trade_proposal,
213
- transaction_date=trade_proposal.trade_date,
214
- portfolio=trade_proposal.portfolio,
211
+ # Create orders for testing
212
+ t1 = order_factory.create(
213
+ order_proposal=order_proposal,
214
+ portfolio=order_proposal.portfolio,
215
215
  weighting=Decimal(0.2),
216
216
  )
217
- t2 = trade_factory.create(
218
- trade_proposal=trade_proposal,
219
- transaction_date=trade_proposal.trade_date,
220
- portfolio=trade_proposal.portfolio,
217
+ t2 = order_factory.create(
218
+ order_proposal=order_proposal,
219
+ portfolio=order_proposal.portfolio,
221
220
  weighting=Decimal(0.26),
222
221
  )
223
- t3 = trade_factory.create(
224
- trade_proposal=trade_proposal,
225
- transaction_date=trade_proposal.trade_date,
226
- portfolio=trade_proposal.portfolio,
222
+ t3 = order_factory.create(
223
+ order_proposal=order_proposal,
224
+ portfolio=order_proposal.portfolio,
227
225
  weighting=Decimal(0.14),
228
226
  )
229
227
 
230
- # Normalize trades
231
- trade_proposal.normalize_trades()
228
+ # Normalize orders
229
+ order_proposal.normalize_orders()
232
230
 
233
- # Refresh trades from the database
231
+ # Refresh orders from the database
234
232
  t1.refresh_from_db()
235
233
  t2.refresh_from_db()
236
234
  t3.refresh_from_db()
@@ -249,23 +247,23 @@ class TestTradeProposal:
249
247
  assert t2.weighting == normalized_t2_weight + quantize_error # Add quantize error to the largest position
250
248
  assert t3.weighting == normalized_t3_weight
251
249
 
252
- # Test resetting trades
253
- def test_reset_trades(self, trade_proposal, instrument_factory, instrument_price_factory, asset_position_factory):
250
+ # Test resetting orders
251
+ def test_reset_orders(self, order_proposal, instrument_factory, instrument_price_factory, asset_position_factory):
254
252
  """
255
- Verify trades are correctly reset based on effective and target portfolios.
253
+ Verify orders are correctly reset based on effective and target portfolios.
256
254
  """
257
- effective_date = trade_proposal.last_effective_date
255
+ effective_date = order_proposal.last_effective_date
258
256
 
259
257
  # Create instruments for testing
260
- i1 = instrument_factory.create(currency=trade_proposal.portfolio.currency)
261
- i2 = instrument_factory.create(currency=trade_proposal.portfolio.currency)
262
- i3 = instrument_factory.create(currency=trade_proposal.portfolio.currency)
258
+ i1 = instrument_factory.create(currency=order_proposal.portfolio.currency)
259
+ i2 = instrument_factory.create(currency=order_proposal.portfolio.currency)
260
+ i3 = instrument_factory.create(currency=order_proposal.portfolio.currency)
263
261
  # Build initial effective portfolio constituting only from two positions of i1 and i2
264
262
  asset_position_factory.create(
265
- portfolio=trade_proposal.portfolio, date=effective_date, underlying_instrument=i1, weighting=Decimal("0.7")
263
+ portfolio=order_proposal.portfolio, date=effective_date, underlying_instrument=i1, weighting=Decimal("0.7")
266
264
  )
267
265
  asset_position_factory.create(
268
- portfolio=trade_proposal.portfolio, date=effective_date, underlying_instrument=i2, weighting=Decimal("0.3")
266
+ portfolio=order_proposal.portfolio, date=effective_date, underlying_instrument=i2, weighting=Decimal("0.3")
269
267
  )
270
268
  p1 = instrument_price_factory.create(instrument=i1, date=effective_date)
271
269
  p2 = instrument_price_factory.create(instrument=i2, date=effective_date)
@@ -276,26 +274,26 @@ class TestTradeProposal:
276
274
  [
277
275
  Position(
278
276
  underlying_instrument=i2.id,
279
- date=trade_proposal.trade_date,
277
+ date=order_proposal.trade_date,
280
278
  weighting=Decimal("0.4"),
281
279
  price=float(p2.net_value),
282
280
  ),
283
281
  Position(
284
282
  underlying_instrument=i3.id,
285
- date=trade_proposal.trade_date,
283
+ date=order_proposal.trade_date,
286
284
  weighting=Decimal("0.6"),
287
285
  price=float(p3.net_value),
288
286
  ),
289
287
  ]
290
288
  )
291
289
 
292
- # Reset trades
293
- trade_proposal.reset_trades(target_portfolio=target_portfolio)
290
+ # Reset orders
291
+ order_proposal.reset_orders(target_portfolio=target_portfolio)
294
292
 
295
- # Get trades for each instrument
296
- t1 = trade_proposal.trades.get(underlying_instrument=i1)
297
- t2 = trade_proposal.trades.get(underlying_instrument=i2)
298
- t3 = trade_proposal.trades.get(underlying_instrument=i3)
293
+ # Get orders for each instrument
294
+ t1 = order_proposal.orders.get(underlying_instrument=i1)
295
+ t2 = order_proposal.orders.get(underlying_instrument=i2)
296
+ t3 = order_proposal.orders.get(underlying_instrument=i3)
299
297
 
300
298
  # Assert trade weights are correctly reset
301
299
  assert t1.weighting == Decimal("-0.7")
@@ -307,27 +305,27 @@ class TestTradeProposal:
307
305
  [
308
306
  Position(
309
307
  underlying_instrument=i1.id,
310
- date=trade_proposal.trade_date,
308
+ date=order_proposal.trade_date,
311
309
  weighting=Decimal("0.2"),
312
310
  price=float(p1.net_value),
313
311
  ),
314
312
  Position(
315
313
  underlying_instrument=i2.id,
316
- date=trade_proposal.trade_date,
314
+ date=order_proposal.trade_date,
317
315
  weighting=Decimal("0.3"),
318
316
  price=float(p2.net_value),
319
317
  ),
320
318
  Position(
321
319
  underlying_instrument=i3.id,
322
- date=trade_proposal.trade_date,
320
+ date=order_proposal.trade_date,
323
321
  weighting=Decimal("0.5"),
324
322
  price=float(p3.net_value),
325
323
  ),
326
324
  ]
327
325
  )
328
326
 
329
- trade_proposal.reset_trades(target_portfolio=new_target_portfolio)
330
- # Refetch the trades for each instrument
327
+ order_proposal.reset_orders(target_portfolio=new_target_portfolio)
328
+ # Refetch the orders for each instrument
331
329
  t1.refresh_from_db()
332
330
  t2.refresh_from_db()
333
331
  t3.refresh_from_db()
@@ -336,48 +334,44 @@ class TestTradeProposal:
336
334
  assert t2.weighting == Decimal("0")
337
335
  assert t3.weighting == Decimal("0.5")
338
336
 
339
- def test_reset_trades_remove_invalid_trades(self, trade_proposal, trade_factory, instrument_price_factory):
337
+ def test_reset_orders_remove_invalid_orders(self, order_proposal, order_factory, instrument_price_factory):
340
338
  # create a invalid trade and its price
341
- invalid_trade = trade_factory.create(trade_proposal=trade_proposal, weighting=0)
342
- instrument_price_factory.create(
343
- date=invalid_trade.transaction_date, instrument=invalid_trade.underlying_instrument
344
- )
339
+ invalid_trade = order_factory.create(order_proposal=order_proposal, weighting=Decimal(0))
340
+ instrument_price_factory.create(date=invalid_trade.value_date, instrument=invalid_trade.underlying_instrument)
345
341
 
346
342
  # create a valid trade and its price
347
- valid_trade = trade_factory.create(trade_proposal=trade_proposal, weighting=1.0)
348
- instrument_price_factory.create(
349
- date=valid_trade.transaction_date, instrument=valid_trade.underlying_instrument
350
- )
343
+ valid_trade = order_factory.create(order_proposal=order_proposal, weighting=Decimal(1))
344
+ instrument_price_factory.create(date=valid_trade.value_date, instrument=valid_trade.underlying_instrument)
351
345
 
352
- trade_proposal.reset_trades()
353
- assert trade_proposal.trades.get(underlying_instrument=valid_trade.underlying_instrument).weighting == Decimal(
346
+ order_proposal.reset_orders()
347
+ assert order_proposal.orders.get(underlying_instrument=valid_trade.underlying_instrument).weighting == Decimal(
354
348
  "1"
355
349
  )
356
- with pytest.raises(Trade.DoesNotExist):
357
- trade_proposal.trades.get(underlying_instrument=invalid_trade.underlying_instrument)
350
+ with pytest.raises(Order.DoesNotExist):
351
+ order_proposal.orders.get(underlying_instrument=invalid_trade.underlying_instrument)
358
352
 
359
- # Test replaying trade proposals
353
+ # Test replaying order proposals
360
354
  @patch.object(Portfolio, "drift_weights")
361
- def test_replay(self, mock_fct, trade_proposal_factory):
355
+ def test_replay(self, mock_fct, order_proposal_factory):
362
356
  """
363
- Ensure replaying trade proposals correctly calls drift_weights for each period.
357
+ Ensure replaying order proposals correctly calls drift_weights for each period.
364
358
  """
365
359
  mock_fct.return_value = None, None
366
360
 
367
- # Create approved trade proposals for testing
368
- tp0 = trade_proposal_factory.create(status=TradeProposal.Status.APPROVED)
369
- tp1 = trade_proposal_factory.create(
361
+ # Create approved order proposals for testing
362
+ tp0 = order_proposal_factory.create(status=OrderProposal.Status.APPROVED)
363
+ tp1 = order_proposal_factory.create(
370
364
  portfolio=tp0.portfolio,
371
- status=TradeProposal.Status.APPROVED,
365
+ status=OrderProposal.Status.APPROVED,
372
366
  trade_date=(tp0.trade_date + BusinessMonthEnd(1)).date(),
373
367
  )
374
- tp2 = trade_proposal_factory.create(
368
+ tp2 = order_proposal_factory.create(
375
369
  portfolio=tp0.portfolio,
376
- status=TradeProposal.Status.APPROVED,
370
+ status=OrderProposal.Status.APPROVED,
377
371
  trade_date=(tp1.trade_date + BusinessMonthEnd(1)).date(),
378
372
  )
379
373
 
380
- # Replay trade proposals
374
+ # Replay order proposals
381
375
  tp0.replay()
382
376
 
383
377
  # Expected calls to drift_weights
@@ -391,7 +385,7 @@ class TestTradeProposal:
391
385
  mock_fct.assert_has_calls(expected_calls)
392
386
 
393
387
  # Test stopping replay on a non-approved proposal
394
- tp1.status = TradeProposal.Status.FAILED
388
+ tp1.status = OrderProposal.Status.FAILED
395
389
  tp1.save()
396
390
  expected_calls = [call(tp0.trade_date, tp1.trade_date - timedelta(days=1), stop_at_rebalancing=True)]
397
391
  mock_fct.assert_has_calls(expected_calls)
@@ -399,18 +393,18 @@ class TestTradeProposal:
399
393
  # Test estimating shares for a trade
400
394
  @patch.object(Portfolio, "get_total_asset_value")
401
395
  def test_get_estimated_shares(
402
- self, mock_fct, trade_proposal, trade_factory, instrument_price_factory, instrument_factory
396
+ self, mock_fct, order_proposal, order_factory, instrument_price_factory, instrument_factory
403
397
  ):
404
398
  """
405
399
  Verify shares estimation based on trade weighting and instrument price.
406
400
  """
407
- portfolio = trade_proposal.portfolio
401
+ portfolio = order_proposal.portfolio
408
402
  instrument = instrument_factory.create(currency=portfolio.currency)
409
- underlying_quote_price = instrument_price_factory.create(instrument=instrument, date=trade_proposal.trade_date)
403
+ underlying_quote_price = instrument_price_factory.create(instrument=instrument, date=order_proposal.trade_date)
410
404
  mock_fct.return_value = Decimal(1_000_000) # 1 million cash
411
- trade = trade_factory.create(
412
- trade_proposal=trade_proposal,
413
- transaction_date=trade_proposal.trade_date,
405
+ trade = order_factory.create(
406
+ order_proposal=order_proposal,
407
+ value_date=order_proposal.trade_date,
414
408
  portfolio=portfolio,
415
409
  underlying_instrument=instrument,
416
410
  )
@@ -418,105 +412,103 @@ class TestTradeProposal:
418
412
 
419
413
  # Assert estimated shares are correctly calculated
420
414
  assert (
421
- trade_proposal.get_estimated_shares(
415
+ order_proposal.get_estimated_shares(
422
416
  trade.weighting, trade.underlying_instrument, underlying_quote_price.net_value
423
417
  )
424
418
  == Decimal(1_000_000) * trade.weighting / underlying_quote_price.net_value
425
419
  )
426
420
 
427
421
  @patch.object(Portfolio, "get_total_asset_value")
428
- def test_get_estimated_target_cash(self, mock_fct, trade_proposal, trade_factory, cash_factory):
429
- trade_proposal.portfolio.only_weighting = False
430
- trade_proposal.portfolio.save()
422
+ def test_get_estimated_target_cash(self, mock_fct, order_proposal, order_factory, cash_factory):
423
+ order_proposal.portfolio.only_weighting = False
424
+ order_proposal.portfolio.save()
431
425
  mock_fct.return_value = Decimal(1_000_000) # 1 million cash
432
- cash = cash_factory.create(currency=trade_proposal.portfolio.currency)
433
- trade_factory.create( # equity trade
434
- trade_proposal=trade_proposal,
435
- transaction_date=trade_proposal.trade_date,
436
- portfolio=trade_proposal.portfolio,
426
+ cash = cash_factory.create(currency=order_proposal.portfolio.currency)
427
+ order_factory.create( # equity trade
428
+ order_proposal=order_proposal,
429
+ value_date=order_proposal.trade_date,
430
+ portfolio=order_proposal.portfolio,
437
431
  weighting=Decimal("0.7"),
438
432
  )
439
- trade_factory.create( # cash trade
440
- trade_proposal=trade_proposal,
441
- transaction_date=trade_proposal.trade_date,
442
- portfolio=trade_proposal.portfolio,
433
+ order_factory.create( # cash trade
434
+ order_proposal=order_proposal,
435
+ value_date=order_proposal.trade_date,
436
+ portfolio=order_proposal.portfolio,
443
437
  underlying_instrument=cash,
444
438
  weighting=Decimal("0.2"),
445
439
  )
446
440
 
447
- target_cash_position = trade_proposal.get_estimated_target_cash(trade_proposal.portfolio.currency)
441
+ target_cash_position = order_proposal.get_estimated_target_cash(order_proposal.portfolio.currency)
448
442
  assert target_cash_position.weighting == Decimal("0.2") + Decimal("1.0") - (Decimal("0.7") + Decimal("0.2"))
449
443
  assert target_cash_position.initial_shares == Decimal(1_000_000) * Decimal("0.3")
450
444
 
451
- def test_trade_proposal_update_inception_date(self, trade_proposal_factory, portfolio, instrument_factory):
452
- # Check that if we create a prior trade proposal, the instrument inception date is updated accordingly
445
+ def test_order_proposal_update_inception_date(self, order_proposal_factory, portfolio, instrument_factory):
446
+ # Check that if we create a prior order proposal, the instrument inception date is updated accordingly
453
447
  instrument = instrument_factory.create(inception_date=None)
454
448
  instrument.portfolios.add(portfolio)
455
- tp = trade_proposal_factory.create(portfolio=portfolio)
449
+ tp = order_proposal_factory.create(portfolio=portfolio)
456
450
  instrument.refresh_from_db()
457
451
  assert instrument.inception_date == (tp.trade_date + BDay(1)).date()
458
452
 
459
- tp2 = trade_proposal_factory.create(portfolio=portfolio, trade_date=tp.trade_date - BDay(1))
453
+ tp2 = order_proposal_factory.create(portfolio=portfolio, trade_date=tp.trade_date - BDay(1))
460
454
  instrument.refresh_from_db()
461
455
  assert instrument.inception_date == (tp2.trade_date + BDay(1)).date()
462
456
 
463
- def test_get_round_lot_size(self, trade_proposal, instrument):
457
+ def test_get_round_lot_size(self, order_proposal, instrument):
464
458
  # without a round lot size, we expect no normalization of shares
465
- assert trade_proposal.get_round_lot_size(Decimal("66"), instrument) == Decimal("66")
459
+ assert order_proposal.get_round_lot_size(Decimal("66"), instrument) == Decimal("66")
466
460
  instrument.round_lot_size = 100
467
461
  instrument.save()
468
462
 
469
463
  # if instrument has a round lot size different than 1, we expect different behavior based on whether shares is positive or negative
470
- assert trade_proposal.get_round_lot_size(Decimal(66.0), instrument) == Decimal("100")
471
- assert trade_proposal.get_round_lot_size(Decimal(-66.0), instrument) == Decimal(-66.0)
472
- assert trade_proposal.get_round_lot_size(Decimal(-120), instrument) == Decimal(-200)
464
+ assert order_proposal.get_round_lot_size(Decimal(66.0), instrument) == Decimal("100")
465
+ assert order_proposal.get_round_lot_size(Decimal(-66.0), instrument) == Decimal(-66.0)
466
+ assert order_proposal.get_round_lot_size(Decimal(-120), instrument) == Decimal(-200)
473
467
 
474
468
  # exchange can disable rounding based on the lot size
475
469
  instrument.exchange.apply_round_lot_size = False
476
470
  instrument.exchange.save()
477
- assert trade_proposal.get_round_lot_size(Decimal("66"), instrument) == Decimal("66")
471
+ assert order_proposal.get_round_lot_size(Decimal("66"), instrument) == Decimal("66")
478
472
 
479
- def test_submit_round_lot_size(self, trade_proposal, trade_factory, instrument):
480
- trade_proposal.portfolio.only_weighting = False
481
- trade_proposal.portfolio.save()
473
+ def test_submit_round_lot_size(self, order_proposal, order_factory, instrument):
474
+ order_proposal.portfolio.only_weighting = False
475
+ order_proposal.portfolio.save()
482
476
  instrument.round_lot_size = 100
483
477
  instrument.save()
484
- trade = trade_factory.create(
485
- status="DRAFT",
478
+ trade = order_factory.create(
486
479
  underlying_instrument=instrument,
487
480
  shares=70,
488
- trade_proposal=trade_proposal,
481
+ order_proposal=order_proposal,
489
482
  weighting=Decimal("1.0"),
490
483
  )
491
- warnings = trade_proposal.submit()
492
- trade_proposal.save()
484
+ warnings = order_proposal.submit()
485
+ order_proposal.save()
493
486
  assert (
494
487
  len(warnings) == 1
495
488
  ) # ensure that submit returns a warning concerning the rounded trade based on the lot size
496
489
  trade.refresh_from_db()
497
490
  assert trade.shares == 100 # we expect the share to be transformed from 70 to 100 (lot size of 100)
498
491
 
499
- def test_submit_round_fractional_shares(self, trade_proposal, trade_factory, instrument):
500
- trade_proposal.portfolio.only_weighting = False
501
- trade_proposal.portfolio.save()
502
- trade = trade_factory.create(
503
- status="DRAFT",
492
+ def test_submit_round_fractional_shares(self, order_proposal, order_factory, instrument):
493
+ order_proposal.portfolio.only_weighting = False
494
+ order_proposal.portfolio.save()
495
+ trade = order_factory.create(
504
496
  underlying_instrument=instrument,
505
497
  shares=5.6,
506
- trade_proposal=trade_proposal,
498
+ order_proposal=order_proposal,
507
499
  weighting=Decimal("1.0"),
508
500
  )
509
- trade_proposal.submit()
510
- trade_proposal.save()
501
+ order_proposal.submit()
502
+ order_proposal.save()
511
503
  trade.refresh_from_db()
512
504
  assert trade.shares == 6 # we expect the fractional share to be rounded
513
505
 
514
506
  def test_ex_post(
515
- self, instrument_factory, asset_position_factory, instrument_price_factory, trade_proposal_factory, portfolio
507
+ self, instrument_factory, asset_position_factory, instrument_price_factory, order_proposal_factory, portfolio
516
508
  ):
517
509
  """
518
510
  Tests the ex-post rebalancing mechanism of a portfolio with two instruments.
519
- Verifies that weights are correctly recalculated after submitting and approving a trade proposal.
511
+ Verifies that weights are correctly recalculated after submitting and approving a order proposal.
520
512
  """
521
513
 
522
514
  # --- Create instruments ---
@@ -575,102 +567,82 @@ class TestTradeProposal:
575
567
  )
576
568
 
577
569
  # --- Create positions on d3 with weights adjusted for returns ---
578
- msft_a3 = asset_position_factory.create(
579
- portfolio=portfolio,
580
- underlying_quote=msft,
581
- date=d3,
582
- initial_shares=10,
583
- weighting=msft_a2.weighting * (Decimal("1.0") + msft_r3) / portfolio_r3,
584
- )
585
- apple_a3 = asset_position_factory.create(
586
- portfolio=portfolio,
587
- underlying_quote=apple,
588
- date=d3,
589
- initial_shares=1,
590
- weighting=apple_a2.weighting * (Decimal("1.0") + apple_r3) / portfolio_r3,
591
- )
592
570
 
593
- # Check that weights on d3 sum to 1
594
- total_weight_d3 = msft_a3.weighting + apple_a3.weighting
595
- assert total_weight_d3 == pytest.approx(Decimal("1.0"), abs=Decimal("1e-6"))
571
+ # Check that weights on d2 sum to 1
572
+ total_weight_d2 = msft_a2.weighting + apple_a2.weighting
573
+ assert total_weight_d2 == pytest.approx(Decimal("1.0"), abs=Decimal("1e-6"))
596
574
 
597
- # --- Create a trade proposal on d3 ---
598
- trade_proposal = trade_proposal_factory.create(portfolio=portfolio, trade_date=d3)
599
- trade_proposal.reset_trades()
600
- # Retrieve trades for each instrument
601
- trade_msft = trade_proposal.trades.get(underlying_instrument=msft)
602
- trade_apple = trade_proposal.trades.get(underlying_instrument=apple)
575
+ # --- Create a order proposal on d3 ---
576
+ order_proposal = order_proposal_factory.create(portfolio=portfolio, trade_date=d3)
577
+ order_proposal.reset_orders()
578
+ # Retrieve orders for each instrument
579
+ orders = order_proposal.get_orders()
580
+ trade_msft = orders.get(underlying_instrument=msft)
581
+ trade_apple = orders.get(underlying_instrument=apple)
603
582
  # Check that trade weights are initially zero
604
583
  assert trade_msft.weighting == Decimal("0")
605
584
  assert trade_apple.weighting == Decimal("0")
606
585
 
586
+ msft_drifted = msft_a2.weighting * (Decimal("1.0") + msft_r3) / portfolio_r3
587
+ apple_drifted = apple_a2.weighting * (Decimal("1.0") + apple_r3) / portfolio_r3
607
588
  # --- Adjust trade weights to target 50% each ---
608
589
  target_weight = Decimal("0.5")
609
- trade_msft.weighting = target_weight - msft_a3.weighting
590
+ trade_msft.weighting = target_weight - msft_drifted
610
591
  trade_msft.save()
611
592
 
612
- trade_apple.weighting = target_weight - apple_a3.weighting
593
+ trade_apple.weighting = target_weight - apple_drifted
613
594
  trade_apple.save()
595
+ orders = order_proposal.get_orders()
596
+ trade_msft = orders.get(underlying_instrument=msft)
597
+ trade_apple = orders.get(underlying_instrument=apple)
614
598
 
615
599
  # --- Check drift factors and effective weights ---
616
- assert trade_msft.drift_factor == pytest.approx(msft_a3.weighting / msft_a2.weighting, abs=Decimal("1e-6"))
617
- assert trade_apple.drift_factor == pytest.approx(apple_a3.weighting / apple_a2.weighting, abs=Decimal("1e-6"))
600
+ assert trade_msft.daily_return == pytest.approx(msft_r3, abs=Decimal("1e-6"))
601
+ assert trade_apple.daily_return == pytest.approx(apple_r3, abs=Decimal("1e-6"))
618
602
 
619
- assert trade_msft._effective_weight == pytest.approx(msft_a3.weighting, abs=Decimal("1e-6"))
620
- assert trade_apple._effective_weight == pytest.approx(apple_a3.weighting, abs=Decimal("1e-6"))
603
+ assert trade_msft._effective_weight == pytest.approx(msft_drifted, abs=Decimal("1e-6"))
604
+ assert trade_apple._effective_weight == pytest.approx(apple_drifted, abs=Decimal("1e-6"))
621
605
 
622
606
  # Check that the target weight is the sum of drifted weight and adjustment
623
- assert trade_msft._target_weight == pytest.approx(
624
- msft_a2.weighting * trade_msft.drift_factor + trade_msft.weighting,
625
- abs=Decimal("1e-6"),
626
- )
627
607
  assert trade_msft._target_weight == pytest.approx(target_weight, abs=Decimal("1e-6"))
628
-
629
- assert trade_apple._target_weight == pytest.approx(
630
- apple_a2.weighting * trade_apple.drift_factor + trade_apple.weighting,
631
- abs=Decimal("1e-6"),
632
- )
633
608
  assert trade_apple._target_weight == pytest.approx(target_weight, abs=Decimal("1e-6"))
634
609
 
635
- # --- Submit and approve the trade proposal ---
636
- trade_proposal.submit()
637
- trade_proposal.save()
638
- trade_proposal.approve()
639
- trade_proposal.save()
640
-
641
- # --- Refresh positions after ex-post rebalancing ---
642
- msft_a3.refresh_from_db()
643
- apple_a3.refresh_from_db()
610
+ # --- Submit and approve the order proposal ---
611
+ order_proposal.submit()
612
+ order_proposal.save()
613
+ order_proposal.approve()
614
+ order_proposal.save()
644
615
 
645
616
  # Final check that weights have been updated to 50%
646
- assert msft_a3.weighting == pytest.approx(target_weight, abs=Decimal("1e-6"))
647
- assert apple_a3.weighting == pytest.approx(target_weight, abs=Decimal("1e-6"))
617
+ assert order_proposal.portfolio.assets.get(underlying_instrument=msft).weighting == pytest.approx(
618
+ target_weight, abs=Decimal("1e-6")
619
+ )
620
+ assert order_proposal.portfolio.assets.get(underlying_instrument=apple).weighting == pytest.approx(
621
+ target_weight, abs=Decimal("1e-6")
622
+ )
648
623
 
649
- def test_replay_reset_draft_trade_proposal(
650
- self, instrument, instrument_price_factory, trade_factory, trade_proposal_factory
624
+ def test_replay_reset_draft_order_proposal(
625
+ self, instrument, instrument_price_factory, order_factory, order_proposal_factory
651
626
  ):
652
- trade_proposal = trade_proposal_factory.create(
653
- status=TradeProposal.Status.DRAFT, trade_date=date.today() - BDay(2)
654
- )
627
+ order_proposal = order_proposal_factory.create(trade_date=date.today() - BDay(2))
655
628
  instrument_price_factory.create(instrument=instrument, date=date.today() - BDay(2))
656
629
  instrument_price_factory.create(instrument=instrument, date=date.today() - BDay(1))
657
630
  instrument_price_factory.create(instrument=instrument, date=date.today())
658
- trade = trade_factory.create(
631
+ trade = order_factory.create(
659
632
  underlying_instrument=instrument,
660
- trade_proposal=trade_proposal,
633
+ order_proposal=order_proposal,
661
634
  weighting=1,
662
- status=TradeProposal.Status.DRAFT,
663
635
  )
664
- trade_proposal.submit()
665
- trade_proposal.approve(replay=False)
666
- trade_proposal.save()
636
+ order_proposal.submit()
637
+ order_proposal.approve(replay=False)
638
+ order_proposal.save()
667
639
 
668
- draft_tp = trade_proposal_factory.create(portfolio=trade_proposal.portfolio, trade_date=date.today() - BDay(1))
669
- assert not Trade.objects.filter(trade_proposal=draft_tp).exists()
640
+ draft_tp = order_proposal_factory.create(portfolio=order_proposal.portfolio, trade_date=date.today() - BDay(1))
641
+ assert not Order.objects.filter(order_proposal=draft_tp).exists()
670
642
 
671
- trade_proposal.replay()
643
+ order_proposal.replay()
672
644
 
673
- assert Trade.objects.filter(trade_proposal=draft_tp).count() == 1
674
- assert Trade.objects.get(
675
- trade_proposal=draft_tp, underlying_instrument=trade.underlying_instrument
645
+ assert Order.objects.filter(order_proposal=draft_tp).count() == 1
646
+ assert Order.objects.get(
647
+ order_proposal=draft_tp, underlying_instrument=trade.underlying_instrument
676
648
  ).weighting == Decimal("0")