@@ -39,56 +39,74 @@ def get_last_n_candles_from_date(from_date: datetime, instrument: Instrument, da
39
39
'''
40
40
Gets last n candles from date, including date
41
41
'''
42
+ if from_date > datetime .now ():
43
+ raise ValueError ("from_date cannot be in the future." )
42
44
43
45
caching = get_caching_file_rw (instrument , data_source )
44
- data = caching .read ()
45
- if not data :
46
- LOGGER .info ("No data in caching" )
47
- # get_last_n_candles_history only returns the last n candles starting with today, so we need to get more data
48
- # calculate how many candles we need to include from today until the from_date
49
- now = datetime .now ()
50
- if from_date < now :
51
- from_today = now - from_date
52
- LOGGER .info (f"From today: { from_today } " )
53
- new_n = n
54
- if instrument .timeframe .period == TIMEFRARME_ENUM .ONE_MONTH .value :
55
- new_n = new_n + math .ceil (from_today .days / 29 )
56
-
57
- history = _get_last_n_from_client (instrument , new_n )
46
+ LOGGER .info (f"Fetching last { n } candles from { from_date } for { instrument .symbol } { instrument .timeframe } file: { caching .file_name } ..." )
47
+ cached_data = caching .read ()
58
48
49
+ if not cached_data :
50
+ LOGGER .info ("No data in cache, fetching initial data..." )
51
+ return _fetch_and_cache_initial_data (from_date , instrument , n , caching )
52
+
53
+ history = History (** cached_data )
54
+
55
+ if from_date in history .date :
56
+ return _handle_from_date_in_history (history , from_date , n , instrument , caching )
57
+
58
+ if from_date > history .date [- 1 ]:
59
+ LOGGER .info ("Fetching data for date greater than cached data's newest date..." )
60
+ return _fetch_and_extend_history (from_date , history , n , instrument , caching , after_cache = True )
61
+
62
+ if from_date < history .date [0 ]:
63
+ LOGGER .info ("Fetching data for date earlier than cached data's oldest date..." )
64
+ return _fetch_and_extend_history (from_date , history , n , instrument , caching , after_cache = False )
65
+ return history .slice_n_candles_before_date (from_date , n )
66
+
67
+ def _fetch_and_cache_initial_data (from_date : datetime , instrument : Instrument , n : int , caching ):
68
+ now = datetime .now ()
69
+ candles_needed = n
70
+
71
+ if instrument .timeframe .period == TIMEFRARME_ENUM .ONE_MONTH .value and from_date < now :
72
+ days_diff = (now - from_date ).days
73
+ candles_needed += math .ceil (days_diff / 29 )
74
+ elif instrument .timeframe .period == TIMEFRARME_ENUM .ONE_DAY .value and from_date < now :
75
+ candles_needed += (now - from_date ).days
76
+
77
+ new_history = _get_last_n_from_client (instrument , candles_needed )
78
+ caching .write (new_history .__dict__ )
79
+ LOGGER .info ("Initial data written to cache." )
80
+ return new_history .slice_n_candles_before_date (from_date , n )
81
+
82
+ def _handle_from_date_in_history (history : History , from_date : datetime , n : int , instrument : Instrument , caching ):
83
+ index = history .date .index (from_date )
84
+ if index - n < 0 :
85
+ # Need more candles to satisfy the request
86
+ LOGGER .info ("Fetching more data to cover from_date..." )
87
+ additional_candles = len (history ) + n - index
88
+ new_history = _get_last_n_from_client (instrument , additional_candles )
89
+ history .extend (new_history )
59
90
caching .write (history .__dict__ )
60
- LOGGER .info ("Data written to caching" )
61
- return history .slice_n_candles_before_date (from_date , n )
91
+ return history .slice_n_candles_before_date (from_date , n )
92
+
93
+ def _fetch_and_extend_history (from_date : datetime , history : History , n : int , instrument : Instrument , caching , after_cache : bool ):
94
+ if after_cache :
95
+ date_diff = (from_date - history .date [- 1 ]).days
62
96
else :
63
- history = History (** data )
64
- history_oldest_date = history .date [0 ]
65
- history_newest_date = history .date [- 1 ]
66
-
67
- if from_date in history .date :
68
- index = history .date .index (from_date )
69
- if index - n < 0 :
70
- # fetch new data
71
- new_n = len (history ) + n - index
72
- LOGGER .info ("Fetching new data for from_date in history" )
73
- new_history = _get_last_n_from_client (instrument , new_n )
74
- history .extend (new_history )
75
- caching .write (history .__dict__ )
76
- elif from_date > history_newest_date :
77
- diff = from_date - history_newest_date
78
- if instrument .timeframe .period == TIMEFRARME_ENUM .ONE_MONTH .value :
79
- new_n = len (history ) + math .ceil (diff .days / 29 ) + 1
80
- LOGGER .info ("Fetching new data for from_date > history_newest_date" )
81
- new_history = _get_last_n_from_client (instrument , new_n )
82
- history .extend (new_history )
83
- caching .write (history .__dict__ )
84
- LOGGER .info ("Data written to caching" )
85
- elif from_date < history_oldest_date :
86
- diff = history_oldest_date - from_date
87
- if instrument .timeframe .period == TIMEFRARME_ENUM .ONE_MONTH .value :
88
- new_n = len (history ) + math .ceil (diff .days / 29 ) + 1
89
- LOGGER .info ("Fetching new data for from_date < history_oldest_date" )
90
- new_history = _get_last_n_from_client (instrument , new_n )
91
- history .extend (new_history )
92
- caching .write (history .__dict__ )
93
- LOGGER .info ("Data written to caching" )
94
- return history .slice_n_candles_before_date (from_date , n )
97
+ date_diff = (history .date [0 ] - from_date ).days
98
+
99
+ candles_needed = n + math .ceil (date_diff / 29 ) if instrument .timeframe .period == TIMEFRARME_ENUM .ONE_MONTH .value else n
100
+ new_history = _get_last_n_from_client (instrument , candles_needed )
101
+ history .extend (new_history )
102
+ caching .write (history .__dict__ )
103
+ LOGGER .info ("Extended data written to cache." )
104
+ return history .slice_n_candles_before_date (from_date , n )
105
+
106
+ if __name__ == '__main__' :
107
+ instrument = Instrument ("EURUSD" , Timeframe ("1D" ))
108
+ from_date = datetime (2020 , 2 , 23 , 1 , 0 )
109
+ n = 5
110
+ data_source = DataSourceEnum .XTB
111
+ last_n = get_last_n_candles_from_date (from_date , instrument , data_source , n )
112
+ print (last_n .date )
0 commit comments