ROOT_Application  2.0
C++ Core modules and GUIStock
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ListDataStock_timpl.h
Go to the documentation of this file.
1 
10 #include <cassert>
11 
12 // to get << ETime, but creates ambiguous with some other as_uint(EDS) not so logic ??
13 //using namespace TimeScale;
14 
17 
18 
20 
21 template<
22 class T,
23 template <class> class PolicyChronologic
24 >
26 {
27 #ifdef DEBUG_CPP
28  std::cout << "List<T> Clear()" << std::endl;
29 #endif
30  // clear internal vector
31  ListData.clear();
32  // reinitialize data member of base class
33  name = "";
34  tmscl = ETime::not_a_time;
35  dates = Utils::get_fldate_default ();
36  fullname = "";
37 }
38 
39 
40 // Append data from a new list ( coming from update or ReadCSV normally ) to the existing list
41 //
42 // \pre Order policy is not checked, they are consider identical (condition to include)
43 // \post new_list is not modified, should be deleted by the calling function (add const)
44 //
45 // First implementation, consider it is an update (only more recent dates)
46 // PolicyChronologic should make the correct work, when updating the vector
47 //
48 // The test are:
49 // - if GetFirstTime() are equal: full update,\n
50 // The last data is removed by default (can be update in the last candle) first_to_skip = GetSize()-1
51 // - else if this->LastDate != new->FristDate(), assume posterior dates for the new_data (added assert)\n
52 // - else (LastDate == new->FirstDate()) \n
53 // Check LastData HasChanged (same date, but different Close() only, e.g., update M5)
54 // if yes : replace_last = true, EraseLastData
55 // if no : first_to_skip +=1
56 //
57 // test size to insert, if new->GetSize = first_to_skip, nothing to do ?
58 //
59 // // never a check about the policy of the entry
60 // // add assert, first, transform if not
61 // // or to do in AddChronoToList, better, all other tests independent of the policy
62 // Finally call Policy::AddChronoToList ( param first_to_skip )
63 //
64 // Effect expected:
65 // - FirstDates are equal : full update
66 // - first date of new == last date of old : check values (only Close) and set replace_last ( values changed )
67 // - else no overlap, add only the new data
68 //
69 // Always call to Policy::AddChronoToList( new_list, first_to_skip )
70 // Maybe replace would work also ?? Or all-in-one
71 //
72 // @param ListDataStockBase* : list to append, never modified by the function
73 //
74 // could return some infos number of updates. Maybe a parameter would be better, bool_replace, bool_update ?
75 // should be the same type, but not necessary the same policy
76 template<
77 class T,
78 template <class> class PolicyChronologic
79 >
81 {
82 #ifdef DEBUG_CPP
83  std::cout << "List<T> AddToList" << std::endl;
84 #endif
85 
86  bool replace_last = false;
87  std::vector<T> vec_new;
88  // default take all the data of new_list
89  unsigned int first_to_skip = 0;
90 
91  // 2 cases :
92  // - first dates are equal, replace all, call Replace
93  // return 0;
94  //
95  // - if first date of new equal last date of old :
96  // - Check for replace_last: true delete last, false set first_to_skip to 1
97  // - Continue (real) update
98  // - Set last date from the new_list
99  // - call AddToListChrono
100  // - return 0;
101 
102  assert ( new_list != nullptr );
103  assert ( new_list->GetSize() > 0 );
104 
105  if ( ( !new_list ) || ( new_list->GetSize() == 0 ) ) {
106 #ifdef DEBUG_CPP
107  std::cout << "Pointer not valid or size is null" << std::endl;
108 #endif
109  // return a error, should not happen internally
110  return 1;
111  }
112 
113  // check if FirstTime are equal, will replace the full list (keep pointer identical)
114  if ( GetFirstTime() == new_list->GetFirstTime() ) {
115 #ifdef DEBUG_CPP
116  std::cout << " GetFirstTime are equal, replace all data " << std::endl;
117 #endif
118  // cannot if call AddChronoToList, must clear the data before, like in Replace !
119  // replace all data, by full copy, dates are updated
120  Replace ( new_list );
121  return 0;
122  }
123 
124  // Try to append data
125  // test last date of old and first date of new overlap
126  if ( NoChronologicAt(0).GetDate() == new_list->ChronologicAt(0).GetDate() ) {
127 #ifdef DEBUG_CPP
128  std::cout << "Last date of old == first date of new" << std::endl;
129  std::cout << "first to skip " << first_to_skip << std::endl;
130 #endif
131  // check if there is a common date, and if the last data must be updated
132  // only Close value is checked
133  replace_last = NoChronologicAt(0)
134  .HasChanged ( new_list->ChronologicAt( first_to_skip ) );
135 #ifdef DEBUG_CPP
136  std::cout << "replace_last " << replace_last << std::endl;
137 #endif
138  // same date and different data, delete the last ( input is correct same date )
139  if ( replace_last ) {
140  // no need full Policy, but still more clear, compiler dependent ??
142  // or same values, shift skip to 1
143  } else {
144  // no need of the first data
145  first_to_skip += 1;
146  }
147  }
148 #ifdef DEBUG_CPP
149  // else no overlap, it is a real update, makes some assert here
150  else {
151  // should apply
152  std::cout << "First dates, no overlap of dates, will append all data" << std::endl;
153  std::cout << "LastUpdate " << Utils::Time_tToString( LastUpdate(), true ) << std::endl;
154  std::cout << "GetFirstTime() " << Utils::Time_tToString( new_list->GetFirstTime(), true ) << std::endl;
155  // keep all, first_to_skip still 0, replace_last still false
156  // here assume that new dates are larger, may include the case if needed
157  assert ( LastUpdate() < new_list->GetFirstTime() );
158  }
159  // assert coherent new_list input, data member and datastock in vector
160  // could be done at any moment ?? even at start ??
161  assert ( new_list->GetFirstTime() == new_list->GetFirstDate() );
162  assert ( new_list->LastUpdate() == new_list->GetLastDate() );
163 #endif
164  //}
165 
166  // need to update the date, can vary in this case, even if no new candle
167  // if update reassign the last date only,
168  // if test not necessary, should never be smaller ?
169  if ( new_list->GetLastDate() > dates.last ) {
170 #ifdef DEBUG_CPP
171  std::cout << "update only dates.last" << std::endl;
172 #endif
173  dates.last = new_list->GetLastDate();
174  }
175 
176  // if only one data and no update of the last nothing to do
177  if ( new_list->GetSize() - first_to_skip == 0 ) {
178 #ifdef DEBUG_CPP
179  std::cout << " size_new_list_update == 0, nothing to do " << std::endl;
180 #endif
181  // it is not an error, 1 candle not updated
182  return 0;
183  }
184 
185 #ifdef DEBUG_CPP
186  std::cout << "call AddChronoToList with first_to_skip " << first_to_skip << std::endl;
187 #endif
188  // extract the vector in the same policy order as this
189  new_list->GetVectorData ( vec_new, bpolicy() );
190  // add the vector(now correctly ordered) to the list
191  PolicyChronologic<T>::AddChronoToList( ListData, vec_new, first_to_skip);
192 
193 #ifdef DEBUG_CPP
194  std::cout << "End ListDataStock::AddToList " << std::endl;
195 #endif
196  return 0;
197 }
198 
199 // better stl for this copy ? problem to check policy is correct
200 // should be the same type, but not necessary the same policy
201 template <
202  class T,
203  template <class> class PolicyChronologic
204 >
206 #ifdef DEBUG_CPP
207  std::cout << "ListDataStock::Replace " << std::endl;
208 #endif
209  // delete previous data, to test with swap
210  ListData.clear();
211  // get the vector of data to insert, in the same order as this.policy
212  std::vector<T> new_vector;
213  ldata_in->GetVectorData( new_vector, bpolicy() );
214  // insert all new data
215  // or use swap, more efficient, data deleted later anyway...
216  ListData.insert( ListData.end(), new_vector.begin(), new_vector.end());
217  // reset the new dates by default, or copy from ldata_in
218  SetDates();
219 }
220 
222 
223 // can add data from multiple ListDataStock
224 // no offsets here, but simple to introduce
225 /*
226 template <
227  class T,
228  template <class> class PolicyChronologic
229 >
230 template <
231  class U
232 >
233 unsigned int ListDataStock<T,PolicyChronologic>::GetCArray2( U **arraydata_c, const EPChrono b_order,
234  const unsigned int no ) const
235 {
236 #ifdef DEBUG_CPP
237  std::cout << "Entry GetCArray2" << std::endl;
238  std::cout << " b_order " << b_order << std::endl;
239  std::cout << " no " << no << std::endl;
240  std::cout << " size_listdata " << GetSize() << std::endl;
241 #endif
242  // size of input
243  size_t size_data = GetSize();
244 
245  // allocate the array, U float/double
246  *arraydata_c = new U[size_data];
247 
248  // fill in chronological order
249  if ( b_order == EPChrono::CHRONO ) {
250  for ( size_t i = 0; i < size_data; ++i ) {
251  // Return no from the vector
252  // GetValues return a copy of the vector, with MultiData could be a ref, not for the others
253  //std::cout << "GetValues()[no] " << ChronologicAt( i ).GetValues()[no] << std::endl;
254  (*arraydata_c)[i] = ChronologicAt( i ).GetValues()[no];
255  }
256  // fill in non-chronological order
257  } else {
258  for ( size_t i = 0; i < size_data; ++i ) {
259  (*arraydata_c)[i] = NoChronologicAt( i ).GetValues()[no];
260  }
261  }
262  return size_data;
263 }
264 */
265 template <
266  class T,
267  template <class> class PolicyChronologic
268 >
269 unsigned int ListDataStock<T,PolicyChronologic>::GetCArray( var_types arraydata_c, const EPChrono b_order,
270  const unsigned int no ) const
271 {
272 #ifdef DEBUG_CPP
273  std::cout << "Entry GetCArray" << std::endl;
274  std::cout << " b_order " << b_order << std::endl;
275  std::cout << " no " << no << std::endl;
276  std::cout << " size_listdata " << GetSize() << std::endl;
277 #endif
278  // size of input
279  size_t size_data = GetSize();
280 
281  // allocate the array, U float/double
282  //*arraydata_c = new U[size_data];
283  boost::apply_visitor( visitor_get_array_allocate(size_data), arraydata_c );
284  std::cout << "After allocation memory " << std::endl;
285 
286 
287  // fill in chronological order
288  if ( b_order == EPChrono::CHRONO ) {
289  for ( size_t i = 0; i < size_data; ++i ) {
290  // GetValues return a copy of the vector, with MultiData could be a ref, not for the others
291  //std::cout << "GetValues()[no] " << ChronologicAt( i ).GetValues()[no] << std::endl;
292  //(*arraydata_c)[i] = ChronologicAt( i ).GetValues()[no];
293  boost::apply_visitor( visitor_get_array_set_value(i,ChronologicAt( i ).GetValues()[no]), arraydata_c );
294  }
295  // fill in non-chronological order
296  } else {
297  for ( size_t i = 0; i < size_data; ++i ) {
298  //(*arraydata_c)[i] = NoChronologicAt( i ).GetValues()[no];
299  boost::apply_visitor( visitor_get_array_set_value(i,NoChronologicAt( i ).GetValues()[no]), arraydata_c );
300  }
301  }
302 
303 
304  return size_data;
305 }
306 
307 template <
308  class T,
309  template <class> class PolicyChronologic
310 >
311 unsigned int ListDataStock<T,PolicyChronologic>::GetCArray( var_types2 arraydata_c, const EPChrono b_order,
312  std::initializer_list<unsigned int> list_no ) const
313 {
314 
315 #ifdef DEBUG_CPP
316  std::cout << "GetCArray2 with initializer_list" << std::endl;
317  std::cout << "b_order " << b_order << std::endl;
318  std::cout << "number in list " << list_no.size() << std::endl;
319  std::cout << "size_data " << GetSize() << std::endl;
320 #endif
321  // store values of the list
322  std::vector<unsigned int> vec_indic;
323  // number of colomn to extract
324  unsigned int nb_indic = list_no.size();
325 
326  // to do
327  // Check nb_indic <= GetNbValues() ?
328 
329  // save values from the input list, list has no []
330  for (auto& value : list_no) {
331  vec_indic.push_back(value);
332  }
333  // allocate the first array, U float/double
334  //*arraydata_c = new U*[ nb_indic ];
335  boost::apply_visitor( visitor_get_array_allocate(nb_indic), arraydata_c );
336 
337  // indice in list may be random
338  unsigned int count = 0;
339  // call the other function, will allocate second dimension
340  for ( auto &nb_indic : vec_indic ) {
341  //this->GetCArray2( &((*arraydata_c)[count]), b_order, nb_indic );
342  try {
343  if ( float*** pf = boost::get<float***>(arraydata_c) )
344  this->GetCArray( &((*pf)[count]), b_order, nb_indic );
345  } catch ( boost::bad_get &e ) {
346  //} catch ( std::exception &e ) {
347  std::cout << "Got exception for float, try float " << std::endl;
348 
349  try {
350  if ( double*** pd = boost::get<double***>(arraydata_c) )
351  this->GetCArray( &((*pd)[count]), b_order, nb_indic );
352  } catch ( boost::bad_get &e ) {
353  std::cout << "Got exception for double, try int " << std::endl;
354 
355  try {
356  if ( int*** pi = boost::get<int***>(arraydata_c) )
357  this->GetCArray( &((*pi)[count]), b_order, nb_indic );
358  } catch ( boost::bad_get &e ) {
359  std::cout << "Got exception for int, rethrow " << std::endl;
360 
361  throw;
362  }
363  }
364  }
365  ++count;
366  }
367  return nb_indic;
368 }
369 
371 template <
372  class T,
373  template <class> class PolicyChronologic
374 >
376  const ListDataStockBase & ldata_date,
377  const unsigned int nb_data,
378  const unsigned size_indic,
379  var_types arraydata_c,
380  const unsigned int offset_begin,
381  const unsigned int offset_end,
382  const EPChrono b_chrono,
383  bool full_array )
384 {
385 
386  using namespace TimeScale;
387 
388 #ifdef DEBUG_CPP
389  std::cout << "In ListDataStock::PutCArray with offset_begin/offset_end " << std::endl;
390  std::cout << "nb_data " << nb_data << std::endl;
391  std::cout << "offset_begin " << offset_begin << std::endl;
392  std::cout << "offset_end " << offset_end << std::endl;
393  std::cout << "size_indic " << size_indic << std::endl;
394  std::cout << "bool chrono " << b_chrono << std::endl;
395  std::cout << "full_array " << full_array << std::endl;
396 #endif
397 
398  Reserve( nb_data );
399 
400  // check, assert some size problem (nb_indic mainly)
401  // size_indic should fit in c-array, cannot check here
402 
403  // size of nb_data, should be smaller than size c-array, but no access here
404  // should fit with ldata_date, maybe very strong but sure it is working like this
405  // maybe later only smaller ? normally nb_data given by TALib
406  assert ( nb_data == ldata_date.GetSize() - offset_begin - offset_end );
407 
408  if ( tmscl != ldata_date.GetTimeScale() ) {
409  if ( tmscl != ETime::not_a_time )
410  std::cout << "Warning, TimeScale has been reset to " << ldata_date.GetTimeScale() << std::endl;
411  tmscl = ldata_date.GetTimeScale();
412  }
413 
414  // need this constructor for all, only used by MultiData, other fixed ?
415  T sdata( size_indic );
416  //std::cout << sdata << std::endl;
417 
418  // use intermediate vector to setup all data stock
419  // conversion between input and type_value_data done automatically
420  std::vector<type_value_data> vec_values;
421  //type_value_data tmp_values;
422  //visitor_type_array Visitor;
423  unsigned int shift_data = 0;
424 
425  // in case of full array of data, need to apply some shift
426  if ( full_array ) {
427 
428  if ( ( b_chrono == EPChrono::CHRONO ) && offset_begin > 0 ) {
429  shift_data = offset_begin;
430  } else if ( ( b_chrono == EPChrono::NO_CHRONO ) && offset_end > 0 ) {
431  shift_data = offset_end;
432  }
433  // the other cases pass without shift
434  }
435 
436  // check order of the array in entry important for the dates
437  // new version, talib output is chronologic, but there is a shift !
438  for ( unsigned int i= 0; i < nb_data; ++i ) {
439 
440  vec_values.clear();
441  for ( unsigned int j=0; j < size_indic; ++j ) {
442 
443  vec_values.push_back( boost::apply_visitor( visitor_type_array(j,i+shift_data), arraydata_c ) );
444  }
445  //std::cout << "vec_values size " << vec_values.size() << std::endl;
446 
447  if ( b_chrono == EPChrono::CHRONO ) {
448  // no change needed if offset_end
449  sdata.SetData( ldata_date.ChronologicAt(i+offset_begin).GetDate(), vec_values );
450  } else {
451  // no change if offset_begin
452  sdata.SetData( ldata_date.NoChronologicAt(i+offset_end).GetDate(), vec_values );
453  }
454  // Add always by push back, efficient if reserve cannot control chronology
455  AddData(sdata);
456  }
457  // this algo loop in the order of input
458  // will come back to the policy chronology of this, depending of the order given in input
459  Order( b_chrono );
460  // Set Dates after reordering
461  SetDates();
462  return 0;
463 }
464 
465 template <
466  class T,
467  template <class> class PolicyChronologic
468 >
469 void ListDataStock<T,PolicyChronologic>::PrintData ( const unsigned int verbose ) const
470 {
471  using namespace TimeScale;
472 
473  std::cout << "\tname: " << GetName() << " size: " << GetSize() << \
474  " ,capacity: " << Capacity() << policy() << std::endl;
475  std::cout << "\ttimescale: " << GetTimeScale() << std::endl;
476  std::cout << "\tfullname: " << GetFullName() << std::endl;
477  std::cout << "\tdates: " << Utils::Time_tToString( GetFirstDate(), true )
478  << " " << Utils::Time_tToString( GetLastDate(), true ) << std::endl;
479  // check size, better here than in Stock
480  if ( ListData.size() == 0 ) {
481  std::cout << "\tList is empty" << std::endl;
482  return;
483  }
484  // if 0 (default) only first and last
485  if ( verbose == 0 ) {
486  std::cout << "\t First: " << std::endl;
487  this->ChronologicAt(0).PrintData( 1 );
488 
489  //if ( verbose == 0 )
490  std::cout << "\t Last: " << std::endl;
491  this->ChronologicAt( ListData.size()-1 ).PrintData( 1 );
492  }
493 
494  // print all the data, no header
495  if ( verbose == 1 ) {
496  std::cout << "Will call ListDataStock::PrintData(0), no header in loop " << std::endl;
497  for (unsigned int i =0; i < ListData.size(); ++i ) {
498  this->ChronologicAt( i ).PrintData( 0 );
499  }
500  }
501  return;
502 }
503 
505 
507 namespace ListDataStock_Utils {
508 
509 
510 // here possible to extend for use of M5 to... H1 or M5 to DAY as well
511 // make a copy
512 
513 // functions called in every loop :
514 // // here ref certainly good as well
515 // new_candle.AdditionData( NoChronologicAt( i ) );
516 // here ref NoChrono is certainly good
517 // tmp_volume += in_vol->NoChronologicAt ( i ).GetValue();
518 //
519 // if candle changed:
520 // new_candle.SetOpen( NoChronologicAt( i-1 ).GetOpen() );
521 // new_candle.SetDate( NoChronologicAt( i-1 ).GetDate());
522 // new_vol.SetData ( new_candle.GetDate(), tmp_volume );
523 // //copy data to the new list, ref is ok, because makes a copy
524 // out_csv.AddData( new_candle );
525 // out_vol.AddData( new_vol );
526 // //Avoid reconstruction of object, Reset not bad..
527 // //new_candle.SetData(0,0.,0.,100000.,0.); / new_candle.Reset();
528 // new_vol.SetData(0,0.);
529 template <
530  template <class> class Policy1,
531  template <class> class Policy2,
532  template <class> class Policy3,
533  template <class> class Policy4
534 >
535 int TransformTimeScale( const ETime new_tmscl, const ListDataStock<DataCSV,Policy1> & list_csv_in,
536  const ListDataStock<SimpleData,Policy2> & list_vol_in,
538 {
539  // to use operator << Etime
540  using namespace TimeScale;
541 
542 #ifdef DEBUG_CPP
543  std::cout << "\tTransformTimeScale, input DataCSV\n" << std::endl;
544 #endif
545 
546  unsigned int size_input_csv= list_csv_in.GetSize();
547 
548  // pass all as run time check, makes sense because friend, public function
549  // assert first
550  //assert ( list_csv_in.GetSize() == list_vol_in.GetSize() );
551  //assert ( new_tmscl != ETime::not_a_time );
552  // pass without forcing int made as
553  //assert ( new_tmscl > ETime::DAY );
554 
555  // Cannot reproduce results when using WEEK intermediates, works for others
556  //assert ( list_csv_in.GetTimeScale() != ETime::WEEK );
557  //assert ( list_vol_in.GetTimeScale() != ETime::WEEK );
558 
559  if ( list_csv_in.GetTimeScale() != list_vol_in.GetTimeScale() ) {
560  std::cout << "Error, TimeScale of the input are different, return 1 " << std::endl;
561  return 1;
562  }
563 
564  // to set correct name and timescale
565  std::string shortname_csv = ShortName::MakeShortName( Indicator::StockCSV );
566  std::string shortname_vol = ShortName::MakeShortName( Indicator::Volume );
567 
568  // check input, WEEK forbidden by assert now
569  // better warning, if WEEK
570  if ( list_csv_in.GetTimeScale() == ETime::WEEK )
571  std::cout << "Warning, Transform TimeScale from WEEK leads to different results " << std::endl;
572 
573  if ( ( new_tmscl < ETime::M5 ) || ( new_tmscl == ETime::not_a_time ) ) {
574  std::cout << "Error, new tmscl must be >= ETime::M5, your input: " << new_tmscl << std::endl;
575  return 1;
576  }
577 
578  if ( list_csv_in.GetSize() != list_vol_in.GetSize() ) {
579  std::cout << "Error, Input lists must have the same size " << std::endl;
580  return 1;
581  }
582 
583  // Set or reset correct TimeScale and Name if not correct
584  if ( list_csv_out.GetName() != shortname_csv ) {
585  // not a warning if empty
586  if ( ! list_csv_out.GetName().empty() )
587  std::cout << "Warning Set correct name for list_csv_out " << shortname_csv << std::endl;
588  list_csv_out.SetName( shortname_csv );
589  }
590 
591  if ( list_csv_out.GetTimeScale() != new_tmscl ) {
592  // not a warning if not_a_time
593  if ( list_csv_out.GetTimeScale() != ETime::not_a_time )
594  // namespace TimeScale to get << ETime, but creates ambiguous with some other as_uint(EDS) not so logic ??
595  // use namespace in function only, ok
596  //std::cout << "Warning Set correct TimeScale to list_csv_out " << TimeScale::GetTimeScaleName(new_tmscl) << std::endl;
597  std::cout << "Warning Set correct TimeScale to list_csv_out " << new_tmscl << std::endl;
598  // not an error if not_a_time, no warning to print
599  list_csv_out.SetTimeScale( new_tmscl );
600  }
601 
602  if ( list_vol_out.GetName() != shortname_vol ) {
603  // not a warning if empty
604  if ( ! list_vol_out.GetName().empty() )
605  std::cout << "Warning Set correct name for list_vol_out " << shortname_vol << std::endl;
606  list_vol_out.SetName( shortname_vol );
607  }
608 
609  if ( list_vol_out.GetTimeScale() != new_tmscl ) {
610  // not a warning if not_a_time
611  if ( list_vol_out.GetTimeScale() != ETime::not_a_time )
612  std::cout << "Warning Set correct TimeScale to list_csv_out " << new_tmscl << std::endl;
613  // not an error if not_a_time, no warning to print
614  list_vol_out.SetTimeScale( new_tmscl );
615  }
616 
617  // used to save previous week, month....
618  char tmp_str[20];
619  bool change_candle= false;
620  struct tm time_tm;
621 
622  // to be sure than a change_candle is first true
623  // need to track hour and date at the minimum, if server stops for a small time
624  // change order week:day:hour:minute
625  int prev_value[3]={-1,-1,-1};
626  // for larger timescale, no problem of missing some datas
627  int previous_value = -1;
628 
629  //create temporary data, will be copy and added in the loop
630  DataCSV new_candle;
631  SimpleData new_vol;
632  //for updating tmp_volume correctly in ListDataStock<DataCSV>, if day must sum
633  // typedef defined in DataStock.h float/double
634  type_value_data tmp_volume=0;
635 
636  // Reserve as much as the original data, swap could be called at the end
637  // really better ? could optimize depending of the transformation
638  list_csv_out.Reserve(size_input_csv);
639  list_vol_out.Reserve(size_input_csv);
640 
641  // Set first candle, get a full copy of the last one: some values are correct, other will be set when close
642  new_candle = list_csv_in.NoChronologicAt( 0 );
643 
644  //give the first value to sum of volume
645  tmp_volume = list_vol_in.NoChronologicAt( 0 ).GetValue();
646  // date is correct with this, but not needed
647  //new_vol = in_vol->NoChronologicAt( 0 )
648 
649  // Utils::GetDateYMD, need really to check (if shift -1 for month)
650  // tm structure to get minute/hour/day/WEEK/month/year number
651  // could use a tm structure to store previous, same logic
652  time_tm = new_candle.GetDateTm();
653 
654  // changed to day, hour, min
655  prev_value[1] = time_tm.tm_hour;
656  // here as well problem with first value, need case
657  // in case H1 only
658  prev_value[2] = time_tm.tm_min;
659  // test
660  prev_value[0] = time_tm.tm_mday;
661 
662  switch ( new_tmscl ) {
663  //case ETime::M5 : prev_value[1] = time_tm.tm_min /5; break;
664  case ETime::M10 : prev_value[2] = time_tm.tm_min /10; break;
665  case ETime::M30 : prev_value[2] = time_tm.tm_min /30; break;
666  // forgot this case ? in purpose ? yes always assigned before the switch
667  // need for the switch
668  case ETime::H1 : prev_value[1] = time_tm.tm_hour; break;
669  //case ETime::DAY : prev_value=time_tm.tm_mday; break; same before the switch
670  case ETime::WEEK :
671  strftime ( tmp_str,3,"%W", &time_tm);
672  previous_value=atoi(tmp_str); break;
673 
674  case ETime::MONTH : previous_value = time_tm.tm_mon; break;
675  case ETime::TRIM : previous_value = (int)(time_tm.tm_mon/3); break;
676  case ETime::YEAR : previous_value = time_tm.tm_year; break;
677  default: std::cout << "Error switch new_tmscl, return 1" << std::endl; return 1;
678  }
679 
680  // ok correct here
681  //std::cout << "first prev value " << prev_value << std::endl;
682 
683 
684  // algo should be independent of order, now always fill in Non-chronologic order
685  // start at 1, but zero not completely filled
686  // if candle changed, use info of the previous (i-1)
687  for (unsigned int i=1; i< size_input_csv; i++) {
688  //std::cout << "Date: " << NoChronologicAt(i).GetDateString() << std::endl;
689  //std::cout << "loop i: " << i << std::endl;
690 
691  // new_tmscl is fixed here, always the same case,
692  // template better ?? or function pointer ?? function in DataStock ??
693  // template function bool test_new_candle<ETime>( time_tm, &prev_value, &new_value ),
694  // new_value test_new_candle<ETime>( time_tm, &prev_value
695  // and Template will optimize the switch ? (avoid to write explicit specialization)
696  // dispatch compile time solutions:
697  // http://stackoverflow.com/questions/1384326/c-optimize-using-templates-variables
698  // always same test, could avoid switch inside the loop
699  // template with enums
700  // http://stackoverflow.com/questions/20289397/add-method-to-class-by-template-parameter
701  // pointer function
702 
703 
704  time_tm = list_csv_in.NoChronologicAt ( i ).GetDateTm();
705 
706  // check from struct tm if a new candle must be opened
707  // here assumes all data are available
708  // no extra tests (test of year if we are dealing with week...)
709  switch ( new_tmscl ) {
710  // M10
711  case ETime::M10 :
712  //if ( (minute/10) != prev_value[1] ) {
713  if ( ( time_tm.tm_min/10) != prev_value[2] ) {
714  change_candle=true;
715  //prev_value[1]= minute/10;
716  prev_value[2] = time_tm.tm_min / 10;
717  }
718  break;
719  // M30
720  case ETime::M30 :
721  //std::cout << "timescale 3 min/30=" <<minute/30 << std::endl;
722  //if ( (minute/30) != prev_value[1] ) {
723  if ( ( time_tm.tm_min/30) != prev_value[2] ) {
724  change_candle=true;
725  //prev_value[1]= minute/30;
726  prev_value[2] = time_tm.tm_min / 30 ;
727  }
728  break;
729  // H1
730  case ETime::H1 :
731  // changed from 0 to 1
732  if ( time_tm.tm_hour != prev_value[1]) {
733  change_candle=true;
734  prev_value[1] = time_tm.tm_hour;
735  }
736  break;
737 
738  // day, test when we need a new candle, will appear if we store hours from server
739  /*
740  case ETime::DAY :
741  if ( time_tm.tm_mday != prev_value ) {
742  change_candle=true;
743  prev_value=time_tm.tm_mday;
744  }
745  break;
746  */
747  case ETime::WEEK :
748  // no week information in time_tm ??
749  strftime ( tmp_str,3,"%W", &time_tm);
750  if ( atoi(tmp_str) != previous_value ) {
751  change_candle=true;
752  previous_value=atoi(tmp_str);
753  }
754  break;
755  case ETime::MONTH :
756  if ( time_tm.tm_mon != previous_value ) {
757  change_candle=true;
758  previous_value = time_tm.tm_mon;
759  }
760  break;
761  case ETime::TRIM :
762  if ( (int)(time_tm.tm_mon/3) != previous_value ) {
763  change_candle=true;
764  previous_value = (int)(time_tm.tm_mon/3);
765  }
766  break;
767  case ETime::YEAR :
768  if ( time_tm.tm_year != previous_value ) {
769  change_candle = true;
770  previous_value = time_tm.tm_year;
771  }
772  break;
773  // check as run time, sure cannot happen ?
774  default:
775  std::cout << "Error in TimeScale Default Switch in TransformTimeScale " << std::endl;
776  return 1;
777  } // end switch
778 
779  if ( change_candle ) {
780  //std::cout << " Change Candle" << std::endl;
781  // set next loop to false by default
782  change_candle = false;
783 
784  // here assure last values are correct, could be here or when AdditionData
785  // Set date and open, always coming from the previous data
786  new_candle.SetOpen( list_csv_in.NoChronologicAt( i-1 ).GetOpen() );
787  //close previous, give the date open of opening, previous one
788  new_candle.SetDate( list_csv_in.NoChronologicAt( i-1 ).GetDate());
789  // for volume, set date and the sum of volume
790  new_vol.SetData ( new_candle.GetDate(), tmp_volume );
791  // copy data to the lists
792  list_csv_out.AddData( new_candle );
793  list_vol_out.AddData( new_vol );
794 
795  // setup new candle and volume
796  // avoid a call to Reset() in making a copy of all, low and high for sure correct
797  // Open and date are wrong, but will be updated before adding to vector
798  new_candle = list_csv_in.NoChronologicAt( i );
799  //std::cout << "SetClose " << new_candle.GetClose() << "i=" << i << std::endl;
800  tmp_volume = 0;
801  }
802  // always update the candle and volume, modify only High and Low
803  new_candle.AdditionData( list_csv_in.NoChronologicAt( i ) );
804  // volume must be sum up in this case
805  tmp_volume += list_vol_in.NoChronologicAt ( i ).GetValue();
806  } //end for loop
807 
808  // last candle never saved
809  new_candle.SetOpen( list_csv_in.NoChronologicAt( size_input_csv-1 ).GetOpen() );
810  new_candle.SetDate( list_csv_in.NoChronologicAt( size_input_csv-1 ).GetDate());
811  // same for volume
812  new_vol.SetData( new_candle.GetDate(), tmp_volume);
813  // append the last candle
814  list_csv_out.AddData( new_candle );
815  list_vol_out.AddData( new_vol );
816 
817  // need to reorder in the correct policy
818  // has been filled in non-chronologic order, maybe need to reorder
819  // possible to combine with swap ?
820  list_csv_out.Order( EPChrono::NO_CHRONO );
821  list_vol_out.Order( EPChrono::NO_CHRONO );
822 
823  // assign the new dates from the data or from the input ?
824  // use initial candle, maybe wrong if later update
825  //out_csv.SetDates( dates.first, dates.last );
826  //out_vol.SetDates( dates.first, dates.last );
827  // not exactly the same date in this case, test this new implementation
828  // here real date of the new candles
829  list_csv_out.SetDates();
830  list_vol_out.SetDates();
831 
832  // Swap efficient ? to reduce capacity.
833  // may need to test on the timescale, for M10 wants to keep some space
834  list_csv_out.Swap();
835  list_vol_out.Swap();
836  return 0;
837 }
838 
839 template <
840  template <class> class Policy1,
841  template <class> class Policy2,
842  template <class> class Policy3,
843  template <class> class Policy4
844 >
845 int TransformTimeScale( const ETime new_tmscl, const ListDataStock<SimpleData,Policy1> & list_dcsv_in,
846  const ListDataStock<SimpleData,Policy2> & list_vol_in,
848 {
849  using namespace TimeScale;
850 
851  unsigned int size_input_csv = list_dcsv_in.GetSize();
852 
853 #ifdef DEBUG_CPP
854  std::cout << "\n\tTransformTimeScale with input SimpleData\n" << std::endl;
855  std::cout << "Size ListData input " << size_input_csv << std::endl;
856  //std::cout << "Test direct GetName, GetSize " << GetName() << " " << GetSize() << std::endl;
857  //std::cout << "TestSize new Vol " << size_input_vol << std::endl;
858 #endif
859 
860  // to set correct name and timescale
861  std::string shortname_csv = ShortName::MakeShortName( Indicator::StockCSV );
862  std::string shortname_vol = ShortName::MakeShortName( Indicator::Volume );
863 
865  // error ? maybe works, check StockCSV ?? also could test not_a_time also
866  if ( ( list_dcsv_in.GetTimeScale() != ETime::INST ) ||
867  ( list_vol_in.GetTimeScale() != ETime::INST ) ) {
868  std::cout << "Error, Input must be a ETime::INST" << std::endl;
869  return 1;
870  }
871 
872  if ( ( new_tmscl >= ETime::DAY ) || ( new_tmscl == ETime::not_a_time ) ) {
873  std::cout << "Error, new tmscl must be < ETime::DAY, your input: " << new_tmscl << std::endl;
874  return 1;
875  }
876 
877  if ( list_dcsv_in.GetSize() != list_vol_in.GetSize() ) {
878  std::cout << "Error, Input lists must have the same size " << std::endl;
879  return 1;
880  }
881 
882  // Set or reset correct TimeScale and Name if not correct
883  if ( list_csv_out.GetName() != shortname_csv ) {
884  // not a warning if empty
885  if ( ! list_csv_out.GetName().empty() )
886  std::cout << "Warning Set correct name for list_csv_out " << shortname_csv << std::endl;
887  list_csv_out.SetName( shortname_csv );
888  }
889 
890  if ( list_csv_out.GetTimeScale() != new_tmscl ) {
891  // not a warning if not_a_time
892  if ( list_csv_out.GetTimeScale() != ETime::not_a_time )
893  std::cout << "Warning Set correct TimeScale to list_csv_out " << new_tmscl << std::endl;
894  // not an error if not_a_time, no warning to print
895  list_csv_out.SetTimeScale( new_tmscl );
896  }
897 
898  if ( list_vol_out.GetName() != shortname_vol ) {
899  // not a warning if empty
900  if ( ! list_vol_out.GetName().empty() )
901  std::cout << "Warning Set correct name for list_vol_out " << shortname_vol << std::endl;
902  list_vol_out.SetName( shortname_vol );
903  }
904 
905  if ( list_vol_out.GetTimeScale() != new_tmscl ) {
906  // not a warning if not_a_time
907  if ( list_vol_out.GetTimeScale() != ETime::not_a_time )
908  std::cout << "Warning Set correct TimeScale to list_csv_out " << new_tmscl << std::endl;
909  // not an error if not_a_time, no warning to print
910  list_vol_out.SetTimeScale( new_tmscl );
911  }
912 
913 
914  // reserve enough space
915  list_csv_out.Reserve(size_input_csv);
916  list_vol_out.Reserve(size_input_csv);
917 
918  bool change_candle=false;
919 
920  int minute; //use for calcul, could be deleted ?
921  struct tm time_tm;
922  // to be sure than a change_candle is first true
923  // keep hour:minute:day (day to avoid problem between missing data I guess)
924  int prev_value[3]={-1,-1,-1};
925 
926  //create temporary data, will be copy and added in the loop
927  DataCSV new_candle;
928  SimpleData new_vol;
929 
930  //for updating tmp_volume correctly, here use difference
931  // typedef defined in DataStock.h float/double
932  type_value_data tmp_volume=0;
933 
934  // keep same logic non-chronologic, open new_candle
935  tmp_volume = list_vol_in.NoChronologicAt(0).GetValue();
936 
937  new_candle.SetDate ( list_dcsv_in.NoChronologicAt( 0 ).GetDate() );
938  new_candle.SetClose( list_dcsv_in.NoChronologicAt( 0 ).GetValue() );
939  // set all explicitely, cannot use assignment because different types here
940  new_candle.SetHigh ( list_dcsv_in.NoChronologicAt( 0 ).GetValue() );
941  new_candle.SetLow ( list_dcsv_in.NoChronologicAt( 0 ).GetValue() );
942 
943  // set prev_value for all cases
944  time_tm = new_candle.GetDateTm();
945  // not logic the order, better min, hour, day
946  prev_value[0] = time_tm.tm_hour;
947  // here as well problem with first value, need case
948  // in case H1 only
949  prev_value[1] = time_tm.tm_min;
950  switch ( new_tmscl ) {
951  case ETime::M5 : prev_value[1] = time_tm.tm_min /5; break;
952  case ETime::M10 : prev_value[1] = time_tm.tm_min /10; break;
953  case ETime::M30 : prev_value[1] = time_tm.tm_min /30; break;
954  // forgot this case ? in purpose ? yes always assigned before the switch
955  //case ETime::H1 :
956  default : break;
957  }
958  prev_value[2] = time_tm.tm_mday;
959 
960  //std::cout << "first candle update tmp_volume " << tmp_volume << std::endl;
961  //std::cout << "new candle GetClose() " << new_candle.GetClose() << std::endl;
962  //std::cout << "Date: " << NoChronologicAt( 0 ).GetDateString() << " tmp_volume "<< tmp_volume << std::endl;
963  //std::cout << "begin loop " << std::endl;
964 
965  // output non-chronologic ? certainly in the output, can reorder after
966  for ( unsigned int i = 1 ; i < size_input_csv ; ++i ) {
967 
968  time_tm = list_dcsv_in.NoChronologicAt( i ).GetDateTm();
969  //std::cout << "Date: " << NoChronologicAt( i ).GetDateString() << " "
970  // << in_vol->NoChronologicAt( i ).GetValue() << std::endl ;
971  //use a modulo for bool to change candle
972  minute = time_tm.tm_min;
973 
974  // 0 added: dcvs, cannot change to this, begin to 1
975  //default MANDATORY otherwise take value ???? bug /???
976  switch (new_tmscl) {
977  // M5
978  case ETime::M5 :
979  // change prev store the real minute
980  // time_tm.tm_min/5
981  if ( (minute/5) != prev_value[1] ) {
982  //std::cout << " M5 change (minute/5)= " << (minute/5) << " prev_value[1]/5 " << prev_value[1]/5 << std::endl;
983  change_candle=true;
984  prev_value[1] = minute/5 ;
985  }
986  break;
987  // M10
988  case ETime::M10 :
989  if ( (minute/10) != prev_value[1] ) {
990  change_candle=true;
991  prev_value[1]= minute/10;
992  }
993  break;
994  // M30
995  case ETime::M30 :
996  //std::cout << "timescale 3 min/30=" <<minute/30 << std::endl;
997  if ( (minute/30) != prev_value[1] ) {
998  change_candle=true;
999  prev_value[1]= minute/30;
1000  }
1001  break;
1002  // H1
1003  case ETime::H1 :
1004  if ( time_tm.tm_hour != prev_value[0]) {
1005  change_candle=true;
1006  prev_value[0] = time_tm.tm_hour;
1007  }
1008  break;
1009 
1010  //to write other, more or egal than 1 day
1011  default:
1012  std::cout << "Error in switch timescale, return 1" << std::endl;
1013  //break;
1014  return 1;
1015  } //end switch
1016  //all case, check day also !
1017  // possible change day, but minute or hour did not change and prev_value not updated
1018  // seems fine, to make unit_test
1019  if ( time_tm.tm_mday != prev_value[2]) {
1020  //std::cout << "change day" << std::endl;
1021  change_candle=true;
1022  prev_value[2] = time_tm.tm_mday;
1023  }
1024 
1025  if ( change_candle ) {
1026  //std::cout << " Change Candle" << std::endl;
1027  change_candle = false;
1028 
1029  // close the candle to the previous value
1030  new_candle.SetOpen ( list_dcsv_in.NoChronologicAt(i-1).GetValue() );
1031  //std::cout << "SetOpen " << new_candle.GetOpen() << std::endl; //GetDateString()
1032  // assign date get previous one, still ok if i==1
1033  new_candle.SetDate( list_dcsv_in.NoChronologicAt(i-1).GetDate() );
1034  // update volume, here makes the difference
1035  new_vol.SetData ( new_candle.GetDate(), tmp_volume - (list_vol_in.NoChronologicAt(i-1).GetValue()) );
1036 
1037  // save in output listdata
1038  list_csv_out.AddData( new_candle);
1039  list_vol_out.AddData( new_vol);
1040 
1041  // clear the min max of candle, or set explicit
1042  //new_candle.Reset();
1043  new_candle.SetHigh ( list_dcsv_in.NoChronologicAt( i ).GetValue() );
1044  new_candle.SetLow ( list_dcsv_in.NoChronologicAt( i ).GetValue() );
1045  new_candle.SetClose( list_dcsv_in.NoChronologicAt( i ).GetValue() );
1046  // initialze volume, here always last
1047  tmp_volume = list_vol_in.NoChronologicAt(i-1).GetValue();
1048 
1049  } // end change_candle
1050  // all case update min-max values
1051  new_candle.AdditionData ( list_dcsv_in.NoChronologicAt( i ) );
1052  // nothing to do for volume
1053  } // end loop i
1054 
1055  // must close last candle
1056  new_candle.SetOpen ( list_dcsv_in.NoChronologicAt( size_input_csv -1 ).GetValue() );
1057  new_candle.SetDate( list_dcsv_in.NoChronologicAt( size_input_csv -1 ).GetDate() );
1058  // tmp_volume initialized only when opened, tmp_volume not really needed
1059  new_vol.SetData ( new_candle.GetDate(),
1060  tmp_volume - (list_vol_in.NoChronologicAt(size_input_csv -1).GetValue()) );
1061 
1062  // add the last data
1063  list_csv_out.AddData( new_candle );
1064  list_vol_out.AddData( new_vol );
1065 
1066  // has been filled in non chronologic order, maybe need to reorder
1067  list_csv_out.Order( EPChrono::NO_CHRONO );
1068  list_vol_out.Order( EPChrono::NO_CHRONO );
1069 
1070  // may swap also here, but may need to extend regularly
1071 
1072  // assign the new dates from the CSV or dcsv
1073  // in fact the last is interesting, want the real last date
1074  //out_csv.SetDates( dates.first, dates.last );
1075  //out_vol.SetDates( dates.first, dates.last );
1076  list_csv_out.SetDates();
1077  list_vol_out.SetDates();
1078 
1079 #ifdef DEBUG_CPP
1080  std::cout << "TestSize out_csv " << list_csv_out.GetSize() << std::endl;
1081  std::cout << "TestSize out_vol " << list_vol_out.GetSize() << std::endl;
1082 #endif
1083  return 0;
1084 }
1085 
1086 } //end namespace_Utils
1087 
void Replace(const ListDataStockBase *ldata_in)
Replace all DataStock's of the list with ldata_in.data, without checking for update.
void SetName(const std::string iname)
Definition: ListDataStock.h:82
type_value_data GetValue() const
Get the unique value.
Definition: DataStock.h:391
void AddData(DataStock &data)
Add a copy of the DataStock into the ListDataStock.
void PrintData(const unsigned int verbose=0) const
Nice formatting output on console.
unsigned int GetSize() const
Return the size of the vector.
virtual time_t LastUpdate() const =0
Get the date of the last data (always chronological meaning)
double type_value_data
Type of the floating values to be stored, can be set to float or double before compilation.
Definition: DataStock.h:49
boost::variant< float **, double **, int ** > var_types
time_t GetFirstDate() const
Get first date from the private data member dates.
Definition: ListDataStock.h:89
const T & NoChronologicAt(const unsigned int offset) const
Get nth element in a non chronological order.
Use a policy PolicyChronologic, default VecNoChronologic.
EPChrono
Define convenient name for the chronology, makes algorithms clearer.
virtual void GetVectorData(std::vector< DataCSV > &, const EPChrono) const
time_t GetLastDate() const
Get last date from the private data member dates.
Definition: ListDataStock.h:91
Data type to describe Japanese candlesticks : open, high, low and close values.
Definition: DataStock.h:502
virtual time_t GetFirstTime() const =0
Get the date of the first data (always chronological meaning)
void Reserve(const unsigned int new_size)
Reserve new_size elements.
boost::variant< float ***, double ***, int *** > var_types2
static Indicator const Volume
Definition: Indicator.h:44
ETime
Enumeration for the different time representation, from instantaneous (INST) to year(YEAR) ...
Definition: TimeScale.h:48
virtual void AdditionData(const DataCSV &new_data)
With an other candlestick.
Definition: DataStock.cpp:843
void Order(const EPChrono b_chronologic=EPChrono::CHRONO)
Function to reverse the internal vector in its original policy.
virtual const DataStock & ChronologicAt(const unsigned int offset) const =0
Get the nth element in a chronological order.
std::string Time_tToString(const time_t &time, const bool b_hour)
Return a string representing the date All times are expressed in the localtime.
Definition: Utils.cpp:157
virtual void SetTimeScale(const ETime new_tmscl)
Definition: ListDataStock.h:81
void Swap()
Reduce the capacity of the internal vector to fit its size.
void SetDates()
Set the correct first/last dates from the DataStock in the vector.
type_value_data GetOpen() const
Definition: DataStock.h:552
struct tm GetDateTm() const
Get a tm structure of the date.
Definition: DataStock.cpp:151
Derive class which contains only one value of type type_value_data (float or double).
Definition: DataStock.h:335
virtual unsigned int GetSize() const =0
Return the size of the vector.
static Indicator const StockCSV
Definition: Indicator.h:44
void Clear()
Clear the vector and reinitialize data members to default values.
std::string GetName() const
Definition: ListDataStock.h:78
Abstract base class for the ListDataStock, for storing base pointers in vectors.
Definition: ListDataStock.h:50
time_t GetDate() const
Get the date data member.
Definition: DataStock.h:126
virtual const DataStock & NoChronologicAt(const unsigned int offset) const =0
Get nth element in a non chronological order.
static SUPPRESS_NOT_USED_WARN firstlast_dates get_fldate_default()
need to be static for using default argument in a function
Definition: Utils.h:60
std::string MakeShortName(const Indicator &indic, const std::vector< int > &param)
Create a short name from its components.
Definition: FullName.cpp:109
virtual ETime GetTimeScale() const
Definition: ListDataStock.h:80
int AddToList(const ListDataStockBase *new_list)
Append all data from a new list ( coming from an Update or ReadCSV normally ) to an existing list...
unsigned int GetCArray(var_types arraydata_c, const EPChrono b_order, const unsigned int no=0) const
Extract the data into a one dimensional C-array.
ETime GetTimeScale(const std::string &fname)
Extract the TimeScale from a fullname.
Definition: FullName.cpp:53
int PutCArray(const ListDataStockBase &ldata_date, const unsigned int nb_data, const unsigned size_indic, var_types arraydata_c, const unsigned int offset_begin, const unsigned int offset_end=0, const EPChrono b_chrono=EPChrono::CHRONO, bool full_array=false)
Fill a ListDataStock<T> from a 2 dimensional C-array.
int TransformTimeScale(const ETime new_tmscl, const ListDataStock< DataCSV, Policy1 > &list_csv_in, const ListDataStock< SimpleData, Policy2 > &list_vol_in, ListDataStock< DataCSV, Policy3 > &list_csv_out, ListDataStock< SimpleData, Policy4 > &list_vol_out)
Transform StockCSV and Volume from M5 into a StockCSV with larger TimeScale, typical DAY to WEEK...