14 import sys, os, logging, types
15 import time, datetime, math
17 from lxml
import objectify, etree
23 from serverportfolio
import Utils
28 from serverportfolio
import wrapPyStock
37 from Validation
import ValidationTkinter
75 def __init__(self, symbol, dict_static = None):
76 self.
_logger = logging.getLogger(
'SP.stock')
77 self._logger.debug(
"Init Stock %s" % symbol)
109 if type(stock) == types.ListType :
113 if (
type(stock) == types.StringType) | ( isinstance(stock,Stock)) | ( isinstance(stock,InvalidStock)) :
116 list_stock.append( stock )
207 e_action = Utils.stringToEAction( action )
208 self.
_dict_stock[ e_action.name ] = StTmpl.get_template_stock( e_action.name )
223 self._logger.debug(
"set_action, new_data %s" % new_data)
224 assert action !=
None,
'set_action, action cannot be None'
236 if 'template' in new_data:
240 self._logger.debug(
"object not iterable")
248 self.
_dict_stock[ action ][
'template'][key] = new_data
255 self._logger.debug(
"get_config action %s, key %s" % (action, key))
288 return dict_config[
'save']
291 if dict_config[
'save'] ==
False:
294 if specific
in dict_config[
'save']:
299 return StTmpl.saved_as(action, specific)
301 self._logger.error(
"saved_as Should not arrive here")
302 assert True,
"Should not arrive here"
310 self._logger.debug(
"Entry get_dict_xml")
320 e_action = Utils.stringToEAction( action )
328 assert action !=
None,
'set_dict_xml, action cannot be None'
336 self._logger.debug(
"get_error, action %s", action)
339 if action
is not None:
344 self._logger.info(
"Error in action: %s" % self.
get_action()[
'global_error'])
345 error_action = self.
get_action()[
'global_error']
346 error = self.
get_action( error_action )[
'error']
347 print "Error ", error
368 raise Exception(
"Cannot change the value of a stock symbol !! stock: %s" % self.
_symbol)
383 state = property(get_state, set_state)
391 return self.
get_action(
'InstValue',
'last_modification')
406 self._logger.debug(
"add_dict_stock() dict_new_data: %s" % dict_new_data )
407 assert ( dict_new_data
is not None ),
"dict_new_data is not defined in Stock.add_dict_stock"
410 for key,value
in dict_new_data.iteritems():
413 if key ==
"InstValue":
417 elif key ==
"HistPrice":
422 self._logger.debug(
"default in add_dict_parser, copy all values, without check")
428 self._logger.debug(
"End add_dict_stock, self.get_action: %s" % (self.
get_action()))
434 self._logger.debug(
"_add_instvalue_data")
435 self._logger.debug(
"template_action: %s", template_action)
442 prev_state = self.
get_action(
'InstValue',
'state')
444 new_state = template_action[
'state']
446 if new_state ==
'CLOSED' :
447 if prev_state ==
'WAIT_OPEN':
448 self._logger.info(
"CLOSED and WAIT_OPEN pass, prev_state %s", self.
state)
451 if (prev_state ==
'OPEN'):
452 self._logger.info(
"new_state CLOSED, OPEN->CLOSED %s, copy the state" % (self.
symbol))
453 prev_state = new_state
457 elif new_state ==
'OPEN':
460 if prev_state ==
'WAIT_OPEN':
461 self._logger.info(
"WAIT_OPEN->OPEN %s" % self.
symbol)
462 prev_state = new_state
465 self.
set_action(
'InstValue',
None, template_action)
468 self.
state = prev_state
469 self._logger.debug(
"updated inst_value: %s", self.
get_action(
'InstValue') )
474 self._logger.debug(
"_add_instvalue_data")
481 hp[
'last_date'] = template_action[
'last_date']
482 hp[
'list_csv'] = template_action[
'list_csv']
483 self._logger.debug(
'hp %s' % hp)
489 self._logger.debug(
"pre_process e_action.name: %s" % ( e_action.name))
491 if ( e_action == EAction.HistPrice ):
499 self._logger.debug(
"Entry Stock.post_process e_action / option_post: %s / %s " % (e_action, option_post))
501 interactive = option_post[
'interactive']
502 to_save = option_post[
'to_save']
507 self.valid_update.post_process_one_action(e_action, option_post)
508 except PortfolioError
as ex:
509 self._logger.debug(
"Caught PortfolioError %s" % ex.get_format_string())
511 except Exception
as ex:
512 self._logger.debug(
"Caught Exception %s" % ex)
530 self._logger.debug(
"Entry save_inst_value call C++ wrapper stock: %s TEST_MODE: %s " % \
531 (self.
symbol, GlobalDicts.TEST_MODE))
535 self._logger.debug(
"full_datetime %s" % full_datetime)
537 time_struct = time.strptime( full_datetime,
"%Y-%m-%d %H:%M:%S")
540 date_tmp = int( round(time.mktime(time_struct)))
545 retour = wrapPyStock.SaveInst( self.
symbol,[ date_tmp, self.
get_action(
'InstValue',
'value'), \
546 self.
get_action(
'InstValue',
'volume') ], GlobalDicts.TEST_MODE )
547 self._logger.debug(
"after wrapper C++ retour %d", retour)
549 except Exception
as ex:
550 self.loogger.debug(
"Catch Exception in Python: %s", ex)
556 self._logger.info(
"SaveInst did not append data !!")
570 self._logger.debug(
"last_CSV symbol %s " % self.
symbol )
571 self._logger.debug(
"action %s" % action)
573 assert( (action ==
'HistPrice') | (action ==
"DivSplit") ),\
574 "last_CSV can be called only with HistPrice or DivSplit"
577 e_action = Utils.stringToEAction( action )
581 self._logger.debug(
"dict_stock action %s: %s" % (action, self.
get_action(action)))
584 if action ==
'HistPrice':
586 last_date_in_file = wrapPyStock.LastCSVUpdate( self.
symbol, GlobalDicts.TEST_MODE )
588 self._logger.debug(
"last_CSV C++ return last_date_in_file %d" % last_date_in_file)
591 self.
set_action(
'HistPrice',
'last_date', datetime.datetime.fromtimestamp( last_date_in_file ))
593 self._logger.debug(
"last date in dict_parser %s" % self.
get_action(
'HistPrice',
'last_date'))
596 return last_date_in_file
598 elif action ==
'DivSplit':
599 print "Action DivSplit, get first and last date available TO IMPLEMENT"
608 self._logger.debug(
"Entry save_hist_price")
612 list_csv_memory = self.
get_action(
'HistPrice',
'list_csv')
621 sub_list_generator = self.gen_part_of_list_csv(
None)
623 tmp = sub_list_generator.send(
None)
626 for group
in sorted( d_inter.keys(), reverse=
True):
627 print "group ", group, d_inter[group]
628 value = d_inter[group]
631 if value[
'repl_add'] == 2:
633 first_date = Utils.string_to_timestamp( value[
'first_date'] )
634 last_date = Utils.string_to_timestamp( value[
'last_date'] )
635 print "first date/last date ", first_date, last_date
636 print "first date/last date ", Utils.timestamp_to_string(first_date), Utils.timestamp_to_string(last_date)
639 sub_list = sub_list_generator.send( first_date )
640 print "sub_list ", sub_list
641 list_csv_copy += sub_list
643 elif value[
'repl_add'] == 0:
644 print "This group was not validated, stop the copy"
648 list_csv_copy = list_csv_memory
651 if any(list_csv_copy):
652 retour = wrapPyStock.UpdateCSV( self.
symbol, sorted(list_csv_copy, reverse=
True), GlobalDicts.TEST_MODE )
663 time_str = GlobalDicts.OpeningMarket[market]
668 time_open=time.strptime(time_str[0],
"%Hh%Mmn")
672 time_now = datetime.datetime.now()
675 time_proba_open = time_now.replace(hour=int(time_open[3]),minute=int(time_open[4]))
677 time_to_open = time_proba_open - time_now
678 self._logger.debug(
"time to open: %s" % time_to_open)
688 self._logger.debug(
"date %s", self.
get_action(
'InstValue',
'date') )
689 self._logger.debug(
"time %s", self.
get_action(
'InstValue',
'time') )
690 last_date = self.
get_action(
'InstValue',
'date')
691 date_last = datetime.date(*time.strptime(last_date,
"%d/%m/%y")[0:3])
692 today= datetime.date.today()
693 last_time = self.
get_action(
'InstValue',
'time')
694 time_last= datetime.time(*time.strptime(last_time,
"%H:%M:%S")[3:6])
695 now = datetime.time(*time.localtime()[3:6])
697 if (date_last==today)
and (now > time_last):
717 stock_line = self.
symbol +
" ERROR NO %s loaded\n" % action
732 if ( action ==
'InstValue'):
734 stock_line = self.
symbol +
" " + str(sub_data[
'value']) +
" " + str(sub_data[
'variation']) +
" "
735 stock_line += str(sub_data[
'time']) +
" " + str(sub_data[
'date']) +
" "
736 stock_line += str(sub_data[
'volume']) +
" " + str(sub_data[
'ouverture']) +
" "
737 stock_line += str(sub_data[
'plushaut']) +
" " + str(sub_data[
'plusbas']) +
" "
738 stock_line += str(self.
state) +
"\n"
739 print "stock_line ", stock_line
742 elif ( action ==
'Fundamental'):
744 stock_line = self.
symbol +
" " + str(sub_data[
'MarketCapitalization']) +
" " + str(sub_data[
'SharesOwned']) +
" "
745 stock_line += str(sub_data[
'DividendYield']) +
" " + str(sub_data[
'BVPS']) +
" " +str(sub_data[
'PriceBook'])
749 elif ( action ==
'Info'):
750 stock_line = self.
symbol +
", " + str(sub_data[
'Name']) +
", " + str(sub_data[
'Sector']) +
", "
751 stock_line += str(sub_data[
'Industry']) +
"\n"
753 elif ( action ==
'HistPrice'):
754 first_str = sub_data[
'first_date'].strftime(
'%Y-%m-%d %H:%M:%S')
755 last_str = sub_data[
'last_date'].strftime(
'%Y-%m-%d %H:%M:%S')
756 stock_line = self.
symbol +
" " + first_str +
" " + last_str +
"\n"
758 elif (action ==
'DatesIntro'):
759 stock_line = self.
symbol +
" " + sub_data[
'intro_str'] +
"\n"
762 stock_line = self.
symbol +
" ERROR action %s Not implemented in Stock\n" % (action)
779 self._logger.debug(
"Entry read_xml")
781 filename = GlobalDicts.PATH_DATA_ROOT + os.sep +
"xml" + os.sep + self.
symbol +
".xml"
782 self._logger.debug(
"to read filename %s", filename)
784 if not os.path.isfile(filename):
785 self._logger.debug(
"File %s does not exist !" % filename )
788 self.
_dict_xml = StTmpl.create_default_template_xml()
796 doc = etree.parse( filename )
799 except etree.XMLSyntaxError, e:
800 self._logger.debug(
"Caught a etree.XMLSyntaxError")
803 print(etree.tostring(root, pretty_print=
True))
813 assert root.find(
"symbol").text == self.
symbol,\
814 "Symbol %s does not correspond in file %s !!" % ( self.
_dict_xml[
'symbol'], filename )
818 for el_action
in root:
820 if el_action.tag ==
'symbol':
823 print "process the child tag %s", el_action.tag
824 print(
"%s - %s" % (el_action.tag, el_action.text))
828 except PortfolioError
as ex:
830 hl_exception =
PortfolioError(
"PortfolioError in Stock.ReadXML for symbol: %s\n%s" % (self.
symbol,ex))
833 hl_exception.traceback = hl_exception.traceback +
'....\n' + ex.traceback
844 except Exception
as ex:
845 self._logger.debug(
"Caught Exception in read_xml")
846 print "sys.exc_info()[2] ", sys.exc_info()[2]
847 print "traceback ", traceback.format_exc(3)
852 self.
_dict_xml[el_action.tag] = dict_action
854 print Utils.pretty_dict( self.
_dict_xml )
859 self._logger.debug(
"Entry element tag %s", el_action.tag )
861 action = el_action.tag
863 tmp_dict = StTmpl.get_template_xml( action )
864 print "tmp_dict default ", tmp_dict
865 print "attributes action ", el_action.attrib
867 tmp_dict[
'attrib'] = el_action.attrib
871 for elem_data
in el_action:
872 self._logger.debug(
"elem_data.tag/ text/ attrib: %s / %s / %s" \
873 % (elem_data.tag, elem_data.text, elem_data.attrib))
875 one_value_xml = StTmpl.get_template_one_value_xml()
877 one_value_xml[
'value'] = elem_data.text
880 for key_attr
in one_value_xml[
'attrib'].keys():
882 if key_attr
in elem_data.attrib:
883 one_value_xml[
'attrib'][key_attr] = elem_data.attrib[key_attr]
885 elif key_attr
in el_action.attrib:
886 one_value_xml[
'attrib'][key_attr] = el_action.attrib[key_attr]
889 assert( 1==1),
"One attribute is neither one_value, netiher default action"
891 tmp_dict[
'template'][ elem_data.tag ].append( one_value_xml )
894 print Utils.pretty_dict(tmp_dict)
1028 self._logger.debug(
"Entry write_xml")
1029 self._logger.debug(
"TEST_MODE %s" % GlobalDicts.TEST_MODE )
1033 self._logger.error(
"write xml with an emptyy dict_xml, do nothing")
1037 if GlobalDicts.TEST_MODE :
1038 filename = GlobalDicts.PATH_DATA_ROOT_TEST + os.sep +
"xml_tmp" + os.sep + self.
symbol +
".xml"
1040 filename = GlobalDicts.PATH_DATA_ROOT + os.sep +
"xml" + os.sep + self.
symbol +
".xml"
1041 self._logger.debug(
"to write filename %s", filename)
1043 self._logger.debug(
"Create a new XML file")
1046 root = etree.Element(
"root")
1047 doc = etree.ElementTree(root)
1051 ch_symbol = etree.SubElement(root,
"symbol")
1052 ch_symbol.text = self.
symbol
1055 for key_action, value_action
in self.
get_dict_xml().iteritems():
1056 self._logger.debug(
"key_action %s" % key_action)
1077 if 'attrib' in value_action:
1079 if value_action[
'attrib'][
'source'] !=
None:
1081 root.append( sub_tree_action )
1088 print(etree.tostring(root, pretty_print=
True))
1090 self._logger.debug(
"write the file")
1091 with open( filename ,
'w')
as out_file:
1092 doc.write(out_file, pretty_print=
True)
1099 self._logger.debug(
"Entry %s %s", sys._getframe().f_code.co_name, self.
symbol )
1100 self._logger.debug(
"key_action %s" % key_action)
1103 action_tree = etree.Element( key_action )
1105 action_attr = action_tree.attrib
1107 for key_attr,value_attr
in value_action[
'attrib'].iteritems():
1108 action_attr[key_attr] = str(value_attr)
1110 b_action_append = action_attr[
'append']
1111 b_action_source = action_attr[
'source']
1114 for key_data, values_data
in value_action[
'template'].iteritems():
1116 if (key_data ==
"error") | (key_data ==
"other"):
1119 for one_value_data
in values_data:
1120 print "one_value_data ", one_value_data
1121 child = etree.SubElement(action_tree, key_data)
1123 child.text = str(one_value_data[
'value'])
1124 one_value_attr = child.attrib
1126 for key_attr
in one_value_data[
'attrib']:
1128 if key_attr ==
'date':
1129 one_value_attr[key_attr] = str(one_value_data[
'attrib'][key_attr])
1132 if key_attr ==
'source':
1133 if str(one_value_data[
'attrib'][key_attr]) != str(b_action_source):
1134 one_value_attr[key_attr] = str(one_value_data[
'attrib'][key_attr])
1137 if key_attr ==
'append':
1138 if str(one_value_data[
'attrib'][key_attr]) != str(b_action_append):
1139 one_value_attr[key_attr] = str(one_value_data[
'attrib'][key_attr])
1144 print "one_value_xml do not repeat attribute %s" % key_attr
1145 print(etree.tostring(action_tree, pretty_print=
True))
1193 tmp = StTmpl.get_template_stock(
'Static')
1194 tmp[
'template'] = StTmpl.get_tmpl_static_invalid()
1196 super(InvalidStock, self).
__init__(symbol, tmp)
1198 self.
_logger = logging.getLogger(
'SP.InvalidStock')
1199 self._logger.warning(
"Init InvalidStock %s" % symbol)
1201 print "init Invalid, dict_static_invalid", dict_static_invalid
1213 return "%s ERROR InvalidStock\n" % self.
symbol
1215 if __name__ ==
"__main__":
1220 logging.basicConfig(level=logging.DEBUG)
1221 logging.getLogger(
'SP')
1222 m_logger = logging.getLogger(
"SP.main")
1224 print "Main Stock.py"
1228 print "m_stock._dict_stock ", m_stock._dict_stock
1231 print "symbol: ", m_stock.symbol
1232 print "market: ", m_stock.get_market()
1233 print "dict_stock: ", m_stock.get_action()
1234 print "dict_stock[static] ", m_stock.get_action(
'Static')
1236 print "\n== last_CSV deactivated for dev."
1250 'Name' :
'GDF-Suez',
1251 'Sector' :
'Energy',
1252 'Industry' :
'EnergyGaz',
1253 'StockExchange' :
'Paris',
1260 m_stock.set_action(
'Info',
None, m_dict_info)
1264 'MarketCapitalization' : float(20000),
1265 'SharesOwned' : int(15000),
1266 'DividendYield' : float(3.5),
1267 'BVPS' : float(5.5),
1268 'PriceBook' : float(3.0),
1276 m_stock.set_action(
'Fundamental',
None, m_dict_fund)
1283 print "_dict_stock ", m_stock.get_action()
1284 print Utils.pretty_dict( m_stock.get_action() )
1289 print "\n== read_xml"
1293 except PortfolioError
as ex:
1294 print "Caught PortfolioError in main, ex:\n ", ex
1295 print "\n",ex.get_format_string()
1298 except Exception, ex:
1299 print "Caught an Exception ", ex
1300 print "sys.exc_info()[2] ", sys.exc_info()[2]
1301 print "traceback ", traceback.format_exc(3)
1321 print "\n==Interactive simulation"
1322 print "_dict_parser:"
1323 print Utils.pretty_dict( m_stock.get_action() )
1327 m_stock.check_new_xml_data( opt_interactive =
False )
1330 except Exception
as ex:
1331 print "Caught an Exception from checkNewData", ex
1333 print "traceback ", traceback.format_exc(3)
1344 m_stock.save_new_xml_data()
1346 except PortfolioError
as ex:
1347 print "Caught PortfolioError ", ex
1348 print ex.get_format_string()
1350 except Exception
as ex:
1351 print "Caught an Exception from save_new_data", ex
1353 print "traceback ", traceback.format_exc(3)
1355 print "\n== Create new XML"
1359 print "\n== Write new empty XML"
def get_last_modification
Return the last modification of the Instantaneous value.
Base class of the custom exceptions.
def set_action
Fill _dict_stock['action'] with new_data.
def get_state
Getter function for the state.
Define class ValidStockUpdate.
def add_dict_stock
Function to update Stock with the data extracted by the Parsers.
def is_valid
Return if the Stock is valid.
def time_to_open
Override method of base class, return None.
def _fill_dict_xml
Create an empty template in _dict_xml and fill with the data in the xml file.
_dict_interactive
Store old/new values before update which may be applied to XML.
def get_error
Return a formatted error.
def set_dict_xml
Similar to set_action with extended dictionary.
def save_inst_value
Save instantaneous values into a file.
def get_action
Return the action template part from _dict_stock or one of its data value.
Define the global variable StockTemplates.StTmpl and dictionary templates.
def get_market
Get the market on which the stock belongs.
def _add_instvalue_data
Update InstValue data.
Class template for invalid stocks, if a stock symbol is not found in the configuration file...
Define custom and specific exceptions for the complete package.
def get_config
return the 'config' dictionary or one of its key from _dict_stock
def print_stock
Create a one line string with the values stored in a dictionary.
def get_dict_xml
Return the dictionary of data for XML input/output.
Extend class Stock with functions related to the validation and saving after a stock update: most of ...
_dict_stock
Set of templates to store results from parsers, include 'Static' data.
def write_xml
Check the validity of the new retrieved data (in _dict_stock), store update in _dict_interactive.
def read_xml
ReadXML data from file into internal xml_dict.
def last_CSV
Get the date of the last data from the file saved on disk.
Store data and functions related to one stock.
state
Define both setter and getter, can use stock.state = new_state or print stock.state.
Container of all Stocks objects, it also reads the static stocks configuration file "dictstocks...
def post_process
Post process the update: check, validate and save the data after one (unique) action is performed...
Global variables for configuration: paths, TCP ports and generic definitions.
def test_ML_done
Check date and time for ML(Marche libre) specifically.
def print_stock
Override method of base class, return string containing ERROR.
def time_to_open
Compute in how long time the stock will open, to test for setting the state 'WAIT_OPEN' in AutoParser...
def symbol
Getter for the symbol.
def _create_xml_action
Helper function, generate xml sub-tree for one action.
def _add_histprice_data
Update Historical Price data.
_dict_xml
Dictionary for storing data for XML input/output, extends _dict_parser templates. ...
valid_update
Validation is done by a ValidStockUpdate object.
def saved_as
query the entry 'config' : 'save' of an action If specifc is indicated return a boolean value ...
_symbol
Main key for all dictionaries.
Define singleton class DictionaryStocks, act as the main container of Stocks objects.
def to_list
Similar to Utils.to_list but deals with Stock or list of Stocks.
def pre_process
Pre-processing only for HistPrice, may extend to all 'csv' later.
def save_hist_price
Save historical price in CSV format in ROOT_data/hp/symbol.DAY.CSV Use C++ wrapPyStock.UpdateCSV function.