9
9
from Trading .live .caching .caching import get_last_n_candles_from_date
10
10
from typing import Optional , Dict
11
11
from dotenv import load_dotenv
12
+ import operator
12
13
import os
13
14
import logging
14
15
import sys
17
18
from typing import List
18
19
from Trading .utils .ratio .ratio import Ratio , DateNotFoundError , CurrentHolding
19
20
from Trading .utils .calculations import calculate_mean
20
- from stateful_data_processor . file_rw import JsonFileRW
21
-
21
+ from Trading . live . ratio . backtest import backtest_ratio
22
+ from Trading . live . ratio . heap import Heap
22
23
23
24
def exit ():
24
25
sys .exit (0 )
25
26
26
-
27
- trades_file_writer = JsonFileRW (
28
- "/home/doru/personal/trading/Trading/live/ratio/trades.json"
29
- )
30
- analysis_file_writer = JsonFileRW (
31
- "/home/doru/personal/trading/Trading/live/ratio/analysis.json"
32
- )
33
-
27
+ #! Used for in-memory caching
34
28
HISTORIES_DICT = {}
29
+
35
30
DATA_SOURCE = DataSourceEnum .XTB
36
31
GET_DATA_BEFORE_DATE = datetime (2025 , 1 , 1 )
32
+ STD_SCALER = 1.5
37
33
34
+ top_10_ratios = Heap (10 , lambda x : x [0 ])
38
35
39
36
@dataclass
40
37
class Criterion :
@@ -107,7 +104,6 @@ def construct_ratio(ratio: Ratio, N_DAYS: int):
107
104
108
105
109
106
def process_ratio (ratio : Ratio , N_DAYS : int , iteration_info : str = "" ):
110
- STD_SCALER = 1.5
111
107
construct_ratio (ratio , N_DAYS )
112
108
# MAIN_LOGGER.info(f"Calculating ratio: {ratio.numerator} / {ratio.denominator}")
113
109
ratio .calculate_ratio ()
@@ -144,6 +140,12 @@ def process_ratio(ratio: Ratio, N_DAYS: int, iteration_info: str = ""):
144
140
print (
145
141
f"Found a ratio with at least one swing per year: { ratio .numerator } / { ratio .denominator } "
146
142
)
143
+
144
+ trade_analysis_result = backtest_ratio (ratio , STD_SCALER , MAIN_LOGGER )
145
+ if trade_analysis_result :
146
+ ar = trade_analysis_result .annualized_return
147
+ top_10_ratios .push ((ar , iteration_info , trade_analysis_result ))
148
+
147
149
# plot_list_dates(
148
150
# ratio_values,
149
151
# dates,
@@ -154,104 +156,6 @@ def process_ratio(ratio: Ratio, N_DAYS: int, iteration_info: str = ""):
154
156
# show_cursor=True,
155
157
# )
156
158
157
- trades = []
158
- if ratio_values != ratio .calculate_ratio ():
159
- raise Exception ("Error in calculating ratio" )
160
-
161
- from Trading .model .trade import (
162
- Trade ,
163
- analyze_trades ,
164
- StrategySummary ,
165
- aggregate_analysis_results ,
166
- )
167
-
168
- current_holding = CurrentHolding .NONE
169
- # for peak, entry_date in zip(peak_dict["values"], peak_dict["dates"]):
170
- index = 0
171
- while index < len (ratio .ratio_values ):
172
- current_value = ratio .ratio_values [index ]
173
- entry_date = ratio .dates [index ]
174
- trade_tuple : List [Trade ] = []
175
- #! WE SHOULD NOT LOOK AT ABS OF CURRENT VALUE - MEAN
176
- if (
177
- current_holding == CurrentHolding .NONE
178
- and abs (current_value - ratio .mean ) >= STD_SCALER * ratio .std
179
- ):
180
- MAIN_LOGGER .info (f"Found a peak at date: { entry_date } " )
181
- if current_value > ratio .mean :
182
- #! At high peak, buy the denominator
183
- entry_prices = ratio .get_denominator_prices_at_date (entry_date )
184
- current_holding = CurrentHolding .DENOMINATOR
185
- d_n = ratio .denominator
186
- else :
187
- #! At low peak, buy the numerator
188
- entry_prices = ratio .get_numerator_prices_at_date (entry_date )
189
- current_holding = CurrentHolding .NUMERATOR
190
- d_n = ratio .numerator
191
- for price , sym in zip (entry_prices , d_n ):
192
- if not price :
193
- raise Exception ("Price is None" )
194
- trade_tuple .append (
195
- Trade (cmd = 0 , entry_date = entry_date , open_price = price , symbol = sym )
196
- )
197
- trades .append (trade_tuple )
198
- if current_holding == CurrentHolding .NONE :
199
- index += 1
200
- continue
201
- try :
202
-
203
- next_date_at_mean , index = ratio .get_next_date_at_mean (entry_date )
204
- MAIN_LOGGER .info (f"Closing on: { next_date_at_mean } " )
205
- if current_holding == CurrentHolding .DENOMINATOR :
206
- exit_prices = ratio .get_denominator_prices_at_date (next_date_at_mean )
207
- elif current_holding == CurrentHolding .NUMERATOR :
208
- exit_prices = ratio .get_numerator_prices_at_date (next_date_at_mean )
209
- for i , p in enumerate (exit_prices ):
210
- trades [- 1 ][i ].exit_date = next_date_at_mean
211
- trades [- 1 ][i ].close_price = p
212
- trades [- 1 ][i ].calculate_max_drawdown_price_diff (
213
- ratio .histories [trade_tuple [i ].symbol ]
214
- )
215
- current_holding = CurrentHolding .NONE
216
- except DateNotFoundError :
217
- MAIN_LOGGER .info (f"No date found at mean for { entry_date } " )
218
- trades .pop ()
219
- break
220
- tuple_analyses = []
221
- for trade_tuple in trades :
222
- # if the trade_tuple does not have a closing price, we should not analyze it
223
- trade_tuple = [t for t in trade_tuple if t .close_price ]
224
- MAIN_LOGGER .info (f"Trade tuple: { trade_tuple } " )
225
- analysis = analyze_trades (
226
- trade_tuple , StrategySummary (False , 1000 , 1 , "USD" , "STC" )
227
- )
228
- if analysis is None :
229
- continue
230
- analysis .print ()
231
- tuple_analyses .append (analysis )
232
-
233
- plot_list_dates (
234
- ratio_values ,
235
- dates ,
236
- f"Iteration number { iteration_info } " ,
237
- "Ratio Value" ,
238
- peak_dict ,
239
- std_scaler = STD_SCALER ,
240
- show_cursor = True ,
241
- )
242
- if not tuple_analyses :
243
- return False
244
- print ("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" )
245
- aggregate_analysis_results (tuple_analyses ).print ()
246
- print ("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" )
247
-
248
- trades = [trade for trade_tuple in trades for trade in trade_tuple ]
249
- trades_dict = dict ()
250
- trades_dict ["trades" ] = [t .dict () for t in trades ]
251
-
252
- trades_file_writer .write (trades_dict )
253
- analysis = analyze_trades (trades , StrategySummary (False , 1000 , 1 , "USD" , "STC" ))
254
- analysis_file_writer .write (analysis .dict ())
255
159
return True
256
160
257
161
@@ -328,5 +232,7 @@ def process_ratio(ratio: Ratio, N_DAYS: int, iteration_info: str = ""):
328
232
r ._process = process_ratio
329
233
r .run (N_DAYS = N_DAYS )
330
234
235
+ print (top_10_ratios )
236
+
331
237
332
238
#! TODO: Use History class, history cache, StatefulDataProcessor
0 commit comments