ROOT_Application  2.0
C++ Core modules and GUIStock
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stock.cpp
Go to the documentation of this file.
1 
11 #include "Stock.h"
12 
13 #include <fstream>
14 #include <ostream>
15 // needed for passing stream by parameter, seems really important !
16 #include <iosfwd>
17 #include <iomanip>
18 
19 #include "ListDataStock.h"
20 // moved here, maybe need other import for other function, more convenient in Stock.h
21 #include "TAlibAPI.h"
22 /* include the wrapper to ParserStock, defined in external file
23  * because include Python.h makes problem with rootcint */
24 #include "StockwrapPyParser.cpp"
25 
27 
28 // old deprecated
29 Stock::Stock( const std::string iname, const std::string isymbol, const std::string ipath):
30  name(iname), symbol(isymbol), path(ipath) {
31 #ifdef DEBUG_CPP
32  std::cout << " Constructor Stock, depreaceated version with symbol " << std::endl;
33 #endif
34  // lazy initialization, created only when calling Compute
35  p_talib = nullptr;
36 }
37 
38 // constructor, ipath has default value with Utils::PATH_DATA
39 Stock::Stock( const std::string iname, const std::string ipath ) :
40  name(iname), path(ipath) {
41  symbol= iname;
42  // lazy initialization, created only when calling Compute
43  p_talib = nullptr;
44 }
45 
46 
48 #ifdef DEBUG_CPP
49  std::cout << "Default destructor stock" << std::endl;
50 #endif
51 
52  for( it_map it_m = mapTime_ListData.begin(); it_m != mapTime_ListData.end(); ++it_m) {
53  for( it_listdata it_l = it_m->second.begin(); it_l != it_m->second.end(); ++it_l) {
54  //std::cout << "Delete ListDatatStock " << std::endl;
55  delete (*it_l);
56  }
57  }
58  // do not seem necessary, done when exiting, but correct if outside the loop
59  mapTime_ListData.clear();
60  // not necessary
61  name.clear();
62  symbol.clear();
63  // nullify the pointer, now with singleton ok, shutdown the library only once
64  delete p_talib;
65  p_talib = nullptr;
66 }
67 
69 
70 // in all GetItList functions check end iterator must be done before
71 // could return end iterator of the map, easier to check
72 Stock::cit_listdata Stock::GetItList( Stock::cit_map& it_m, const Indicator& indic, const std::vector<int> & param ) const
73 {
74  cit_listdata it_l;
75  std::string full_indic_label = ShortName::MakeShortName( indic, param );
76  //std::cout << "Stock::GetItList full_indic_label " << full_indic_label << std::endl;
77 
78  return GetItList( it_m, full_indic_label );
79 }
80 
81 Stock::cit_listdata Stock::GetItList( Stock::cit_map& it_m, const std::string& sname ) const
82 {
83  cit_listdata it_l;
84  // or use find algorithm
85  for( it_l = (*it_m).second.begin(); it_l != (*it_m).second.end(); it_l ++) {
86  if ( (*it_l)->GetName() == sname ) {
87  return it_l;
88  }
89  }
90  return (*it_m).second.end();
91 }
92 
93 // version non-const, to be called by non-const function
94 Stock::it_listdata Stock::GetItList( it_map& it_m, const Indicator& indic, const std::vector<int>& param )
95 {
96  // call only one version
97  std::string full_indic_label = ShortName::MakeShortName( indic, param );
98  return GetItList( it_m, full_indic_label );
99 }
100 
101 Stock::it_listdata Stock::GetItList( it_map& it_m, const std::string& sname )
102 {
103  // here iterator it_m should be checked before
104  for( it_listdata it_l = (*it_m).second.begin(); it_l != (*it_m).second.end(); it_l ++) {
105  if ( (*it_l)->GetName() == sname ) {
106  return it_l;
107  }
108  }
109  return (*it_m).second.end();
110 }
111 
112 // only in one place, extract dates and timescale maybe (for check as well)
113 // made private and static
114 // suppress ETime & tmscl, not used until now
115 // version static, can be called by Read_HeaderCSV_static
116 int Stock::ReadLineHeader( const std::string & line, Utils::firstlast_dates & dates )
117 {
118  std::vector<std::string> line_split;
119  Utils::splitline(line," ", line_split);
120  // could choose format from the TimeScale, tricky here int
121  //tmscl = static_cast<ETime>(( unsigned int) line_split[1]);
122  //tmscl = static_cast<ETime>( line_split[1]);
123 
124  // for daily data, StringToTime_t return -1/-105 if an error occured (bad format)
125  if ( line_split.size() == 4 ) {
126  dates.first = Utils::StringToTime_t ( line_split[2] );
127  dates.last = Utils::StringToTime_t ( line_split[3] );
128  // for dcsv
129  } else if ( line_split.size() == 6 ) {
130  dates.first = Utils::StringToTime_t ( line_split[2]+" "+line_split[3] );
131  dates.last = Utils::StringToTime_t ( line_split[4]+" "+line_split[5] );
132  }
133 
134  // else problem, should not appear
135  else {
136  std::cout << "ERROR Stock::ReadLineHeader in reading dates, return 1 " << std::endl;
137  return 1;
138  }
139 
140  // -1 possibly a time shift with origin date and locatime ? yes seems, use -105
141  if ( dates.first == Utils::ERROR_StrToTime || dates.last == Utils::ERROR_StrToTime ) {
142 #ifdef DEBUG_CPP
143  std::cout << "ERROR Stock::ReadLineHeader from Utils::StringToTime_t, return 1" << std::endl;
144 #endif
145  return 1;
146  }
147 
148 #ifdef DEBUG_CPP
149  std::cout << "ReadLineHeader dates " << Utils::Time_tToString( dates.first, true ) << " "
150  << Utils::Time_tToString( dates.last, true ) << std::endl;
151 #endif
152  return 0;
153 }
154 
155 // advantage of stream, keep previous modificator (fixed, precision), solve bug volume with exponential ??
156 // include string timescale (DAY) on 5 characters
157 // include version number, only fixed now
158 // made static as well
159 void Stock::WriteLineHeader( const ETime & tmscl, const Utils::firstlast_dates & dates, std::ostringstream & ss_header )
160 {
161  // test to print the name, 5 is max with MONTH, do not include HH:MM:SS
162  if ( tmscl >= ETime::DAY ) {
163  ss_header << "#0.1 " << std::setw(5) << std::left << tmscl << " " << Utils::Time_tToString( dates.first, false )
164  << " " << Utils::Time_tToString( dates.last, false );
165  // need exact time
166  } else {
167  ss_header << "#0.1 " << std::setw(5)<< std::left << tmscl << " " << Utils::Time_tToString( dates.first, true )
168  << " " << Utils::Time_tToString( dates.last, true );
169  }
170  return;
171 }
172 
173 // private member now, could change the name ReadFileListData or LoadCSVdata, LoadHistoricalData
174 // Read the correct file ( need infos about dates) try to avoid the default values here
175 // Call Transform Time if necessary
176 // return value not used, use exception
177 void Stock::LoadCSVData(const ETime& tmscl, Utils::firstlast_dates & dates) throw ( StockException )
178 {
179 #ifdef DEBUG_CPP
180  std::cout << "Stock::LoadCSVData argument tmscl: " << tmscl << std::endl;
181 #endif
182  // test first if the candle is already loaded
183  // case INST, indicator is different StockInst
184  if ( tmscl == ETime::INST ) {
185 
186  // better, more accurate
187  if ( CheckLoaded( tmscl, Indicator::StockInst ) && CheckLoaded( tmscl, Indicator::Volume ) ) {
188 #ifdef DEBUG_CPP
189  std::cout << "Indicator::StockInst and Volume for timescale " << tmscl << " is already loaded" << std::endl;
190 #endif
191  return;
192  }
193  // all other cases, use Candle
194  } else {
195  if ( CheckLoaded( tmscl, Indicator::StockCSV ) && CheckLoaded( tmscl, Indicator::Volume ) ) {
196 #ifdef DEBUG_CPP
197  std::cout << "Indicator::StockCSV and Volume for timescale " << tmscl << " is already loaded" << std::endl;
198 #endif
199  return;
200  }
201  }
202 
203  // Case read data from a file
204  if ( (tmscl == ETime::DAY) or (tmscl == ETime::INST) ) {
205 #ifdef DEBUG_CPP
206  //create ListCSV in Read and fill
207  std::cout << " ReadCSV timescale " << tmscl << std::endl;
208  //here read all data, by default last_time = 0, could make a first_time to limit the data to load(not implemented)
209 #endif
210  // return is not needed anymore
211  try {
212  ReadCSV( tmscl, dates );
213  } catch ( const StockFileError & e ) {
214 #ifdef DEBUG_CPP
215  std::cout << "LoadListData catch FileError exception" << std::endl;
216  std::cout << "what() " << e.what() << std::endl;
217  std::cout << "Will Create a StockFileError " << std::endl;
218 #endif
219  // need to clean some data ?? only inside ReadCSV...
220  // rethrow error, already of type StockException
221  throw;
222  }
223  // return here for iteration, before transform_timescale
224  return;
225  }
226 
227  // not DAY or dcsv, need to transform to an other timescale
228  if (tmscl > ETime::DAY) {
229  //new_tmscl = ETime::DAY;
230  // new version check exactly one of mandatory if missing
231  // if one is missing, force to read again the file, old list will be "replaced" (first time equal)
232  // and it solves the bug
233  if ( !CheckLoaded(ETime::DAY, Indicator::StockCSV) ||
234  !CheckLoaded( ETime::DAY, Indicator::Volume) ) {
235  LoadCSVData( ETime::DAY, dates);
236  }
237  } else if (tmscl < ETime::DAY) {
238  //new_tmscl = ETime::INST;
239  if ( !CheckLoaded(ETime::INST, Indicator::StockInst) ||
240  !CheckLoaded( ETime::INST, Indicator::Volume) ) {
241  std::cout << "At least one missing, force to read the file " << std::endl;
242  LoadCSVData( ETime::INST, dates);
243  }
244  }
245 
246  // transform to the timescale, problem if StockCSV or Volume deleted, but not both
247  std::cout << "before transform_timescale " << std::endl;
248  if ( Transform_TimeScale(tmscl) != 0 ) {
249  // message not clear...
250  std::cout << "TransformTimeScale problem throw exception " << std::endl;
251  throw ( StockException( name, "Error in Transform_TimeScale tmscl") );
252  }
253  return;
254 }
255 
256 // may check before ?
257 // to delete
259 {
260  std::string tmp_string = GetName()+"_"+ GetTimeScaleName( p_listdata->GetTimeScale() ) +
261  "_" + p_listdata->GetName();
262 #ifdef DEBUG_CPP
263  std::cout << "Entry Stock::SetLDataFullName " << std::endl;
264  std::cout << " tmp_string " << tmp_string << std::endl;
265 #endif
266  p_listdata->SetFullName( tmp_string );
267 }
268 
269 // no exception from ListDataStock
270 // should be used only internally ? now is private
271 // Swap is done according to ListDataStock_Utils::TransformTimeScale
272 // dynamic_cast still needed here ?? yes to call TransformTimeScale
273 int Stock::Transform_TimeScale( const ETime & new_tmscl )
274 {
275 #ifdef DEBUG_CPP
276  std::cout << "\n\tEntry Transform_TimeScale " << new_tmscl << std::endl;
277 #endif
278 
279  assert( new_tmscl != ETime::DAY);
280  assert( new_tmscl != ETime::INST);
281  assert( new_tmscl != ETime::not_a_time);
282 
283  // output type is known for sure
284  ldata_candle *out_csv = new ldata_candle ("StockCSV", new_tmscl);
285  ldata_volume *out_vol = new ldata_volume("Volume", new_tmscl);
286  // input volume
287  ldata_volume *in_vol;
288 
289  // need to load DAY if transform > DAY
290  if ( new_tmscl > ETime::DAY) {
291 #ifdef DEBUG_CPP
292  std::cout << " new_tmscl > DAY " << new_tmscl << std::endl;
293 #endif
294  // cannot avoid dynamic_cast here ?? no or should use Base for all lists
295  // volume the same class in both case
296  in_vol = dynamic_cast<ldata_volume*>( GetListData(ETime::DAY, Indicator::Volume ));
297  if ( in_vol == nullptr ) {
298  std::cout << "ERROR in Stock::Transform_TimeScale in dynamic_cast volume " << std::endl;
299  return 1;
300  }
301 
303  if ( in_csv == nullptr ) {
304  std::cout << "ERROR in Stock::Transform_TimeScale in dynamic_cast candle" << std::endl;
305  return 1;
306  }
307  //std::cout << "Call ListDataStock::TransformTimeScale " << std::endl;
308  // make transformation in ListData, correct call done by the argument list
309  ListDataStock_Utils::TransformTimeScale ( new_tmscl, *in_csv, *in_vol, *out_csv, *out_vol );
310 
311  //else use dcsv, assert to check for bad tmscl
312  } else if ( new_tmscl < ETime::DAY) {
313 #ifdef DEBUG_CPP
314  std::cout << " new_tmscl < DAY " << new_tmscl << std::endl;
315 #endif
316  // volume the same class in both case
317  in_vol = dynamic_cast<ldata_volume*>( GetListData(ETime::INST, Indicator::Volume ));
318  if ( in_vol == nullptr ) {
319  std::cout << "ERROR in Stock::Transform_TimeScale in dynamic_cast volume " << std::endl;
320  return 1;
321  }
322  ldata_dcsv *in_dcsv = dynamic_cast<ldata_volume*>( GetListData(ETime::INST, Indicator::StockInst) );
323  if ( in_dcsv == nullptr ) {
324  std::cout << "ERROR in Stock::Transform_TimeScale in dynamic_cast candle " << std::endl;
325  return 1;
326  }
327  ListDataStock_Utils::TransformTimeScale ( new_tmscl, *in_dcsv, *in_vol, *out_csv, *out_vol );
328  }
329 
330  // if == 1 update of a previous listdata, need to delete the local pointer
331  if ( AddListDataToMap( new_tmscl,out_csv ) == 1 ) {
332 #ifdef DEBUG_CPP
333  std::cout << "return 1 (update) from AddListData, so delete temporary list" << std::endl;
334 #endif
335  delete ( out_csv );
336  out_csv = 0;
337  }
338  if ( AddListDataToMap( new_tmscl,out_vol ) == 1 ) {
339 #ifdef DEBUG_CPP
340  std::cout << "return 1 (update) from AddListData, so delete temporary " << std::endl;
341 #endif
342  delete ( out_vol );
343  out_vol = 0;
344  }
345  return 0;
346 }
347 
349 // exception useful here, for log, gui...
350 // Computation of any TAlib indicator */
351 // maybe Indicator, param easier. Could check default parameter, now only in GUI.
352 int Stock::ComputeTA( const ETime & tmscl, const std::string & name_new_indic ) throw(TALibException)
353 {
354 #ifdef DEBUG_CPP
355  std::cout << "\n\tEntry Stock::ComputeTA, name_new_indic: " << name_new_indic << std::endl;
356 #endif
357 
358  int new_size;
359  int retour=0;
360  //get indicator and parameters, here extract parameters from name, could pass correct indicator and param
361  //could be a function GetvecParam, better than new indic ??
362  std::vector<int> vec_param;
363  Indicator new_indic(Indicator::Null);
364  new_indic.Set(name_new_indic,vec_param);
365  // for exception
366  //std::string msg;
367 
368  // They could be in TALib and throw appropriate exception
369  // This case cannot appear from LoadListData, need a real Indicator
370  // From other ?? or delete this test
371  // new_indic
372  if (new_indic == Indicator::Null || new_indic.nb_output() < 1 ) { // || vec_param.empty() ) { //deleted for AD, no parameter
373 #ifdef DEBUG_CPP
374  std::cout << "\n\t Stock::ComputeTA" << std::endl;
375  std::cout << "Error, indicator is null" << std::endl;
376  std::cout << "label indicator after extract "<< new_indic.label() << std::endl;
377 #endif
378  std::string msg = "TALibException: Error, indicator is null or nb_output <= 0, label received = "+ Utils::toString(name_new_indic);
379  throw ( TALibException( new_indic, vec_param, msg ) );
380  //return 1;
381  }
382  // test the number of parameter is correct
383  if ( new_indic.nb_param() != (int)vec_param.size() ) {
384 #ifdef DEBUG_CPP
385  std::cout << "\n\t Stock::ComputeTA" << std::endl;
386  std::cout << "Error required number of parameters "<< new_indic.nb_param() << std::endl;
387 #endif
388  std::string msg = "Error required number of parameters = " + Utils::toString(new_indic.nb_param());
389  throw ( TALibException( new_indic, vec_param, msg ) );
390 
391  }
392  //End of check
393 #ifdef DEBUG_CPP
394  std::cout << new_indic.label() << " will give " << new_indic.nb_output() << " output " << std::endl;
395 #endif
396  assert ( new_indic.nb_output() > 0 );
397 
398  // never sure here of its life time, good use of std::unqique_ptr ?
399  // now with exception potential more problem with deletion ? deleted before it is copied with release ?
400  ListDataStockBase *ldata_base_out;
401  //std::unique_ptr< ListDataStockBase> ldata_base_out;
402 
403 
404  // kind of factory, see later if needed as separate function
405  // creates default SimpleData or MultiData for the output
406  switch ( new_indic.nb_output() ) {
407  case 1:
408  //can create correct type ??
409 #ifdef DEBUG_CPP
410  std::cout << "case : nb_output 1 " << std::endl;
411 #endif
412  ldata_base_out = new ldata_ta_sd( name_new_indic, tmscl );
413  //std::unique_ptr< ListDataStockBase > *ldata_base_out = new ldata_ta_sd( name_new_indic, tmscl );
414  break;
415 
416  // equal or larger than 2
417  default:
418  ldata_base_out = new ldata_ta_md( name_new_indic, tmscl );
419  }
420 
421  // ok for the moment send stockCSV with correct timescale, need also volume for momentum !
422  // now extend to INST as well
423  std::vector< ListDataStockBase *> vec_ldata_in;
424 
425  // here may be problem as well, should work with INST as well ! but need dynamic_cast after
426  if ( tmscl == ETime::INST )
427  vec_ldata_in.push_back( GetListData(tmscl,Indicator::StockInst) );
428  else
429  vec_ldata_in.push_back( GetListData(tmscl,Indicator::StockCSV) );
430 
431  // case where volume is needed
432  if ( new_indic == Indicator::AD ) {
433 #ifdef DEBUG_CPP
434  std::cout << " case of AD need the volume in vec_ldata_in " << std::endl;
435 #endif
436  vec_ldata_in.push_back( GetListData(tmscl, Indicator::Volume) );
437  }
438 
439 #ifdef DEBUG_CPP
440  std::cout << "ldata_in[0] Name " << vec_ldata_in[0]->GetName() << std::endl;
441  std::cout << "ldata_in[0] Size " << vec_ldata_in[0]->GetSize() << std::endl;
442  //if ( vec_ldata_in.size() == 2 ) {
443  // std::cout << "Name " << vec_ldata_in[1]->GetName() << std::endl;
444  // std::cout << "Size " << vec_ldata_in[1]->GetSize() << std::endl;
445  //}
446 #endif
447 
448 
449  // lazy initialization, assign the pointer if not done and init TAlib
450  if ( p_talib == nullptr ) {
451 #ifdef DEBUG_CPP
452  std::cout << "p_talib is null, must initialize the library " << std::endl;
453 #endif
454  p_talib = new TAlibAPI();
455  }
456 #ifdef DEBUG_CPP
457  else {
458  std::cout << "p_talib is not null, library already initialized " << std::endl;
459  }
460 #endif
461 
462  // Treated here, made check, not to do in TAlibAPI
463  try {
464  retour = p_talib->Compute( tmscl, new_indic, vec_param, vec_ldata_in, ldata_base_out);
465 #ifdef DEBUG_CPP
466  std::cout << "TAlibAPI::Compute retour " << retour << std::endl;
467 #endif
468 
469  } catch ( TALibException & e ) {
470  std::cout << "Catch Stock::ComputeTA TALibException " << std::endl;
471  std::cout << "what() of TALib " << e.what() << std::endl;
472  // throw to the caller or here throw StockException( TALibException ) to write
473 
474  // need to delete list_out
475  delete ldata_base_out; ldata_base_out = nullptr;
476  throw;
477  }
478 
479  // test not needed anymore if an exception is throw ?
480  if ( !retour ) {
481 
482  new_size = ldata_base_out->GetSize();
483  std::cout << " size new data " << new_size << std::endl;
484  //std::cout << "name_new_indic " << name_new_indic << std::endl;
485 
486  //certainly need to delete previous and replace by new, default for all indicator recomputed ??
487  // may work for update SMA, should be default but may do better...
488 
489  // old test, should not be true, except mistake ask 2 times, so check first !,
490  // keep as example, and for test, but can delete
491  /*
492  if ( GetListData( tmscl, name_new_indic ) != 0 ) {
493  std::cout << "size old data " << GetListData ( tmscl, name_new_indic ) -> GetSize() << std::endl;
494  //default delete previous ListData
495  std::cout << "existing ldata pointer " << GetListData( tmscl, name_new_indic ) << std::endl;
496  std::cout << "GetName of existing data " << GetListData( tmscl, name_new_indic )->GetName() << std::endl;
497 
498  //cannot delete pointer is present in THStock... need to resize, keep same pointer
499  //DeleteListData( tmscl, GetListData( tmscl, name_new_indic )->GetName() );
500  }*/
501 
502  // Set the dates of the new List. Here will apply to all computations.
503  ldata_base_out->SetDates();
504 
505  // Will insert or replace the indicator, delete if replaced
506  // can avoid those tests, should be automatic with smart pointer ?? if unique_ptr.release maybe
507  if ( AddListDataToMap ( tmscl, ldata_base_out ) == 1 ) {
508 #ifdef DEBUG_CPP
509  std::cout << " update will delete original list " << std::endl;
510 #endif
511  delete ( ldata_base_out );
512  ldata_base_out = nullptr;
513  }
514  }
515  //else return != 0 , error in TALib, not exception for all
516  else {
517  std::cout << "\n\t retour of TAlib::Compute !=0 Error\n" << std::endl;
518  delete ( ldata_base_out );
519  ldata_base_out = 0;
520  return 1;
521  }
522 #ifdef DEBUG_CPP
523  std::cout << "\n\treturn from Stock::ComputeTA no error\n" << std::endl;
524 #endif
525  return 0;
526 }
527 
529 bool Stock::CheckLoaded( const ETime& tmscl) const
530 {
531  cit_map it = mapTime_ListData.find( tmscl );
532  if ( it==mapTime_ListData.end() )
533  return false;
534 
535  return true;
536 }
537 
538 // need to split in 2, need to be sure first iterator is valid
539 bool Stock::CheckLoaded( const ETime& tmscl, const Indicator& indic, const std::vector<int>& param ) const
540 {
541  cit_map it_m = mapTime_ListData.find( tmscl );
542  if ( it_m == mapTime_ListData.end() ) {
543  return false;
544  }
545 
546  cit_listdata it_l = GetItList( it_m, indic, param );
547  if ( it_l == (*it_m).second.end() ) {
548  return false;
549  }
550  return true;
551 }
552 
553 bool Stock::CheckLoaded( const ETime& tmscl, const std::string& sname ) const
554 {
555  cit_map it_m = mapTime_ListData.find( tmscl );
556  if ( it_m == mapTime_ListData.end() ) {
557  return false;
558  }
559 
560  cit_listdata it_l = GetItList( it_m, sname );
561  if ( it_l == (*it_m).second.end() ) {
562  return false;
563  }
564  return true;
565 }
566 
567 bool Stock::IsEmpty() const
568 {
569  if ( mapTime_ListData.empty() ) {
570 #ifdef DEBUG_CPP
571  std::cout << " The map of Stock " << name << " Is empty " << std::endl;
572 #endif
573  return true;
574  }
575  return false;
576 }
577 
578 // new, add param in input
579 // could perform the dynamic cast here ?? from Indicator should be possible ??
580 // indicator optional, send back StockCSV or StockInst ?
581 ListDataStockBase* Stock::GetListData( const ETime& tmscl, const Indicator& indic, const std::vector<int> param ) const
582 {
583  // new design, safer, obliged to check in calling
584  cit_map it_m = mapTime_ListData.find( tmscl );
585  if ( it_m == mapTime_ListData.end() ) {
586  return nullptr;
587  }
588  // map entry exist, search in vector
589  cit_listdata it_l = GetItList( it_m, indic, param );
590  if ( it_l == (*it_m).second.end() ) {
591  return nullptr;
592  }
593  return *it_l;
594 }
595 
596 // if can make the dynamic cast here, call the other function
597 ListDataStockBase* Stock::GetListData( const ETime& tmscl, const std::string& sname) const
598 {
599  cit_map it_m = mapTime_ListData.find( tmscl );
600  if ( it_m == mapTime_ListData.end() ) {
601  return nullptr;
602  }
603  cit_listdata it_l = GetItList( it_m, sname );
604  if ( it_l == (*it_m).second.end() ) {
605  return nullptr;
606  }
607  return *it_l;
608 }
609 
610 // new version, should be called in all cases
611 // creates the key timescale if it does not exist and insert the list
612 //
613 // 1. if size new data == 0 error with assert
614 // 2. Get it_map on the timescale, creates it if it does not exist. ok
615 //
616 // 3. Check if a previous listdata_old exists, with same shortname as p_listdata
617 // - if exists: if StockCSV,Stockdcsv or Volume (Indicator::ToUpdate()) : update with ListDataStock::AddToList
618 // else if TA_Indicator : replace with ListDataStock::Replace, set fullname
619 // return 1 == update
620 // else: set fullname, insert directly the pointer p_listdata into map
621 // return 0
622 int Stock::AddListDataToMap( const ETime& tmscl, ListDataStockBase* p_listdata )
623 {
624 
625  std::string sname = p_listdata->GetName();
626  unsigned int new_ldata_size = p_listdata->GetSize();
627  ListDataStockBase *ldata_old = 0;
628 
629  //Add a pointeur to the vector of pointeur on listdata
630 #ifdef DEBUG_CPP
631  std::cout << "\n\t Stock::AddListDataToMap " << tmscl ;
632  std::cout << " new list p_listdata->name " << p_listdata->GetName() ;
633  std::cout << " new list p_listdata->size " << p_listdata->GetSize() << std::endl;
634 #endif
635 
636  //for real time, AddListDataToMap should be called only if new data to add
637  // much better, keep it for test use assert
638  if ( new_ldata_size == 0 ) {
639  std::cout << "Stock::AddListDataToMap p_listdata size = 0 , return 2, SHOULD NOT APPEAR !!" << std::endl;
640  assert ( new_ldata_size !=0 );
641  return 2;
642  }
643 
644  // get iterator on timescale if exists
645  //it_map it_m = GetItMap(tmscl);
646  it_map it_m = mapTime_ListData.find( tmscl );
647  // if tmscl key does not exist, create
648  if ( it_m == mapTime_ListData.end() ) {
649 #ifdef DEBUG_CPP
650  std::cout << "In Map, ETime " << tmscl << " does not exist, create " << std::endl;
651 #endif
652  std::vector < ListDataStockBase* > vec;
653  // create a new timescale, with a default empty vector
654  mapTime_ListData[tmscl] = vec;
655  // used later if insertion
656  //it_m = GetItMap( tmscl );
657  it_m = mapTime_ListData.find( tmscl );
658  }
659 
660  // check if listdata already exists, in this case it is an update should return 1
661  // could use it_m, faster, clearer
662 #ifdef DEBUG_CPP
663  std::cout << "Check old data with same name " << sname << std::endl;
664 #endif
665  ldata_old = GetListData ( tmscl, sname );
666 
667  if ( ldata_old ) {
668 #ifdef DEBUG_CPP
669  std::cout << " Will Update existing ListDataStock " << std::endl;
670  std::cout << " name listdata old " << ldata_old->GetName() << std::endl;
671 #endif
672  Indicator indic = ShortName::GetIndicator( ldata_old->GetName() );
673  //std::cout << "Get indicator old " << indic.label() << std::endl;
674 
675  // Test indicator, could be a function of Indicator::ToReplace, ToCheck...
676  // try to update
677  if ( ( indic == Indicator::StockCSV ) || ( indic == Indicator::StockInst ) ||
678  ( indic == Indicator::Volume ) ) {
679 
680 #ifdef DEBUG_CPP
681  std::cout << "Update Stock or Volume, call AddToList " << std::endl;
682 #endif
683  // all details let to ListDataStock now
684  // number of inserted of modified values should be done there
685  ldata_old->AddToList ( p_listdata );
686 
687  //else indicator to recompute SMA, MACD... by default call ListDataStock->Replace()
688  // could update, more efficient, but more tricky... memory effect ...
689  // now all recomputed, force to replace all, not want to update like AddToList
690  } else {
691 #ifdef DEBUG_CPP
692  std::cout << "Will replace indicator (SMA,MACD...) " << std::endl;
693 #endif
694  // If fullname is missing creates it, could be done once
695  if ( p_listdata->GetFullName() == "" ) {
696  //std::cout << "SetFullname " << std::endl;
697  SetLDataFullName ( p_listdata );
698  }
699  //std::cout << "Check if fullname exist :" << p_listdata->GetFullName() << std::endl;
700  ldata_old->Replace( p_listdata );
701  }
702  // ldata_old exists, an update has been done
703 #ifdef DEBUG_CPP
704  std::cout << "ldata_old exists, an update has been done, return 1" << std::endl;
705 #endif
706  // return 1 == update p_listdata to delete
707  return 1;
708  } //end if ldata_old
709 
710  // else listdata_old does not exist, insert the full list in map
711  // and return 0
712 #ifdef DEBUG_CPP
713  std::cout << "ListData does not exist, insert " << std::endl;
714  std::cout << "Check if fullname exist to set fullname :" << p_listdata->GetFullName() << std::endl;
715 #endif
716  // could be done once ?
717  if ( p_listdata->GetFullName() == "" ) {
718  //std::cout << "SetFullname " << std::endl;
719  // cannot call ListDataStock method ??
720  SetLDataFullName ( p_listdata );
721  }
722  // add to the map, copy the pointer only
723  (*it_m).second.push_back(p_listdata);
724  // return 0, new insertion
725  return 0;
726 }
727 
728 // to_replace, replace existing entry, update maybe later...
729 // Call AddListDataToMap, follow same logic for insertion and update
730 void Stock::MergeStock( const Stock *new_stock, bool /*to_replace*/)
731 {
732 #ifdef DEBUG_CPP
733  std::cout << "Entry MergeStock " << std::endl;
734  std::cout << "this " << this << std::endl;
735  std::cout << "new_stock " << new_stock << std::endl;
736 #endif
737  // can get access to private member of new_stock
738  //it_listdata it_l_new = new_stock->GetItList(ETime::DAY,"StockCSV");
739  const Stock & rnew_stock = (*new_stock);
740  int status;
741 
742  if ( this == new_stock ) {
743 #ifdef DEBUG_CPP
744  std::cout << "Same pointer ! already updated ? just return...\n" << std::endl;
745 #endif
746  return;
747  }
748 
749 #ifdef DEBUG_CPP
750  std::cout << "Different pointer ! Make a copy... " << std::endl;
751 #endif
752  cit_map it_map_new;
753  cit_listdata it_list_new;
754 
755  for ( it_map_new = rnew_stock.mapTime_ListData.cbegin();
756  it_map_new != rnew_stock.mapTime_ListData.cend();
757  it_map_new++) {
758 
759  // print the timescale normally, ok
760  ETime tmscl = (*it_map_new).first;
761  std::cout << "ETime " << (*it_map_new).first << std::endl;
762 
763  // loop over listdata
764  for ( it_list_new = (*it_map_new).second.cbegin();
765  it_list_new != (*it_map_new).second.cend();
766  it_list_new++ ) {
767 #ifdef DEBUG_CPP
768  std::cout << "fullname list " << (*it_list_new)->GetFullName() << std::endl;
769  std::cout << "name list " << (*it_list_new)->GetName() << std::endl;
770 #endif
771  // use existing interface AddListDataToMap
772  // case to replace here to improve
773  status = AddListDataToMap( tmscl, *it_list_new );
774 
775 #ifdef DEBUG_CPP
776  if ( status==0 ) {
777  std::cout <<"status 0: insertion " << std::endl;
778  } else if (status == 1) {
779  std::cout <<"status 1: update " << std::endl;
780  }
781 #endif
782  } // end loop over vector lists
783  } // end loop over key
784  return;
785 }
786 
787 // use private LoadCSVData to load historical data
788 // return 0 if correct
789 // return 1 if already present, just return
790 //
791 // wrong to test with ETime::INST
792 // works fine if Load( M5, Indicator::StockCSV ), so name is wrong, it should be Indicator::StockInst !
793 //
794 // If load Indicator, missing parameter, status 0, no exception ?? corrected, throw exception
795 //
796 // to load historic data, no need to give the indicator in fact, LoadCSVData guess about the timescale, overload the input
797 // done
798 //
799 // made Indicator default StockCSV (if INST, will overload) done !
800 // not sure about return value or exception, at the moment only if already loaded return 1
801 int Stock::LoadListData(const ETime& tmscl, const Indicator& indic, const std::vector<int>& param,
802  Utils::firstlast_dates dates ) throw (StockException)
803 {
804  std::string sname;
805  sname = ShortName::MakeShortName( indic, param );
806 
807 #ifdef DEBUG_CPP
808  std::cout << "\n\tEntry Stock::LoadListData ";
809  std::cout << "timescale " << tmscl << std::endl;
810  std::cout << " indic " << indic.label() << std::endl;
811  std::for_each(param.cbegin(),param.cend(),
812  [](int value){std::cout << value << " ";} );
813  std::cout << "first time " << dates.first << " " << Utils::Time_tToString( dates.first, true ) << std::endl;
814  std::cout << "last time " << dates.last << " " << Utils::Time_tToString ( dates.last, true ) << std::endl;
815  std::cout << "ShortName " << sname << std::endl;
816 #endif
817 
818  // Check for Indicator::Null
819  if ( indic == Indicator::Null ) {
820  throw StockException("StockException: LoadListData with indicator Null");
821  }
822 
823  // already loaded, return 1
824  // need to test for the exact indicator as well
825  if ( CheckLoaded( tmscl, sname ) ) {
826 #ifdef DEBUG_CPP
827  std::cout << "Indicator " << sname << " Already in Map" << std::endl;
828 #endif
829  return 1;
830  }
831 
832  // assure StockCSV (Stockdcsv to do) with the correct timescale is loaded in Stock
833  // may throw a StockFileError (StockException specific) as well, must be caught by the caller
834  // this is done before check of the indicator...
835  //
836  // here problem if INST Volume is still present, but StockInst deleted.
837  // crash in Stock::TransformTimeScale, ok problem solved now
838  LoadCSVData( tmscl, dates );
839 
840  // check if this indicator need to be computed by Talib
841  if ( indic.NeedToComputeTA() ) {
843 #ifdef DEBUG_CPP
844  std::cout << "LoadListData call ComputeTA " << std::endl;
845 #endif
846  // throw TAlibException if not enough data for instance
847  // retour not needed anymore ?
848  // if indicator has wrong parameter, return 1, does not throw exception.
849  try {
850  ComputeTA( tmscl, sname );
851  // expect a TALibException if any problem in this part
852  } catch ( const TALibException & e ) {
853 #ifdef DEBUG_CPP
854  std::cout << "Stock::LoadListData catch TALibException " << std::endl;
855  std::cout << "what() " << e.what() << std::endl;
856 #endif
857  // rethrow, transform to StockTALibError
858  throw ( StockTALibError( name, TimeScale::GetTimeScaleName(tmscl), e) );
859  }
860  } // end ComputeTA
861 
862 #ifdef DEBUG_CPP
863  std::cout << "Exit Stock::LoadListDataStock without problem " << std::endl;
864  //PrintMapChrono();
865 #endif
866  // all fine, new inserted by default
867  return 0;
868 }
869 
870 
871 // only call other version
872 void Stock::DeleteListData( const ETime& tmscl, const Indicator& indic, std::vector<int> param )
873 {
874 #ifdef DEBUG_CPP
875  std::cout << "Stock::DeleteListData with indic" << indic.label() << " tmscl " << tmscl << std::endl;
876  //PrintMapChrono();
877 #endif
878 
879  std::string sname = ShortName::MakeShortName( indic, param );
880  DeleteListData( tmscl, sname );
881 }
882 
883 // Delete one ListDataStock with shortname
884 // check if the dictionary TimeScale entry is empty and delete it
885 void Stock::DeleteListData( const ETime& tmscl, const std::string& sname )
886 {
887 #ifdef DEBUG_CPP
888  std::cout << "Stock::DeleteListData " << sname << " tmscl " << tmscl << std::endl;
889  //PrintMapChrono();
890 #endif
891 
892  it_map it_m = mapTime_ListData.find( tmscl );
893  // if time does not exist, do nothing
894  if ( it_m != mapTime_ListData.end() ) {
895 
896  it_listdata it_l = GetItList ( it_m, sname );
897  // if name does not exist, do nothing
898  if ( it_l != (*it_m).second.end() ) {
899  // delete object ListData
900  delete(*it_l);
901  // erase entry in map value
902  mapTime_ListData[tmscl].erase(it_l);
903 
904  // if size of the vector TimeScale is null, delete completely the entry in map
905  if ( mapTime_ListData[tmscl].size() == 0 ) {
906 #ifdef DEBUG_CPP
907  std::cout << " size of map with key " << tmscl << " is empty, delete it " << std::endl;
908 #endif
909  mapTime_ListData.erase ( tmscl );
910  }
911  }
912  }
913 }
914 
915 // Delete all ListData corresponding to a TimeScale, delete entry timescale in map */
916 void Stock::DeleteAllListData( const ETime & tmscl )
917 {
918  #ifdef DEBUG_CPP
919  std::cout << " Entry DeleteAllListData " << tmscl << std::endl;
920  #endif
921 
922  it_map it_m = mapTime_ListData.find( tmscl );
923  // if time does nott exist, return
924  if ( it_m == mapTime_ListData.end() )
925  return;
926 
927  //stl remove-erase-idiom, p 1020, not really applicable here
928 
929  // Best way, delete data and then the map reference by erase all
930  for ( it_listdata it_l = ((*it_m).second.begin()); it_l != (*it_m).second.end(); it_l++ ) {
931 #ifdef DEBUG_CPP
932  std::cout << (*it_l)->GetName() << std::endl;
933 #endif
934  //if not called, destructor of ListDataStock is not called
935  delete ( *it_l );
936  }
937  // here sure to delete the map entry, should be empty already
938  mapTime_ListData[tmscl].clear();
939  //(it_m).clear(); //not compile, it is a pair Etime, vector
940  // erasing by key directly
941  mapTime_ListData.erase ( tmscl );
942 #ifdef DEBUG_CPP
943  std::cout << "Stock::End DeleteAllListData " << std::endl;
944  PrintMapChrono();
945 #endif
946 }
947 
949 
950 // book, p 1119, force stream to throw exception
951 //cout.exceptions(ios::failbit | ios::badbit | ios::eofbit);
952 
953 // Could be in ListDataStock, and forward the call here. But read only DAY and dcsv....
954 // read StockCSV and volume
955 // or StockdCVS and volume
956 // full implementation of dates now
957 unsigned int Stock::ReadCSV( const ETime tmscl, Utils::firstlast_dates dates )
958  throw ( StockFileError )
959 {
960 #ifdef DEBUG_CPP
961  std::cout << "\n\tEntry ReadCSV ,timescale " << tmscl << std::endl;
962  std::cout << " opt dates first " << dates.first <<" " << Utils::Time_tToString( dates.first, true ) << std::endl;
963  std::cout << " opt dates last " << dates.last << " " << Utils::Time_tToString( dates.last ) << std::endl;
964  std::cout << " path data: " << path << std::endl;
965 #endif
966 
967  std::string line;
968  std::vector<std::string> line_split;
969  // return value
970  int new_size = 0;
971  // tmp values
972  time_t time_tmp;
973  // float or double for DataStock values
974  type_value_data tmp_vol;
975  int count = 0;
976  // file input
977  std::string filename;
978  std::ifstream file;
979 
980  // Use base pointer for filling the map
981  ListDataStockBase *plist_data;
982  ListDataStockBase *plist_volume;
983 
984  assert( tmscl != ETime::not_a_time);
985 
986  // really needed to split in 2 subdirectories ? more general csv/symbol.timescale.csv
987  // better historic/CAC40.csv and historic/CAC40.dcsv is enough (no timescale info) or CAC40.DAY.csv CAC40.dcsv.csv
988  // dcsv, changed to INST, clearer Indicator::StockInst (better than dcsv)
989  // CAC40.5.csv or CAC40.DAY.csv / CAC40.dcsv.csv
990 
991  // all in one directory now
992  filename = path + "/historical/"+ name +"."+ TimeScale::GetTimeScaleName(tmscl) + ".csv";
993 #ifdef DEBUG_CPP
994  std::cout << "read filename " << filename << std::endl;
995 #endif
996 
997  // force as input, redundant with ifstream ?
998  file.open ( filename.c_str(), std::ios_base::in );
999  // throw exception if cannot open
1000  if ( file.fail() ) {
1001 #ifdef DEBUG_EXCEPT
1002  std::cout << "Stock::ReadCVS Opening failed, will throw exception StockFileError with a FileOpenError " << std::endl;
1003 #endif
1004  throw StockFileError ( name, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(), FileOpenError( filename ) );
1005  }
1006 
1007  // read the first line: header, check if file empty
1008  std::getline( file, line );
1009  // test correct, not empty
1010  if ( file.fail() ) {
1011 #ifdef DEBUG_CPP
1012  std::cout << "Get first line failed, throw exception " << std::endl;
1013 #endif
1014  throw StockFileError ( name, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(), FileEmptyError( filename ) );
1015  }
1016 
1017  // move logic of reading the header in one private method
1018  Utils::firstlast_dates dates_file;
1019  // return 0 ok, or or error
1020  if ( ReadLineHeader( line, dates_file ) ) {
1021 #ifdef DEBUG_CPP
1022  std::cout << "Error return from ReadLineHeader " << std::endl;
1023 #endif
1024  // Read Error exception, header is line 1
1025  throw StockFileError ( name, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(),
1026  FileReadError( filename, 1 ) );
1027  }
1028 
1029  // could check date input are valid with dates_file in supplement
1030  // use data from header if not specified as argument
1031  if ( dates.first == 0 )
1032  dates.first = dates_file.first;
1033  if ( dates.last == 0 )
1034  dates.last = dates_file.last;
1035 #ifdef DEBUG_CPP
1036  std::cout << "modified first dates " << Utils::Time_tToString( dates.first, true) << std::endl;
1037  std::cout << "modified last dates " << Utils::Time_tToString( dates.last, true) << std::endl;
1038 #endif
1039 
1040  // count valid lines with the dates, allow to size correctly the lists
1041  while (true) {
1042  // exists std::getline( file, line, delimiter) //avoids splitline
1043  // or std::istream::getline( char * s, streamsize n, delimiter)
1044  std::getline( file, line );
1045  // full test if file.good() {make logic} else if file.eof() {break} else {clear and can get the error}, p1136
1046  if ( file.eof() )
1047  break;
1048 
1049  // could read the first 19 characters also (if sure of the format)
1050  // exists
1051  Utils::splitline ( line, ",", line_split );
1052  // return -105 if not correct
1053  time_tmp = Utils::StringToTime_t( line_split[0] );
1054 
1055  //std::cout << "time_tmp " << Utils::Time_tToString( time_tmp, true ) << std::endl;
1056  // check with dates
1057  if ( ( time_tmp >= dates.first ) && ( time_tmp <= dates.last ) )
1058  ++count;
1059  line_split.clear();
1060  }
1061 #ifdef DEBUG_CPP
1062  std::cout << " count " << count << " lines " << std::endl;
1063 #endif
1064  // with exception, will get problem if no dates
1065  // here throw no data to read from file
1066  if ( count == 0 ) {
1067 #ifdef DEBUG_CPP
1068  std::cout << "will throw a StockFileError, dates are wrong " << std::endl;
1069 #endif
1070  // add better nessage, with dates, real input is missing
1071  std::string msg = "Dates provided give no data \ndates used: " +
1072  Utils::Time_tToString(dates.first, true) + " " + Utils::Time_tToString(dates.last, true) +" ";
1073  // must be a StockFileError !
1074  throw StockFileError (name, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(), FileReadError( filename, msg ) );
1075  }
1076 
1077  // both are mandatory, not sure why ? becasue eof ?
1078  file.clear();
1079  file.seekg(0, std::ios::beg);
1080 
1081  // need polymorphism for data, stack more efficient ?
1082  DataStock *data = 0;
1083  // for volume exact type is known for sure
1084  SimpleData data_volume;
1085 
1086  if ( tmscl == ETime::INST ) {
1087  // only one value with dcsv
1088  data = new SimpleData();
1089  // SimpleData and order given in tydedef
1090  plist_data = new ldata_dcsv("StockInst", tmscl, count);
1091 
1092  // now read all
1093  //} else if (tmscl == ETime::DAY) {
1094  } else if ( tmscl != ETime::not_a_time) {
1095  data = new DataCSV();
1096  plist_data = new ldata_candle("StockCSV", tmscl, count);
1097  }
1098  //else error timescale, exception
1099  // always set the volume
1100  plist_volume = new ldata_volume("Volume", tmscl, count);
1101 
1102  //Reread the file, first line header, do nothing
1103  getline (file,line);
1104  //std::cout << "Read line: " << line << std::endl;
1105 
1106  //could add a line number for exception
1107  //count = 0;
1108  while ( std::getline(file,line) ) {
1109  //std::cout << "Read line: " << line << std::endl;
1110 
1111  // new operator<< for data_csv : data << line
1112  // not possible yet to combine with data_vol << data_csv << line
1113 
1114  // need to clear line before reuse ! very important !
1115  // or need to modify function, clear at the entrance ? default behaviour
1116  Utils::splitline ( line, ",", line_split );
1117 
1118  // data and data stock treated by correct type CSV or dCSV (with simple data)
1119  // good test for exception here !! for sure !!
1120  //data->ExtractCSVLine(line_split);
1121  // new style, error assert in load_list_data_dcsv ! line_split != 2
1122  // be less specific, >= 2
1123  //(*data) << line;
1124  line >> *data;
1125 
1126  // to test, operator not implemented for string, only stringstream at now
1127  //data_volume << (*data << line );
1128 
1129  // extract time in time_t format
1130  time_tmp = data->GetDate();
1131  //std::cout << " time_tmp " << time_tmp << " " << Utils::Time_tToString ( time_tmp, true ) << std::endl;
1132 
1133  // test dates match
1134  if ( ( time_tmp >= dates.first ) && ( time_tmp <= dates.last ) ) {
1135  // add the new data_csv
1136  plist_data->AddData( *data );
1137 
1138  // volume, always last one, trick use previous conversion of date !
1139  tmp_vol = Utils::fromString<type_value_data>( line_split[line_split.size()-1] );
1140  // C++11, new conversion function
1141 
1142  // SetData
1143  data_volume.SetData( data->GetDate(), tmp_vol );
1144  // add data volume to the list
1145  plist_volume->AddData( data_volume );
1146  }
1147  //break the loop if nothing more to read in CSV ( can be a lot !! )
1148  else {
1149  // simple shortcut, because always written non-chronologic
1150  if ( ( tmscl == ETime::DAY ) && ( time_tmp < dates.first ) ) {
1151  // if day chronologic, no need to continue to read data
1152  //if ( time_tmp < dates.first ) {
1153 #ifdef DEBUG_CPP
1154  std::cout << " \nNo need to read others if DAY, can stop !\n " << std::endl;
1155 #endif
1156  break;
1157  }
1158  }
1159  //clear line before reuse ! very important !
1160  line_split.clear();
1161  }
1162  // no more need of object and pointer on data csv, volume on stack
1163  delete ( data ); data = nullptr;
1164  // use volume because always filled
1165  new_size = plist_volume->GetSize();
1166 
1167 #ifdef DEBUG_CPP
1168  std::cout << " size new list volume " << plist_volume->GetSize() << " " << new_size << std::endl;
1169  std::cout << " should be equal to count " << count << std::endl;
1170  std::cout << " after loop last date " << Utils::Time_tToString ( time_tmp, true ) << std::endl;
1171 #endif
1172  // maybe too strong here ?
1173  assert ( new_size==count );
1174 
1175  // case of dates, maybe no new data
1176  if ( new_size ) {
1177 
1178  // need to setup the correct order here, before Adding data to Map
1179  // indicates in which order the data have been read, to order accordingly to the Policy
1180  // if could assign ChronologicAt() = data, maybe not needed, but order is different for CSV and dcsv
1181 
1182  // case dcsv it is chronologic
1183  if ( tmscl == ETime::INST ) {
1184  plist_data->Order( EPChrono::CHRONO );
1185  plist_volume->Order( EPChrono::CHRONO );
1186  }
1187  // other non-chrono, but may change later (keep M5,..H1 chrono), just change the reorder
1188  else {
1189  plist_data->Order( EPChrono::NO_CHRONO );
1190  plist_volume->Order ( EPChrono::NO_CHRONO );
1191  }
1192 
1193  // need better after, case of update..., not bad here setup correctly
1194  // maybe updated in AddListDataToMap
1195  // if later read M5, ... should use the header dates, can be different from data
1196  // maybe too early if update, done in AddListDataToMap() after ?? to check but yes I guess
1197  // if commented unit-test failed
1198  plist_data->SetDates();
1199  plist_volume->SetDates();
1200 
1201  // Append to the map, check if it is an update
1202  // return 1 is an update, need to delete local p_listdata
1203  if ( AddListDataToMap( tmscl, plist_data ) == 1 ) {
1204 #ifdef DEBUG_CPP
1205  std::cout << "AddListDataToMap list_data==1 delete plist_data " << std::endl;
1206 #endif
1207  delete ( plist_data ); plist_data=0;
1208  }
1209 
1210  if ( AddListDataToMap ( tmscl,plist_volume ) == 1 ) {
1211 #ifdef DEBUG_CPP
1212  std::cout << "AddListDataToMap list_volume==1 delete plist_data " << std::endl;
1213 #endif
1214  delete ( plist_volume ); plist_volume=0;
1215  }
1216  // read nothing
1217  } else {
1218 #ifdef DEBUG_CPP
1219  std::cout << "ReadCSV new_size==0, Not call AddListDataToMap and return 0" << std::endl;
1220  std::cout << "and need to delete listdata" << std::endl;
1221 #endif
1222  delete ( plist_data ); plist_data=0;
1223  delete ( plist_volume ); plist_volume=0;
1224  // return 0
1225  return new_size;
1226  }
1227  //not sure the return value is needed, can be used in case of error in dates also
1228  //used by UpdateAllTimeScale, see UpdateCSVFromFile
1229 #ifdef DEBUG_CPP
1230  std::cout << "End ReadCSV, return new_size " << new_size << std::endl;
1231 #endif
1232  // here new size read, not new size really added by AddListToMap, difficult to get
1233  PrintMapChrono();
1234  return new_size;
1235 }
1236 
1237 // only write CSV data, may extend later ?? could specialize for tmscl dcsv
1238 // commented, few changes to make it work for dcsv.
1239 // complex with indicator, see later with enum indicator
1240 //int Stock::WriteIndicator(TimeScale tmscl, std::string dir, std::vector<std::string name_indic> list_indic)
1241 
1242 // opt_name optional for unit_test, output directory ( tmp can be in the opt_name and replace the dir
1243 // opt_name more general, keep it for writing
1244 
1245 // strange behaviour to load the data if not already in memory ? should return 1, nothing done
1246 // deleted this behaviour, was only for tests ?
1247 void Stock::WriteCSV( const ETime tmscl, bool opt_tmp ) const throw (StockException)
1248 {
1249 #ifdef DEBUG_CPP
1250  std::cout << "\tWriteCSV" << std::endl;
1251  std::cout << "opt_tmp " << opt_tmp << std::endl; //opt_name "tmp"
1252 #endif
1253 
1254  // file to output
1255  std::ofstream file;
1256  std::string filename;
1257  //for float or double or int or timescale to string
1258  std::stringstream ss (std::stringstream::in | std::stringstream::out);
1259  //std::ostream os;
1260  // for header, could use the same !
1261  std::ostringstream ss_header;
1262 
1263  assert( tmscl != ETime::not_a_time);
1264 
1265  // default
1266  if ( opt_tmp == false )
1267  filename = path + "/historical/"+ name +"."+ TimeScale::GetTimeScaleName(tmscl) + ".csv";
1268  // for test, output in a different directory to not overwrite
1269  else
1270  filename = path + "/historical_tmp/"+ name +"."+ TimeScale::GetTimeScaleName(tmscl) + ".csv";
1271 
1272 #ifdef DEBUG_CPP
1273  std::cout << "write csv filename :" << filename << std::endl;
1274 #endif
1275 
1276  // extend to DAY and INST
1277  ListDataStockBase *csv;
1278 
1279  // if not in memory, throw StockException
1280  if ( tmscl == ETime::INST) {
1281  if ( CheckLoaded( tmscl, Indicator::StockInst ) == false )
1282  throw StockException( name, "Indicator::StockInst for the timescale " + TimeScale::GetTimeScaleName(tmscl) + " is not loaded");
1283 
1284  csv = GetListData( tmscl, Indicator::StockInst );
1285 
1286  // all other case, CSV data
1287  } else {
1288  if ( CheckLoaded( tmscl, Indicator::StockCSV ) == false )
1289  throw StockException( name, "Indicator::StockCSV for the timescale " + TimeScale::GetTimeScaleName(tmscl) + " is not loaded");
1290 
1291  csv = GetListData( tmscl, Indicator::StockCSV );
1292  }
1293 
1294  // identical for volume
1295  ldata_volume *vol = dynamic_cast<ldata_volume *>( GetListData( tmscl, Indicator::Volume ) );
1296 
1297  // this is to put in define debug or assert
1298  if ( (!csv) or (!vol) ) {
1299  std::cout << "Error casting in write CSV csv !" << std::endl;
1300  throw StockException( name, "Error in getting the indicators pointers !!!");
1301  }
1302 
1303  //file.open ( filename.c_str() ); // default ios_base::out, start at beginning and overwrite the content
1304  file.open ( filename.c_str(), std::ios_base::out );
1305  // check correct
1306  if ( file.fail() ) {
1307 #ifdef DEBUG_EXCEPT
1308  std::cout << "Stock::WriteCVS Opening failed, will throw exception StockFileError with a FileOpenError " << std::endl;
1309 #endif
1310  throw StockFileError ( name, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(), FileOpenError( filename ) );
1311  }
1312  std::cout << "Stock::WriteCSV file opened, " << filename.c_str() << std::endl;
1313 
1314  // create header in stringstream, same for dcsv
1315  WriteLineHeader( tmscl, csv->GetDates(), ss_header );
1316  // write to file, line or stream
1317  file << ss_header.str() << std::endl;
1318 
1319  // NeedToForce the order, use NoChronologicAt() for CSV data, chronological for dcsv
1320  // INST convenient for python, real time can simply append the data, to keep
1321  for ( unsigned int i = 0; i < csv->GetSize(); ++i ) {
1322 
1323  // clear content before reuse
1324  ss.str("");
1325  // DAY and most non-chronologic
1326  if ( tmscl > ETime::INST ) {
1327  // new style with operator for data_csv, works well with stringstream
1328  //vol->NoChronologicAt(i) >> ( csv->NoChronologicAt(i) >> ss );
1329  ss << csv->NoChronologicAt(i) << vol->NoChronologicAt(i);
1330 
1331  // only INST, chronologic order
1332  } else {
1333  // new style operator <<
1334  //vol->ChronologicAt(i) >> ( csv->ChronologicAt(i) >> ss );
1335  ss << csv->ChronologicAt(i) << vol->ChronologicAt(i);
1336  }
1337  // write to file and check it is correct
1338  file << ss.str() << std::endl;
1339  if ( file.fail() ) {
1340  std::cout << "\n Failed in writing, big error, disk space ??" << std::endl;
1341  throw StockFileError( name, FileError ( filename, "Fail in writing into the file ! Disk space error ??") );
1342  }
1343  // or check only good at the end ?
1344  }
1345 #ifdef DEBUG_CPP
1346  std::cout << "End Stock::WriteCSV" << std::endl;
1347 #endif
1348 
1349  return;
1350 }
1351 
1352 // save file without loosing data, main point !
1353 // empty List no point ? UpdateFromFile before or UpdateFromWeb (List at least exists)
1354 // UpdateFromServer, same the last data are loaded
1355 // if required, creates a tmp_stock with all data (+new data??) and writes all, tricky to combine ?
1356 // can read tmp_stock from first to lb->First(), and AddToList( this->List ) (will append, but no need to delete this->List after)
1357 int Stock::SaveCSV ( const ETime tmscl, bool opt_tmp ) const
1358 {
1359 #ifdef DEBUG_CPP
1360  std::cout << "\n Stock::SaveCSV tmscl " << tmscl << std::endl;
1361  std::cout << "opt_tmp " << opt_tmp << std::endl;
1362 #endif
1363 
1364  assert( tmscl != ETime::not_a_time);
1365 
1366  ListDataStockBase *lb;
1368 
1369  if ( tmscl == ETime::INST ) {
1370  lb = GetListData( tmscl, Indicator::StockInst );
1371  } else {
1372  lb = GetListData( tmscl, Indicator::StockCSV );
1373  }
1374 
1375  Read_HeaderCSV( tmscl, dates_header );
1376  /*
1377  std::cout << "First Time header " << Utils::Time_tToString( dates_header.first ) << std::endl;
1378  std::cout << "Last Time header " << Utils::Time_tToString( dates_header.last ) << std::endl;
1379  */
1380 
1381  // if loaded in memory, need to be sure all data are present before overwriting the file
1382  // should be called by UpdateParserFromWeb (DAY)
1383  // or general before closing (? not really)
1384  if ( lb == nullptr ) {
1385  std::cout << "List is not loaded in memory, nothing to do, return -1" << std::endl;
1386  return -1;
1387  }
1388 
1389  // else if no new data to add, nothing to do
1390  // check size ? lb->GetSize() > 0
1391  /*
1392  std::cout << "List is loaded in memory " << std::endl;
1393  std::cout << "GetFirstTime " << Utils::Time_tToString( lb->GetFirstTime(), true ) << std::endl;
1394  std::cout << "LastUpdate() " << Utils::Time_tToString( lb->LastUpdate(), true ) << std::endl;
1395  */
1396 
1397  // if header == Last, nothing to do. UpdateFromServer to check (Progress DAY)
1398  // Progress DAY, need a general check, IsLastDataOver() ? Check with today ? Hour 00:00:00 ?
1399  if ( dates_header.last == lb->LastUpdate() ) {
1400 #ifdef DEBUG_CPP
1401  std::cout << "Header is Up to date, return -1" << std::endl;
1402 #endif
1403  return -1;
1404  }
1405 
1406  // possible Update, but a sub-range is loaded. but UpdateFromWeb return CANNOT_UPDATE,
1407  // HERE would need an other parameter, ListDataStock *to_add for this case
1408 
1409  // all in memory just write the data
1410  // Case UpdateFromWeb with DAY,
1411  // UpdateFromFile with INST no point, UpdateFromFile with DAY (no point also, file is up to date)
1412  if ( ( dates_header.first == lb->GetFirstTime() ) &&
1413  ( dates_header.last <= lb->LastUpdate() ) ) {
1414 #ifdef DEBUG_CPP
1415  std::cout << "Ok dates first== && last >, after an update can write and return" << std::endl;
1416 #endif
1417  WriteCSV( tmscl, opt_tmp );
1418  return 0;
1419  }
1420 
1421  // case first data are missing in-memory, need a tmp_stock
1422  // Case UpdateFromWeb with DAY
1423  if ( ( dates_header.first < lb->GetFirstTime() ) &&
1424  ( dates_header.last < lb->LastUpdate() ) ) {
1425 #ifdef DEBUG_CPP
1426  std::cout << "First dates are missing, need a tmp_stock trick ! " << std::endl;
1427 #endif
1428 
1429  int status_ll, status_al;
1430  // tmp stock, will contain missing and new values
1431  Stock *tmp_stock = new Stock( name );
1432 
1433  // read only the missing data from file
1434  dates_header.last = lb->GetFirstTime();
1435 
1436  //Load all first missing data in lb
1437  if ( tmscl >= ETime::M5 )
1438  status_ll = tmp_stock->LoadListData ( tmscl, Indicator::StockCSV, std::vector<int>{}, dates_header );
1439  else
1440  status_ll = tmp_stock->LoadListData ( tmscl, Indicator::StockInst, std::vector<int>{}, dates_header );
1441 
1442  if ( status_ll ) {
1443  std::cout << "Error in loading data in tmp_stock, return -1" << std::endl;
1444  return -1;
1445  }
1446  //std::cout << "Before Adding new data" << std::endl;
1447  //tmp_stock->PrintMapChrono(1);
1448 
1449  // Update INST or DAY data, sure Order is correct here ?
1450  if ( tmscl >= ETime::M5 )
1451  status_al = tmp_stock->AddListDataToMap( tmscl, GetListData( tmscl, Indicator::StockCSV ) );
1452  else
1453  status_al = tmp_stock->AddListDataToMap( tmscl, GetListData( tmscl, Indicator::StockInst ) );
1454  /*
1455  if ( status_al != 1 ) {
1456  std::cout << "Stock::SaveCSV expects always an update " << std::endl;
1457  }*/
1458  assert (status_al == 1);
1459 
1460  // for all timescale Volume
1461  status_al = tmp_stock->AddListDataToMap( tmscl, GetListData( tmscl, Indicator::Volume ) );
1462  /*
1463  if ( status_al != 1 ) {
1464  std::cout << "Stock::SaveCSV expects always an update " << std::endl;
1465  }*/
1466  assert (status_al == 1);
1467 
1468  //std::cout << "After Adding new data" << std::endl;
1469  //tmp_stock->PrintMapChrono(1);
1470  tmp_stock->WriteCSV( tmscl, opt_tmp );
1471 
1472  // delete tmp_stock after writing all data
1473  delete tmp_stock; tmp_stock = nullptr;
1474 
1475  }
1476  return 0;
1477 }
1478 
1479 // Read only the first line, and then close the file.
1480 // Could be static, called from outside and send back explicitly all info, to see from GUI
1481 // Made Read_HeaderCSV_static, to replace this function
1482 //
1483 // return value to delete ? now Exception
1484 // ?? optional ifstream, if empty open and close
1485 // To be static need to add the name of the stock (and the path) makes sense ? yes if stock is not needed
1486 // At the moment only called by TransDateBox, now more but all in Stock (wrap construct object only for calling this function)
1488  throw ( StockFileError )
1489 {
1490 #ifdef DEBUG_CPP
1491  std::cout << "Read_HeaderCSV version with timescale " << std::endl;
1492 #endif
1493  std::string filename;
1494  std::string line;
1495 
1496  // all in one directory now
1497  filename = path + "/historical/"+ name +"."+ TimeScale::GetTimeScaleName(tmscl) + ".csv";
1498  #ifdef DEBUG_CPP
1499  std::cout << "read filename " << filename << std::endl;
1500  #endif
1501 
1502  // default, read normally
1503  std::ifstream file( filename.c_str() );
1504  if ( file.fail() ) {
1505 #ifdef DEBUG_EXCEPT
1506  std::cout << "Opening failed, will create and throw a StockFileError " << std::endl;
1507 #endif
1508  throw StockFileError ( name, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(), FileOpenError ( filename) );
1509  }
1510  // maybe a return value or exception ?? to check
1511  std::getline( file, line );
1512  // move logic of reading data in one function, can deal with version
1513  ReadLineHeader( line, dates );
1514  // file close out of scope
1515  return 0;
1516 }
1517 
1518 // static version for test, use Utils::PATH_DATA may be an argument
1519 int Stock::Read_HeaderCSV_static( std::string namestock, ETime tmscl, Utils::firstlast_dates & dates )
1520  throw ( StockFileError )
1521 {
1522 #ifdef DEBUG_CPP
1523  std::cout << "Read_HeaderCSV_static " << std::endl;
1524 #endif
1525  std::string filename;
1526  std::string line;
1527 
1528  // all in one directory now
1529  filename = Utils::GetPathData() + "/historical/"+ namestock +"."+ TimeScale::GetTimeScaleName(tmscl) + ".csv";
1530  #ifdef DEBUG_CPP
1531  std::cout << "read filename " << filename << std::endl;
1532  #endif
1533 
1534  // default, read normally
1535  std::ifstream file( filename.c_str() );
1536  if ( file.fail() ) {
1537 #ifdef DEBUG_EXCEPT
1538  std::cout << "Opening failed, will create and throw a StockFileError " << std::endl;
1539 #endif
1540  throw StockFileError ( namestock, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(), FileOpenError ( filename) );
1541  }
1542  // maybe a return value or exception ?? to check
1543  std::getline( file, line );
1544 
1545  // move logic of reading data in one function, can deal with version
1546  // need to be static as well
1547  ReadLineHeader( line, dates );
1548 
1549 
1550  // file close out of scope
1551  return 0;
1552 }
1553 
1554 
1555 int Stock::UpdateCSV_Inst( std::string namestock, DataStock& inst_value, DataStock& inst_volume, ETime tmscl, bool opt_tmp )
1556  throw ( StockFileError )
1557 {
1558  // file to output, open a new file return fail
1559  std::fstream file;
1560  // if ofstream open creates a new file
1561  //std::ofstream file;
1562  std::string filename;
1563  std::string line;
1566  // default false, set to true if fail in opening
1567  bool new_file = false;
1568  //for float or double or int or timescale to string, in/out important for formatting (align right !!)
1569  std::stringstream ss (std::stringstream::in | std::stringstream::out);
1570  // for header
1571  std::ostringstream ss_header;
1572 
1573  assert( tmscl != ETime::not_a_time);
1574  assert( tmscl == ETime::INST );
1575 
1576  // default
1577  if ( opt_tmp == false )
1578  filename = Utils::GetPathData() + "/historical/"+ namestock +"."+ TimeScale::GetTimeScaleName(tmscl) + ".csv";
1579  // for test, output in a different directory to not overwrite
1580  else
1581  filename = Utils::GetPathData() + "/historical_tmp/"+ namestock +"."+ TimeScale::GetTimeScaleName(tmscl) + ".csv";
1582 
1583 #ifdef DEBUG_CPP
1584  std::cout << "update csv INST filename :" << filename << std::endl;
1585 #endif
1586 
1587  // open for reading / writing, and will create if necessary.
1588  file.open ( filename.c_str() );
1589  if ( !file.is_open() ) {
1590  // to create a new file, need trunc flag as well
1591  file.open ( filename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::trunc );
1592  assert ( file.good() == true );
1593  new_file = true;
1594  }
1595 
1596  // default dates from the data
1597  dates_data.first = inst_value.GetDate();
1598  dates_data.last = inst_value.GetDate();
1599 
1600  // create the file, write header and data
1601  if ( new_file ) {
1602  // create header in stringstream, same for dcsv
1603  WriteLineHeader( tmscl, dates_data, ss_header );
1604  // write to file, line or stream
1605  file << ss_header.str() << std::endl;
1606  // write values
1607  ss << inst_value << inst_volume << std::endl;
1608  file << ss.str();
1609 
1610  // append data to file and modify the header
1611  } else {
1612  // read the first line: header, check if file empty (should not exist and be empty)
1613  std::getline( file, line );
1614  // test correct, not empty
1615  if ( file.fail() ) {
1616  #ifdef DEBUG_CPP
1617  std::cout << "Get first line failed, throw exception " << std::endl;
1618  #endif
1619  throw StockFileError ( namestock, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(), FileEmptyError( filename ) );
1620  }
1621 
1622  // return 0 ok, or error
1623  if ( ReadLineHeader( line, dates_header ) ) {
1624 #ifdef DEBUG_CPP
1625  std::cout << "Error return from ReadLineHeader " << std::endl;
1626 #endif
1627  // Read Error exception, header is line 1
1628  throw StockFileError ( namestock, TimeScale::GetTimeScaleName(tmscl), Indicator::StockCSV.label(),
1629  FileReadError( filename, 1 ) );
1630  }
1631 
1632  // Check no simple mistakes in the update, return -1 if dates are identical
1633  // Check here on in python ?? python should decide to write or not, but can add simple test
1634  dates_data.first = dates_header.first;
1635  if ( dates_header.last > dates_data.last ) {
1636  std::cout << "Error Stock::UpdateCSV_Inst dates are wrong " << std::endl;
1637  return -1;
1638  }
1639 
1640  if ( dates_header.last == dates_data.last ) {
1641  std::cout << "Warning Stock::UpdateCSV_Inst dates last identical with present in header!!!" << std::endl;
1642  return -1;
1643  }
1644 
1645  // erase header at the beginning of the file
1646  file.seekg(0, std::ios::beg);
1647  WriteLineHeader( tmscl, dates_data, ss_header );
1648  file << ss_header.str();
1649  // append data at the end of the file
1650  file.seekg(0, std::ios::end);
1651  ss.str("");
1652  ss << inst_value << inst_volume << std::endl;
1653  file << ss.str();
1654  }
1655 
1656  return 0;
1657 }
1658 
1660 // long int better for python, correct for C++ but not good for internal, changed in wrapper
1661 
1662 // indicator not really needed(parameter missing), apply only StockCSV DAY or INST, deleted
1663 //
1664 // may keep an option force to load, convenient for other Updates functions
1665 //
1666 // If only ReadHeader, no point... call Read_HeaderCSV, but Header may not be up to date
1667 // If can read in memory and in header better
1668 // maybe good point compared to ReaderHeader_CSV, can check in-memory in-file consistency...
1669 //
1670 
1671 // This logic applies to SaveTimeScale (saving data to file), not for update
1672 // Check than last date in header < in-memory : Means a sub-part of the list has been loaded.\n
1673 // Cannot make any update !! return 0 ? Could have an explicit Error return, user should know why
1674 // Exception will stop the process
1675 // Same for first date, can update but may he problem to save the file. An other problem for write!
1676 
1677 // FILE is up-to-date !!
1678 // Wrong can update from file from the last in-memory ! will read more data that's all !
1679 // Same with first date, will be still missing in-memory, but file is OK.
1680 // It is what the user expects ? Maybe not, but should not done automatically or GUI message before running
1681 //
1682 // last = Header last
1683 // If in memory get last from it
1684 // else If load_list == true load the file, and get date from the data
1685 //
1686 //
1687 
1688 // To delete, Read_Header when needed, Load by default ? really useful ?
1689 //time_t Stock::LastCSVUpdate(ETime tmscl, Indicator indic) throw(StockException)
1690 /*
1691 time_t Stock::LastCSVUpdate(ETime tmscl, bool load_list ) throw(StockException)
1692 {
1693 #ifdef DEBUG_CPP
1694  std::cout << "LastCSVUpdate tmscl " << tmscl << std::endl;
1695 #endif
1696  //int status;
1697  time_t last_time = (time_t)0;
1698  time_t last_time_memory = (time_t)0;
1699 
1700  // should not happen, or correctly return 0
1701  //assert ( ( (tmscl == ETime::DAY ) || ( tmscl == ETime::INST ) ) == true );
1702  if ( ( (tmscl == ETime::DAY ) || ( tmscl == ETime::INST ) ) == false ) {
1703  std::cout << "Error tmscl is not valid " << tmscl << std::endl;
1704  return 0;
1705  }
1706 
1708  Utils::firstlast_dates fldates_header;
1709  //Utils::firstlast_dates fldates_memory_dm = Utils::get_fldate_default();
1710 
1711  try {
1712  Read_HeaderCSV ( tmscl, fldates_header );
1713  last_time = fldates_header.last;
1714  } catch ( StockFileError & e){
1715  std::cout << "Stock::LastCSVUpdate caught StockFileError " << std::endl;
1716  //throw StockException( e );
1717  throw;
1718  }
1719 
1720  // make indicator here, maybe later extend to other indicators ??
1721  Indicator indic = Indicator::Null;
1722  if ( tmscl == ETime::INST )
1723  indic = Indicator::StockInst;
1724  else
1725  indic = Indicator::StockCSV;
1726 
1727  // if data in memory, load_list has no effect
1728  if ( CheckLoaded( tmscl, indic) ) {
1729  // date from data member
1730  //fldates_memory_dm = GetListData( tmscl, indic )->GetDates();
1731  // use from data rather
1732  last_time_memory = GetListData( tmscl, indic )->LastUpdate();
1733  // ok works
1734  if ( last_time > last_time_memory ) {
1735  // ok pass existing unit-tests
1736  std::cout << "\nERROR Stock::LastCSVUpdate last header > last memory, cannot proceed to an update \n" << std::endl;
1737  //exit(1);
1738  return 0;
1739  }
1740  last_time = last_time_memory;
1741 
1742  // force to load the data in memory
1743  } else if ( load_list ) {
1744 
1745  try {
1746  // here date header and memory are identical for sure
1747  LoadListData(tmscl,indic);
1748  assert ( last_time == GetListData( tmscl, indic )->LastUpdate() );
1749  //fldates_memory_dm = GetListData( tmscl, indic )->GetDates();
1750  last_time = GetListData( tmscl, indic )->LastUpdate();
1751  } catch (StockException & e) {
1752  throw;
1753  // ok, pass existing unit-tests
1754  if ( last_time != fldates_header.last ) {
1755  std::cout << "\nERROR Stock::LastCSVUpdate\n" << std::endl;
1756  exit(1);
1757  }
1758  }
1759  }
1760  // else do nothing and last from header
1761 
1762 #ifdef DEBUG_CPP
1763  std::cout << "Stock::LastCSVUpdate From header " << Utils::Time_tToString ( fldates_header.last , true ) << std::endl;
1764  //std::cout << "From memory data member " << Utils::Time_tToString ( fldates_memory_dm.last, true ) << std::endl;
1765  std::cout << "Stock::LastCSVUpdate From header or memory return last " << Utils::Time_tToString ( last_time, true ) << std::endl;
1766 #endif
1767  // from header, or if present, in-memory
1768  return last_time;
1769 
1770  // original implementation, force to load the data
1772  // if not available yet, load from disk by default ! what we want ??
1773  if ( !CheckLoaded(tmscl,indic) ) {
1774  std::cout << "Stock::LastCSVUpdate force to load data tmscl " << GetTimeScaleName(tmscl) << " " << indic.label() << std::endl;
1775  //status = LoadListData(tmscl,indic);
1776  // exception not needed, will throw the exception anyway "!
1777  //try {
1778  LoadListData(tmscl,indic);
1779  //} catch (StockException & e) {
1780  // throw;
1781  //}
1782  }
1783  //now loaded, keep base and use virtual
1784  ListDataStockBase *ldata = GetListData( tmscl, indic );
1785  last_time = ldata->LastUpdate();
1787 #ifdef DEBUG_CPP
1788  std::cout << "Stock::LastCSVUpdate last_time = " << last_time << std::endl;
1789 #endif
1790  return last_time;
1791 }
1792 */
1793 
1794 
1795 // call by StockManger when a new TCP message has been received
1796 // to Inform than new data have been provided ( Inst now, later can be csv as well )
1797 // Call UpdateAllTimeScale, specifying the data must not been read from file.
1798 // All other indicator update, recomputation similar
1799 void Stock::Updated( const ETime tmscl )
1800 {
1801 #ifdef DEBUG_CPP
1802  std::cout << "Entry Stock::Updated tmscl " << tmscl << std::endl;
1803  std::cout << "(TimeScale) dcsv: " << ETime::INST << std::endl;
1804  std::cout << "(TimeScale) M5: " << ETime::M5 << std::endl;
1805 #endif
1806 
1807  assert( tmscl != ETime::not_a_time);
1808 
1809  ETime tmscl_to_update;
1810  // no used need only the argument
1812 
1813  if ( tmscl < ETime::DAY ) {
1814 
1815 #ifdef DEBUG_CPP
1816  std::cout << "Need to update all indic between INST and H1" << std::endl;
1817 #endif
1818 
1819  // loop over the timescale and check it is in memory
1820  for ( unsigned int i= as_uint(ETime::M5); i < as_uint(ETime::DAY); ++i ) {
1821 
1822  // alternative, http://stackoverflow.com/questions/261963/c-iterate-through-an-enum
1823  tmscl_to_update = static_cast<ETime>( i );//i; //static_cast<ETime>( i );
1824  std::cout << "tmscl_to_update " << as_uint(tmscl_to_update) << std::endl;
1825 
1826  // test if entry tmscl exists, not working ??
1827  //if ( GetItMap( tmscl_to_update ) != mapTime_ListData.end() ) {
1828  if ( mapTime_ListData.find( tmscl_to_update ) != mapTime_ListData.end() ) {
1829  // update all indicator at this specific timescale
1830  UpdateAllTimeScale( tmscl_to_update, tmp_date, false );
1831 
1832  }
1833  /* else {
1834  std::cout << "Stock::Updated this indicator is not loaded " << std::endl;
1835  } */
1836  }
1837  } else {
1838  std::cout << "\n Need to update all indic between DAY and year not implemented yet \n" << std::endl;
1839  }
1840 
1841 }
1842 
1843 // Update all ListDataStock of the given TimeScale.
1844 //
1845 // Problem reading of the file by default, not needed if update from TCPServer.
1846 // Need optional argument b_readfile or make a check with the date ( dates may be good ).
1847 // or split in 2 functions but not so clear..
1848 // Advantage in 1 function use b_readfile
1849 //
1850 //
1851 // Both of theses function call LastCSVUpdate:
1852 // If StockCSV and tmscl >= DAY
1853 // call on UpdateCSVFromParser( "Yahoo" ) and Transform_TimeScale
1854 // StockCSV and tmsc < DAY
1855 // UpdateCSVFromFile ( Indicator::StockInst, dcsv ) and Transform_TimeScale
1856 //
1857 //
1858 //
1859 // Case StockInst not taken into account: no need ? at least CSV 5mn...
1860 //
1861 // UpdateCSVFromParser, read header
1862 // download data from Yahoo from last_day to today, add to ListDataStock and write into file
1863 //
1864 // UpdateCSVFromFile, only readCSV ( dcsv in this case ).
1865 // This file is kept up to date only by real time
1866 //
1867 // loop over all the map entry.
1868 // only use python Yahoo_CSV class at the moment.
1869 //
1870 // todo : call to bourso ?? partly done within RealTime ?
1871 // return size of ListData StockCSV, the largest one, not implemented.
1872 //
1873 // b_readfile : allow to check for update from file or from web
1874 // if false (as used now) only recompute TA indicator in memory, for sure more efficient !
1875 //
1876 // useful to get exception from this call, action from GUI to catch
1877 // maybe more work to get the exception (From PyWrapper), but could create them here
1878 
1879 // only called by Updated with b_readfile to false (apply only to Inst up to now)
1880 // ok, go it, it is now used to only recompute TA indicators
1881 // (StockInst updated by Server, DAY updated by direct call to UpdateFromParser) name is wrong ! or use is wrong !
1882 // ReadCSV throw exception, should specify here (rules: no or all)
1883 
1884 // maybe not bad to have bool argument: b_update_from_file, b_update_from_web
1885 // if server, normally need UpdateFromWeb only once a DAY, not regularly for DAY
1886 // got INST value regularly, must recompute TA Indicators
1887 // if no_server : Must UpdateFromFile regularly (INST) (ServerPortfolio running, server not running, no normal)
1888 // Must UpdateFromWeb only once a DAY (Later can replace server with call to Bourso if ServerPortfolio is not running)
1889 //
1890 // option : b_update_by_server b_server running
1891 // or send the data (INST, DAY?) if server is running (got from the queue)
1892 void Stock::UpdateAllTimeScale( ETime tmscl, Utils::firstlast_dates opt_dates, bool b_readfile )
1893 {
1894 #ifdef DEBUG_CPP
1895  std::cout << "\n\t Entry Stock::UpdateAllTimeScale: " << tmscl << std::endl;
1896  std::cout << "opt_dates first/last " << opt_dates.last << std::endl;
1897 #endif
1898 
1899  // get the list of this timescale
1900  it_map it_m = mapTime_ListData.find( tmscl );
1901  // still need to test, return only an iterator
1902  // should be safe here
1903  /*
1904  if ( it_m == mapTime_ListData.end() ) {
1905  std::cout << "GetItMap is at the end in UpdateAllTimeScale, return " << std::endl;
1906  return; -1 for nothing has been done ?
1907  }*/
1908 
1909  // key tmscl does not exist, still continue and so can read files ! but next iteraotr will crash !
1910 
1911  // return value of ReadCSV when reading new data (file or Parser_Stock)
1912  unsigned int new_added_size = 0;
1913  //by default it is done, false if error or not new data in Stock
1914  bool recompute = true;
1915  // return value of Transform_TimeScale
1916  int status_tt;
1917  std::string name_indic;
1918  // make a list, for indicator to recompute (possible OpenMP)
1919  std::vector< std::string > vec_indic;
1920 
1921  // more useful if set full dates first/last for use with Yahoo, upload from introduction
1922  // and default value of now.
1923  if ( opt_dates.last == 0 ) {
1924  opt_dates.last = time ( NULL );
1925 #ifdef DEBUG_CPP
1926  std::cout << "opt_date set up to now by call to time(NULL) " << std::endl;
1927 #endif
1928  }
1929 
1930  // Loop over the ListData, treat StockCSV and Volume first.
1931  // Store other in vec_indic to recompute after the loop
1932  for ( it_listdata it_l = it_m->second.begin(); it_l != it_m->second.end() ; it_l++ ) {
1933  std::cout << " name listdata " << (*it_l)->GetName() << std::endl;
1934  name_indic = (*it_l)->GetName();
1935 
1936  // indicator present now in listdata as well
1937  if ( ( name_indic == "StockCSV" ) || ( name_indic == "StockInst") ) {
1938 
1939  // add option here, if already updated do not need to read the file
1940  // strange here, this function is called only by Updated ? b_readfile is set to false so never used
1941 
1942  // b_server is off, may be possible to update
1943  // more logic server_off && ServerPortfolio running
1944  if ( b_readfile ) {
1945 
1946 #ifdef DEBUG_CPP
1947  std::cout << "b_readfile is true " << std::endl;
1948 #endif
1949  // This should not be called regularly (For DAY), or quick check
1950  // if server off, can call Bourso to update INST later (case server off,ServerPortfolio not running)
1951  if ( tmscl >= ETime::DAY ) {
1952  std::cout << " UpdateCSV, Yahoo, data and volume " << std::endl;
1953  //call wrapper python, change return new_size of (already added) data, if null, nothing to transform
1954 
1955  // throw a specific exception here, problem with Network, with parsing...
1956  // not sure very useful call to Web now.
1957  try {
1958  new_added_size = UpdateCSVFromWeb( "Yahoo", opt_dates );
1959  //} catch ( StockPythonException )
1960  } catch ( StockException & e ) {
1961  std::cout << "Caught an exception " << std::endl;
1962  // something to delete ? seems not ?
1963  // rethrow
1964  throw;
1965  }
1966 
1967  // If server off, but ServerPortfolio running, can read file regularly (INST)
1968  // For DAY, same for Progress DAY, consider INST is loaded
1969  } else {
1970  std::cout << " Update INST, (Bourso to do?) Read from file *dcsv " << std::endl;
1971  // first Update_dCSV, to check for the size
1972  new_added_size = UpdateCSVFromFile ( ETime::INST );
1973  }
1974 
1975  // strange check, should agree on the retour new_added_size
1976  // common check
1977  //if == 0 it is ok, nothing to add, -1 an error
1978  //if ( ( new_added_size == -1 ) || ( new_added_size == 0 ) ) {
1979  // UpdateFromFile will throw exception if problem, size 0 means nothing new found
1980  // FromWeb return -1, change to return 0, need to implement throw Exceptino
1981  if ( new_added_size == 0 ) {
1982  //std::cout << " return Python new_added_size == " << new_added_size << std::endl;
1983  std::cout << "\n\t UpdateAllTimeScale returned new_added_size == 0" << new_added_size << std::endl;
1984  recompute = false;
1985  // better with continue, maybe other set to update, other indicator
1986  //break; //ok, goes out directly to recompute, but no need to recompute if error
1987  continue;
1988  }
1989 
1990  } //end if b_readfile
1991 
1992 
1993  // all cases want to recompute the correct TimeScale
1994  if ( ( tmscl != ETime::DAY ) && ( tmscl != ETime::INST ) ) {
1995 #ifdef DEBUG_CPP
1996  std::cout << "Will call Transform_TimeScale tmscl= " << tmscl << std::endl;
1997 #endif
1998  // should make a test, something new ? here or in Transform
1999  status_tt = Transform_TimeScale( tmscl );
2000  // what to do here, no return value, no exception...
2001  if ( status_tt != 0 ) {
2002  std::cout << "\nERROR in Stock::UpdateAllTimeScale in TransformTimeScale !!\n" << std::endl;
2003  }
2004  }
2005  } //end StockCSV or StockInst
2006 
2007  //Volume done with StockCSV or StockInst by default
2008  else if ( name_indic == "Volume")
2009  continue;
2010 
2011  //all other indicators, may add case later, to recompute after the update of stock and volume only
2012  // can be updated by server, so to recompute often (independent of other update before)
2013  // ca ncheck NeedComputeTA()
2014  else {
2015 #ifdef DEBUG_CPP
2016  std::cout << "Add " << name_indic << " to the list of indicator to recompute " << std::endl;
2017 #endif
2018  vec_indic.push_back( name_indic );
2019  }
2020 
2021  //} //end if b_readfile
2022 
2023  } //end loop over listdata
2024 
2025 #ifdef DEBUG_CPP
2026  std::cout << "test to recompute other indicators, recompute: " << recompute << std::endl;
2027  //PrintMapChrono();
2028 #endif
2029 
2030  // main point of the function, Update HistoricalData could be done apart
2031  if ( recompute ) {
2032  //loop over the indicator to recompute
2033  //could be threaded to speed up, TAlib thread-safe, to see later
2034  for ( unsigned int i=0; i< vec_indic.size(); i++ ) {
2035  //keep local variable for thread ??
2036  std::string name_ind;
2037  Indicator new_indic(Indicator::Null);
2038  std::vector< int > vec_param;
2039 
2040  name_ind = FullName::GetNameStock( vec_indic[i] );
2041  //std::cout << "name_ind " << name_ind << std::endl;
2042  // Set vec_param, just for test...
2043  new_indic.Set( vec_indic[i], vec_param );
2044  /*
2045  if ( vec_param.size() > 0 ) {
2046  std::cout << " Recompute " << name_ind << " indic " << new_indic << " first arg " << vec_param[0] << std::endl;
2047  }
2048  */
2049  std::cout << "ComputeTA to test for exception" << std::endl;
2050  ComputeTA( tmscl, vec_indic[i] );
2051  //std::cout << "End ComputeTA" << std::endl;
2052 
2053  //here special AddListDataToMap, need to replace all data,
2054  // or done in ComputeTA, better
2055  }
2056  } //end recompute
2057 }
2058 
2059 
2060 // Load last data from the filesystem
2061 // Called by UpdateAllTimescale()
2062 // Call LastCSVUpdate
2063 // Was used when ServerPortfolio saved INST data to file. To check now with RealTime.
2064 //
2065 // ok for LastCSVUpdate, can get last date from file (with header), or from memory if available.
2066 // in fact, a check in header info could be done before...
2067 //
2069 {
2070  unsigned int new_size;
2071  // no need to initialize ? if error in ReadHeaderCSV ?
2072  Utils::firstlast_dates dates_header;
2073  // first is set to default, all data
2075  time_t last_in_memory = 0;
2076 
2077 #ifdef DEBUG_CPP
2078  std::cout << "\n\t Entry Stock::UpdateCSVFromFile tmscl " << tmscl << std::endl;
2079 #endif
2080 
2081  // assert for INST / DAY not really needed, may work on other if file exists !
2082  // throw exception if problem
2083  Read_HeaderCSV( tmscl, dates_header );
2084  //dates_to_load.last = dates_header.last;
2085 
2086  // could be avoid if parameter (as before)
2087  Indicator indic = Indicator::Null;
2088  if ( tmscl == ETime::INST )
2089  indic = Indicator::StockInst;
2090  else
2091  indic = Indicator::StockCSV;
2092 
2093  // if DAY Progress, may call intermediate rounding or test
2094  if ( CheckLoaded( tmscl, indic ) ) {
2095  last_in_memory = GetListData( tmscl, indic )->LastUpdate();
2096  dates_to_load.first = GetListData( tmscl, indic )->LastUpdate();
2097  }
2098 
2099  std::cout << "last in memory " << Utils::Time_tToString( last_in_memory, true) << std::endl;
2100  std::cout << "last header " << Utils::Time_tToString( dates_header.last, true) << std::endl;
2101 
2102  // return if not possible to update, already updated by server
2103  if ( last_in_memory > dates_header.last )
2104  return -1;
2105 
2106  // not in memory, read all
2107  new_size = ReadCSV( tmscl, dates_to_load );
2108 
2109 #ifdef DEBUG_CPP
2110  std::cout << "UpdateCSVFromFile ReadCSV return new_size " << new_size << std::endl;
2111 #endif
2112  return new_size;
2113 }
2114 
2115 // Stupid no point to read here !! already on disk, it is the logic for SaveTimeScale here !
2116 
2117 // - if cannot(first or last), we can create a tmp_stock_update, empty, ReadAll, NO need to write(file is updated), Delete tmp
2118 // retrurn a code to say do not recompute TA in-memory, in-memory not updated, only file
2119 // - if can, just call ReadCSV on this, return new_added data, recomputeTA
2120 
2121 // call with opt_dates == update, can add check in ReadCSV
2122 // original, always ReadCSV, even if it was in memory after LastCSVUpdate...
2123 // ReadCSV will now check if new data available
2124 
2125 
2126 // verbose is send directly to ListDataStock
2127 void Stock::PrintMapChrono( const unsigned int verbose ) const
2128 {
2129  std::cout << "===================\n\t ShowMap Stock Chrono " << GetName() << std::endl;
2130  std::cout << "Size " << mapTime_ListData.size() << std::endl;
2131 
2132  for( cit_map it_m = mapTime_ListData.begin(); it_m != mapTime_ListData.end(); it_m++) {
2133 
2134  std::cout << "timescale: " << it_m->first << std::endl;
2135  if ( (it_m->second).empty() ) {
2136  std::cout << " list data defined and empty" << std::endl;
2137  }
2138  else if ( (it_m->second).size() > 0 ) {
2139 
2140  std::cout << " list data defined, " << (it_m->second).size() << " pointeur on List " << std::endl;
2141  for( cit_listdata it_l= it_m->second.begin(); it_l !=it_m->second.end(); it_l++) {
2142  // call ListDataStock function
2143  std::cout << "\t========================" << std::endl;
2144  (*it_l)->PrintData( verbose );
2145  }
2146  }
2147  // done in ListDataStock now
2148  //else
2149  // std::cout << " list data with size == 0 " << std::endl;
2150  }
2151  std::cout << "\n" << std::endl;
2152  return;
2153 }
2154 
2155 
2156 
2157 /*
2158 //before int, need to use !!
2159 WaveletBase* Stock::ComputeWavelet( ETime tmscl ) //, std::string name_new_indic ) same problem as PatternRecognition...
2160 {
2161  std::cout << "Entry Stock::ComputeWavelet, tmscl " << tmscl << std::endl;
2162 
2163  //array of array for input, simpler pointer in this case
2164  double **arraydata_c_in = 0;
2165  //unsigned int size;
2166 
2167  //need to allocate first pointer first! reason of the bug !!
2168  arraydata_c_in = new double*[ 1 ];
2169 
2170  //need explicit ??
2171  //Indicator indic = Indicator::StockCSV;
2172  //by default get StockCSV, need dynamic_cast ?? why ??
2173  ListDataStock<DataCSV> *ldata = dynamic_cast< ListDataStock<DataCSV>* >(GetListData(tmscl,Indicator::StockCSV));
2174  // get close in double ??, need to allocate ??
2175  ldata->GetCArray( &(arraydata_c_in[0]), "Close");
2176  std::cout << " ldata->GetSize() " << ldata->GetSize() << std::endl;
2177 
2178  //should split creation, from computation, easier
2179  Haar *haar = new Haar( &(arraydata_c_in[0][0]), ldata->GetSize() );
2180 
2181  std::cout << " now compute Haar transform size " << haar->GetSize() << std::endl;
2182  //need size / 2 for recursive function
2183  //haar->Calc( haar->GetValues(), haar->GetSize()/2 );
2184  //add new interface
2185  haar->Transform();
2186 
2187  return haar;
2188 }
2189 */
2190 
ListDataStock< DataCSV, VecChronologic > ldata_candle
Define a default policy for candlestick.
Definition: typedef.h:26
Define the class Stock to deal with an unique stock: DJ, IBM...
int SaveCSV(const ETime tmscl, bool opt_tmp=false) const
Save Historical data to file.
Definition: Stock.cpp:1357
Define a list of DataStock objects.
Specific, inherit from FileError from utils.
virtual void AddData(DataStock &)=0
Add a copy of the DataStock into the ListDataStock.
"Clever" enumeration of the ListDataStock type : StockCSV, Volume, EMA, BOLL,...
Definition: Indicator.h:29
int nb_param() const
Nb of parameters necessary to be computed.
Definition: Indicator.cpp:68
void Set(std::string str_name, std::vector< int > &param)
Definition: Indicator.cpp:304
int UpdateCSVFromFile(const ETime tmscl)
Load the last historical data from the filesystem into a List in memory.
Definition: Stock.cpp:2068
static Indicator const Null
Predefined static instances of the class.
Definition: Indicator.h:44
int UpdateCSVFromWeb(const std::string &source, Utils::firstlast_dates opt_dates=Utils::get_fldate_default())
Update data from the Python parser (and save into the filesystem).
void SetLDataFullName(ListDataStockBase *p_listdata) const
Function to complete the fullname of a listdatastock.
Definition: Stock.cpp:258
virtual time_t LastUpdate() const =0
Get the date of the last data (always chronological meaning)
virtual int AddToList(const ListDataStockBase *)=0
Append all data from a new list ( coming from an Update or ReadCSV normally ) to an existing list...
ListDataStock< SimpleData, VecChronologic > ldata_volume
Volume has also one value.
Definition: typedef.h:38
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
Base class for error handling with files.
std::map< ETime, std::vector< ListDataStockBase * > >::iterator it_map
Definition: Stock.h:61
static int ReadLineHeader(const std::string &line, Utils::firstlast_dates &dates)
Extract dates from the header of the historic data files.
Definition: Stock.cpp:116
ListDataStock< SimpleData, VecChronologic > ldata_dcsv
dcsv is for instantateneous values, only one value
Definition: typedef.h:36
std::vector< ListDataStockBase * >::iterator it_listdata
Definition: Stock.h:63
const T & NoChronologicAt(const unsigned int offset) const
Get nth element in a non chronological order.
Base Exception for Stock and StockManager, all src_cpp code.
std::map< ETime, std::vector< ListDataStockBase * > >::const_iterator cit_map
Definition: Stock.h:62
bool IsEmpty() const
Test if some ListData are still present, whatever the timescale.
Definition: Stock.cpp:567
Use a policy PolicyChronologic, default VecNoChronologic.
static Indicator const AD
Definition: Indicator.h:44
Specific class when the file cannot be found and opened.
std::string GetNameStock(const std::string &fname)
Extract the name of the stock.
Definition: FullName.cpp:46
void UpdateAllTimeScale(const ETime tmscl, Utils::firstlast_dates opt_dates=Utils::get_fldate_default(), bool b_readfile=true)
Update all indicators of the given TimeScale.
Definition: Stock.cpp:1892
Main class to deal with one stock.
Definition: Stock.h:56
Data type to describe Japanese candlesticks : open, high, low and close values.
Definition: DataStock.h:502
auto as_uint(ETime const value) -> unsigned int
Provides explicit conversion to unsigned int.
Definition: TimeScale.h:59
virtual time_t GetFirstTime() const =0
Get the date of the first data (always chronological meaning)
for dealing with error in reading, problem of formatting for instance
int AddListDataToMap(const ETime &tmscl, ListDataStockBase *p_listdata)
Insert a ListDataStock to the map.
Definition: Stock.cpp:622
const time_t ERROR_StrToTime
Error code returned by StringToTime_t if the string cannot be parsed correctly Must be a time_t...
Definition: Utils.h:51
virtual const char * what() const noexcept
for getting the message with standard interface do not throw exception
Wrapper/Adapter to the library ta-lib.
Definition: TAlibAPI.h:74
virtual void Order(const EPChrono chrono)=0
Function to reverse the internal vector in its original policy.
std::vector< ListDataStockBase * >::const_iterator cit_listdata
Definition: Stock.h:64
Indicator GetIndicator(const std::string &sname)
Extract the indicator from a frame name.
Definition: FullName.cpp:103
void DeleteListData(const ETime &tmscl, const Indicator &indic, std::vector< int > param=std::vector< int >())
Delete a list given the TimeScale, Indicator and param.
Definition: Stock.cpp:872
virtual void Replace(const ListDataStockBase *)=0
Replace all DataStock's of the list with ldata_in.data, without checking for update.
static void WriteLineHeader(const ETime &tmscl, const Utils::firstlast_dates &dates, std::ostringstream &ss_header)
Write the header in a stream.
Definition: Stock.cpp:159
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
int nb_output() const
Nb of ListDataStock output of TALib computation.
Definition: Indicator.cpp:78
int Transform_TimeScale(const ETime &new_tmscl)
Transform history values dcsv or DAY to M5,M10..H1 or WEEK, MONTH..YEAR.
Definition: Stock.cpp:273
static Indicator const StockInst
Definition: Indicator.h:44
ListDataStock< SimpleData, VecChronologic > ldata_ta_sd
For technical indicator, TAlib process and return always chronologic data.
Definition: typedef.h:40
ListDataStockBase * GetListData(const ETime &tmscl, const Indicator &indic, const std::vector< int > param=std::vector< int >()) const
Get the ListDataStock from a TimeScale, Indicator and vector of parameters.
Definition: Stock.cpp:581
void LoadCSVData(const ETime &tmscl, Utils::firstlast_dates &dates)
Get Indicator::StockCSV or StockdCSV with the correct TimeScale Call functions to read and load data ...
Definition: Stock.cpp:177
virtual Utils::firstlast_dates GetDates() const
Return the structure Utils::firstlast_dates of the private data member, not from the data...
Definition: ListDataStock.h:87
std::string toString(const T &t)
Definition: Utils.h:69
virtual const DataStock & ChronologicAt(const unsigned int offset) const =0
Get the nth element in a chronological order.
void WriteCSV(const ETime tmscl, bool opt_tmp=false) const
Write historical data into files.
Definition: Stock.cpp:1247
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
bool CheckLoaded(const ETime &tmscl) const
Definition: Stock.cpp:529
ListDataStock< MultiData, VecChronologic > ldata_ta_md
For dealing with multiple values, e.g., MACD.
Definition: typedef.h:42
virtual void SetData(const time_t d, const std::vector< type_value_data > &vec)
Set a full Data : date + value(s) in a vector.
Definition: DataStock.h:366
Stock()
Default constructor.
Definition: Stock.h:198
virtual ~Stock()
Definition: Stock.cpp:47
time_t StringToTime_t(const std::string &str_date)
Return the time_t from a string .
Definition: Utils.cpp:93
Specific for TALib part of the code.
void MergeStock(const Stock *new_stock, bool)
Merge entries with an other stock.
Definition: Stock.cpp:730
unsigned int ReadCSV(const ETime tmscl, Utils::firstlast_dates dates=Utils::get_fldate_default())
Read DAY or INST file depending on the TimeScale.
Definition: Stock.cpp:957
std::string GetTimeScaleName(const ETime &tmscl)
Get the string, i.e., "DAY".
Definition: TimeScale.cpp:24
std::string GetPathData()
Definition: Utils.cpp:42
int ComputeTA(const ETime &tmscl, const std::string &name_indic)
Compute an indicator using the TAlib library.
Definition: Stock.cpp:352
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.
virtual void SetDates(const time_t first, const time_t last)
Set dates, 2 arguments.
Definition: ListDataStock.h:93
virtual const char * what() const noexcept
static Indicator const StockCSV
Definition: Indicator.h:44
std::string GetName() const
Definition: ListDataStock.h:78
virtual std::string GetFullName() const
Definition: ListDataStock.h:79
Abstract base class for the ListDataStock, for storing base pointers in vectors.
Definition: ListDataStock.h:50
void Updated(const ETime tmscl)
Return the last available date of historical data.
Definition: Stock.cpp:1799
void DeleteAllListData(const ETime &tmscl)
Delete all data of the given TimeScale.
Definition: Stock.cpp:916
TAlibAPI * p_talib
pointer to TA-lib API object, use a lazy initialization of the library
Definition: Stock.h:89
void PrintMapChrono(const unsigned int verbose=0) const
Print map content to the console.
Definition: Stock.cpp:2127
Base class for exception coming from talibapi interface.
time_t GetDate() const
Get the date data member.
Definition: DataStock.h:126
virtual void SetFullName(std::string fname)
Definition: ListDataStock.h:83
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::map< ETime, std::vector< ListDataStockBase * > > mapTime_ListData
map TimeScale : vector of ListDataStockBase pointers
Definition: Stock.h:92
static int Read_HeaderCSV_static(std::string namestock, ETime tmscl, Utils::firstlast_dates &dates)
Static version of Read_HeaderCSV.
Definition: Stock.cpp:1519
int LoadListData(const ETime &tmscl, const Indicator &indic=Indicator::StockCSV, const std::vector< int > &param=std::vector< int >(), Utils::firstlast_dates dates=Utils::get_fldate_default())
Load or/and compute an indicator in the Stock.
Definition: Stock.cpp:801
API for using TA_lib of X in ROOT_Application.
cit_listdata GetItList(cit_map &it_m, const Indicator &indic, const std::vector< int > &param=std::vector< int >()) const
Definition: Stock.cpp:72
int Read_HeaderCSV(ETime tmscl, Utils::firstlast_dates &dates) const
Read the dates from the header file.
Definition: Stock.cpp:1487
static int UpdateCSV_Inst(std::string namestock, DataStock &inst_value, DataStock &inst_volume, ETime tmscl, bool opt_tmp=false)
Update file with TimeScale INST.
Definition: Stock.cpp:1555
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
void splitline(const std::string &str, const std::string &delimiters, std::vector< std::string > &tokens)
splitline
Definition: Utils.cpp:56
general structure for dates in csv files
Definition: Utils.h:54
std::string symbol
symbol refers to the code, i.e., CAC40
Definition: Stock.h:77
File included by Stock.cpp, Function for embedding python in Stock class.
add my own, if file is empty really or empty of data
std::string GetName() const
Definition: Stock.h:210
const std::string path
Abstract base class for all Data to be stored in ListDataStock.
Definition: DataStock.h:90
std::string const label() const
Get the label.
Definition: Indicator.cpp:51
std::string name
Name of the stock.
Definition: Stock.h:71
const T & ChronologicAt(const unsigned int offset) const
Get the nth element in a chronological order.
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...