1- use core:: fmt;
2-
31use chrono:: { DateTime , Duration , Utc } ;
2+ use core:: fmt;
43use serde:: { Deserialize , Serialize } ;
4+ use std:: collections:: BTreeMap ;
55
66use crate :: pocketoption:: error:: PocketOptionError ;
77
@@ -21,6 +21,7 @@ pub struct UpdateHistoryNewFast {
2121 pub asset : String ,
2222 pub period : i64 ,
2323 pub history : Vec < Candle > ,
24+ pub candles : Vec < Candle > ,
2425}
2526
2627#[ derive( Debug , Deserialize , Serialize , Clone ) ]
@@ -38,6 +39,7 @@ pub enum Candle {
3839 Processed ( ProcessedCandle ) ,
3940 ProcessedNew ( ProcessedCandleNew ) ,
4041 Update ( UpdateCandle ) ,
42+ UpdateNew ( UpdateCandleNew ) ,
4143}
4244
4345#[ derive( Debug , Deserialize , Serialize , Clone ) ]
@@ -86,6 +88,16 @@ pub struct UpdateCandle {
8688 price : f64 ,
8789}
8890
91+ #[ derive( Debug , Deserialize , Serialize , Clone ) ]
92+ pub struct UpdateCandleNew {
93+ #[ serde( with = "float_time" ) ]
94+ time : DateTime < Utc > ,
95+ open : f64 ,
96+ close : f64 ,
97+ high : f64 ,
98+ low : f64 ,
99+ }
100+
89101#[ derive( Debug , Deserialize , Serialize , Clone ) ]
90102#[ serde( rename_all = "camelCase" ) ]
91103pub struct UpdateBalance {
@@ -171,20 +183,29 @@ impl From<&Candle> for DataCandle {
171183 candle. low ,
172184 ) ,
173185 Candle :: ProcessedNew ( candle) => {
174- let timestamp = DateTime :: from_timestamp ( candle. time , 0 )
175- . unwrap_or_else ( || {
176- eprintln ! ( "Invalid timestamp {}, using current time" , candle. time) ;
177- Utc :: now ( )
178- } ) ;
186+ let timestamp = DateTime :: from_timestamp ( candle. time , 0 ) . unwrap_or_else ( || {
187+ eprintln ! ( "Invalid timestamp {}, using current time" , candle. time) ;
188+ Utc :: now ( )
189+ } ) ;
179190 Self :: new (
180191 timestamp,
181192 candle. open ,
182193 candle. close ,
183194 candle. high ,
184195 candle. low ,
185196 )
186- } ,
197+ }
187198 Candle :: Update ( candle) => Self :: new_price ( candle. time , candle. price ) ,
199+ Candle :: UpdateNew ( candle) => {
200+ let timestamp = candle. time ;
201+ Self :: new (
202+ timestamp,
203+ candle. open ,
204+ candle. close ,
205+ candle. high ,
206+ candle. low ,
207+ )
208+ }
188209 }
189210 }
190211}
@@ -210,7 +231,63 @@ impl LoadHistoryPeriodResult {
210231
211232impl UpdateHistoryNewFast {
212233 pub fn candle_data ( & self ) -> Vec < DataCandle > {
213- self . history . iter ( ) . map ( DataCandle :: from) . collect ( )
234+ // 1) snapshot candles (descending)
235+ let existing: Vec < DataCandle > = self . candles . iter ( ) . map ( DataCandle :: from) . collect ( ) ;
236+ let mut history_dc: Vec < DataCandle > = self . history . iter ( ) . map ( DataCandle :: from) . collect ( ) ;
237+
238+ history_dc. sort_unstable_by_key ( |c| c. time . timestamp ( ) ) ;
239+
240+ // 3) cutoff: up through the last snapshot candle
241+ let last_cutoff = existing
242+ . first ( )
243+ . map ( |c| c. time . timestamp ( ) )
244+ . unwrap_or_else ( || {
245+ let ts = history_dc
246+ . first ( )
247+ . expect ( "history cannot be empty" )
248+ . time
249+ . timestamp ( ) ;
250+ ( ts / self . period ) * self . period - self . period
251+ } ) ;
252+
253+ // 4) aggregate into period-buckets via a BTreeMap
254+ let mut buckets: BTreeMap < i64 , ( f64 , f64 , f64 , f64 ) > = BTreeMap :: new ( ) ;
255+ for dc in & history_dc {
256+ let ts = dc. time . timestamp ( ) ;
257+ let bucket = ( ts / self . period ) * self . period ;
258+ if bucket <= last_cutoff {
259+ continue ;
260+ }
261+
262+ let price = dc. close ; // or whichever price you want
263+ buckets
264+ . entry ( bucket)
265+ . and_modify ( |e| {
266+ e. 1 = e. 1 . max ( price) ; // high
267+ e. 2 = e. 2 . min ( price) ; // low
268+ e. 3 = price; // close
269+ } )
270+ . or_insert ( ( price, price, price, price) ) ;
271+ }
272+
273+ // 5) build new candles (descending) and prepend snapshot
274+ let mut new_candles: Vec < DataCandle > = buckets
275+ . into_iter ( )
276+ . rev ( )
277+ . map ( |( bucket_ts, ( open, high, low, close) ) | {
278+ let dt = DateTime :: from_timestamp ( bucket_ts, 0 ) . unwrap ( ) ;
279+ DataCandle {
280+ time : dt,
281+ open,
282+ high,
283+ low,
284+ close,
285+ }
286+ } )
287+ . collect ( ) ;
288+
289+ new_candles. extend ( existing) ;
290+ new_candles
214291 }
215292}
216293
0 commit comments