14 import copy, types, logging
18 from lxml
import html, etree
20 from serverportfolio
import GlobalDicts
23 from serverportfolio
import Utils
41 __HISTORY_QUOTES_URL=
"http://ichart.yahoo.com/table.csv?"
53 __HISTORY_QUOTES_X_URL=
"http://ichart.finance.yahoo.com/x?"
62 __HISTORY_DATES_URL=
"http://fr.finance.yahoo.com/q/hp?"
65 __QUOTES_CSV_URL=
"http://download.finance.yahoo.com/d/quotes.csv?"
71 super(YahooCSV, self).
__init__(e_action)
74 self.
logger = logging.getLogger(
'SP.YahooCSV')
75 self.logger.debug(
"Init class YahooCSV")
83 self.logger.debug(
"YahooCSV::create_url")
84 self.logger.debug(
"local stock: %s", self.
local_stock)
87 code_yahoo =
','.join( stock.get_action(
'Static',
'code_yahoo')
for stock
in self.local_stock.values() )
88 self.logger.debug(
"code yahoo: %s" % code_yahoo)
91 self.logger.debug(
"YahooCSV with EAction.HistPrice, only one stock")
92 assert ( len(self.
local_stock) == 1 ),
"YahooCSV with HistPrice deals only with one Stock at a time"
94 symbol = self.local_stock.keys()[0]
95 self.logger.debug(
"full dictionary symbol %s: %s" % (symbol, self.
local_stock[symbol].get_action()))
98 lastdate = self.
local_stock[symbol].get_action(
'HistPrice',
'last_date')
100 firstdate = self.
local_stock[symbol].get_action(
'HistPrice',
'first_date')
102 self.logger.debug(
"lastdate %s" % lastdate)
103 (year,month,day)=(lastdate.year,lastdate.month,lastdate.day)
106 today = datetime.date.today()
107 self.logger.debug(
"max_date 0, today %s" % today)
108 (tyear,tmonth,tday)=(today.year,today.month,today.day)
109 self.logger.debug(
"today day %d" % tday)
118 +
"&d=" + str(tmonth-1) +
"&e=" + str(tday) +
"&f=" + str(tyear) \
120 +
"&a=" + str(month-1) +
"&b=" + str(day) +
"&c=" + str(year)
124 elif self.
e_action == EAction.DivSplit :
126 assert ( len(self.
local_stock) == 1 ),
"YahooCSV with DivSplit deals only with one Stock at a time"
127 symbol = self.local_stock.keys()[0]
128 self.logger.debug(
"full dictionary symbol %s: %s" % (symbol, self.
local_stock[symbol].get_action()))
131 lastdate = self.
local_stock[symbol].get_action(
'DivSplit',
'last_date')
133 firstdate = self.
local_stock[symbol].get_action(
'DivSplit',
'first_date')
135 self.logger.debug(
"lastdate %s" % lastdate)
136 (year,month,day)=(lastdate.year,lastdate.month,lastdate.day)
137 self.logger.debug(
"lastdate.day %d" % day)
140 today = datetime.date.today()
141 self.logger.debug(
"max_date today %s" % today)
142 (tyear,tmonth,tday)=(today.year,today.month,today.day)
143 self.logger.debug(
"today day %s" % tday)
147 +
"&a=" + str(month-1) +
"&b=" + str(day) +
"&c=" + str(year) \
148 +
"&d=" + str(tmonth-1) +
"&e=" + str(tday) +
"&f=" + str(tyear)
151 elif self.
e_action == EAction.DatesIntro :
152 assert ( len(self.
local_stock) == 1 ),
"YahooCSV with DatesIntro deals only with one Stock at a time"
156 elif self.
e_action == EAction.Fundamental :
164 self.logger.critical(
"ERROR method parser not valid %s" % self.
e_action)
166 self.local_stock.keys(), self.e_action.name,
'None' )
168 self.logger.debug(
"url: %s",self.
url)
173 self.logger.debug(
"parse()")
174 self.logger.debug(
"self.e_action.name %s " % self.e_action.name )
178 if self.
e_action == EAction.HistPrice:
180 self.logger.debug(
"size of listCSV: %d" %
183 elif self.
e_action == EAction.DivSplit:
186 elif self.
e_action == EAction.Fundamental:
189 elif self.
e_action == EAction.DatesIntro:
193 self.logger.error(
"Specific parse() function not defined for action: %s" % self.
e_action)
194 raise ParserError(
"Specific parse() function not defined for action: %s" % (self.
e_action),\
195 self.local_stock.keys()[0], self.e_action.name, self.
url)
197 except ParserError
as ex:
198 self.logger.error(
"parse() caught ParserError ex: %s\n" % ex )
202 except Exception
as ex:
203 self.logger.error(
"parse() caught Exception ex: %s\n" % ex )
204 raise ParserError(ex, self.local_stock.keys()[0], self.e_action.name, self.
url)
212 self.logger.debug(
"parse_hp()")
217 line_split=all_line.split(
"\n")
220 for line_tmp
in line_split[1:-1]:
223 data_split=line_tmp.split(
",")
226 for data_tmp
in data_split[:-1]:
230 tmp_date=time.strptime(data_tmp,
"%Y-%m-%d")
231 data_tmp=int( round(time.mktime(tmp_date)))
232 tmp_CSV.append(data_tmp)
238 tmp_CSV.append(float(data_tmp))
242 listCSV.append(tmp_CSV)
244 self.logger.debug(
"listCSV.size %d ", len(listCSV))
252 tmp_templ[
'last_date'] = datetime.datetime.fromtimestamp( listCSV[0][0] )
253 tmp_templ[
'list_csv'] = listCSV
263 self.logger.debug(
"parse_div()")
264 print "all_line ", all_line
271 line_split=all_line.split(
"\n")
276 for line_tmp
in line_split[1:]:
278 data_split=line_tmp.split(
",")
280 if data_split[0] ==
'DIVIDEND':
284 date = time.strptime( data_split[1].strip(),
"%Y%m%d" )
285 value = float(data_split[2])
286 self.logger.debug(
"dividend: %s %f" % (date, value))
287 self.logger.debug(
"mktime %d", int (time.mktime(date)))
288 date = int ( time.mktime( date ) )
289 list_div.append( [date, value])
291 elif data_split[0] ==
'SPLIT':
292 date = int ( time.mktime( time.strptime( data_split[1].strip(),
"%Y%m%d" ) ) )
294 value = data_split[2]
295 self.logger.debug(
"split: %s %s" % (date, value))
296 list_split.append( [date, value])
301 if data_split[0] ==
"STATUS":
302 assert( data_split[1].strip() ==
'0' )
314 tmp_template[
'last_date'] = max( datetime.datetime.fromtimestamp( list_div[0][0] ), \
315 datetime.datetime.fromtimestamp( list_div[0][0] ) )
316 tmp_template[
'list_div'] = list_div
317 tmp_template[
'list_split'] = list_split
320 self.logger.debug(
"list_div.size %d ", len(list_div))
321 self.logger.debug(
"list_split.size %d ", len(list_split))
332 self.logger.debug(
"parse_fund()")
333 self.logger.debug(
"all_line %s" % all_line)
343 line_split = all_line.split(
"\n")
344 for line
in line_split :
347 self.logger.warning(
"1 line is empty")
349 self.logger.debug(
"line: %s" % line)
352 elem_line = line.split(
',')
356 yahoo_code = elem_line[0].replace(
'"',
'').strip()
357 self.logger.debug(
"yahoo_code: %s" % yahoo_code )
364 dict_data_stock =
None
365 dict_data_stock = StTmpl.get_template_parser( self.e_action.name )
366 dict_data_stock[
'symbol'] = symbol
371 if UtilsParsers.check_nan(elem_line[10]) ==
False:
372 self.logger.error(
"error in parsing csv element[10] :%s" % line )
376 tmp_dict = dict_data_stock[
'action_templ'][ self.e_action.name ]
386 tmp_dict[
'MarketCapitalization'] = UtilsParsers.extract_number(elem_line[3])
388 tmp_dict[
'SharesOwned'] = UtilsParsers.extract_number( elem_line[4] )
390 tmp_dict[
'DividendYield'] = UtilsParsers.extract_number( elem_line[5] )
391 tmp_dict[
'BVPS'] = UtilsParsers.extract_number( elem_line[6] )
392 tmp_dict[
'PriceBook'] = UtilsParsers.extract_number( elem_line[7] )
393 tmp_dict[
'PER'] = UtilsParsers.extract_number (elem_line[8])
394 tmp_dict[
'PEG'] = UtilsParsers.extract_number (elem_line[9])
397 self.list_return_data.append( dict_data_stock )
401 self.logger.debug(
"pretty test:\n%s" % Utils.pretty_dict( self.
list_return_data ) )
408 htmltree = html.document_fromstring ( html_page )
409 input_extracted = htmltree.xpath(
"//input[@id='startday']")
410 day_start = input_extracted[0].get(
"value")
413 main_parent = input_extracted[0].getparent().getparent()
414 option_selected = main_parent.xpath(
"td/select/option[@selected]")
415 month_start = option_selected[0].get(
"value")
416 year_selected=main_parent.xpath(
"td/input[@id='startyear']")
417 year_start=year_selected[0].get(
"value")
419 first_day = year_start+
'-'+str(int(month_start)+1)+
'-'+day_start
421 date_start = time.strptime(first_day,
"%Y-%m-%d")
422 datestamp_start=int( round(time.mktime(date_start)))
424 self.logger.debug(
"date_start: %s" % date_start)
426 self.logger.debug(
"datestamp_start: %d" % datestamp_start)
435 self.
list_return_data[
'action_templ'][self.e_action.name][
'intro'] = datestamp_start
437 datetime.datetime.fromtimestamp( datestamp_start ).strftime(
'%Y-%m-%d %H:%M:%S')
440 if __name__ ==
"__main__":
443 import sys, traceback
445 print "main module YahooCSV"
447 logging.basicConfig(level=logging.DEBUG)
448 logging.getLogger(
'SP')
449 m_logger = logging.getLogger(
"SP.main")
452 m_stock = sys.argv[1]
453 m_action = sys.argv[2]
455 print " Only for debugging, should call ./Run_Parsers for all options "
457 print " YahooCSV CAC40 HistPrice"
458 print " Action: HistPrice / Fundamental / DatesIntro / DivSplit"
459 print " For Fundamental it is possible to query multi-stocks CAC40,GSZ,FSLR"
463 m_list_stock = m_stock.split(
',')
466 if type(m_action) == types.StringType:
467 m_e_action = EAction[m_action]
470 m_e_action = m_action
472 m_logger.error(
"Exception from EActione numeration, cannot assign an e_action from action: %s" % m_action)
475 m_logger.info(
"list_stock: %s" % m_list_stock)
476 m_logger.info(
"e_action: %s " % m_e_action)
477 m_parserCSV =
YahooCSV( m_e_action )
480 m_logger.debug(
"\n== store copy of object in parser")
482 m_parserCSV.store_stock_copy( m_list_stock )
484 except ParserError
as ex:
485 print "Caught ParserError ex", ex.get_format_string()
488 except Exception
as ex:
489 print "Got error in store_stock_copy"
494 if ( m_action == EAction.HistPrice.name ) | ( m_action == EAction.DivSplit.name ):
495 print "\n Preprocess for Action ", m_action
498 m_logger.debug(
"\n== create_url default 0 0")
500 m_parserCSV.create_url()
502 except PortfolioError
as ex:
503 print "Catch PortfolioError from create_url: ", ex
504 print ex.get_format_string()
507 except Exception
as ex:
508 print "Catch Exception from create_url: ", ex
510 exc_type, exc_value, exc_traceback = sys.exc_info()
511 print "*** print_tb:"
512 traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
516 print "exec_info ", sys.exc_info()
517 print "exec_info[2] ", sys.exc_info()[2]
520 traceback.print_tb( sys.exc_info()[2] )
523 m_logger.debug(
"\n== web_query ")
525 m_s = UtilsParsers.web_query( m_parserCSV.url )
527 except Exception
as ex:
528 print "Got exception from web_query: ", ex
532 m_logger.debug(
"\n== parse the web page")
534 m_parserCSV.parse(m_s)
536 except ParserError
as ex:
537 print "Catch PaserError ", ex
538 print "ex.get_format_string"
540 print ex.get_format_string()
543 except Exception
as ex:
544 print "Catch Exception from parse() ", ex
547 m_logger.debug(
"\n== update the stock(s)")
555 m_parserCSV.update_stock()
557 m_logger.debug(
"\n== print stock(s)")
559 for stock
in m_list_stock:
560 print Utils.pretty_dict(
DictionaryStocks().get_stocks( stock ).get_action() )
def parse_div
Specific parsing function for dividends/split.
string __HISTORY_QUOTES_URL
e_action
enumeration (EAction) of the type of query to perform
def create_url
Create the url according to the action and the stock(s).
def parse_dates_intro
To get introduction date of a stock, (first available on Yahoo) and last available.
def parse
Parser implementation for YahooCSV, action dependent.
string __HISTORY_DATES_URL
Define the global variable StockTemplates.StTmpl and dictionary templates.
Define 2 abstract methods which need to be overridden by the Parsers and a generic algorithm (run_pa...
Define custom and specific exceptions for the complete package.
Derived class specific to the parsers.
def parse_fund
Parse fundamental data with old API, CSV data.
Define an abstract base class for specific Parsers.
def parse_hp
Specific parsing function to read a list of CSV, only daily values.
def get_symbol_from_code
Retrieve the symbol (or Stock) from the code_yahoo or code_bourso.
Container of all Stocks objects, it also reads the static stocks configuration file "dictstocks...
Global variables for configuration: paths, TCP ports and generic definitions.
url
save url, useful for reporting errors and exceptions
Define singleton class DictionaryStocks, act as the main container of Stocks objects.
Derived parser class for retrieving divers data from the 'old' Yahoo API.
string __HISTORY_QUOTES_X_URL