├── .gitignore ├── README.md ├── adx.py ├── algorithm.py ├── app.py ├── bbcross.py ├── connorsrsi.py ├── cross.py ├── data.py ├── data ├── GOOG_20100101_20121231.pkl ├── GOOG_20120101_20120131.pkl ├── GOOG_20120101_20120631.pkl ├── GOOG_20120101_20121231.pkl ├── IBM_20120101_20120131.pkl ├── YHOO_20120101_20120131.pkl ├── YHOO_20120101_20121231.pkl └── test.csv ├── down.py ├── dva.py ├── dvtest.py ├── indicators.py ├── macd.py ├── momentum.py ├── nn.py ├── nn2.py ├── pennant.py ├── plot.py ├── positions.py ├── pxcross.py ├── sellinmay.py ├── spy.py ├── squeeze.py ├── util.py ├── vwap.py ├── vwapcross.py ├── yf.py └── ystockquote.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.pyo 3 | *.log 4 | passwords.py 5 | .project 6 | .pydevproject 7 | .settings 8 | *.csv 9 | *.pkl -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | trading 2 | ======= 3 | This repository provides a light-weight framework for designing and back-testing technical analysis and indicators. 4 | 5 | More details available at http://www.craigperler.com/blog/2013/03/08/analysis-of-technical-analysis/ and http://www.craigperler.com/blog/2013/03/17/analysis-of-moving-average-triggers/. 6 | -------------------------------------------------------------------------------- /adx.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from indicators import * 5 | from plot import * 6 | import pprint 7 | 8 | stocks = ['AAPL'] 9 | 10 | class ADXTest(Algorithm): 11 | def __init__(self, symbols, start_date, end_date): 12 | super(ADXTest, self).__init__(symbols, start_date, end_date) 13 | 14 | def pre_run(self): 15 | super(ADXTest, self).pre_run() 16 | 17 | for symbol in self.symbols: 18 | high_series = self.cube.data[(symbol, 'high')] 19 | low_series = self.cube.data[(symbol, 'low')] 20 | close_series = self.cube.data[(symbol, 'close')] 21 | 22 | self.add_indicator(TR('TR', high_series, low_series, close_series)) 23 | self.add_indicator(PlusDM('PlusDM', high_series, low_series)) 24 | self.add_indicator(MinusDM('MinusDM', high_series, low_series)) 25 | self.add_indicator(Smooth('ATR', self.i('TR'), 14)) 26 | self.add_indicator(Smooth('PlusDM14', self.i('PlusDM'), 14)) 27 | self.add_indicator(Smooth('MinusDM14', self.i('MinusDM'), 14)) 28 | self.add_indicator(DI('PlusDI', self.i('PlusDM14'), self.i('ATR'))) 29 | self.add_indicator(DI('MinusDI', self.i('MinusDM14'), self.i('ATR'))) 30 | self.add_indicator(DX('DX', self.i('PlusDI'), self.i('MinusDI'))) 31 | self.add_indicator(ADX('ADX', self.i('PlusDI'), self.i('MinusDI'), 14)) 32 | 33 | def handle_data(self, dt, symbols, keys, data): 34 | symbol = symbols[0] 35 | 36 | yesterday = self.cube.go_back(dt, 1) 37 | 38 | adx = self.i('ADX')[dt] 39 | adx_y = self.i('ADX')[yesterday] 40 | pdi = self.i('PlusDI')[dt] 41 | pdi_y = self.i('PlusDI')[yesterday] 42 | mdi = self.i('MinusDI')[dt] 43 | mdi_y = self.i('MinusDI')[yesterday] 44 | px = data[(symbol, 'close')] 45 | px_y = self.cube.data[(symbol, 'close')][yesterday] 46 | 47 | if adx and adx > 25: 48 | if pdi > mdi and pdi_y < mdi_y: 49 | if symbol not in self.oms.portfolio.positions or not self.oms.portfolio.positions[symbol].is_open(): 50 | self.oms.add(Transaction(symbol, dt, px, 500)) 51 | elif pdi < mdi and pdi_y > mdi_y: 52 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 53 | self.oms.add(Transaction(symbol, dt, px, -500)) 54 | 55 | def post_run(self): 56 | self.results() 57 | for symbol in self.symbols: 58 | self.plot(symbol=symbol, indicator_list=['TR', 'PlusDM', 'MinusDM', 'ATR', 'PlusDM14', 'MinusDM14', 'PlusDI', 'MinusDI', 'DX', 'ADX']).show() 59 | 60 | 61 | test = ADXTest(stocks, '20120813', '20130206') 62 | test.run() 63 | test.results() 64 | 65 | #test.write_to_csv('adx.csv', indicator_list=['TR', 'PlusDM', 'MinusDM', 'ATR', 'PlusDM14', 'MinusDM14', 'PlusDI', 'MinusDI', 'DX', 'ADX']) 66 | 67 | stock = stocks[0] 68 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 69 | [[test.cube.get_values(stock, 'adjclose')],[test.i('PlusDI').as_series(), test.i('MinusDI').as_series(),test.i('ADX').as_series()]], 70 | 'Date', 71 | ['Price','Value'], 72 | '-', 73 | [['Close'],['+DI', '-DI','ADX']], 74 | stock) 75 | for t in test.oms.blotter.all(symbols=stock): 76 | dt = t.dt 77 | high = test.cube.data[(stock, 'high')][dt] 78 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.05), xytext=(dt, high*1.08), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 79 | plt.show() -------------------------------------------------------------------------------- /algorithm.py: -------------------------------------------------------------------------------- 1 | from positions import OMS, Transaction 2 | from indicators import Indicator 3 | import data 4 | import plot 5 | 6 | class Algorithm(object): 7 | def __init__(self, symbols, start_date, end_date, cash=1000): 8 | self.oms = OMS() 9 | self.symbols = symbols 10 | self.start_date = start_date 11 | self.end_date = end_date 12 | self.cash = cash 13 | self.initial_cash = cash 14 | self.indicators = {} 15 | 16 | def add_indicator(self, indicator): 17 | indicator.algorithm = self 18 | self.indicators[indicator.name] = indicator 19 | 20 | def get_indicator(self, name): 21 | return self.indicators.get(name) 22 | 23 | def i(self, name): 24 | return self.get_indicator(name) 25 | 26 | def setup_indicator(self, indicator): 27 | if indicator.ready == True or indicator is None: 28 | return 29 | 30 | if issubclass(type(indicator.series), Indicator): 31 | self.setup_indicator(indicator.series) 32 | 33 | indicator.calculate() 34 | indicator.ready = True 35 | 36 | def setup_indicators(self): 37 | for indicator in self.indicators.values(): 38 | self.setup_indicator(indicator) 39 | 40 | def pre_run(self): 41 | pass 42 | 43 | def handle_data(self, dt, symbols, keys, data): 44 | pass 45 | 46 | def post_run(self): 47 | pass 48 | 49 | def run(self): 50 | self.cube = data.load(self.symbols, self.start_date, self.end_date) 51 | self.pre_run() 52 | self.setup_indicators() 53 | for dt in self.cube.get_dates(): 54 | step_data = {} 55 | symbols = [] 56 | keys = [] 57 | for (symbol, key) in self.cube.data: 58 | if symbol not in symbols: 59 | symbols.append(symbol) 60 | if key not in keys: 61 | keys.append(key) 62 | if dt in self.cube.data[(symbol, key)]: 63 | step_data[(symbol, key)] = self.cube.data[(symbol, key)][dt] 64 | else: 65 | step_data[(symbol, key)] = None 66 | self.handle_data(dt, symbols, keys, step_data) 67 | self.post_run() 68 | 69 | def write_to_csv(self, file_name, indicator_list=None): 70 | extra_series = [] 71 | if indicator_list: 72 | if type(indicator_list) is str: indicator_list = [indicator_list] 73 | for indicator in indicator_list: 74 | i = self.i(indicator) 75 | extra_series.append({'name': i.name, 'data': i}) 76 | self.cube.write_to_csv(file_name, extra_series) 77 | 78 | def plot(self, symbol=None, indicator_list=None, show_signals=True, exclude_price=False): 79 | if not symbol: 80 | symbol = self.symbols[0] 81 | 82 | indicators = [] 83 | indicator_names = [] 84 | if indicator_list: 85 | if type(indicator_list) is str: indicator_list = [indicator_list] 86 | indicators.extend([self.i(indicator).as_series() for indicator in indicator_list]) 87 | indicator_names.extend([self.i(indicator).name for indicator in indicator_list]) 88 | num_series = len(indicators) + 1 89 | 90 | date_series_list = [self.cube.get_dates()] * num_series 91 | plot_series_list = [self.cube.get_values(symbol, 'close')] + indicators 92 | plot_names_list = ['Close'] + indicator_names 93 | if exclude_price: 94 | date_series_list = [self.cube.get_dates()] * (num_series-1) 95 | plot_series_list = indicators 96 | plot_names_list = indicator_names 97 | 98 | plt = plot.plot_data_with_dates(date_series_list, plot_series_list, 'Date', '' if exclude_price else 'Px', '-', plot_names_list, symbol) 99 | 100 | if show_signals: 101 | for t in self.oms.blotter.all(symbols=symbol): 102 | dt = t.dt 103 | high = self.i(indicator_list[0]).value[dt] if exclude_price else self.cube.data[(symbol, 'high')][dt] 104 | plt.annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.02), xytext=(dt, high*1.03), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 105 | 106 | return plt 107 | 108 | def get_buy_and_hold(self, field='close'): 109 | bh = {} 110 | dates = self.cube.get_dates() 111 | for symbol in self.symbols: 112 | idx = 0 113 | while dates[idx] not in self.cube.data[(symbol, field)]: 114 | idx += 1 115 | p1 = self.cube.data[(symbol, field)][dates[idx]] 116 | px = self.cube.data[(symbol, field)][dates[-1]] 117 | v = px / p1 * self.initial_cash 118 | bh[symbol] = v - self.initial_cash 119 | return bh 120 | 121 | def calculate_pandl(self): 122 | closeout = 0.0 123 | for symbol, position in self.oms.portfolio.positions.items(): 124 | if position.is_open(): 125 | dt = self.cube.get_dates()[-1] 126 | px = self.cube.data[(symbol, 'close')][dt] 127 | closeout += Transaction(symbol, dt, px, position.amount).cost() 128 | pandl = self.oms.blotter.calculate_pandl() 129 | return {'only_closed' : pandl, 'only_open' : closeout, 'total' : closeout+pandl} 130 | 131 | def results(self, bhfield='close'): 132 | print('') 133 | print('-- Results for {} on symbols {} from {} to {} --'.format(self.__class__.__name__, self.symbols, self.start_date, self.end_date)) 134 | print ('') 135 | print ('Transactions:') 136 | transactions = list(self.oms.blotter.all()) 137 | for t in transactions: 138 | print ('\t{}'.format(t)) 139 | if len(transactions) == 0: 140 | print('\tno transactions') 141 | print('') 142 | print('Holdings:') 143 | holdings = self.oms.portfolio.all(only_open=True) 144 | for p in holdings: 145 | print('\t{} (px = {})'.format(p, self.cube.data[(p.symbol, 'close')][self.cube.get_dates()[-1]])) 146 | if len(holdings) == 0: 147 | print('\tno open holdings') 148 | pandl = self.calculate_pandl() 149 | print('Unrealized = {}'.format(pandl['only_open'])) 150 | print('Realized = {}'.format(pandl['only_closed'])) 151 | print('Total P&L = {}'.format(pandl['total'])) 152 | print('B&H = {}'.format(sum([v-10000 for _, v in self.get_buy_and_hold(field=bhfield).items()]))) 153 | print('') 154 | return {'strategy' : int(pandl['total']), 'bh' : int(sum([v for _, v in self.get_buy_and_hold().items()])-10000)} -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from indicators import * 5 | import pprint 6 | 7 | stocks = ["MMM","AA","MO","AXP","AIG","T","BA","CAT","C","KO","DD","XOM","GE","GM","HPQ","HD","HON","IBM","INTC","JNJ","JPM","MCD","MRK","MSFT","PFE","PG","UTX","VZ","WMT","DIS"] 8 | stocks = ['SPY'] 9 | 10 | class SMATest(Algorithm): 11 | def __init__(self, symbols, start_date, end_date): 12 | super(SMATest, self).__init__(symbols, start_date, end_date) 13 | 14 | def pre_run(self): 15 | super(SMATest, self).pre_run() 16 | 17 | for symbol in self.symbols: 18 | close_series = self.cube.data[(symbol, 'close')] 19 | self.add_indicator(SMA('ShortSMA-' + symbol, close_series, 5)) 20 | self.add_indicator(SMA('LongSMA-' + symbol, close_series, 20)) 21 | self.add_indicator(RSMA('LongRSMA-' + symbol, close_series, 20)) 22 | self.add_indicator(BBandLower('BBandLower-20-' + symbol, close_series, 20, 2)) 23 | self.add_indicator(BBandUpper('BBandUpper-20-' + symbol, close_series, 20, 2)) 24 | self.add_indicator(ROC('ROC-' + symbol, self.i('LongSMA-' + symbol))) 25 | self.add_indicator(ATR('ATR-' + symbol, self.i('ATR-' + symbol))) 26 | 27 | def handle_data(self, dt, symbols, keys, data): 28 | yesterday = self.cube.go_back(dt, 1) 29 | 30 | for symbol in symbols: 31 | shortsma = self.i('ShortSMA-' + symbol) 32 | shortsma_yesterday = shortsma[yesterday] 33 | shortsma_today = shortsma[dt] 34 | longsma = self.i('LongSMA-' + symbol) 35 | longsma_yesterday = longsma[yesterday] 36 | longsma_today = longsma[dt] 37 | bbandlower = self.i('BBandLower-20-' + symbol) 38 | bbandlower_yesterday = bbandlower[yesterday] 39 | bbandlower_today = bbandlower[dt] 40 | roc = self.i('ROC-' + symbol) 41 | roc_yesterday = roc[yesterday] 42 | roc_today = roc[dt] 43 | close_yesterday = self.cube.data[(symbol, 'adjclose')][yesterday] 44 | px = data[(symbol, 'adjclose')] 45 | 46 | if roc_yesterday is not None: 47 | if roc_yesterday < -0.5: 48 | if symbol not in self.oms.portfolio.positions or not self.oms.portfolio.positions[symbol].is_open(): 49 | self.oms.add(Transaction(symbol, dt, px, 10000.0/px)) 50 | elif roc_yesterday > 0.5: 51 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 52 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 53 | 54 | def post_run(self): 55 | self.results() 56 | #for symbol in self.symbols: 57 | #self.plot(symbol=symbol, indicator_list=['ROC-' + symbol, 'Fixed-0']).show() 58 | 59 | results = {} 60 | from plot import * 61 | for stock in stocks: 62 | test = SMATest([stock], '20100101', '20130131') 63 | test.run() 64 | result = test.results() 65 | results[stock] = result 66 | 67 | pp = pprint.PrettyPrinter(indent=4) 68 | pp.pprint(results) 69 | 70 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 71 | [[test.cube.get_values(stock, 'adjclose'), test.i('LongSMA-' + stock).as_series()],[test.i('ROC-' + stock).as_series()], [test.i('LongRSMA-' + stock).as_series()]], 72 | 'Date', 73 | ['Price','Value', 'Value'], 74 | '-', 75 | [['Close', 'ShortSMA'],['ROC'], ['LongRSMA']], 76 | stock) 77 | for t in test.oms.blotter.all(symbols=stock): 78 | dt = t.dt 79 | high = test.cube.data[(stock, 'high')][dt] 80 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.05), xytext=(dt, high*1.08), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 81 | plt.show() -------------------------------------------------------------------------------- /bbcross.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | stocks = ["MMM","AA","MO","AXP","AIG","T","BA","CAT","KO","DD","XOM","GE","GM","HPQ","HD","HON","IBM","INTC","JNJ","JPM","MCD","MRK","MSFT","PFE","PG","UTX","VZ","WMT","DIS", "SPY"] 8 | stocks = ['ATVI','ADBE','AKAM','ALXN','ALTR','AMZN','AMGN','ADI','AAPL','AMAT','ADSK','ADP','AVGO','BIDU','BBBY','BIIB','BRCM','CHRW','CA','CTRX','CELG','CERN','CHTR','CHKP','CSCO','CTXS','CTSH','CMCSA','COST','XRAY','DTV','DISCA','DLTR','EBAY','EQIX','EXPE','EXPD','ESRX','FFIV','FB','FAST','FISV','FOSL','GRMN','GILD','GOOG','GMCR','HSIC','INTC','INTU','ISRG','KLAC','KRFT','LBTYA','LINTA','LLTC','MAT','MXIM','MCHP','MU','MSFT','MDLZ','MNST','MYL','NTAP','NFLX','NUAN','NVDA','ORLY','PCAR','PAYX','PCLN','QCOM','GOLD','REGN','ROST','SNDK','SBAC','STX','SHLD','SIAL','SIRI','SPLS','SBUX','SRCL','SYMC','TSLA','TXN','FOXA','VRSK','VRTX','VIAB','VIP','VOD','WDC','WFM','WYNN','XLNX','YHOO','SPY','EEM','GDX','XLF','IWM','QQQ','EWJ','FXI','VWO','EWZ','EFA','XIV','VXX','TZA','IYR','XLU','SDS','SLV','TNA','XLE','GLD','XLI','TLT','XLP','UVXY','DIA','XLK','ITB','FAZ','USO','EWT','SSO','XHB','XLV','XLY','SPXU','FAS','XLB','DXJ','DUST','JNK','EPI','XOP','NUGT','IVV','UNG','IAU','VGK','HYG','EZU','TVIX','SH','OIH','TBT','RSX','QID','VEA','VNQ','EWW','EWH','XRT','AMLP','XME','KRE','MDY','BKLN','EWG','SQQQ','EWY','EWU','VTI','TWM','DBC','UPRO','QLD','AGQ','LQD','IWF','PFF','SPXL','EWM','SPXS','EDC','FEZ','SCO','IJH','EWA','RWM','REM','EWS','IWD','EWI','UGAZ','KBE','EWC','SPLV','TQQQ','IEF'] 9 | 10 | stocks = ['SPY', 'VXX', 11 | # nasdaq 12 | 'ATVI','ADBE','AKAM','ALXN','ALTR','AMZN','AMGN','ADI','AAPL','AMAT','ADSK','ADP','AVGO','BIDU','BBBY','BIIB','BRCM','CHRW','CA','CTRX','CELG','CERN','CHTR','CHKP','CSCO','CTXS','CTSH','CMCSA','COST','XRAY','DTV','DISCA','DLTR','EBAY','EQIX','EXPE','EXPD','ESRX','FFIV','FB','FAST','FISV','FOSL','GRMN','GILD','GOOG','GMCR','HSIC','INTC','INTU','ISRG','KLAC','KRFT','LBTYA','LINTA','LMCA','LLTC','MAR','MAT','MXIM','MCHP','MU','MSFT','MDLZ','MNST','MYL','NTAP','NFLX','NUAN','NVDA','ORLY','PCAR','PAYX','PCLN','QCOM','REGN','ROST','SNDK','SBAC','STX','SHLD','SIAL','SIRI','SPLS','SBUX','SRCL','SYMC','TSLA','TXN','FOXA','VRSK','VRTX','VIAB','VIP','VOD','WDC','WFM','WYNN','XLNX','YHOO', 13 | # s&P 14 | 'A','AA','AAPL','ABBV','ABC','ABT','ACE','ACN','ACT','ADBE','ADI','ADM','ADP','ADSK','ADT','AEE','AEP','AES','AET','AFL','AGN','AIG','AIV','AIZ','AKAM','ALL','ALTR','ALXN','AMAT','AME','AMGN','AMP','AMT','AMZN','AN','ANF','AON','APA','APC','APD','APH','ARG','ATI','AVB','AVP','AVY','AXP','AZO','BA','BAC','BAX','BBBY','BBT','BBY','BCR','BDX','BEAM','BEN','BF.B','BHI','BIIB','BK','BLK','BLL','BMS','BMY','BRCM','BRK.B','BSX','BTU','BWA','BXP','C','CA','CAG','CAH','CAM','CAT','CB','CBG','CBS','CCE','CCI','CCL','CELG','CERN','CF','CFN','CHK','CHRW','CI','CINF','CL','CLF','CLX','CMA','CMCSA','CME','CMG','CMI','CMS','CNP','CNX','COF','COG','COH','COL','COP','COST','COV','CPB','CRM','CSC','CSCO','CSX','CTAS','CTL','CTSH','CTXS','CVC','CVS','CVX','D','DAL','DD','DE','DFS','DG','DGX','DHI','DHR','DIS','DISCA','DLPH','DLTR','DNB','DNR','DO','DOV','DOW','DPS','DRI','DTE','DTV','DUK','DVA','DVN','EA','EBAY','ECL','ED','EFX','EIX','EL','EMC','EMN','EMR','EOG','EQR','EQT','ESRX','ESV','ETFC','ETN','ETR','EW','EXC','EXPD','EXPE','F','FAST','FCX','FDO','FDX','FE','FFIV','FIS','FISV','FITB','FLIR','FLR','FLS','FMC','FOSL','FOXA','FRX','FSLR','FTI','FTR','GAS','GCI','GD','GE','GILD','GIS','GLW','GM','GME','GNW','GOOG','GPC','GPS','GRMN','GS','GT','GWW','HAL','HAR','HAS','HBAN','HCBK','HCN','HCP','HD','HES','HIG','HOG','HON','HOT','HP','HPQ','HRB','HRL','HRS','HSP','HST','HSY','HUM','IBM','ICE','IFF','IGT','INTC','INTU','IP','IPG','IR','IRM','ISRG','ITW','IVZ','JBL','JCI','JCP','JDSU','JEC','JNJ','JNPR','JOY','JPM','JWN','K','KEY','KIM','KLAC','KMB','KMI','KMX','KO','KR','KRFT','KSS','KSU','L','LEG','LEN','LH','LIFE','LLL','LLTC','LLY','LM','LMT','LNC','LO','LOW','LRCX','LSI','LUK','LUV','LYB','M','MA','MAC','MAR','MAS','MAT','MCD','MCHP','MCK','MCO','MDLZ','MDT','MET','MHFI','MJN','MKC','MMC','MMM','MNST','MO','MOLX','MON','MOS','MPC','MRK','MRO','MS','MSFT','MSI','MTB','MU','MUR','MWV','MYL','NBL','NBR','NDAQ','NE','NEE','NEM','NFLX','NFX','NI','NKE','NLSN','NOC','NOV','NRG','NSC','NTAP','NTRS','NU','NUE','NVDA','NWL','NWSA','OI','OKE','OMC','ORCL','ORLY','OXY','PAYX','PBCT','PBI','PCAR','PCG','PCL','PCLN','PCP','PDCO','PEG','PEP','PETM','PFE','PFG','PG','PGR','PH','PHM','PKI','PLD','PLL','PM','PNC','PNR','PNW','POM','PPG','PPL','PRGO','PRU','PSA','PSX','PVH','PWR','PX','PXD','QCOM','QEP','R','RAI','RDC','REGN','RF','RHI','RHT','RL','ROK','ROP','ROST','RRC','RSG','RTN','SBUX','SCG','SCHW','SE','SEE','SHW','SIAL','SJM','SLB','SLM','SNA','SNDK','SNI','SO','SPG','SPLS','SRCL','SRE','STI','STJ','STT','STX','STZ','SWK','SWN','SWY','SYK','SYMC','SYY','T','TAP','TDC','TE','TEG','TEL','TER','TGT','THC','TIF','TJX','TMK','TMO','TRIP','TROW','TRV','TSN','TSO','TSS','TWC','TWX','TXN','TXT','TYC','UNH','UNM','UNP','UPS','URBN','USB','UTX','V','VAR','VFC','VIAB','VLO','VMC','VNO','VRSN','VRTX','VTR','VZ','WAG','WAT','WDC','WEC','WFC','WFM','WHR','WIN','WLP','WM','WMB','WMT','WPX','WU','WY','WYN','WYNN','X','XEL','XL','XLNX','XOM','XRAY','XRX','XYL','YHOO','YUM','ZION','ZMH','ZTS', 15 | #dow 16 | 'AXP','BA','CAT','CSCO','CVX','DD','DIS','GE','GS','HD','IBM','INTC','JNJ','JPM','KO','MCD','MMM','MRK','MSFT','NKE','PFE','PG','T','TRV','UNH','UTX','V','VZ','WMT','XOM'] 17 | 18 | class BBCross(Algorithm): 19 | def __init__(self, symbols, start_date, end_date): 20 | super(BBCross, self).__init__(symbols, start_date, end_date) 21 | self.cash = 10000 22 | self.buys = {} 23 | self.stops = {} 24 | 25 | def pre_run(self): 26 | super(BBCross, self).pre_run() 27 | 28 | for symbol in self.symbols: 29 | close_series = self.cube.data[(symbol, 'close')] 30 | 31 | self.add_indicator(SMA('SMA20-' + symbol, close_series, 20)) 32 | self.add_indicator(BBandLower('BBandLower-' + symbol, close_series, 20, 2, self.i('SMA20-' + symbol))) 33 | self.add_indicator(EMA('EMA200-' + symbol, close_series, 200)) 34 | 35 | def handle_data(self, dt, symbols, keys, data): 36 | yesterday = self.cube.go_back(dt, 1) 37 | 38 | for symbol in symbols: 39 | try: 40 | px = data[(symbol, 'close')] 41 | ema200 = self.i('EMA200-' + symbol)[dt] 42 | prior_ema200 = self.i('EMA200-' + symbol)[yesterday] 43 | bb = self.i('BBandLower-' + symbol)[dt] 44 | prior_bb = self.i('BBandLower-' + symbol)[yesterday] 45 | 46 | entry_condition = prior_ema200 < prior_bb and ema200 > bb 47 | exit_condition = prior_ema200 > prior_bb and ema200 < bb 48 | 49 | if dt == datetime.datetime(2014, 1, 17): 50 | if entry_condition: 51 | print 'BUY', dt, symbol 52 | except: 53 | pass 54 | 55 | test = BBCross(stocks, '20120101', '20140117') 56 | test.run() 57 | test.results() 58 | ''' 59 | stock = stocks[0] 60 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 61 | [[test.cube.get_values(stock, 'adjclose'), test.i('EMA200-' + stock).as_series(), test.i('BBandLower-'+stock).as_series()]], 62 | 'Date', 63 | ['Price'], 64 | '-', 65 | [['Close', 'EMA200', 'BBandLower']], 66 | stock) 67 | for t in test.oms.blotter.all(symbols=stock): 68 | dt = t.dt 69 | high = test.cube.data[(stock, 'high')][dt] 70 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.02), xytext=(dt, high*1.03), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 71 | plt.show() 72 | ''' -------------------------------------------------------------------------------- /connorsrsi.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from indicators import * 5 | from plot import * 6 | import pprint 7 | 8 | stocks = ['SPY'] 9 | stocks = ['ATVI','ADBE','AKAM','ALXN','ALTR','AMZN','AMGN','ADI','AAPL','AMAT','ADSK','ADP','AVGO','BIDU','BBBY','BIIB','BRCM','CHRW','CA','CTRX','CELG','CERN','CHTR','CHKP','CSCO','CTXS','CTSH','CMCSA','COST','XRAY','DTV','DISCA','DLTR','EBAY','EQIX','EXPE','EXPD','ESRX','FFIV','FB','FAST','FISV','FOSL','GRMN','GILD','GOOG','GMCR','HSIC','INTC','INTU','ISRG','KLAC','KRFT','LBTYA','LINTA','LLTC','MAT','MXIM','MCHP','MU','MSFT','MDLZ','MNST','MYL','NTAP','NFLX','NUAN','NVDA','ORLY','PCAR','PAYX','PCLN','QCOM','GOLD','REGN','ROST','SNDK','SBAC','STX','SHLD','SIAL','SIRI','SPLS','SBUX','SRCL','SYMC','TSLA','TXN','FOXA','VRSK','VRTX','VIAB','VIP','VOD','WDC','WFM','WYNN','XLNX','YHOO','SPY','EEM','GDX','XLF','IWM','QQQ','EWJ','FXI','VWO','EWZ','EFA','XIV','VXX','TZA','IYR','XLU','SDS','SLV','TNA','XLE','GLD','XLI','TLT','XLP','UVXY','DIA','XLK','ITB','FAZ','USO','EWT','SSO','XHB','XLV','XLY','SPXU','FAS','XLB','DXJ','DUST','JNK','EPI','XOP','NUGT','IVV','UNG','IAU','VGK','HYG','EZU','TVIX','SH','OIH','TBT','RSX','QID','VEA','VNQ','EWW','EWH','XRT','AMLP','XME','KRE','MDY','BKLN','EWG','SQQQ','EWY','EWU','VTI','TWM','DBC','UPRO','QLD','AGQ','LQD','IWF','PFF','SPXL','EWM','SPXS','EDC','FEZ','SCO','IJH','EWA','RWM','REM','EWS','IWD','EWI','UGAZ','KBE','EWC','SPLV','TQQQ','IEF'] 10 | stocks = ['NFLX'] 11 | class Connors(Algorithm): 12 | def __init__(self, symbols, start_date, end_date): 13 | super(Connors, self).__init__(symbols, start_date, end_date) 14 | self.cash = 10000 15 | self.buys = {} 16 | 17 | def pre_run(self): 18 | super(Connors, self).pre_run() 19 | 20 | for symbol in self.symbols: 21 | close_series = self.cube.data[(symbol, 'close')] 22 | high_series = self.cube.data[(symbol, 'high')] 23 | low_series = self.cube.data[(symbol, 'low')] 24 | 25 | self.add_indicator(AverageGain('AG-' + symbol, close_series, 3)) 26 | self.add_indicator(AverageLoss('AL-' + symbol, close_series, 3)) 27 | self.add_indicator(RSI('RSI-' + symbol, self.i('AG-' + symbol), self.i('AL-' + symbol))) 28 | 29 | self.add_indicator(Streak('Streak-' + symbol, close_series)) 30 | self.add_indicator(AverageGain('AGStreak-' + symbol, self.i('Streak-' + symbol), 2)) 31 | self.add_indicator(AverageLoss('ALStreak-' + symbol, self.i('Streak-' + symbol), 2)) 32 | self.add_indicator(RSI('RSIStreak-' + symbol, self.i('AGStreak-' + symbol), self.i('ALStreak-' + symbol))) 33 | 34 | self.add_indicator(PercentRank('PercentRank-' + symbol, close_series, 100)) 35 | 36 | self.add_indicator(ConnorsRSI('ConnorsRSI-'+symbol, close_series, self.i('RSI-'+symbol), self.i('RSIStreak-'+symbol), self.i('PercentRank-'+symbol))) 37 | 38 | self.add_indicator(TR('TR-'+symbol, high_series, low_series, close_series)) 39 | self.add_indicator(PlusDM('PlusDM-'+symbol, high_series, low_series)) 40 | self.add_indicator(MinusDM('MinusDM-'+symbol, high_series, low_series)) 41 | self.add_indicator(Smooth('ATR-'+symbol, self.i('TR-'+symbol), 10)) 42 | self.add_indicator(Smooth('PlusDM14-'+symbol, self.i('PlusDM-'+symbol), 10)) 43 | self.add_indicator(Smooth('MinusDM14-'+symbol, self.i('MinusDM-'+symbol), 10)) 44 | self.add_indicator(DI('PlusDI-'+symbol, self.i('PlusDM14-'+symbol), self.i('ATR-'+symbol))) 45 | self.add_indicator(DI('MinusDI-'+symbol, self.i('MinusDM14-'+symbol), self.i('ATR-'+symbol))) 46 | self.add_indicator(ADX('ADX-'+symbol, self.i('PlusDI-'+symbol), self.i('MinusDI-'+symbol), 10)) 47 | 48 | def handle_data(self, dt, symbols, keys, data): 49 | yesterday = self.cube.go_back(dt, 1) 50 | 51 | for symbol in symbols: 52 | try: 53 | px = data[(symbol, 'close')] 54 | h = data[(symbol, 'high')] 55 | l = data[(symbol, 'low')] 56 | c = data[(symbol, 'close')] 57 | prior_l = self.cube.data[(symbol, 'low')][yesterday] 58 | 59 | connors_rsi = self.i('ConnorsRSI-'+symbol)[dt] 60 | adx = self.i('ADX-'+symbol)[dt] 61 | 62 | closing_range = 100 * ((px - l) / (h - l)) 63 | entry_condition = connors_rsi is not None and connors_rsi <= 10 and adx > 30 and l <= prior_l * .94 and closing_range < 25 64 | exit_condition = connors_rsi >= 80 65 | 66 | if symbol in self.buys: 67 | buy_limit_px = self.buys[symbol] 68 | if (symbol not in self.oms.portfolio.positions or self.oms.portfolio.positions[symbol].amount == 0) and l <= buy_limit_px and self.cash > 0: 69 | buy_px = min(buy_limit_px, h) 70 | qty = int(self.cash / buy_px) 71 | #qty = int(1000/buy_px) 72 | print('{} buying {} at {}'.format(dt, qty, buy_px)) 73 | self.oms.add(Transaction(symbol, dt, buy_px, qty)) 74 | self.cash = 0 75 | #print '{} removing limit to buy {}'.format(dt, buy_limit_px) 76 | del self.buys[symbol] 77 | elif entry_condition: 78 | buy_limit_px = round(px * .92, 2) 79 | self.buys[symbol] = buy_limit_px 80 | print('{} setting limit px at {} - crsi={}'.format(dt, buy_limit_px, connors_rsi)) 81 | elif symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].amount > 0: 82 | if exit_condition: 83 | print('{} exiting {} at {} - crsi={}'.format(dt, self.oms.portfolio.positions[symbol].amount, px, connors_rsi)) 84 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 85 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 86 | self.cash += gains_cash 87 | except: 88 | pass 89 | 90 | test = Connors(stocks, '20110101', '20131127') 91 | test.run() 92 | test.results() 93 | print(test.cube) 94 | stock = stocks[0] 95 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 96 | [[test.cube.get_values(stock, 'close')], [test.i('ConnorsRSI-' + stock).as_series()], [test.i('ADX-'+stock).as_series()]], 97 | 'Date', 98 | ['Price', 'Value', 'Value'], 99 | '-', 100 | [['Close'], ['ConnorsRSI'], ['ADX']], 101 | stock) 102 | for t in test.oms.blotter.all(symbols=stock): 103 | dt = t.dt 104 | high = test.cube.data[(stock, 'high')][dt] 105 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.02), xytext=(dt, high*1.03), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 106 | plt.show() 107 | 108 | #test.write_to_csv('connors.csv', indicator_list=['RSI-MTL', 'RSIStreak-MTL', 'PercentRank-MTL', 'ConnorsRSI-MTL']) -------------------------------------------------------------------------------- /cross.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | 8 | stocks = ["MMM","AA","MO","AXP","AIG","T","BA","CAT","C","KO","DD","XOM","GE","GM","HPQ","HD","HON","IBM","INTC","JNJ","JPM","MCD","MRK","MSFT","PFE","PG","UTX","VZ","WMT","DIS", "SPY"] 9 | results = {} 10 | for stock in stocks: 11 | for speriod in [2,3,5,10,15,20,30,50,100,200]: 12 | for lperiod in [2,3,5,10,15,20,30,50,100,200]: 13 | class SMATest(Algorithm): 14 | def __init__(self, symbols, start_date, end_date): 15 | super(SMATest, self).__init__(symbols, start_date, end_date) 16 | self.cash = 10000 17 | 18 | def pre_run(self): 19 | super(SMATest, self).pre_run() 20 | 21 | for symbol in self.symbols: 22 | close_series = self.cube.data[(symbol, 'adjclose')] 23 | self.add_indicator(SMA('SMA-' + symbol, close_series, speriod)) 24 | self.add_indicator(SMA('LSMA-' + symbol, close_series, lperiod)) 25 | self.add_indicator(RSMA('RSMA-' + symbol, close_series, speriod)) 26 | self.add_indicator(SMA('SSS-' + symbol, self.i('RSMA-' + symbol), speriod)) 27 | self.add_indicator(BBandLower('BBandLower-' + symbol, close_series, speriod, 2)) 28 | self.add_indicator(BBandUpper('BBandUpper-' + symbol, close_series, speriod, 2)) 29 | self.add_indicator(ROC('ROC-' + symbol, self.i('SSS-' + symbol))) 30 | self.add_indicator(VWAP('VWAP-' + symbol, close_series, self.cube.data[(symbol, 'volume')], speriod)) 31 | 32 | def handle_data(self, dt, symbols, keys, data): 33 | yesterday = self.cube.go_back(dt, 1) 34 | for symbol in symbols: 35 | vwap = self.i('VWAP-' + symbol) 36 | px = data[(symbol, 'adjclose')] 37 | shortsma = self.i('SMA-' + symbol) 38 | shortsma_yesterday = shortsma[yesterday] 39 | shortsma_today = shortsma[dt] 40 | longsma = self.i('LSMA-' + symbol) 41 | longsma_yesterday = longsma[yesterday] 42 | longsma_today = longsma[dt] 43 | 44 | if shortsma_yesterday and longsma_yesterday: 45 | if shortsma_yesterday < longsma_yesterday and shortsma_today > longsma_today: 46 | if self.cash > 0: 47 | self.oms.add(Transaction(symbol, dt, px, self.cash / px)) 48 | self.cash = 0 49 | elif shortsma_yesterday > longsma_yesterday and shortsma_today < longsma_today: 50 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 51 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 52 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 53 | self.cash += gains_cash 54 | 55 | def post_run(self): 56 | pass 57 | #self.results() 58 | #for symbol in self.symbols: 59 | # self.plot(symbol=symbol, indicator_list=['VWAP-' + symbol, 'BBandLower-' + symbol, 'BBandUpper-' + symbol, 'SMA-' + symbol, 'LSMA-' + symbol, 'RSMA-'+ symbol, 'SSS-' + symbol, 'ROC-' + symbol]).show() 60 | 61 | test = SMATest([stock], '20050101', '20130131') 62 | test.run() 63 | results[(stock, speriod, lperiod)] = test.results() 64 | ''' 65 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 66 | [[test.cube.get_values(stock, 'adjclose'), test.i('VWAP-' + stock).as_series(), test.i('SMA-' + stock).as_series(), test.i('LSMA-' + stock).as_series(), test.i('BBandLower-' + stock).as_series(), test.i('BBandUpper-' + stock).as_series()],[test.i('RSMA-' + stock).as_series(), test.i('SSS-' + stock).as_series()],[test.i('ROC-' + stock).as_series()]], 67 | 'Date', 68 | ['Price','Value', 'Value'], 69 | '-', 70 | [['Close', 'VWAP', 'SMA', 'LSMA', 'BBandLower', 'BBandUpper'],['RSMA', 'SSS'],['ROC']], 71 | stock) 72 | for t in test.oms.blotter.all(symbols=stock): 73 | dt = t.dt 74 | high = test.cube.data[(stock, 'high')][dt] 75 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.05), xytext=(dt, high*1.08), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 76 | #plt.show() 77 | ''' 78 | file = open('crossover.out', 'w') 79 | pp = pprint.PrettyPrinter(indent=4, stream=file) 80 | pp.pprint(results) -------------------------------------------------------------------------------- /data.py: -------------------------------------------------------------------------------- 1 | import yf 2 | from util import * 3 | import logging 4 | import time 5 | from datetime import datetime 6 | import itertools as it 7 | import pprint 8 | 9 | class Quote(object): 10 | def __init__(self, d, o, h, l, c, v): 11 | self.d = datetime(*(time.strptime(d, '%Y-%m-%d')[0:6])) 12 | self.o = float(o) 13 | self.h = float(h) 14 | self.l = float(l) 15 | self.c = float(c) 16 | self.v = float(v) 17 | 18 | def __str__(self): 19 | return '[' + datetime.strftime(self.d, '%Y-%m-%d') + '] ' + str(self.a) 20 | 21 | def __repr__(self): 22 | return self.__str__() 23 | 24 | class Cube(object): 25 | '''symbol -> key -> date -> value''' 26 | def __init__(self): 27 | self.dates = [] 28 | self.symbols = [] 29 | self.keys = [] 30 | self.data = {} 31 | 32 | def add_quote(self, symbol, quote): 33 | self.add(quote.d, symbol, 'open', quote.o) 34 | self.add(quote.d, symbol, 'high', quote.h) 35 | self.add(quote.d, symbol, 'low', quote.l) 36 | self.add(quote.d, symbol, 'close', quote.c) 37 | self.add(quote.d, symbol, 'volume', quote.v) 38 | 39 | def add(self, date, symbol, key, value): 40 | if date not in self.dates: 41 | self.dates.append(date) 42 | if symbol not in self.symbols: 43 | self.symbols.append(symbol) 44 | if key not in self.keys: 45 | self.keys.append(key) 46 | 47 | data_key = (symbol, key) 48 | if data_key not in self.data: 49 | self.data[data_key] = {} 50 | if date not in self.data[data_key]: 51 | self.data[data_key][date] = value 52 | 53 | def write_to_csv(self, location, extra_series = None): 54 | headings = list(it.product(self.symbols, self.keys)) 55 | 56 | out = 'date,' + ','.join(['_'.join(heading) for heading in headings]) 57 | if extra_series is not None: 58 | for series in extra_series: 59 | out += ',' + series['name'] 60 | 61 | for dt in sorted(self.dates): 62 | out += '\n' + datetime.strftime(dt, '%Y-%m-%d') + ',' + \ 63 | ','.join([str(self.data[(symbol, key)][dt]) for symbol, key in headings]) 64 | if extra_series is not None: 65 | for series in extra_series: 66 | out += ',' + str(series['data'][dt]) 67 | write_to_file(location, out) 68 | 69 | def get_dates(self): 70 | return sorted(self.dates) 71 | 72 | def go_back(self, dt, num_days): 73 | dates = self.get_dates() 74 | index_of = dates.index(dt) 75 | return dates[max(0, index_of - num_days)] 76 | 77 | def get_values(self, symbol, key): 78 | values = [] 79 | for dt in self.get_dates(): 80 | values.append(self.data[(symbol, key)][dt]) 81 | return values 82 | 83 | def pretty_print(self): 84 | pp = pprint.PrettyPrinter(indent=4) 85 | pp.pprint(self.data) 86 | 87 | def load(symbols, start, end): 88 | if type(symbols) is str: 89 | symbols = [symbols] 90 | 91 | cube = Cube() 92 | for symbol in symbols: 93 | logging.debug('Loading data for {}, {} - {}.'.format(symbol, start, end)) 94 | filename = '{}_{}_{}.pkl'.format(symbol, start, end) 95 | if file_exists(filename): 96 | data = pickle_load(filename) 97 | else: 98 | data = yf.get_historical_prices(symbol, start[:4]+'-'+start[4:6]+'-'+start[6:], end[:4]+'-'+end[4:6]+'-'+end[6:]) 99 | pickle_it(filename, data) 100 | try: 101 | for i in range(0, len(data)): 102 | d = str(data.index[i].date()) 103 | o = data.iloc[i].Open 104 | h = data.iloc[i].High 105 | l = data.iloc[i].Low 106 | c = data.iloc[i].Close 107 | v = data.iloc[i].Volume 108 | quote = Quote(d, o, h, l, c, v) 109 | cube.add_quote(symbol, quote) 110 | except Exception as e: 111 | print('Trouble getting data for {}'.format(symbol)) 112 | print('{}'.format(e)) 113 | return cube -------------------------------------------------------------------------------- /data/GOOG_20120101_20120131.pkl: -------------------------------------------------------------------------------- 1 | (lp0 2 | (lp1 3 | S'Date' 4 | p2 5 | aS'Open' 6 | p3 7 | aS'High' 8 | p4 9 | aS'Low' 10 | p5 11 | aS'Close' 12 | p6 13 | aS'Volume' 14 | p7 15 | aS'Adj Clos' 16 | p8 17 | aa(lp9 18 | S'2012-01-31' 19 | p10 20 | aS'583.00' 21 | p11 22 | aS'584.00' 23 | p12 24 | aS'575.15' 25 | p13 26 | aS'580.11' 27 | p14 28 | aS'2142400' 29 | p15 30 | aS'580.1' 31 | p16 32 | aa(lp17 33 | S'2012-01-30' 34 | p18 35 | aS'578.05' 36 | p19 37 | aS'580.00' 38 | p20 39 | aS'573.40' 40 | p21 41 | aS'577.69' 42 | p22 43 | aS'2330500' 44 | p23 45 | aS'577.6' 46 | p24 47 | aa(lp25 48 | S'2012-01-27' 49 | p26 50 | aS'570.78' 51 | p27 52 | aS'580.32' 53 | p28 54 | aS'569.33' 55 | p29 56 | aS'579.98' 57 | p30 58 | aS'3617500' 59 | p31 60 | aS'579.9' 61 | p32 62 | aa(lp33 63 | S'2012-01-26' 64 | p34 65 | aS'571.98' 66 | p35 67 | aS'574.48' 68 | p36 69 | aS'564.55' 70 | p37 71 | aS'568.10' 72 | p38 73 | aS'3226200' 74 | p39 75 | aS'568.1' 76 | p40 77 | aa(lp41 78 | S'2012-01-25' 79 | p42 80 | aS'577.51' 81 | p43 82 | aS'578.71' 83 | p44 84 | aS'566.38' 85 | p45 86 | aS'569.49' 87 | p46 88 | aS'4987700' 89 | p47 90 | aS'569.4' 91 | p48 92 | aa(lp49 93 | S'2012-01-24' 94 | p50 95 | aS'586.32' 96 | p51 97 | aS'587.68' 98 | p52 99 | aS'578.00' 100 | p53 101 | aS'580.93' 102 | p54 103 | aS'3055800' 104 | p55 105 | aS'580.9' 106 | p56 107 | aa(lp57 108 | S'2012-01-23' 109 | p58 110 | aS'586.00' 111 | p59 112 | aS'588.66' 113 | p60 114 | aS'583.16' 115 | p61 116 | aS'585.52' 117 | p62 118 | aS'3412900' 119 | p63 120 | aS'585.5' 121 | p64 122 | aa(lp65 123 | S'2012-01-20' 124 | p66 125 | aS'590.53' 126 | p67 127 | aS'591.00' 128 | p68 129 | aS'581.70' 130 | p69 131 | aS'585.99' 132 | p70 133 | aS'10576300' 134 | p71 135 | aS'585.9' 136 | p72 137 | aa(lp73 138 | S'2012-01-19' 139 | p74 140 | aS'640.99' 141 | p75 142 | aS'640.99' 143 | p76 144 | aS'631.46' 145 | p77 146 | aS'639.57' 147 | p78 148 | aS'6305300' 149 | p79 150 | aS'639.5' 151 | p80 152 | aa(lp81 153 | S'2012-01-18' 154 | p82 155 | aS'626.63' 156 | p83 157 | aS'634.00' 158 | p84 159 | aS'622.12' 160 | p85 161 | aS'632.91' 162 | p86 163 | aS'2761700' 164 | p87 165 | aS'632.9' 166 | p88 167 | aa(lp89 168 | S'2012-01-17' 169 | p90 170 | aS'631.98' 171 | p91 172 | aS'631.98' 173 | p92 174 | aS'625.68' 175 | p93 176 | aS'628.58' 177 | p94 178 | aS'1909300' 179 | p95 180 | aS'628.5' 181 | p96 182 | aa(lp97 183 | S'2012-01-13' 184 | p98 185 | aS'626.26' 186 | p99 187 | aS'626.95' 188 | p100 189 | aS'621.06' 190 | p101 191 | aS'624.99' 192 | p102 193 | aS'2307300' 194 | p103 195 | aS'624.9' 196 | p104 197 | aa(lp105 198 | S'2012-01-12' 199 | p106 200 | aS'631.22' 201 | p107 202 | aS'632.89' 203 | p108 204 | aS'626.50' 205 | p109 206 | aS'629.64' 207 | p110 208 | aS'1875200' 209 | p111 210 | aS'629.6' 211 | p112 212 | aa(lp113 213 | S'2012-01-11' 214 | p114 215 | aS'623.50' 216 | p115 217 | aS'629.39' 218 | p116 219 | aS'621.12' 220 | p117 221 | aS'625.96' 222 | p118 223 | aS'2400000' 224 | p119 225 | aS'625.9' 226 | p120 227 | aa(lp121 228 | S'2012-01-10' 229 | p122 230 | aS'629.75' 231 | p123 232 | aS'633.80' 233 | p124 234 | aS'616.91' 235 | p125 236 | aS'623.14' 237 | p126 238 | aS'4395600' 239 | p127 240 | aS'623.1' 241 | p128 242 | aa(lp129 243 | S'2012-01-09' 244 | p130 245 | aS'646.50' 246 | p131 247 | aS'647.00' 248 | p132 249 | aS'621.23' 250 | p133 251 | aS'622.46' 252 | p134 253 | aS'5822600' 254 | p135 255 | aS'622.4' 256 | p136 257 | aa(lp137 258 | S'2012-01-06' 259 | p138 260 | aS'659.15' 261 | p139 262 | aS'660.00' 263 | p140 264 | aS'649.79' 265 | p141 266 | aS'650.02' 267 | p142 268 | aS'2692900' 269 | p143 270 | aS'650.0' 271 | p144 272 | aa(lp145 273 | S'2012-01-05' 274 | p146 275 | aS'662.13' 276 | p147 277 | aS'663.97' 278 | p148 279 | aS'656.23' 280 | p149 281 | aS'659.01' 282 | p150 283 | aS'3282900' 284 | p151 285 | aS'659.0' 286 | p152 287 | aa(lp153 288 | S'2012-01-04' 289 | p154 290 | aS'665.03' 291 | p155 292 | aS'670.25' 293 | p156 294 | aS'660.62' 295 | p157 296 | aS'668.28' 297 | p158 298 | aS'2864000' 299 | p159 300 | aS'668.2' 301 | p160 302 | aa(lp161 303 | S'2012-01-03' 304 | p162 305 | aS'652.94' 306 | p163 307 | aS'668.15' 308 | p164 309 | aS'652.37' 310 | p165 311 | aS'665.41' 312 | p166 313 | aS'3676500' 314 | p167 315 | aS'665.4' 316 | p168 317 | aa. -------------------------------------------------------------------------------- /data/IBM_20120101_20120131.pkl: -------------------------------------------------------------------------------- 1 | (lp0 2 | (lp1 3 | S'Date' 4 | p2 5 | aS'Open' 6 | p3 7 | aS'High' 8 | p4 9 | aS'Low' 10 | p5 11 | aS'Close' 12 | p6 13 | aS'Volume' 14 | p7 15 | aS'Adj Clos' 16 | p8 17 | aa(lp9 18 | S'2012-01-31' 19 | p10 20 | aS'193.09' 21 | p11 22 | aS'193.10' 23 | p12 24 | aS'191.00' 25 | p13 26 | aS'192.60' 27 | p14 28 | aS'4826800' 29 | p15 30 | aS'189.4' 31 | p16 32 | aa(lp17 33 | S'2012-01-30' 34 | p18 35 | aS'189.39' 36 | p19 37 | aS'192.73' 38 | p20 39 | aS'188.22' 40 | p21 41 | aS'192.50' 42 | p22 43 | aS'4359000' 44 | p23 45 | aS'189.3' 46 | p24 47 | aa(lp25 48 | S'2012-01-27' 49 | p26 50 | aS'190.01' 51 | p27 52 | aS'191.77' 53 | p28 54 | aS'189.81' 55 | p29 56 | aS'190.46' 57 | p30 58 | aS'3360400' 59 | p31 60 | aS'187.3' 61 | p32 62 | aa(lp33 63 | S'2012-01-26' 64 | p34 65 | aS'191.79' 66 | p35 67 | aS'192.79' 68 | p36 69 | aS'190.47' 70 | p37 71 | aS'190.98' 72 | p38 73 | aS'4004700' 74 | p39 75 | aS'187.8' 76 | p40 77 | aa(lp41 78 | S'2012-01-25' 79 | p42 80 | aS'191.33' 81 | p43 82 | aS'192.24' 83 | p44 84 | aS'189.61' 85 | p45 86 | aS'191.73' 87 | p46 88 | aS'4359700' 89 | p47 90 | aS'188.5' 91 | p48 92 | aa(lp49 93 | S'2012-01-24' 94 | p50 95 | aS'188.63' 96 | p51 97 | aS'192.30' 98 | p52 99 | aS'188.52' 100 | p53 101 | aS'191.93' 102 | p54 103 | aS'5345700' 104 | p55 105 | aS'188.7' 106 | p56 107 | aa(lp57 108 | S'2012-01-23' 109 | p58 110 | aS'187.91' 111 | p59 112 | aS'190.52' 113 | p60 114 | aS'187.67' 115 | p61 116 | aS'189.98' 117 | p62 118 | aS'5751700' 119 | p63 120 | aS'186.8' 121 | p64 122 | aa(lp65 123 | S'2012-01-20' 124 | p66 125 | aS'185.77' 126 | p67 127 | aS'188.97' 128 | p68 129 | aS'184.75' 130 | p69 131 | aS'188.52' 132 | p70 133 | aS'12849700' 134 | p71 135 | aS'185.4' 136 | p72 137 | aa(lp73 138 | S'2012-01-19' 139 | p74 140 | aS'181.79' 141 | p75 142 | aS'182.36' 143 | p76 144 | aS'180.35' 145 | p77 146 | aS'180.52' 147 | p78 148 | aS'8567200' 149 | p79 150 | aS'177.5' 151 | p80 152 | aa(lp81 153 | S'2012-01-18' 154 | p82 155 | aS'179.83' 156 | p83 157 | aS'181.60' 158 | p84 159 | aS'179.50' 160 | p85 161 | aS'181.07' 162 | p86 163 | aS'4600600' 164 | p87 165 | aS'178.0' 166 | p88 167 | aa(lp89 168 | S'2012-01-17' 169 | p90 170 | aS'180.36' 171 | p91 172 | aS'182.00' 173 | p92 174 | aS'179.32' 175 | p93 176 | aS'180.00' 177 | p94 178 | aS'6003400' 179 | p95 180 | aS'177.0' 181 | p96 182 | aa(lp97 183 | S'2012-01-13' 184 | p98 185 | aS'179.48' 186 | p99 187 | aS'179.61' 188 | p100 189 | aS'177.35' 190 | p101 191 | aS'179.16' 192 | p102 193 | aS'5279200' 194 | p103 195 | aS'176.1' 196 | p104 197 | aa(lp105 198 | S'2012-01-12' 199 | p106 200 | aS'181.86' 201 | p107 202 | aS'181.91' 203 | p108 204 | aS'178.38' 205 | p109 206 | aS'180.55' 207 | p110 208 | aS'6881000' 209 | p111 210 | aS'177.5' 211 | p112 212 | aa(lp113 213 | S'2012-01-11' 214 | p114 215 | aS'180.73' 216 | p115 217 | aS'182.81' 218 | p116 219 | aS'180.50' 220 | p117 221 | aS'182.32' 222 | p118 223 | aS'4110800' 224 | p119 225 | aS'179.3' 226 | p120 227 | aa(lp121 228 | S'2012-01-10' 229 | p122 230 | aS'183.23' 231 | p123 232 | aS'183.72' 233 | p124 234 | aS'181.20' 235 | p125 236 | aS'181.31' 237 | p126 238 | aS'5161000' 239 | p127 240 | aS'178.3' 241 | p128 242 | aa(lp129 243 | S'2012-01-09' 244 | p130 245 | aS'182.20' 246 | p131 247 | aS'182.27' 248 | p132 249 | aS'180.27' 250 | p133 251 | aS'181.59' 252 | p134 253 | aS'5201200' 254 | p135 255 | aS'178.5' 256 | p136 257 | aa(lp137 258 | S'2012-01-06' 259 | p138 260 | aS'184.39' 261 | p139 262 | aS'184.48' 263 | p140 264 | aS'182.31' 265 | p141 266 | aS'182.54' 267 | p142 268 | aS'4897100' 269 | p143 270 | aS'179.5' 271 | p144 272 | aa(lp145 273 | S'2012-01-05' 274 | p146 275 | aS'184.81' 276 | p147 277 | aS'185.03' 278 | p148 279 | aS'183.10' 280 | p149 281 | aS'184.66' 282 | p150 283 | aS'4463100' 284 | p151 285 | aS'181.6' 286 | p152 287 | aa(lp153 288 | S'2012-01-04' 289 | p154 290 | aS'185.57' 291 | p155 292 | aS'186.33' 293 | p156 294 | aS'184.94' 295 | p157 296 | aS'185.54' 297 | p158 298 | aS'4346700' 299 | p159 300 | aS'182.4' 301 | p160 302 | aa(lp161 303 | S'2012-01-03' 304 | p162 305 | aS'186.73' 306 | p163 307 | aS'188.71' 308 | p164 309 | aS'186.00' 310 | p165 311 | aS'186.30' 312 | p166 313 | aS'5646000' 314 | p167 315 | aS'183.2' 316 | p168 317 | aa. -------------------------------------------------------------------------------- /data/YHOO_20120101_20120131.pkl: -------------------------------------------------------------------------------- 1 | (lp0 2 | (lp1 3 | S'Date' 4 | p2 5 | aS'Open' 6 | p3 7 | aS'High' 8 | p4 9 | aS'Low' 10 | p5 11 | aS'Close' 12 | p6 13 | aS'Volume' 14 | p7 15 | aS'Adj Clos' 16 | p8 17 | aa(lp9 18 | S'2012-01-31' 19 | p10 20 | aS'15.54' 21 | p11 22 | aS'15.62' 23 | p12 24 | aS'15.41' 25 | p13 26 | aS'15.47' 27 | p14 28 | aS'10725500' 29 | p15 30 | aS'15.4' 31 | p16 32 | aa(lp17 33 | S'2012-01-30' 34 | p18 35 | aS'15.61' 36 | p19 37 | aS'15.65' 38 | p20 39 | aS'15.50' 40 | p21 41 | aS'15.55' 42 | p22 43 | aS'11076900' 44 | p23 45 | aS'15.5' 46 | p24 47 | aa(lp25 48 | S'2012-01-27' 49 | p26 50 | aS'15.50' 51 | p27 52 | aS'15.80' 53 | p28 54 | aS'15.46' 55 | p29 56 | aS'15.74' 57 | p30 58 | aS'10859000' 59 | p31 60 | aS'15.7' 61 | p32 62 | aa(lp33 63 | S'2012-01-26' 64 | p34 65 | aS'15.63' 66 | p35 67 | aS'15.69' 68 | p36 69 | aS'15.42' 70 | p37 71 | aS'15.53' 72 | p38 73 | aS'15408400' 74 | p39 75 | aS'15.5' 76 | p40 77 | aa(lp41 78 | S'2012-01-25' 79 | p42 80 | aS'15.60' 81 | p43 82 | aS'15.71' 83 | p44 84 | aS'15.46' 85 | p45 86 | aS'15.56' 87 | p46 88 | aS'23349500' 89 | p47 90 | aS'15.5' 91 | p48 92 | aa(lp49 93 | S'2012-01-24' 94 | p50 95 | aS'15.57' 96 | p51 97 | aS'15.81' 98 | p52 99 | aS'15.55' 100 | p53 101 | aS'15.69' 102 | p54 103 | aS'17152200' 104 | p55 105 | aS'15.6' 106 | p56 107 | aa(lp57 108 | S'2012-01-23' 109 | p58 110 | aS'15.85' 111 | p59 112 | aS'15.93' 113 | p60 114 | aS'15.64' 115 | p61 116 | aS'15.68' 117 | p62 118 | aS'17864500' 119 | p63 120 | aS'15.6' 121 | p64 122 | aa(lp65 123 | S'2012-01-20' 124 | p66 125 | aS'16.11' 126 | p67 127 | aS'16.11' 128 | p68 129 | aS'15.85' 130 | p69 131 | aS'15.96' 132 | p70 133 | aS'22003800' 134 | p71 135 | aS'15.9' 136 | p72 137 | aa(lp73 138 | S'2012-01-19' 139 | p74 140 | aS'15.90' 141 | p75 142 | aS'16.15' 143 | p76 144 | aS'15.89' 145 | p77 146 | aS'16.12' 147 | p78 148 | aS'22645000' 149 | p79 150 | aS'16.1' 151 | p80 152 | aa(lp81 153 | S'2012-01-18' 154 | p82 155 | aS'15.87' 156 | p83 157 | aS'16.00' 158 | p84 159 | aS'15.69' 160 | p85 161 | aS'15.92' 162 | p86 163 | aS'35695800' 164 | p87 165 | aS'15.9' 166 | p88 167 | aa(lp89 168 | S'2012-01-17' 169 | p90 170 | aS'15.63' 171 | p91 172 | aS'15.66' 173 | p92 174 | aS'15.39' 175 | p93 176 | aS'15.43' 177 | p94 178 | aS'15334200' 179 | p95 180 | aS'15.4' 181 | p96 182 | aa(lp97 183 | S'2012-01-13' 184 | p98 185 | aS'15.65' 186 | p99 187 | aS'15.67' 188 | p100 189 | aS'15.43' 190 | p101 191 | aS'15.48' 192 | p102 193 | aS'11704700' 194 | p103 195 | aS'15.4' 196 | p104 197 | aa(lp105 198 | S'2012-01-12' 199 | p106 200 | aS'15.58' 201 | p107 202 | aS'15.73' 203 | p108 204 | aS'15.45' 205 | p109 206 | aS'15.66' 207 | p110 208 | aS'12664600' 209 | p111 210 | aS'15.6' 211 | p112 212 | aa(lp113 213 | S'2012-01-11' 214 | p114 215 | aS'15.56' 216 | p115 217 | aS'15.62' 218 | p116 219 | aS'15.35' 220 | p117 221 | aS'15.53' 222 | p118 223 | aS'10800800' 224 | p119 225 | aS'15.5' 226 | p120 227 | aa(lp121 228 | S'2012-01-10' 229 | p122 230 | aS'15.57' 231 | p123 232 | aS'15.71' 233 | p124 234 | aS'15.50' 235 | p125 236 | aS'15.51' 237 | p126 238 | aS'14048800' 239 | p127 240 | aS'15.5' 241 | p128 242 | aa(lp129 243 | S'2012-01-09' 244 | p130 245 | aS'15.59' 246 | p131 247 | aS'15.61' 248 | p132 249 | aS'15.35' 250 | p133 251 | aS'15.46' 252 | p134 253 | aS'13191900' 254 | p135 255 | aS'15.4' 256 | p136 257 | aa(lp137 258 | S'2012-01-06' 259 | p138 260 | aS'15.64' 261 | p139 262 | aS'15.66' 263 | p140 264 | aS'15.40' 265 | p141 266 | aS'15.52' 267 | p142 268 | aS'13308400' 269 | p143 270 | aS'15.5' 271 | p144 272 | aa(lp145 273 | S'2012-01-05' 274 | p146 275 | aS'15.60' 276 | p147 277 | aS'15.69' 278 | p148 279 | aS'15.44' 280 | p149 281 | aS'15.64' 282 | p150 283 | aS'19422800' 284 | p151 285 | aS'15.6' 286 | p152 287 | aa(lp153 288 | S'2012-01-04' 289 | p154 290 | aS'16.12' 291 | p155 292 | aS'16.16' 293 | p156 294 | aS'15.74' 295 | p157 296 | aS'15.78' 297 | p158 298 | aS'35655300' 299 | p159 300 | aS'15.7' 301 | p160 302 | aa(lp161 303 | S'2012-01-03' 304 | p162 305 | aS'16.27' 306 | p163 307 | aS'16.39' 308 | p164 309 | aS'16.20' 310 | p165 311 | aS'16.29' 312 | p166 313 | aS'19708600' 314 | p167 315 | aS'16.2' 316 | p168 317 | aa. -------------------------------------------------------------------------------- /data/test.csv: -------------------------------------------------------------------------------- 1 | date,GOOG_open,GOOG_high,GOOG_low,GOOG_close,GOOG_volume,GOOG_adjclose,GOOG_SMA_50,GOOG_SMA_200 2 | 2010-01-04,626.95,629.51,624.24,626.75,1956200.0,626.7,None,None 3 | 2010-01-05,627.18,627.84,621.54,623.99,3004700.0,623.9,None,None 4 | 2010-01-06,625.86,625.86,606.36,608.26,3978700.0,608.2,None,None 5 | 2010-01-07,609.4,610.0,592.65,594.1,6414300.0,594.1,None,None 6 | 2010-01-08,592.0,603.25,589.11,602.02,4724300.0,602.0,None,None 7 | 2010-01-11,604.46,604.46,594.04,601.11,7212900.0,601.1,None,None 8 | 2010-01-12,597.65,598.16,588.0,590.48,4853300.0,590.4,None,None 9 | 2010-01-13,576.49,588.38,573.9,587.09,6496600.0,587.0,None,None 10 | 2010-01-14,583.9,594.2,582.81,589.85,4240100.0,589.8,None,None 11 | 2010-01-15,593.34,593.56,578.04,580.0,5434500.0,580.0,None,None 12 | 2010-01-19,581.2,590.42,576.29,587.62,4316700.0,587.6,None,None 13 | 2010-01-20,585.98,585.98,575.29,580.41,3250700.0,580.4,None,None 14 | 2010-01-21,583.44,586.82,572.25,582.98,6307700.0,582.9,None,None 15 | 2010-01-22,564.5,570.6,534.86,550.01,6800400.0,550.0,None,None 16 | 2010-01-25,546.59,549.88,535.51,540.0,4419900.0,540.0,None,None 17 | 2010-01-26,537.97,549.6,536.29,542.42,4355500.0,542.4,None,None 18 | 2010-01-27,541.27,547.65,535.31,542.1,3964400.0,542.1,None,None 19 | 2010-01-28,544.49,547.0,530.6,534.29,3229100.0,534.2,None,None 20 | 2010-01-29,538.49,540.99,525.61,529.94,4140500.0,529.9,None,None 21 | 2010-02-01,534.6,535.81,530.3,533.02,2250800.0,533.0,None,None 22 | 2010-02-02,534.96,534.96,527.61,531.12,4096200.0,531.1,None,None 23 | 2010-02-03,528.67,542.1,528.23,540.82,2999100.0,540.8,None,None 24 | 2010-02-04,537.0,538.0,525.56,526.78,3377700.0,526.7,None,None 25 | 2010-02-05,528.4,533.5,522.46,531.29,3156000.0,531.2,None,None 26 | 2010-02-08,532.5,542.0,531.53,533.47,2694300.0,533.4,None,None 27 | 2010-02-09,539.54,541.53,535.07,536.44,2819600.0,536.4,None,None 28 | 2010-02-10,534.07,537.79,527.69,534.45,2674500.0,534.4,None,None 29 | 2010-02-11,533.32,540.49,529.5,536.4,2410000.0,536.4,None,None 30 | 2010-02-12,532.97,537.15,530.5,533.12,2279700.0,533.1,None,None 31 | 2010-02-16,536.87,544.13,534.3,541.3,3654400.0,541.3,None,None 32 | 2010-02-17,542.0,543.4,537.61,538.21,2029700.0,538.2,None,None 33 | 2010-02-18,537.54,545.01,536.14,543.22,2336900.0,543.2,None,None 34 | 2010-02-19,540.53,544.03,539.7,540.76,2553100.0,540.7,None,None 35 | 2010-02-22,547.35,547.5,541.0,542.8,2144600.0,542.8,None,None 36 | 2010-02-23,543.0,543.63,532.29,535.07,2872600.0,535.0,None,None 37 | 2010-02-24,533.98,538.44,530.51,531.47,2326600.0,531.4,None,None 38 | 2010-02-25,527.12,528.49,520.0,526.43,3309200.0,526.4,None,None 39 | 2010-02-26,527.42,531.75,523.48,526.8,2049300.0,526.8,None,None 40 | 2010-03-01,529.2,533.29,527.74,532.69,2237900.0,532.6,None,None 41 | 2010-03-02,535.48,545.66,535.01,541.06,4356800.0,541.0,None,None 42 | 2010-03-03,542.36,548.12,539.25,545.32,3089400.0,545.3,None,None 43 | 2010-03-04,546.5,556.13,546.2,554.59,3183800.0,554.5,None,None 44 | 2010-03-05,561.35,567.67,559.9,564.21,3912200.0,564.2,None,None 45 | 2010-03-08,564.78,565.18,561.01,562.48,2386400.0,562.4,None,None 46 | 2010-03-09,559.85,564.66,556.5,560.19,3176600.0,560.1,None,None 47 | 2010-03-10,563.76,578.5,562.21,576.45,5654900.0,576.4,None,None 48 | 2010-03-11,574.26,586.21,574.2,581.14,4233300.0,581.1,None,None 49 | 2010-03-12,588.14,588.28,579.16,579.54,2753400.0,579.5,None,None 50 | 2010-03-15,566.68,569.45,556.0,563.18,4653900.0,563.1,None,None 51 | 2010-03-16,561.83,568.42,560.76,565.2,3431500.0,565.2,557.608,None 52 | 2010-03-17,568.3,571.45,564.25,565.56,3321600.0,565.5,556.384,None 53 | 2010-03-18,564.72,568.44,562.96,566.4,1777200.0,566.4,555.234,None 54 | 2010-03-19,566.23,568.0,557.28,560.0,4792400.0,560.0,554.27,None 55 | 2010-03-22,556.11,566.85,554.28,557.5,4004800.0,557.5,553.538,None 56 | 2010-03-23,557.04,558.31,542.0,549.0,5501300.0,549.0,552.478,None 57 | 2010-03-24,545.51,559.85,539.7,557.33,6565200.0,557.3,551.602,None 58 | 2010-03-25,559.02,572.0,558.66,562.88,3930900.0,562.8,551.05,None 59 | 2010-03-26,565.27,567.39,560.02,562.69,2696200.0,562.6,550.562,None 60 | 2010-03-29,563.0,564.72,560.57,562.45,3104500.0,562.4,550.014,None 61 | 2010-03-30,562.83,567.63,560.28,566.71,1977900.0,566.7,549.748,None 62 | 2010-03-31,565.05,569.74,562.81,567.12,3030800.0,567.1,549.338,None 63 | 2010-04-01,571.35,573.45,565.55,568.8,2102700.0,568.8,549.106,None 64 | 2010-04-05,570.9,574.88,569.0,571.01,1901500.0,571.0,548.868,None 65 | 2010-04-06,569.46,570.89,565.4,568.22,2060100.0,568.2,549.232,None 66 | 2010-04-07,567.3,568.75,561.86,563.54,2581000.0,563.5,549.702,None 67 | 2010-04-08,563.32,569.85,560.05,567.49,1947500.0,567.4,550.202,None 68 | 2010-04-09,567.49,568.77,564.0,566.22,2056600.0,566.2,550.684,None 69 | 2010-04-12,567.35,574.0,566.22,572.73,2352400.0,572.7,551.454,None 70 | 2010-04-13,572.53,588.88,571.13,586.77,3912300.0,586.7,552.59,None 71 | 2010-04-14,590.06,592.34,584.01,589.0,3402700.0,589.0,553.71,None 72 | 2010-04-15,592.17,597.84,588.29,595.3,6761800.0,595.3,554.994,None 73 | 2010-04-16,563.0,568.81,549.63,550.15,12235500.0,550.1,555.18,None 74 | 2010-04-19,548.75,553.99,545.0,550.1,3894000.0,550.1,555.648,None 75 | 2010-04-20,554.17,559.66,551.06,555.04,2977400.0,555.0,556.124,None 76 | 2010-04-21,556.46,560.25,552.16,554.3,2391500.0,554.3,556.542,None 77 | 2010-04-22,552.0,552.5,543.35,547.06,3280700.0,547.0,556.754,None 78 | 2010-04-23,547.25,549.32,542.27,544.99,2089400.0,544.9,556.964,None 79 | 2010-04-26,544.97,544.99,529.21,531.64,4368800.0,531.6,556.868,None 80 | 2010-04-27,528.95,538.33,527.23,529.06,3844700.0,529.0,556.786,None 81 | 2010-04-28,532.1,534.83,521.03,529.19,3406100.0,529.1,556.542,None 82 | 2010-04-29,533.37,536.5,526.67,532.0,3058900.0,532.0,556.418,None 83 | 2010-04-30,531.13,537.68,525.44,525.7,2435400.0,525.7,556.068,None 84 | 2010-05-03,526.5,532.92,525.08,530.6,1857800.0,530.6,555.866,None 85 | 2010-05-04,526.52,526.74,504.21,506.37,6076300.0,506.3,555.136,None 86 | 2010-05-05,500.98,515.72,500.47,509.76,4582200.0,509.7,554.63,None 87 | 2010-05-06,508.75,517.52,460.0,498.67,5000100.0,498.6,553.974,None 88 | 2010-05-07,499.97,505.32,481.33,493.14,5089000.0,493.1,553.308,None 89 | 2010-05-10,513.97,522.82,512.6,521.65,4128000.0,521.6,553.204,None 90 | 2010-05-11,515.67,519.88,508.22,509.05,3322600.0,509.0,552.732,None 91 | 2010-05-12,512.04,512.04,502.0,505.39,3851800.0,505.3,552.018,None 92 | 2010-05-13,516.5,522.0,510.37,510.88,3325800.0,510.8,551.328,None 93 | 2010-05-14,509.77,510.99,496.25,507.53,4116000.0,507.5,550.388,None 94 | 2010-05-17,506.78,508.36,498.35,507.97,2793800.0,507.9,549.262,None 95 | 2010-05-18,510.0,510.97,497.07,498.37,2825500.0,498.3,547.98,None 96 | 2010-05-19,496.26,499.44,487.74,494.43,3445700.0,494.4,546.666,None 97 | 2010-05-20,485.07,485.58,473.8,475.01,4913300.0,475.0,544.638,None 98 | 2010-05-21,469.06,485.0,464.4,472.05,9690800.0,472.0,542.456,None 99 | 2010-05-24,480.73,489.79,476.8,477.16,4345600.0,477.1,540.408,None 100 | 2010-05-25,468.15,477.45,464.01,477.07,3017400.0,477.0,538.686,None 101 | 2010-05-26,482.07,489.76,475.0,475.47,3475600.0,475.4,536.89,None 102 | 2010-05-27,484.95,492.31,481.05,490.46,2809100.0,490.4,535.388,None 103 | 2010-05-28,492.74,493.45,483.0,485.63,2894800.0,485.6,533.772,None 104 | 2010-06-01,480.43,491.06,480.12,482.37,2666800.0,482.3,532.218,None 105 | 2010-06-02,486.68,493.87,481.46,493.37,2540800.0,493.3,530.934,None 106 | 2010-06-03,495.11,508.0,494.7,505.6,3650700.0,505.6,530.066,None 107 | 2010-06-04,499.72,509.25,496.7,498.72,3920300.0,498.7,528.894,None 108 | 2010-06-07,499.06,500.91,483.15,485.52,3632700.0,485.5,527.348,None 109 | 2010-06-08,487.85,488.84,477.54,484.78,2685100.0,484.7,525.79,None 110 | 2010-06-09,487.22,488.88,472.0,474.02,2729000.0,474.0,524.022,None 111 | 2010-06-10,480.37,488.5,475.84,487.01,2577900.0,487.0,522.428,None 112 | 2010-06-11,482.5,488.71,481.62,488.5,1781700.0,488.5,520.856,None 113 | 2010-06-14,494.48,494.5,483.19,483.19,2040400.0,483.1,519.142,None 114 | 2010-06-15,483.08,500.4,482.18,497.99,4259600.0,497.9,517.68,None 115 | 2010-06-16,496.17,504.0,496.11,501.27,2289300.0,501.2,516.34,None 116 | 2010-06-17,503.45,505.87,496.69,500.08,1977300.0,500.0,515.07,None 117 | 2010-06-18,502.51,503.47,498.13,500.03,2872900.0,500.0,513.722,None 118 | 2010-06-21,499.9,500.97,484.89,488.56,2983500.0,488.5,512.168,None 119 | 2010-06-22,489.9,496.6,485.73,486.25,2219700.0,486.2,510.438,None 120 | 2010-06-23,486.89,486.89,478.16,482.05,2029100.0,482.0,508.344,None 121 | 2010-06-24,479.66,482.75,473.26,475.1,1893600.0,475.1,506.066,None 122 | 2010-06-25,477.06,477.65,470.56,472.68,2245200.0,472.6,503.612,None 123 | 2010-06-28,472.59,477.55,469.01,472.08,1762300.0,472.0,502.05,None 124 | 2010-06-29,463.44,464.55,451.12,454.26,3502100.0,454.2,500.132,None 125 | 2010-06-30,454.96,457.83,444.72,444.95,3603200.0,444.9,497.93,None 126 | 2010-07-01,445.29,448.4,433.63,439.49,3513600.0,439.4,495.632,None 127 | 2010-07-02,441.62,442.28,436.0,436.55,1936000.0,436.5,493.422,None 128 | 2010-07-06,444.0,447.67,433.63,436.07,2560100.0,436.0,491.244,None 129 | 2010-07-07,438.31,451.29,435.38,450.2,3129700.0,450.2,489.616,None 130 | 2010-07-08,453.55,457.33,449.66,456.56,2668900.0,456.5,488.166,None 131 | 2010-07-09,471.96,473.26,462.78,467.49,4331500.0,467.4,486.932,None 132 | 2010-07-12,472.37,479.44,471.08,475.83,3334400.0,475.8,485.808,None 133 | 2010-07-13,482.25,492.99,480.28,489.2,3976300.0,489.2,485.078,None 134 | 2010-07-14,489.88,493.83,486.46,491.34,3118000.0,491.3,484.292,None 135 | 2010-07-15,491.73,494.7,482.68,494.02,4858200.0,494.0,484.046,None 136 | 2010-07-16,469.12,470.56,459.52,459.61,7824800.0,459.6,483.044,None 137 | 2010-07-19,461.01,469.65,457.52,466.18,4550300.0,466.1,482.394,None 138 | 2010-07-20,461.03,482.99,460.6,481.59,4054500.0,481.5,482.162,None 139 | 2010-07-21,484.0,485.7,475.43,477.5,3279600.0,477.5,481.28,None 140 | 2010-07-22,483.23,488.98,482.48,484.81,2147700.0,484.8,480.796,None 141 | 2010-07-23,480.77,490.59,480.01,490.06,2264400.0,490.0,480.49,None 142 | 2010-07-26,489.09,490.75,484.88,488.97,1995200.0,488.9,480.052,None 143 | 2010-07-27,490.58,497.5,490.17,492.63,2451200.0,492.6,479.754,None 144 | 2010-07-28,494.94,495.25,482.67,484.35,2496000.0,484.3,479.282,None 145 | 2010-07-29,485.95,488.88,479.33,484.99,2675500.0,484.9,479.014,None 146 | 2010-07-30,479.65,487.36,479.14,484.85,2144100.0,484.8,478.822,None 147 | 2010-08-02,488.99,493.28,486.94,490.41,1858700.0,490.4,479.13,None 148 | 2010-08-03,490.5,492.46,486.76,489.83,1802300.0,489.8,479.486,None 149 | 2010-08-04,492.18,507.0,491.05,506.32,3812500.0,506.3,480.07,None 150 | 2010-08-05,505.89,508.6,503.56,508.1,2420400.0,508.1,480.692,None 151 | 2010-08-06,505.4,505.74,496.05,500.22,3319500.0,500.2,481.188,None 152 | 2010-08-09,502.25,505.5,501.36,505.35,1872200.0,505.3,481.486,None 153 | 2010-08-10,502.35,506.0,498.57,503.71,2074000.0,503.7,481.848,None 154 | 2010-08-11,497.73,498.0,491.5,491.74,2223000.0,491.7,482.036,None 155 | 2010-08-12,483.94,494.75,482.51,492.01,2204600.0,492.0,482.01,None 156 | 2010-08-13,489.0,491.19,486.01,486.35,1934700.0,486.3,481.624,None 157 | 2010-08-16,483.68,489.87,480.5,485.59,1305000.0,485.5,481.36,None 158 | 2010-08-17,488.53,494.7,486.03,490.52,1890700.0,490.5,481.46,None 159 | 2010-08-18,490.44,490.87,481.55,482.15,2686400.0,482.1,481.408,None 160 | 2010-08-19,481.01,482.51,467.25,467.97,3925000.0,467.9,481.286,None 161 | 2010-08-20,467.97,471.59,461.02,462.02,3917600.0,462.0,480.786,None 162 | 2010-08-23,461.5,468.25,457.73,464.07,2986200.0,464.0,480.296,None 163 | 2010-08-24,457.7,458.37,450.92,451.39,2762700.0,451.3,479.66,None 164 | 2010-08-25,450.0,457.81,450.0,454.62,2592100.0,454.6,478.794,None 165 | 2010-08-26,456.06,457.26,450.44,450.98,1777000.0,450.9,477.788,None 166 | 2010-08-27,452.56,459.99,447.65,458.83,2312400.0,458.8,476.964,None 167 | 2010-08-30,459.15,459.76,452.42,452.69,1231400.0,452.6,476.016,None 168 | 2010-08-31,450.11,454.87,448.0,450.02,1946800.0,450.0,475.246,None 169 | 2010-09-01,454.98,464.94,452.5,460.33,3228300.0,460.3,474.728,None 170 | 2010-09-02,462.84,464.43,460.31,463.18,1684200.0,463.1,474.35,None 171 | 2010-09-03,470.52,471.88,467.44,470.3,2540400.0,470.3,474.254,None 172 | 2010-09-07,464.5,467.59,463.02,464.4,1709900.0,464.4,474.09,None 173 | 2010-09-08,465.19,472.5,464.51,470.58,2401800.0,470.5,474.06,None 174 | 2010-09-09,477.83,480.4,470.58,476.18,2430600.0,476.1,474.498,None 175 | 2010-09-10,479.02,479.79,475.08,476.14,1974300.0,476.1,475.122,None 176 | 2010-09-13,480.9,484.35,479.53,482.27,2241500.0,482.2,475.978,None 177 | 2010-09-14,482.01,484.75,480.08,480.43,2216500.0,480.4,476.856,None 178 | 2010-09-15,479.95,481.89,478.5,480.64,2402800.0,480.6,477.748,None 179 | 2010-09-16,479.95,482.45,479.41,481.06,1969500.0,481.0,478.364,None 180 | 2010-09-17,483.75,491.2,481.18,490.15,5641600.0,490.1,479.036,None 181 | 2010-09-20,492.5,510.41,492.06,508.28,4403500.0,508.2,479.852,None 182 | 2010-09-21,509.68,519.98,508.91,513.46,4466300.0,513.4,480.604,None 183 | 2010-09-22,512.86,517.78,511.68,516.0,2537100.0,516.0,481.14,None 184 | 2010-09-23,514.61,519.69,511.3,513.48,2317400.0,513.4,481.582,None 185 | 2010-09-24,521.74,527.83,518.26,527.29,3356900.0,527.2,482.246,None 186 | 2010-09-27,528.85,536.85,528.85,530.41,3107400.0,530.4,483.662,None 187 | 2010-09-28,533.48,533.59,518.45,527.17,3654700.0,527.1,484.882,None 188 | 2010-09-29,527.85,532.94,524.71,527.69,2172200.0,527.6,485.804,None 189 | 2010-09-30,529.16,531.87,518.92,525.79,3244100.0,525.7,486.768,None 190 | 2010-10-01,530.0,530.62,523.0,525.62,2225000.0,525.6,487.584,None 191 | 2010-10-04,524.95,528.25,518.85,522.35,1940500.0,522.3,488.23,None 192 | 2010-10-05,528.38,540.0,526.55,538.23,3507100.0,538.2,489.216,None 193 | 2010-10-06,539.26,539.95,529.94,534.35,2762300.0,534.3,490.05,None 194 | 2010-10-07,536.21,537.2,529.14,530.01,2395800.0,530.0,490.964,None 195 | 2010-10-08,532.77,537.6,527.62,536.35,2859200.0,536.3,491.992,None 196 | 2010-10-11,538.48,544.6,537.17,538.84,2626300.0,538.8,493.072,None 197 | 2010-10-12,540.12,545.99,537.79,541.39,3753600.0,541.3,494.09,None 198 | 2010-10-13,547.0,547.49,542.33,543.3,3055600.0,543.3,495.16,None 199 | 2010-10-14,544.18,545.25,537.11,540.93,6634100.0,540.9,495.852,None 200 | 2010-10-15,599.27,601.64,591.6,601.45,14824800.0,601.4,497.718,None 201 | 2010-10-18,600.55,619.69,600.55,617.71,7098200.0,617.7,500.068,518.9385 202 | 2010-10-19,608.85,614.82,602.86,607.83,4587900.0,607.8,502.118,518.844 203 | 2010-10-20,608.14,617.38,607.5,607.98,3525100.0,607.9,504.202,518.764 204 | 2010-10-21,611.51,616.0,606.0,611.99,2920500.0,611.9,506.606,518.7825 205 | 2010-10-22,611.92,614.82,610.05,612.53,2256100.0,612.5,509.016,518.8745 206 | 2010-10-25,615.59,624.74,614.97,616.5,3158400.0,616.5,511.62,518.947 207 | 2010-10-26,613.1,621.23,611.03,618.6,2512900.0,618.6,514.282,519.0345 208 | 2010-10-27,615.77,620.0,612.33,616.47,2241900.0,616.4,516.8,519.1645 209 | 2010-10-28,620.05,621.0,613.3,618.58,2184300.0,618.5,519.528,519.322 210 | 2010-10-29,617.07,619.0,612.99,613.7,2278300.0,613.7,522.444,519.4415 211 | 2010-11-01,615.73,620.66,611.21,615.0,3087100.0,615.0,525.504,519.6165 212 | 2010-11-02,618.67,620.0,614.58,615.6,1997600.0,615.6,528.536,519.7565 213 | 2010-11-03,617.5,621.83,613.5,620.18,3380500.0,620.1,531.912,519.955 214 | 2010-11-04,624.64,629.92,622.1,624.27,3570800.0,624.2,535.304,520.1615 215 | 2010-11-05,623.18,625.49,621.11,625.08,1765700.0,625.0,538.786,520.5365 216 | 2010-11-08,624.02,629.49,623.13,626.77,2101300.0,626.7,542.144,520.97 217 | 2010-11-09,630.0,630.85,620.51,624.82,2237200.0,624.8,545.588,521.382 218 | 2010-11-10,622.08,623.0,617.51,622.88,2497000.0,622.8,549.044,521.7855 219 | 2010-11-11,619.7,619.85,614.21,617.19,2261600.0,617.1,552.18,522.2 220 | 2010-11-12,613.99,616.9,601.21,603.29,3393000.0,603.2,554.982,522.5665 221 | 2010-11-15,603.08,604.0,594.05,595.47,3478900.0,595.4,557.484,522.8785 222 | 2010-11-16,592.76,597.89,583.45,583.72,3307400.0,583.7,559.87,523.1415 223 | 2010-11-17,585.0,589.5,581.37,583.55,2442500.0,583.5,562.13,523.355 224 | 2010-11-18,589.0,599.98,588.56,596.56,2590000.0,596.5,564.538,523.704 225 | 2010-11-19,597.0,597.89,590.34,590.83,2297500.0,590.8,566.832,524.002 226 | 2010-11-22,587.47,593.44,582.75,591.22,2186600.0,591.2,569.012,524.291 227 | 2010-11-23,587.01,589.01,578.2,583.01,2162600.0,583.0,571.064,524.524 228 | 2010-11-24,587.31,596.6,587.05,594.97,2396400.0,594.9,573.35,524.8265 229 | 2010-11-26,590.46,592.98,587.0,590.0,1311100.0,590.0,575.53,525.0945 230 | 2010-11-29,589.17,589.8,579.95,582.11,2859700.0,582.1,577.37,525.3395 231 | 2010-11-30,574.32,574.32,553.31,555.71,7117400.0,555.7,578.32,525.4115 232 | 2010-12-01,563.0,571.57,562.4,564.35,3754100.0,564.3,579.338,525.542 233 | 2010-12-02,568.66,573.33,565.35,571.82,2547900.0,571.8,580.454,525.685 234 | 2010-12-03,569.45,576.48,568.0,573.0,2631200.0,573.0,581.646,525.8465 235 | 2010-12-06,580.57,582.0,576.61,578.36,2093800.0,578.3,582.668,526.024 236 | 2010-12-07,591.27,593.0,586.0,587.14,3042200.0,587.1,583.802,526.2845 237 | 2010-12-08,591.97,592.52,583.69,590.54,1756900.0,590.5,585.07,526.58 238 | 2010-12-09,593.88,595.58,589.0,591.5,1868900.0,591.5,586.348,526.9055 239 | 2010-12-10,593.14,593.99,590.29,592.21,1704700.0,592.2,587.678,527.2325 240 | 2010-12-13,597.12,603.0,594.09,594.62,2398500.0,594.6,589.058,527.5425 241 | 2010-12-14,597.09,598.29,592.48,594.91,1643300.0,594.9,590.51,527.812 242 | 2010-12-15,594.2,596.45,589.15,590.3,2167700.0,590.3,591.552,528.037 243 | 2010-12-16,592.85,593.77,588.07,591.71,1596900.0,591.7,592.7,528.223 244 | 2010-12-17,591.0,592.56,587.67,590.8,3087100.0,590.8,593.916,528.356 245 | 2010-12-20,594.65,597.88,588.66,595.06,1973300.0,595.0,595.09,528.519 246 | 2010-12-21,598.57,604.72,597.61,603.07,1879500.0,603.0,596.374,528.7335 247 | 2010-12-22,604.0,607.0,603.28,605.49,1207500.0,605.4,597.656,528.8785 248 | 2010-12-23,605.34,606.0,602.03,604.23,1110800.0,604.2,598.874,528.994 249 | 2010-12-27,602.74,603.78,599.5,602.38,1208100.0,602.3,600.102,529.108 250 | 2010-12-28,602.05,603.87,598.01,598.92,1064800.0,598.9,600.052,529.287 251 | 2010-12-29,602.0,602.41,598.92,601.0,1019200.0,601.0,599.718,529.466 252 | 2010-12-30,598.0,601.33,597.39,598.86,989500.0,598.8,599.538,529.6325 253 | 2010-12-31,596.74,598.42,592.03,593.97,1539300.0,593.9,599.258,529.77 254 | 2011-01-03,596.48,605.59,596.48,604.35,2365200.0,604.3,599.106,529.9915 255 | 2011-01-04,605.62,606.18,600.12,602.12,1824500.0,602.1,598.898,530.2145 256 | 2011-01-05,600.07,610.33,600.05,609.07,2532300.0,609.0,598.748,530.5145 257 | 2011-01-06,610.68,618.43,610.05,613.5,2057800.0,613.5,598.646,530.7955 258 | 2011-01-07,615.91,618.25,610.13,616.44,2101200.0,616.4,598.646,531.0635 259 | 2011-01-10,614.8,615.39,608.56,614.21,1579200.0,614.2,598.56,531.3215 260 | 2011-01-11,617.71,618.8,614.5,616.01,1439300.0,616.0,598.606,531.5895 261 | 2011-01-12,619.35,619.35,614.77,616.87,1632700.0,616.8,598.642,531.84 262 | 2011-01-13,616.97,619.67,614.16,616.69,1334000.0,616.6,598.662,532.0875 263 | 2011-01-14,617.4,624.27,617.08,624.18,2365600.0,624.1,598.742,532.364 264 | 2011-01-18,626.06,641.99,625.27,639.63,3617000.0,639.6,599.05,532.707 265 | 2011-01-19,642.12,642.96,629.66,631.75,3406100.0,631.7,599.184,533.0245 266 | 2011-01-20,632.21,634.08,623.29,626.77,5485800.0,626.7,599.184,533.3405 267 | 2011-01-21,639.58,641.73,611.36,611.83,8904400.0,611.8,598.924,533.5625 268 | 2011-01-24,607.57,612.49,601.23,611.08,4599200.0,611.0,598.688,533.7865 269 | 2011-01-25,608.2,620.69,606.52,619.91,3646800.0,619.9,598.744,534.0225 270 | 2011-01-26,620.33,622.49,615.28,616.5,2038100.0,616.5,599.01,534.1715 271 | 2011-01-27,617.89,619.7,613.25,616.79,2019200.0,616.7,599.436,534.31 272 | 2011-01-28,619.07,620.36,599.76,600.99,4231100.0,600.9,599.78,534.338 273 | 2011-01-31,603.6,604.47,595.55,600.36,2804900.0,600.3,600.116,534.589 274 | 2011-02-01,604.49,613.35,603.11,611.04,2745300.0,611.0,600.406,534.8935 275 | 2011-02-02,611.0,614.34,607.53,612.0,1760700.0,612.0,600.83,535.1785 276 | 2011-02-03,609.48,611.45,606.13,610.15,1495100.0,610.1,601.208,535.4575 277 | 2011-02-04,610.15,611.44,606.61,610.98,1550800.0,610.9,601.766,535.777 278 | 2011-02-07,610.16,618.39,609.21,614.29,1799600.0,614.2,602.152,536.1235 279 | 2011-02-08,614.93,619.63,614.51,618.38,1694900.0,618.3,602.718,536.557 280 | 2011-02-09,616.87,619.45,612.34,616.5,1842500.0,616.5,603.406,536.9945 281 | 2011-02-10,613.9,617.5,611.56,616.44,2334400.0,616.4,604.62,537.431 282 | 2011-02-11,613.79,625.0,613.0,624.5,2589900.0,624.5,605.824,537.8935 283 | 2011-02-14,623.34,629.64,620.04,628.15,2128000.0,628.1,606.95,538.4055 284 | 2011-02-15,627.32,630.09,623.1,624.15,2092000.0,624.1,607.972,538.873 285 | 2011-02-16,625.63,626.5,622.1,624.22,1684000.0,624.2,608.89,539.4625 286 | 2011-02-17,621.25,627.25,620.28,625.26,1478800.0,625.2,609.652,540.04 287 | 2011-02-18,626.0,631.18,624.18,630.08,3217900.0,630.0,610.442,540.697 288 | 2011-02-22,620.03,624.93,607.77,610.21,3639900.0,610.2,610.816,541.2825 289 | 2011-02-23,610.33,614.7,604.0,611.32,2889600.0,611.3,611.198,541.731 290 | 2011-02-24,611.39,613.09,601.35,608.82,2711700.0,608.8,611.482,542.23 291 | 2011-02-25,611.86,614.72,609.5,610.04,1932400.0,610.0,611.784,542.7535 292 | 2011-02-28,610.0,616.49,608.01,613.4,2281500.0,613.4,612.246,543.2665 293 | 2011-03-01,617.78,619.22,599.3,600.76,3323200.0,600.7,612.426,543.7325 294 | 2011-03-02,599.8,606.0,595.19,600.79,2026700.0,600.7,612.624,544.1965 295 | 2011-03-03,606.38,611.49,605.0,609.56,1945300.0,609.5,612.914,544.7525 296 | 2011-03-04,608.33,608.98,600.2,600.62,3011000.0,600.6,612.866,545.2835 297 | 2011-03-07,600.55,603.69,587.0,591.66,3462700.0,591.6,612.59,545.8665 298 | 2011-03-08,592.93,597.98,590.2,592.31,2284900.0,592.3,612.352,546.468 299 | 2011-03-09,591.0,594.51,585.75,591.77,2151000.0,591.7,612.14,547.041 300 | 2011-03-10,585.44,586.62,579.45,580.3,3128100.0,580.3,611.768,547.5575 301 | 2011-03-11,578.22,580.0,573.33,576.71,3032000.0,576.7,611.282,548.064 302 | 2011-03-14,572.8,578.29,568.02,569.99,2816100.0,569.9,610.704,548.4615 303 | 2011-03-15,557.5,571.0,555.5,569.56,4005600.0,569.5,610.216,548.881 304 | 2011-03-16,568.01,569.79,551.28,557.1,3798500.0,557.1,609.272,549.255 305 | 2011-03-17,564.48,569.0,560.54,561.36,2899300.0,561.3,608.456,549.595 306 | 2011-03-18,564.64,567.99,559.74,561.06,3298600.0,561.0,607.496,549.872 307 | 2011-03-21,570.22,579.8,569.02,576.5,3020900.0,576.5,606.756,550.261 308 | 2011-03-22,577.27,579.23,572.51,577.32,1886900.0,577.3,605.974,550.72 309 | 2011-03-23,575.19,582.45,572.0,582.16,1816200.0,582.1,605.332,551.207 310 | 2011-03-24,585.43,588.39,578.8,586.89,2098700.0,586.8,604.748,551.771 311 | 2011-03-25,586.88,586.91,579.24,579.74,2858400.0,579.7,604.006,552.2345 312 | 2011-03-28,582.07,584.99,574.71,575.36,2218400.0,575.3,603.18,552.6685 313 | 2011-03-29,576.0,581.89,573.01,581.73,1604800.0,581.7,602.332,553.1615 314 | 2011-03-30,584.38,585.5,580.58,581.84,1422300.0,581.8,601.176,553.581 315 | 2011-03-31,583.0,588.16,581.74,586.76,2029400.0,586.7,600.276,554.0085 316 | 2011-04-01,588.76,595.19,588.76,591.8,2613200.0,591.8,599.578,554.4675 317 | 2011-04-04,593.0,594.74,583.1,587.68,2054500.0,587.6,599.094,554.9055 318 | 2011-04-05,581.08,581.49,565.68,569.09,6047500.0,569.0,598.254,555.308 319 | 2011-04-06,572.18,575.16,568.0,574.18,2668300.0,574.1,597.338,555.7475 320 | 2011-04-07,575.73,580.64,574.19,580.0,2531500.0,580.0,596.608,556.2375 321 | 2011-04-08,584.89,584.89,578.06,578.16,1901800.0,578.1,595.836,556.7525 322 | 2011-04-11,576.2,578.1,573.0,577.37,1858200.0,577.3,595.364,557.276 323 | 2011-04-12,575.0,576.91,568.05,570.61,2085600.0,570.6,594.77,557.769 324 | 2011-04-13,575.51,577.6,571.75,576.28,2069400.0,576.2,594.074,558.379 325 | 2011-04-14,575.19,579.45,572.1,578.51,5456300.0,578.5,593.404,559.047 326 | 2011-04-15,545.29,545.75,530.06,530.7,14043700.0,530.7,591.816,559.5035 327 | 2011-04-18,526.42,527.66,519.0,526.84,5039800.0,526.8,590.134,559.955 328 | 2011-04-19,529.95,530.88,520.9,521.53,2684100.0,521.5,588.28,560.3825 329 | 2011-04-20,525.9,526.82,521.39,525.73,3060000.0,525.7,586.428,560.76 330 | 2011-04-21,527.49,528.28,522.39,525.1,2470100.0,525.1,584.6,561.103 331 | 2011-04-25,525.25,527.0,522.01,525.05,1630800.0,525.0,582.772,561.391 332 | 2011-04-26,526.52,537.44,525.21,532.82,3500000.0,532.8,580.938,561.676 333 | 2011-04-27,538.0,538.11,534.35,537.76,2298400.0,537.7,579.13,561.9185 334 | 2011-04-28,538.06,539.25,534.08,537.97,2000000.0,537.9,577.406,562.1515 335 | 2011-04-29,540.0,544.1,538.51,544.1,4228500.0,544.1,575.804,562.402 336 | 2011-05-02,545.7,545.73,537.12,538.56,2133700.0,538.5,574.07,562.7965 337 | 2011-05-03,537.13,542.01,529.63,533.89,2081500.0,533.8,572.146,563.135 338 | 2011-05-04,535.17,539.0,533.02,535.79,2117000.0,535.7,570.656,563.406 339 | 2011-05-05,533.86,539.42,531.5,534.27,1997800.0,534.2,569.114,563.6895 340 | 2011-05-06,538.15,541.46,535.18,535.3,2056100.0,535.3,567.644,563.942 341 | 2011-05-09,535.0,538.49,531.1,537.68,1948700.0,537.6,566.196,564.18 342 | 2011-05-10,540.0,544.43,537.54,542.66,2042900.0,542.6,564.78,564.4485 343 | 2011-05-11,540.14,543.55,533.69,535.45,2338800.0,535.4,563.474,564.6625 344 | 2011-05-12,535.24,536.94,530.91,535.05,1448300.0,535.0,562.16,564.916 345 | 2011-05-13,534.61,535.92,529.05,529.55,2108700.0,529.5,560.56,565.139 346 | 2011-05-16,526.31,527.27,516.4,518.42,2958200.0,518.4,558.916,565.307 347 | 2011-05-17,515.43,531.22,515.03,530.46,3303600.0,530.4,557.692,565.507 348 | 2011-05-18,529.54,530.33,525.7,529.81,1953200.0,529.8,556.442,565.707 349 | 2011-05-19,532.73,536.54,529.72,531.25,2468700.0,531.2,555.232,565.8315 350 | 2011-05-20,531.8,531.99,523.13,524.03,2317500.0,524.0,554.106,565.911 351 | 2011-05-23,516.6,520.0,513.4,518.39,2300000.0,518.3,552.938,566.0015 352 | 2011-05-24,520.37,523.96,518.15,518.26,1900000.0,518.2,551.904,566.066 353 | 2011-05-25,519.67,522.77,517.25,519.67,1301600.0,519.6,550.906,566.1455 354 | 2011-05-26,517.7,522.12,515.0,518.13,2118500.0,518.1,550.126,566.2775 355 | 2011-05-27,518.48,521.79,516.3,520.9,1745800.0,520.9,549.318,566.422 356 | 2011-05-31,525.0,529.05,523.5,529.02,2687300.0,529.0,548.678,566.6355 357 | 2011-06-01,528.04,533.2,525.31,525.6,2955900.0,525.6,547.66,566.836 358 | 2011-06-02,527.57,530.3,522.48,528.06,2204500.0,528.0,546.674,567.0235 359 | 2011-06-03,522.0,527.6,521.5,523.08,1748500.0,523.0,545.492,567.228 360 | 2011-06-06,523.54,526.82,519.25,521.06,1942100.0,521.0,544.176,567.4935 361 | 2011-06-07,522.89,524.63,518.99,519.03,1907600.0,519.0,542.962,567.7785 362 | 2011-06-08,516.53,521.24,515.78,519.17,1653400.0,519.1,541.838,568.054 363 | 2011-06-09,520.0,520.0,515.64,516.73,1689100.0,516.7,540.538,568.381 364 | 2011-06-10,514.08,516.69,509.29,509.51,2439900.0,509.5,539.092,568.6555 365 | 2011-06-13,510.0,510.2,502.17,504.73,2427300.0,504.7,537.452,568.9245 366 | 2011-06-14,508.15,514.08,506.99,508.37,2341500.0,508.3,535.782,569.172 367 | 2011-06-15,505.03,508.35,500.61,502.95,2073300.0,502.9,534.088,569.4235 368 | 2011-06-16,502.81,506.57,496.67,500.37,2757000.0,500.3,532.714,569.675 369 | 2011-06-17,506.18,506.69,484.8,485.02,5245400.0,485.0,530.932,569.7985 370 | 2011-06-20,485.0,486.23,479.23,484.58,3028600.0,484.5,529.022,569.9055 371 | 2011-06-21,487.19,493.94,484.73,493.0,2765400.0,493.0,527.32,570.019 372 | 2011-06-22,491.45,492.35,486.73,487.01,2407100.0,487.0,525.514,570.132 373 | 2011-06-23,482.13,482.86,473.73,480.22,4801700.0,480.2,523.706,570.1805 374 | 2011-06-24,480.68,480.75,473.02,474.88,3805600.0,474.8,521.678,570.174 375 | 2011-06-27,474.0,488.4,473.6,482.8,3444700.0,482.8,519.764,570.2075 376 | 2011-06-28,484.02,496.21,484.02,493.65,2715100.0,493.6,519.022,570.2645 377 | 2011-06-29,496.54,500.25,492.38,497.57,2343000.0,497.5,518.436,570.35 378 | 2011-06-30,501.99,506.67,501.5,506.38,2428400.0,506.3,518.132,570.4785 379 | 2011-07-01,506.74,521.18,506.38,521.03,3636700.0,521.0,518.038,570.6785 380 | 2011-07-05,525.3,535.4,525.3,532.44,3849200.0,532.4,518.184,570.89 381 | 2011-07-06,533.5,538.51,533.04,535.36,2695600.0,535.3,518.39,571.0255 382 | 2011-07-07,541.0,550.68,535.88,546.6,3935500.0,546.6,518.666,571.1915 383 | 2011-07-08,532.95,537.65,527.27,531.99,4770200.0,531.9,518.55,571.271 384 | 2011-07-11,528.18,535.98,525.5,527.28,2839300.0,527.2,518.336,571.34 385 | 2011-07-12,528.16,539.42,526.0,534.01,2841200.0,534.0,518.134,571.374 386 | 2011-07-13,537.0,544.0,536.48,538.26,2790200.0,538.2,518.128,571.413 387 | 2011-07-14,539.12,542.0,526.73,528.94,6649500.0,528.9,518.03,571.422 388 | 2011-07-15,597.5,600.25,588.16,597.62,13732100.0,597.6,519.268,571.772 389 | 2011-07-18,592.49,602.05,592.0,594.94,4468300.0,594.9,520.482,572.118 390 | 2011-07-19,596.14,604.68,595.53,602.55,2967500.0,602.5,521.826,572.5025 391 | 2011-07-20,602.18,602.83,595.35,595.35,2227800.0,595.3,522.98,572.8675 392 | 2011-07-21,594.03,608.06,594.01,606.99,3469500.0,606.9,524.266,573.211 393 | 2011-07-22,605.39,619.5,604.27,618.23,3528200.0,618.2,525.922,573.6305 394 | 2011-07-25,613.36,625.41,613.0,618.98,3131600.0,618.9,527.6,574.075 395 | 2011-07-26,618.05,627.5,617.22,622.52,2342900.0,622.5,529.46,574.506 396 | 2011-07-27,617.18,620.95,604.75,607.22,3934400.0,607.2,531.236,574.848 397 | 2011-07-28,605.19,615.98,603.0,610.94,3108400.0,610.9,532.846,575.196 398 | 2011-07-29,604.23,614.96,603.69,603.69,4137400.0,603.6,534.322,575.4975 399 | 2011-08-01,611.22,615.5,599.18,606.77,3966100.0,606.7,535.832,575.8265 400 | 2011-08-02,606.0,609.67,591.57,592.4,3200600.0,592.4,537.2,575.7815 401 | 2011-08-03,594.27,603.0,583.63,601.17,3825700.0,601.1,538.856,575.6985 402 | 2011-08-04,594.5,598.85,577.47,577.52,4914600.0,577.5,540.042,575.547 403 | 2011-08-05,582.54,590.0,562.0,579.04,5929100.0,579.0,541.23,575.4025 404 | 2011-08-08,562.98,569.0,544.35,546.02,7496600.0,546.0,541.788,575.073 405 | 2011-08-09,561.0,574.61,541.01,573.41,6469700.0,573.4,542.838,574.8775 406 | 2011-08-10,561.38,564.12,547.73,549.01,5369600.0,549.0,543.238,574.54 407 | 2011-08-11,553.82,568.5,548.41,562.13,4830600.0,562.1,543.968,574.2575 408 | 2011-08-12,569.5,570.5,560.4,563.77,3154300.0,563.7,544.682,573.994 409 | 2011-08-15,553.43,564.99,546.05,557.23,7144900.0,557.2,545.366,573.6875 410 | 2011-08-16,552.43,552.44,530.3,539.0,6939400.0,539.0,545.726,573.314 411 | 2011-08-17,540.03,543.69,530.77,533.15,4079100.0,533.1,546.008,572.9045 412 | 2011-08-18,523.47,524.89,500.49,504.88,6290700.0,504.8,545.722,572.3505 413 | 2011-08-19,499.34,514.87,490.86,490.92,5410000.0,490.9,545.206,571.7045 414 | 2011-08-22,504.0,507.0,494.53,498.17,4905900.0,498.1,544.978,571.074 415 | 2011-08-23,503.5,521.41,499.06,518.82,4346800.0,518.8,545.26,570.543 416 | 2011-08-24,519.33,530.0,517.23,523.29,3594500.0,523.2,545.558,570.0255 417 | 2011-08-25,530.38,537.27,518.3,520.04,3293000.0,520.0,545.9,569.5015 418 | 2011-08-26,519.99,530.45,513.14,526.86,3596300.0,526.8,546.43,569.0215 419 | 2011-08-29,534.56,539.45,533.56,539.08,2335800.0,539.0,547.51,568.631 420 | 2011-08-30,538.19,542.99,530.81,540.7,2989000.0,540.7,548.634,568.3185 421 | 2011-08-31,544.74,546.3,536.0,540.96,2693300.0,540.9,549.592,568.046 422 | 2011-09-01,540.75,543.83,531.22,532.5,2415500.0,532.5,550.502,567.79 423 | 2011-09-02,524.47,527.92,520.73,524.84,2401200.0,524.8,551.394,567.4965 424 | 2011-09-06,510.8,522.76,510.5,522.18,2715800.0,522.1,552.34,567.1245 425 | 2011-09-07,530.45,535.94,527.4,534.03,2755800.0,534.0,553.364,566.8405 426 | 2011-09-08,533.8,539.1,531.9,534.96,2380500.0,534.9,554.19,566.559 427 | 2011-09-09,531.4,534.65,521.19,524.85,3268800.0,524.8,554.736,566.268 428 | 2011-09-12,517.96,531.99,517.5,530.12,2670400.0,530.1,555.212,565.944 429 | 2011-09-13,532.0,533.88,523.4,529.52,2354200.0,529.5,555.382,565.6415 430 | 2011-09-14,532.59,536.95,525.82,532.07,2694400.0,532.0,555.374,565.391 431 | 2011-09-15,535.5,544.98,534.56,542.56,2960800.0,542.5,555.518,565.325 432 | 2011-09-16,544.8,546.84,543.14,546.68,3534300.0,546.6,555.518,565.2365 433 | 2011-09-19,540.35,549.9,535.38,546.67,2468400.0,546.6,555.812,565.1105 434 | 2011-09-20,549.4,558.52,542.67,546.63,2779100.0,546.6,556.2,564.9785 435 | 2011-09-21,547.69,555.0,538.86,539.2,2514300.0,539.2,556.304,564.783 436 | 2011-09-22,526.25,528.78,514.0,520.66,4400300.0,520.6,555.952,564.4505 437 | 2011-09-23,516.56,526.42,514.5,525.51,2777300.0,525.5,555.884,564.1255 438 | 2011-09-26,527.25,532.93,513.25,531.89,2634200.0,531.8,554.568,563.827 439 | 2011-09-27,538.2,547.05,536.05,539.34,3010900.0,539.3,553.456,563.5625 440 | 2011-09-28,541.5,544.02,527.7,528.84,2263300.0,528.8,551.982,563.2335 441 | 2011-09-29,536.04,537.3,519.41,527.5,2906600.0,527.5,550.626,562.8965 442 | 2011-09-30,520.21,524.0,514.38,515.04,2723600.0,515.0,548.788,562.52 443 | 2011-10-03,509.85,512.0,495.0,495.52,4474400.0,495.5,546.334,562.039 444 | 2011-10-04,490.03,503.44,480.6,501.9,4158800.0,501.9,543.994,561.5945 445 | 2011-10-05,496.35,507.8,480.77,504.7,4534100.0,504.7,541.638,561.143 446 | 2011-10-06,507.5,515.23,502.6,514.71,3424300.0,514.7,539.788,560.7015 447 | 2011-10-07,516.83,520.5,510.3,515.12,2855900.0,515.1,537.872,560.25 448 | 2011-10-10,525.18,537.47,523.2,537.17,2322200.0,537.1,536.542,559.9145 449 | 2011-10-11,533.46,546.8,533.46,543.18,2853400.0,543.1,535.27,559.6185 450 | 2011-10-12,548.13,555.23,544.63,548.5,3177800.0,548.5,534.392,559.3665 451 | 2011-10-13,550.03,559.0,548.02,558.99,5687600.0,558.9,533.548,559.156 452 | 2011-10-14,599.47,599.6,587.57,591.68,8529900.0,591.6,533.83,559.12 453 | 2011-10-17,583.72,591.83,578.0,582.41,4008200.0,582.4,533.898,559.0625 454 | 2011-10-18,580.19,592.56,577.4,590.51,3800800.0,590.5,534.788,558.9935 455 | 2011-10-19,587.34,592.06,579.22,580.7,2931500.0,580.7,534.934,558.8865 456 | 2011-10-20,581.9,588.89,579.51,583.67,3379000.0,583.6,535.626,558.7595 457 | 2011-10-21,589.51,592.75,586.7,590.49,3391000.0,590.4,536.192,558.644 458 | 2011-10-24,586.72,599.97,586.5,596.42,3426900.0,596.4,536.846,558.544 459 | 2011-10-25,593.1,595.0,582.85,583.16,2540500.0,583.1,537.364,558.3885 460 | 2011-10-26,589.55,590.18,572.86,586.31,2873100.0,586.3,538.31,558.24 461 | 2011-10-27,598.42,602.7,593.3,598.67,3780300.0,598.6,539.62,558.149 462 | 2011-10-28,594.52,602.3,594.25,600.14,2508000.0,600.1,541.526,558.0665 463 | 2011-10-31,595.09,599.69,591.67,592.64,2557800.0,592.6,543.56,557.909 464 | 2011-11-01,580.1,585.51,576.75,578.65,3125100.0,578.6,545.17,557.604 465 | 2011-11-02,584.9,587.96,580.48,584.82,2120900.0,584.8,546.49,557.3695 466 | 2011-11-03,587.0,597.5,583.72,597.5,2669800.0,597.5,547.976,557.2235 467 | 2011-11-04,593.5,599.74,592.43,596.14,2834800.0,596.1,549.498,557.145 468 | 2011-11-07,593.32,608.78,592.23,608.33,3357400.0,608.3,551.128,557.1315 469 | 2011-11-08,609.0,614.37,603.6,612.34,3029400.0,612.3,552.594,557.0935 470 | 2011-11-09,604.26,609.39,598.66,600.95,3711000.0,600.9,553.798,557.0155 471 | 2011-11-10,605.93,605.95,591.56,595.08,2868400.0,595.0,554.88,556.907 472 | 2011-11-11,601.3,612.09,598.6,608.35,3977000.0,608.3,556.396,556.944 473 | 2011-11-14,608.0,618.08,607.78,613.0,3188700.0,613.0,558.16,557.0075 474 | 2011-11-15,612.8,618.08,610.5,616.56,2676000.0,616.5,560.048,557.035 475 | 2011-11-16,612.08,618.3,610.61,611.47,2608500.0,611.4,561.596,557.032 476 | 2011-11-17,610.05,612.29,596.78,600.87,3493300.0,600.8,562.914,556.9855 477 | 2011-11-18,602.0,604.5,593.75,594.88,3287700.0,594.8,564.314,556.905 478 | 2011-11-21,587.76,588.5,572.09,580.94,3001300.0,580.9,565.33,556.7385 479 | 2011-11-22,580.0,584.97,575.24,580.0,2405300.0,580.0,566.34,556.547 480 | 2011-11-23,575.35,580.25,570.11,570.11,2325800.0,570.1,567.102,556.315 481 | 2011-11-25,565.19,574.27,561.33,563.0,1562400.0,563.0,567.512,556.048 482 | 2011-11-28,579.37,588.82,576.5,588.19,2828900.0,588.1,568.342,555.866 483 | 2011-11-29,587.88,590.36,581.33,582.93,1831800.0,582.9,569.068,555.64 484 | 2011-11-30,597.95,599.51,592.09,599.39,3397000.0,599.3,570.122,555.516 485 | 2011-12-01,600.0,616.0,599.0,613.77,3620600.0,613.7,571.612,555.4635 486 | 2011-12-02,617.05,624.0,616.26,620.36,4085700.0,620.3,573.606,555.439 487 | 2011-12-05,627.64,631.9,622.4,625.65,3197500.0,625.6,575.608,555.417 488 | 2011-12-06,622.99,628.62,620.24,623.77,2326500.0,623.7,577.446,555.4845 489 | 2011-12-07,621.68,625.66,618.1,623.39,2257300.0,623.3,579.126,555.5445 490 | 2011-12-08,621.04,627.45,615.3,616.05,2413100.0,616.0,580.87,555.5805 491 | 2011-12-09,618.0,629.13,617.01,627.42,2766200.0,627.4,582.868,555.6675 492 | 2011-12-12,621.88,626.18,620.29,625.39,2183900.0,625.3,585.074,555.727 493 | 2011-12-13,628.76,636.56,622.85,625.63,4028200.0,625.6,587.676,555.8515 494 | 2011-12-14,621.85,624.32,612.49,618.07,3903700.0,618.0,589.998,555.938 495 | 2011-12-15,622.52,624.0,618.69,619.54,2408600.0,619.5,592.294,555.988 496 | 2011-12-16,624.32,629.32,621.47,625.96,4459300.0,625.9,594.518,556.1145 497 | 2011-12-19,628.01,628.5,620.0,621.83,2143500.0,621.8,596.652,556.2655 498 | 2011-12-20,628.0,631.84,627.99,630.37,2388200.0,630.3,598.516,556.4555 499 | 2011-12-21,630.01,631.82,618.96,625.82,2497900.0,625.8,600.17,556.626 500 | 2011-12-22,627.95,631.73,627.01,629.7,1822300.0,629.7,601.794,556.873 501 | 2011-12-23,632.0,634.68,630.56,633.14,1453700.0,633.1,603.278,557.155 502 | 2011-12-27,632.05,644.49,632.0,640.25,1606400.0,640.2,604.25,557.5065 503 | 2011-12-28,642.75,645.0,638.1,639.7,2127200.0,639.7,605.396,557.8575 504 | 2011-12-29,641.49,643.0,635.2,642.4,1575400.0,642.4,606.434,558.284 505 | 2011-12-30,642.02,646.76,642.02,645.9,1782300.0,645.9,607.738,558.707 506 | 2012-01-03,652.94,668.15,652.37,665.41,3676500.0,665.4,609.374,559.229 507 | 2012-01-04,665.03,670.25,660.62,668.28,2864000.0,668.2,610.93,559.6875 508 | 2012-01-05,662.13,663.97,656.23,659.01,3282900.0,659.0,612.182,560.096 509 | 2012-01-06,659.15,660.0,649.79,650.02,2692900.0,650.0,613.52,560.4355 510 | 2012-01-09,646.5,647.0,621.23,622.46,5822600.0,622.4,614.242,560.6135 511 | 2012-01-10,629.75,633.8,616.91,623.14,4395600.0,623.1,614.732,560.8305 512 | 2012-01-11,623.5,629.39,621.12,625.96,2400000.0,625.9,615.248,561.0835 513 | 2012-01-12,631.22,632.89,626.5,629.64,1875200.0,629.6,615.988,561.323 514 | 2012-01-13,626.26,626.95,621.06,624.99,2307300.0,624.9,616.914,561.5385 515 | 2012-01-17,631.98,631.98,625.68,628.58,1909300.0,628.5,617.788,561.7475 516 | 2012-01-18,626.63,634.0,622.12,632.91,2761700.0,632.9,618.496,561.953 517 | 2012-01-19,640.99,640.99,631.46,639.57,6305300.0,639.5,619.364,562.2125 518 | 2012-01-20,590.53,591.0,581.7,585.99,10576300.0,585.9,618.916,562.297 519 | 2012-01-23,586.0,588.66,583.16,585.52,3412900.0,585.5,618.38,562.354 520 | 2012-01-24,586.32,587.68,578.0,580.93,3055800.0,580.9,617.98,562.3585 521 | 2012-01-25,577.51,578.71,566.38,569.49,4987700.0,569.4,617.468,562.315 522 | 2012-01-26,571.98,574.48,564.55,568.1,3226200.0,568.1,616.664,562.269 523 | 2012-01-27,570.78,580.32,569.33,579.98,3617500.0,579.9,616.002,562.3155 524 | 2012-01-30,578.05,580.0,573.4,577.69,2330500.0,577.6,615.224,562.3225 525 | 2012-01-31,583.0,584.0,575.15,580.11,2142400.0,580.1,614.598,562.3305 526 | 2012-02-01,584.94,585.5,579.14,580.83,2320700.0,580.8,614.198,562.581 527 | 2012-02-02,584.87,586.41,582.08,585.11,2414700.0,585.1,614.004,562.8725 528 | 2012-02-03,590.66,597.07,588.05,596.33,3168500.0,596.3,614.312,563.2465 529 | 2012-02-06,595.01,610.83,594.01,609.09,3679600.0,609.0,614.892,563.663 530 | 2012-02-07,607.15,609.39,603.76,606.77,2092100.0,606.7,615.624,564.071 531 | 2012-02-08,608.64,611.35,604.74,609.85,1836400.0,609.8,616.56,564.495 532 | 2012-02-09,612.02,614.5,609.0,611.46,2264700.0,611.4,617.026,564.888 533 | 2012-02-10,607.88,608.13,604.0,605.91,2325200.0,605.9,617.486,565.229 534 | 2012-02-13,610.5,613.84,610.02,612.2,1816300.0,612.2,617.744,565.6005 535 | 2012-02-14,611.54,612.0,604.76,609.76,1803700.0,609.7,617.664,565.9285 536 | 2012-02-15,612.93,612.93,602.56,605.56,2425900.0,605.5,617.368,566.2635 537 | 2012-02-16,602.82,608.81,597.73,606.52,2530900.0,606.5,616.986,566.627 538 | 2012-02-17,604.97,607.63,602.4,604.64,2449100.0,604.6,616.604,566.9715 539 | 2012-02-21,603.87,617.88,602.88,614.0,2480800.0,614.0,616.418,567.3705 540 | 2012-02-22,611.96,616.78,606.71,607.94,1967000.0,607.9,616.256,567.7335 541 | 2012-02-23,607.0,607.94,600.35,606.11,2055000.0,606.1,615.83,568.076 542 | 2012-02-24,607.35,611.65,605.51,609.9,1935600.0,609.9,615.522,568.4125 543 | 2012-02-27,606.59,612.36,605.06,609.31,1813900.0,609.3,615.196,568.782 544 | 2012-02-28,610.0,619.77,607.68,618.39,2847600.0,618.3,615.202,569.1985 545 | 2012-02-29,618.6,625.6,615.5,618.25,3136900.0,618.2,615.176,569.642 546 | 2012-03-01,622.26,625.7,618.15,622.4,2237700.0,622.4,615.106,570.162 547 | 2012-03-02,622.0,624.0,620.32,621.25,1573300.0,621.2,615.094,570.616 548 | 2012-03-05,620.43,622.49,611.38,614.25,1593300.0,614.2,614.772,571.038 549 | 2012-03-06,608.05,608.81,593.84,604.96,3174400.0,604.9,614.354,571.4065 550 | 2012-03-07,609.05,611.19,605.86,606.8,1264500.0,606.8,613.896,571.8205 551 | 2012-03-08,610.04,611.5,606.35,607.14,1345500.0,607.1,613.376,572.2645 552 | 2012-03-09,607.95,611.9,600.0,600.25,2670600.0,600.2,612.576,572.6745 553 | 2012-03-12,600.0,607.0,599.26,605.15,1669000.0,605.1,611.884,573.102 554 | 2012-03-13,608.75,617.85,605.55,617.78,2245800.0,617.7,611.39,573.6 555 | 2012-03-14,615.0,622.78,613.46,615.99,2936900.0,615.9,610.79,574.075 556 | 2012-03-15,616.6,623.5,614.83,621.13,2435100.0,621.1,609.904,574.5355 557 | 2012-03-16,620.89,625.91,620.05,625.04,3050500.0,625.0,609.04,575.0325 558 | 2012-03-19,623.12,637.27,621.24,633.98,2172800.0,633.9,608.538,575.562 559 | 2012-03-20,630.92,636.06,627.27,633.49,1540500.0,633.4,608.206,576.114 560 | 2012-03-21,634.61,647.39,632.51,639.98,2469600.0,639.9,608.556,576.7085 561 | 2012-03-22,638.5,648.8,631.0,646.05,2410200.0,646.0,609.014,577.3435 562 | 2012-03-23,646.6,648.5,640.9,642.59,1940200.0,642.5,609.346,577.9605 563 | 2012-03-26,645.0,649.49,639.54,649.33,1819200.0,649.3,609.74,578.6235 564 | 2012-03-27,647.03,653.5,644.8,647.02,2007200.0,647.0,610.182,579.311 565 | 2012-03-28,652.03,658.59,651.08,655.76,2538900.0,655.7,610.726,580.066 566 | 2012-03-29,653.44,656.59,644.3,648.41,1924300.0,648.4,611.036,580.7665 567 | 2012-03-30,651.75,653.49,641.0,641.24,2310700.0,641.2,611.07,581.458 568 | 2012-04-02,640.77,647.5,634.84,646.92,2284200.0,646.9,612.29,582.191 569 | 2012-04-03,645.41,647.95,638.64,642.62,2044900.0,642.6,613.432,582.979 570 | 2012-04-04,638.45,639.0,631.1,635.15,1627600.0,635.1,614.516,583.732 571 | 2012-04-05,632.24,636.43,628.57,632.32,2318700.0,632.3,615.774,584.4285 572 | 2012-04-09,628.48,635.33,625.29,630.84,2182700.0,630.8,617.028,585.1475 573 | 2012-04-10,633.52,634.5,624.55,626.86,2482000.0,626.8,617.966,585.8805 574 | 2012-04-11,633.97,636.0,631.3,635.96,2199000.0,635.9,619.132,586.686 575 | 2012-04-12,642.35,653.14,640.26,651.01,5756600.0,651.0,620.55,587.527 576 | 2012-04-13,647.55,648.99,623.54,624.6,8159300.0,624.6,621.426,588.182 577 | 2012-04-16,623.0,623.81,601.66,606.07,5692100.0,606.0,621.844,588.7245 578 | 2012-04-17,608.56,617.69,607.01,609.57,3023900.0,609.5,622.108,589.2405 579 | 2012-04-18,608.05,612.8,602.81,607.45,2669500.0,607.4,622.076,589.6725 580 | 2012-04-19,605.69,616.26,599.0,599.3,3294600.0,599.3,621.928,590.007 581 | 2012-04-20,604.25,608.85,595.83,596.06,3058400.0,596.0,621.652,590.3105 582 | 2012-04-23,592.9,598.45,590.2,597.6,2197800.0,597.6,621.376,590.5655 583 | 2012-04-24,598.24,606.63,597.32,601.27,1929100.0,601.2,621.282,590.912 584 | 2012-04-25,604.0,611.35,602.88,609.72,1821100.0,609.7,621.232,591.3245 585 | 2012-04-26,610.91,618.0,609.7,615.47,2092500.0,615.4,621.346,591.7315 586 | 2012-04-27,615.02,616.74,610.6,614.98,1636400.0,614.9,621.534,592.115 587 | 2012-04-30,612.99,616.08,600.61,604.85,2407300.0,604.8,621.5,592.4945 588 | 2012-05-01,603.79,611.6,600.19,604.43,2002300.0,604.4,621.496,592.5285 589 | 2012-05-02,601.2,608.11,600.61,607.26,1611500.0,607.2,621.36,592.59 590 | 2012-05-03,609.62,614.83,608.95,611.02,1868000.0,611.0,621.422,592.6325 591 | 2012-05-04,605.92,607.89,596.81,596.97,2207400.0,596.9,621.238,592.6405 592 | 2012-05-07,595.0,610.57,595.0,607.55,1994500.0,607.5,621.19,592.6435 593 | 2012-05-08,605.53,616.9,600.7,612.79,2677300.0,612.7,621.258,592.616 594 | 2012-05-09,606.82,616.38,601.81,609.15,2328800.0,609.1,621.074,592.567 595 | 2012-05-10,612.96,616.19,610.23,613.66,1535900.0,613.6,620.982,592.5225 596 | 2012-05-11,610.35,614.55,604.77,605.23,2099400.0,605.2,620.638,592.5125 597 | 2012-05-14,600.78,608.5,600.58,604.0,1824400.0,604.0,620.294,592.478 598 | 2012-05-15,605.35,615.0,603.75,611.11,2102100.0,611.1,620.232,592.5155 599 | 2012-05-16,617.96,630.1,615.94,628.93,4835100.0,628.9,620.712,592.6265 600 | 2012-05-17,633.83,637.85,621.23,623.05,3353800.0,623.0,621.036,592.7795 601 | 2012-05-18,625.1,632.42,596.7,600.4,5973500.0,600.4,620.902,592.776 602 | 2012-05-21,600.51,615.69,600.0,614.11,3075400.0,614.1,621.18,592.959 603 | 2012-05-22,613.44,613.81,596.0,600.8,3051900.0,600.8,621.094,593.068 604 | 2012-05-23,601.65,609.6,597.12,609.46,3178100.0,609.4,620.928,593.385 605 | 2012-05-24,609.16,611.92,598.87,603.66,1891300.0,603.6,620.682,593.536 606 | 2012-05-25,601.0,601.73,588.28,591.53,3581900.0,591.5,620.09,593.7485 607 | 2012-05-29,595.81,599.13,588.32,594.34,2605700.0,594.3,619.476,593.9095 608 | 2012-05-30,588.16,591.9,583.53,588.23,1906700.0,588.2,618.562,594.032 609 | 2012-05-31,588.72,590.0,579.0,580.86,2968300.0,580.8,617.51,594.15 610 | 2012-06-01,571.79,572.65,568.35,570.98,3057900.0,570.9,616.13,594.3095 611 | 2012-06-04,570.22,580.49,570.01,578.59,2432700.0,578.5,614.78,594.5365 612 | 2012-06-05,575.45,578.13,566.47,570.41,2339900.0,570.4,613.338,594.8645 613 | 2012-06-06,576.48,581.97,573.61,580.57,2095800.0,580.5,611.962,595.3125 614 | 2012-06-07,587.6,587.89,577.25,578.23,1758500.0,578.2,610.586,595.713 615 | 2012-06-08,575.85,581.0,574.58,580.45,1410400.0,580.4,609.08,596.021 616 | 2012-06-11,584.21,585.32,566.69,568.5,2661100.0,568.5,607.482,596.2475 617 | 2012-06-12,569.77,570.3,558.58,565.1,3224200.0,565.1,605.96,596.473 618 | 2012-06-13,561.72,567.0,558.68,561.09,1954200.0,561.0,604.242,596.644 619 | 2012-06-14,561.3,565.07,556.52,559.05,2344900.0,559.0,602.57,596.744 620 | 2012-06-15,560.34,564.52,557.09,564.51,3001200.0,564.5,601.158,596.863 621 | 2012-06-18,562.62,574.21,559.25,570.85,2496900.0,570.8,599.928,597.0125 622 | 2012-06-19,573.59,584.28,573.12,581.53,2076200.0,581.5,598.942,597.2575 623 | 2012-06-20,579.81,580.0,573.51,577.51,2346700.0,577.5,597.956,597.521 624 | 2012-06-21,579.84,579.84,563.73,565.21,2011300.0,565.2,596.542,597.7365 625 | 2012-06-22,568.0,571.48,565.82,571.48,2227900.0,571.4,594.95,597.9235 626 | 2012-06-25,567.33,568.09,557.35,560.7,1581600.0,560.7,593.672,598.0525 627 | 2012-06-26,562.76,566.6,559.48,564.68,1350200.0,564.6,592.844,598.2515 628 | 2012-06-27,567.7,573.99,566.02,569.3,1692300.0,569.3,592.04,598.4475 629 | 2012-06-28,565.9,566.23,557.21,564.31,1920900.0,564.3,591.178,598.6215 630 | 2012-06-29,574.96,580.13,572.2,580.07,2519500.0,580.0,590.792,598.8615 631 | 2012-07-02,581.82,583.0,576.5,580.47,1655500.0,580.4,590.48,599.051 632 | 2012-07-03,580.01,588.41,578.0,587.83,1189500.0,587.8,590.284,599.257 633 | 2012-07-05,588.76,600.06,588.54,595.92,2345900.0,595.9,590.178,599.5035 634 | 2012-07-06,592.45,593.52,582.82,585.98,2161800.0,585.9,589.702,599.7 635 | 2012-07-09,584.95,588.6,581.25,586.01,1715100.0,586.0,589.114,599.934 636 | 2012-07-10,590.19,592.43,578.74,581.7,1923100.0,581.7,588.45,600.2395 637 | 2012-07-11,576.3,577.85,564.94,571.19,3499300.0,571.1,587.776,600.4675 638 | 2012-07-12,567.12,571.93,562.09,570.48,2309800.0,570.4,587.096,600.6605 639 | 2012-07-13,572.15,579.15,568.55,576.52,1976000.0,576.5,586.482,600.8465 640 | 2012-07-16,576.37,579.19,571.78,574.92,1462600.0,574.9,585.76,601.077 641 | 2012-07-17,578.43,580.67,568.4,576.73,1680100.0,576.7,585.356,601.323 642 | 2012-07-18,576.98,583.69,576.13,580.76,1548200.0,580.7,584.82,601.6515 643 | 2012-07-19,586.14,598.48,586.0,593.06,4674700.0,593.0,584.426,602.139 644 | 2012-07-20,608.76,612.94,598.18,610.82,6463700.0,610.8,584.46,602.6835 645 | 2012-07-23,600.48,618.35,598.25,615.51,3561700.0,615.5,584.498,603.2375 646 | 2012-07-24,615.0,617.93,604.34,607.57,2009400.0,607.5,584.544,603.7015 647 | 2012-07-25,608.32,613.38,605.37,607.99,1823000.0,607.9,584.622,604.1655 648 | 2012-07-26,615.0,616.87,610.03,613.36,1685200.0,613.3,584.666,604.5465 649 | 2012-07-27,618.89,635.0,617.5,634.96,3549700.0,634.9,584.786,605.0055 650 | 2012-07-30,636.05,642.6,629.5,632.3,2186700.0,632.3,584.972,605.4245 651 | 2012-07-31,628.26,636.5,628.22,632.97,1865600.0,632.9,585.622,605.7945 652 | 2012-08-01,637.3,639.51,631.38,632.68,1844600.0,632.6,585.992,605.9995 653 | 2012-08-02,625.51,638.03,623.41,628.75,1977700.0,628.7,586.55,606.231 654 | 2012-08-03,640.0,643.72,636.14,641.33,1897100.0,641.3,587.188,606.485 655 | 2012-08-06,639.61,649.38,639.22,642.82,1782400.0,642.8,587.972,606.7955 656 | 2012-08-07,641.79,644.26,636.47,640.54,1981800.0,640.5,588.952,607.08 657 | 2012-08-08,639.05,645.87,638.5,642.23,1322200.0,642.2,589.91,607.339 658 | 2012-08-09,644.51,646.37,641.52,642.35,1070300.0,642.3,590.992,607.5685 659 | 2012-08-10,638.59,642.24,636.13,642.0,1434600.0,642.0,592.216,607.863 660 | 2012-08-13,647.42,660.15,646.68,660.01,3267900.0,660.0,593.998,608.2315 661 | 2012-08-14,659.25,672.85,659.0,668.66,3661700.0,668.6,595.8,608.5815 662 | 2012-08-15,670.28,674.25,664.1,667.54,2410700.0,667.5,597.742,608.9185 663 | 2012-08-16,667.51,674.64,667.08,672.87,1717700.0,672.8,599.588,609.3195 664 | 2012-08-17,674.12,677.25,671.7,677.14,2177700.0,677.1,601.566,609.812 665 | 2012-08-20,675.5,678.87,672.66,675.54,1758100.0,675.5,603.468,610.2655 666 | 2012-08-21,673.11,678.0,662.17,669.51,2222200.0,669.5,605.488,610.6255 667 | 2012-08-22,667.38,680.6,666.7,677.18,1909200.0,677.1,607.728,611.0305 668 | 2012-08-23,674.27,680.48,671.0,676.8,1784200.0,676.8,610.044,611.373 669 | 2012-08-24,675.6,680.45,674.08,678.63,1426600.0,678.6,612.436,611.7045 670 | 2012-08-27,662.99,672.0,659.24,669.22,2613700.0,669.2,614.53,612.046 671 | 2012-08-28,665.0,677.62,664.74,677.25,2058600.0,677.2,616.658,612.457 672 | 2012-08-29,677.37,688.99,676.15,688.01,2990300.0,688.0,618.788,612.8555 673 | 2012-08-30,684.24,687.39,680.18,681.68,1626900.0,681.6,620.87,613.1985 674 | 2012-08-31,684.0,688.58,680.04,685.09,2127100.0,685.0,623.266,613.541 675 | 2012-09-04,684.55,685.0,673.5,681.04,1889600.0,681.0,625.458,613.889 676 | 2012-09-05,680.0,686.5,679.14,680.72,1708200.0,680.7,627.858,614.2885 677 | 2012-09-06,685.96,699.89,684.73,699.4,3043500.0,699.4,630.554,614.8115 678 | 2012-09-07,700.0,712.25,697.67,706.15,3233000.0,706.1,633.29,615.4375 679 | 2012-09-10,709.76,712.81,698.39,700.77,2560000.0,700.7,636.018,616.041 680 | 2012-09-11,697.96,700.65,691.0,692.19,1873800.0,692.1,638.26,616.651 681 | 2012-09-12,689.41,694.91,680.88,690.88,2642300.0,690.8,640.468,617.29 682 | 2012-09-13,693.09,709.0,690.54,706.04,2659000.0,706.0,642.832,617.8795 683 | 2012-09-14,709.6,713.0,707.01,709.68,2618500.0,709.6,645.106,618.513 684 | 2012-09-17,708.11,712.88,705.0,709.98,1508300.0,709.9,647.586,619.066 685 | 2012-09-18,707.78,718.66,706.78,718.28,2066800.0,718.2,650.23,619.5885 686 | 2012-09-19,717.5,728.56,716.41,727.5,3098300.0,727.5,653.146,620.1245 687 | 2012-09-20,724.47,731.38,721.22,728.12,2907400.0,728.1,656.286,620.637 688 | 2012-09-21,732.21,734.92,730.12,733.99,6359100.0,733.9,659.556,621.188 689 | 2012-09-24,731.0,750.04,730.25,749.38,3563800.0,749.3,663.012,621.818 690 | 2012-09-25,753.05,764.89,747.66,749.16,6058500.0,749.1,666.496,622.4835 691 | 2012-09-26,749.85,761.24,741.0,753.46,5672900.0,753.4,670.03,623.1135 692 | 2012-09-27,759.95,762.84,751.65,756.5,3931100.0,756.5,673.546,623.7695 693 | 2012-09-28,754.15,759.3,751.15,754.5,2783500.0,754.5,676.776,624.414 694 | 2012-10-01,759.05,765.0,756.21,761.78,3168000.0,761.7,679.794,625.1325 695 | 2012-10-02,765.2,765.99,750.27,756.99,2790200.0,756.9,682.622,625.8195 696 | 2012-10-03,755.72,763.92,752.2,762.5,2208300.0,762.5,685.722,626.5025 697 | 2012-10-04,762.75,769.89,759.4,768.05,2454200.0,768.0,688.924,627.2335 698 | 2012-10-05,770.71,774.38,765.01,767.65,2735900.0,767.6,692.01,627.92 699 | 2012-10-08,761.0,763.58,754.15,757.84,1958600.0,757.8,694.468,628.58 700 | 2012-10-09,759.67,761.32,742.53,744.09,3003200.0,744.0,696.702,629.1515 701 | 2012-10-10,741.86,747.53,738.29,744.56,2039900.0,744.5,698.934,629.7085 702 | 2012-10-11,752.9,758.5,750.29,751.48,2383900.0,751.4,701.31,630.2645 703 | 2012-10-12,751.85,754.87,744.1,744.75,2404200.0,744.7,703.63,630.7895 704 | 2012-10-15,741.94,743.83,730.7,740.98,3019100.0,740.9,705.622,631.282 705 | 2012-10-16,740.13,746.99,736.46,744.7,2058200.0,744.7,707.66,631.776 706 | 2012-10-17,743.95,756.34,740.26,755.49,2292900.0,755.4,709.958,632.226 707 | 2012-10-18,755.54,759.42,676.0,695.0,12442400.0,695.0,711.014,632.36 708 | 2012-10-19,705.58,706.7,672.0,681.79,11482200.0,681.7,711.802,632.4735 709 | 2012-10-22,681.01,684.63,669.7,678.67,4055600.0,678.6,712.534,632.6165 710 | 2012-10-23,672.01,687.33,672.0,680.35,2916600.0,680.3,712.94,632.906 711 | 2012-10-24,686.8,687.0,675.27,677.3,2496500.0,677.3,713.114,633.177 712 | 2012-10-25,680.0,682.0,673.51,677.76,2401100.0,677.7,713.318,633.436 713 | 2012-10-26,676.5,683.03,671.2,675.15,1950800.0,675.1,713.364,633.6635 714 | 2012-10-31,679.86,681.0,675.0,680.3,1537000.0,680.3,713.428,633.9405 715 | 2012-11-01,679.5,690.9,678.72,687.59,2050100.0,687.5,713.668,634.2355 716 | 2012-11-02,694.79,695.55,687.37,687.92,2324400.0,687.9,714.036,634.5105 717 | 2012-11-05,684.5,686.86,675.56,682.96,1635900.0,682.9,714.152,634.7275 718 | 2012-11-06,685.48,686.5,677.55,681.72,1582800.0,681.7,714.25,635.2065 719 | 2012-11-07,675.0,678.23,666.49,667.12,2232300.0,667.1,714.02,635.6145 720 | 2012-11-08,670.2,671.49,651.23,652.29,2597000.0,652.2,713.68,635.971 721 | 2012-11-09,654.65,668.34,650.3,663.03,3114100.0,663.0,713.396,636.439 722 | 2012-11-12,663.75,669.8,660.87,665.9,1405900.0,665.9,712.954,636.928 723 | 2012-11-13,663.0,667.6,658.23,659.05,1594200.0,659.0,712.502,637.3235 724 | 2012-11-14,660.66,662.18,650.5,652.55,1668400.0,652.5,711.852,637.698 725 | 2012-11-15,650.0,660.0,643.9,647.26,1848900.0,647.2,711.176,638.0335 726 | 2012-11-16,645.99,653.02,636.0,647.18,3438200.0,647.1,710.504,638.365 727 | 2012-11-19,655.7,668.92,655.53,668.21,2368200.0,668.2,709.88,638.7805 728 | 2012-11-20,669.51,678.0,664.57,669.97,2088700.0,669.9,709.156,639.1485 729 | 2012-11-21,668.99,669.8,660.4,665.87,2112200.0,665.8,708.458,639.4325 730 | 2012-11-23,669.97,670.0,666.1,667.97,922500.0,667.9,707.974,639.7385 731 | 2012-11-26,666.44,667.0,659.02,661.15,2204600.0,661.1,707.38,639.995 732 | 2012-11-27,660.17,675.0,658.0,670.71,2508700.0,670.7,706.674,640.2915 733 | 2012-11-28,668.01,684.91,663.89,683.67,3042000.0,683.6,706.154,640.68 734 | 2012-11-29,687.78,693.9,682.0,691.89,2776500.0,691.8,705.792,641.078 735 | 2012-11-30,691.31,699.22,685.69,698.37,3163600.0,698.3,705.394,641.521 736 | 2012-12-03,702.24,705.89,694.11,695.25,2192500.0,695.2,704.748,641.9695 737 | 2012-12-04,695.0,695.51,685.7,691.03,1991700.0,691.0,704.006,642.392 738 | 2012-12-05,692.15,694.5,682.33,687.82,1862400.0,687.8,703.084,642.808 739 | 2012-12-06,687.59,695.61,684.51,691.13,1462300.0,691.1,701.92,643.1935 740 | 2012-12-07,695.0,696.88,682.42,684.21,1919300.0,684.2,700.622,643.575 741 | 2012-12-10,685.39,691.65,683.79,685.42,1366700.0,685.4,699.262,643.9715 742 | 2012-12-11,690.0,701.92,687.72,696.88,2687600.0,696.8,698.068,644.406 743 | 2012-12-12,699.23,703.51,693.48,697.56,2426000.0,697.5,696.928,644.847 744 | 2012-12-13,715.92,716.47,699.55,702.7,3444900.0,702.7,695.748,645.269 745 | 2012-12-14,699.17,707.82,698.43,701.96,2130100.0,701.9,694.648,645.6875 746 | 2012-12-17,705.5,721.92,704.02,720.78,3035400.0,720.7,693.812,646.179 747 | 2012-12-18,716.6,729.1,715.05,721.07,3004900.0,721.0,692.872,646.678 748 | 2012-12-19,720.71,723.0,716.68,720.11,1918600.0,720.1,691.922,647.2075 749 | 2012-12-20,723.26,724.65,716.97,722.36,1657000.0,722.3,691.212,647.7945 750 | 2012-12-21,713.97,718.82,710.52,715.63,3526000.0,715.6,690.644,648.3385 751 | 2012-12-24,714.51,715.18,707.47,709.5,840900.0,709.5,689.944,648.8505 752 | 2012-12-26,708.07,712.88,702.41,708.87,1182400.0,708.8,689.092,649.3935 753 | 2012-12-27,707.14,708.84,698.61,706.29,1647400.0,706.2,688.322,649.899 754 | 2012-12-28,701.69,706.91,700.01,700.01,1402000.0,700.0,687.504,650.3105 755 | 2012-12-31,700.0,710.57,696.0,707.38,1997400.0,707.3,686.756,650.7675 -------------------------------------------------------------------------------- /down.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from indicators import * 5 | from plot import * 6 | import pprint 7 | 8 | stocks = ['SPY'] 9 | cnt = 0 10 | gain = [] 11 | bhgain = [] 12 | bhcnt = 0 13 | results = {} 14 | 15 | class DownTest(Algorithm): 16 | def __init__(self, symbols, start_date, end_date): 17 | self.check = 0.1 18 | super(DownTest, self).__init__(symbols, start_date, end_date) 19 | 20 | def handle_data(self, dt, symbols, keys, data): 21 | for symbol in symbols: 22 | yesterday = self.cube.go_back(dt, 1) 23 | yesterday_c = self.cube.data[(symbol, 'close')][yesterday] 24 | yesterday_l = self.cube.data[(symbol, 'low')][yesterday] 25 | yesterday_h = self.cube.data[(symbol, 'high')][yesterday] 26 | yesterday_o = self.cube.data[(symbol, 'open')][yesterday] 27 | today_o = data[(symbol, 'open')] 28 | today_c = data[(symbol, 'close')] 29 | 30 | check = (yesterday_c - yesterday_l) / (yesterday_h - yesterday_l) 31 | yesterday_move = 100 * (yesterday_c / yesterday_o) 32 | gap_down = (today_o / yesterday_c) 33 | 34 | global bhcnt 35 | global bhgain 36 | bhcnt += 1 37 | bhgain.append(100 * ((today_c / today_o) - 1)) 38 | 39 | if yesterday != dt and check < self.check and gap_down < 1: 40 | shares = int(10000/today_o) 41 | global cnt 42 | cnt+=1 43 | global gain 44 | gain.append(100 * ((today_c / today_o) - 1)) 45 | self.oms.add(Transaction(symbol, dt, today_o, shares)) 46 | self.oms.add(Transaction(symbol, dt, today_c, -shares)) 47 | 48 | def post_run(self): 49 | self.results(bhfield='close') 50 | for symbol in self.symbols: 51 | self.plot(symbol=symbol).show() 52 | 53 | test = DownTest(stocks, '20050101', '20130226') 54 | test.run() 55 | 56 | print cnt, 'trades' 57 | print 'strategy avg trade',(sum(gain) / cnt) 58 | print 'bh avg trade', (sum(bhgain) / bhcnt) 59 | print 'tx cost', 8 * cnt 60 | -------------------------------------------------------------------------------- /dva.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import datetime 3 | from positions import * 4 | from algorithm import Algorithm 5 | from indicators import * 6 | from plot import * 7 | import pprint 8 | 9 | stocks = ['SPY'] 10 | 11 | class DVATest(Algorithm): 12 | def __init__(self, symbols, start_date, end_date): 13 | self.one_day = datetime.timedelta(days=1) 14 | self.target_value = 0 15 | self.expected_monthly_return = 1.006 16 | self.initial_investment = 500 17 | self.initial_investment_made = False 18 | super(DVATest, self).__init__(symbols, start_date, end_date) 19 | 20 | def handle_data(self, dt, symbols, keys, data): 21 | for symbol in symbols: 22 | 23 | px = data[(symbol, 'close')] 24 | if self.initial_investment_made == False: 25 | shares_to_order = round((self.initial_investment - 9.99) / px) 26 | self.oms.add(Transaction(symbol, dt, px, shares_to_order)) 27 | print('Initial investment: we buy %s shares for %s on %s' % (shares_to_order, px, dt)) 28 | self.initial_investment_made = True 29 | self.target_value += self.initial_investment * self.expected_monthly_return 30 | 31 | next_trade_day = None 32 | while next_trade_day is None or next_trade_day.weekday() > 4: 33 | if next_trade_day is None: 34 | next_trade_day = dt 35 | next_trade_day = next_trade_day + self.one_day 36 | current_month = dt.month 37 | 38 | cost = self.oms.portfolio.positions[symbol].amount * px 39 | if next_trade_day.month != current_month: 40 | if cost < self.target_value: 41 | budget = self.target_value - cost - 9.99 42 | shares_to_order = round(budget / px) 43 | if shares_to_order >= 2: 44 | self.oms.add(Transaction(symbol, dt, px, shares_to_order)) 45 | print('Target value (%s) exceeds portfolio value (%s). We buy %s shares for %s on %s' % (self.target_value, cost, shares_to_order, px, dt)) 46 | else: 47 | print("Minimum buying threshold not reached") 48 | elif self.oms.portfolio.positions[symbol].is_open(): 49 | budget = cost - self.target_value - 9.99 50 | shares_to_sell = round(budget / px) 51 | if shares_to_sell >= 2: 52 | self.oms.add(Transaction(symbol, dt, px, -shares_to_sell)) 53 | print('Portfolio value (%s) is below target value (%s). We sell %s shares for %s on %s' % (cost, self.target_value, shares_to_sell, px, dt)) 54 | else: 55 | print("Minimum selling threshold not reached") 56 | 57 | self.target_value += 500 58 | 59 | def post_run(self): 60 | self.results() 61 | for symbol in self.symbols: 62 | self.plot(symbol=symbol).show() 63 | 64 | test = DVATest(stocks, '20130103', '20131021') 65 | test.run() -------------------------------------------------------------------------------- /dvtest.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | 8 | stock = 'SPY' 9 | 10 | class SMATest(Algorithm): 11 | def __init__(self, symbols, start_date, end_date): 12 | super(SMATest, self).__init__(symbols, start_date, end_date) 13 | self.cash = 10000 14 | 15 | def pre_run(self): 16 | super(SMATest, self).pre_run() 17 | 18 | for symbol in self.symbols: 19 | close_series = self.cube.data[(symbol, 'adjclose')] 20 | high_series = self.cube.data[(symbol, 'high')] 21 | low_series = self.cube.data[(symbol, 'low')] 22 | self.add_indicator(DV('DV-' + symbol, close_series, self.cube.data[(symbol, 'volume')])) 23 | self.add_indicator(ZScore('ZScore-' + symbol, self.i('DV-' + symbol), 20)) 24 | 25 | self.add_indicator(EMA('EMA-' + symbol, close_series, 20)) 26 | self.add_indicator(BBandLower('BBandLower-' + symbol, close_series, 20, 2)) 27 | self.add_indicator(BBandUpper('BBandUpper-' + symbol, close_series, 20, 2)) 28 | self.add_indicator(KeltnerLower('KeltnerLower-' + symbol, 20, self.i('EMA-' + symbol), 1.5, high_series, low_series, close_series)) 29 | self.add_indicator(KeltnerUpper('KeltnerUpper-' + symbol, 20, self.i('EMA-' + symbol), 1.5, high_series, low_series, close_series)) 30 | self.add_indicator(Squeeze('Squeeze-' + symbol, self.i('BBandLower-' + symbol), self.i('BBandUpper-' + symbol), self.i('KeltnerLower-' + symbol), self.i('KeltnerUpper-' + symbol))) 31 | 32 | def handle_data(self, dt, symbols, keys, data): 33 | for symbol in symbols: 34 | px = data[(symbol, 'adjclose')] 35 | z = self.i('ZScore-' + symbol)[dt] 36 | if z: 37 | if z >= 1: 38 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].amount < 0: 39 | print 'covering {}'.format(-self.oms.portfolio.positions[symbol].amount) 40 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 41 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 42 | self.cash += gains_cash 43 | 44 | if self.cash > 0: 45 | print 'buying {}'.format(self.cash / px) 46 | self.oms.add(Transaction(symbol, dt, px, self.cash / px)) 47 | self.cash = 0 48 | elif z <= -1: 49 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].amount > 0: 50 | print 'selling {}'.format(self.oms.portfolio.positions[symbol].amount) 51 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 52 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 53 | self.cash += gains_cash 54 | elif symbol not in self.oms.portfolio.positions or self.oms.portfolio.positions[symbol].amount > px * 100: 55 | print 'shorting {}'.format(self.cash / px) 56 | self.oms.add(Transaction(symbol, dt, px, -self.cash / px)) 57 | self.cash *= 2 58 | 59 | test = SMATest([stock], '20130101', '20131017') 60 | test.run() 61 | test.results() 62 | 63 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 64 | [[test.cube.get_values(stock, 'adjclose'), test.i('BBandLower-' + stock).as_series(), test.i('BBandUpper-' + stock).as_series(), test.i('KeltnerUpper-' + stock).as_series(), test.i('KeltnerLower-' + stock).as_series()],[test.i('DV-' + stock).as_series()], [test.i('ZScore-' + stock).as_series()], [test.i('Squeeze-' + stock).as_series()]], 65 | 'Date', 66 | ['Price', 'Value', 'Value', 'Value'], 67 | '-', 68 | [['Close', 'BBandLower', 'BBandUpper', 'KeltnerUpper', 'KeltnerLower'],['DV'], ['ZScore'], ['Squeeze']], 69 | stock) 70 | for t in test.oms.blotter.all(symbols=stock): 71 | dt = t.dt 72 | high = test.cube.data[(stock, 'high')][dt] 73 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.02), xytext=(dt, high*1.03), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 74 | plt.show() -------------------------------------------------------------------------------- /indicators.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | class Indicator(object): 4 | def __init__(self, name, series, **kwargs): 5 | self.ready = False 6 | self.name = name 7 | self.series = series 8 | self.values = OrderedDict() 9 | 10 | def dates(self): 11 | return sorted(self.series.keys()) 12 | 13 | def calculate(self): 14 | if issubclass(type(self.series), Indicator): 15 | self.series = self.series.as_series() 16 | 17 | def as_series(self): 18 | return self.values 19 | 20 | def __getitem__(self, dt): 21 | return self.values[dt] 22 | 23 | class SMA(Indicator): 24 | def __init__(self, name, series, period, **kwargs): 25 | super(SMA, self).__init__(name, series, **kwargs) 26 | self.period = period 27 | 28 | def calculate(self): 29 | super(SMA, self).calculate() 30 | sorted_dates = self.dates() 31 | 32 | dates = self.dates() 33 | for i, dt in enumerate(dates): 34 | if i >= 0 and i < min(len(dates), self.period-1): 35 | self.values[dt] = None 36 | else: 37 | values = [self.series[x] for x in dates[i-self.period+1:i+1]] 38 | if None in values: 39 | self.values[dt] = None 40 | else: 41 | self.values[dt] = sum(values) / self.period 42 | 43 | class RSMA(SMA): 44 | def __init__(self, name, series, period, **kwargs): 45 | super(RSMA, self).__init__(name, series, period, **kwargs) 46 | 47 | def calculate(self): 48 | super(RSMA, self).calculate() 49 | 50 | for dt in self.dates(): 51 | if self.values[dt] != None and self.series[dt] != 0: 52 | self.values[dt] /= self.series[dt] 53 | else: 54 | self.values[dt] = None 55 | 56 | class EMA(SMA): 57 | def __init__(self, name, series, period, **kwargs): 58 | super(EMA, self).__init__(name, series, period, **kwargs) 59 | 60 | def calculate(self): 61 | super(EMA, self).calculate() 62 | 63 | yesterday = None 64 | for dt in self.dates(): 65 | sma = self.values[dt] 66 | if sma is not None: 67 | prior_ema = self.values[yesterday] 68 | if prior_ema is not None: 69 | multiplier = (2.0 / (self.period + 1.0)) 70 | ema_val = ((self.series[dt] - prior_ema) * multiplier) + prior_ema 71 | self.values[dt] = ema_val 72 | yesterday = dt 73 | 74 | class StdDev(Indicator): 75 | def __init__(self, name, series, period, **kwargs): 76 | super(StdDev, self).__init__(name, series, **kwargs) 77 | self.period = period 78 | 79 | def calculate(self): 80 | super(StdDev, self).calculate() 81 | 82 | dates = self.dates() 83 | for i, dt in enumerate(dates): 84 | if i >= 0 and i < min(len(self.series), self.period-1): 85 | self.values[dt] = None 86 | else: 87 | values = [self.series[a] for a in dates[i-self.period+1:i+1]] 88 | if None in values: 89 | self.values[dt] = None 90 | else: 91 | avg = sum(values) / self.period 92 | sum_of_squares = sum([(self.series[a]-avg)**2 for a in dates[i-self.period+1:i+1]]) 93 | stdev = (sum_of_squares / (self.period - 1)) ** 0.5 94 | self.values[dt] = stdev 95 | 96 | class ZScore(StdDev): 97 | def __init__(self, name, series, period, **kwargs): 98 | super(ZScore, self).__init__(name, series, period, **kwargs) 99 | 100 | def calculate(self): 101 | super(ZScore, self).calculate() 102 | 103 | dates = self.dates() 104 | for i, dt in enumerate(dates): 105 | stddev = self.values[dt] 106 | if i >= 0 and i < min(len(self.series), self.period-1): 107 | self.values[dt] = None 108 | else: 109 | values = [self.series[a] for a in dates[i-self.period+1:i+1]] 110 | if None in values: 111 | self.values[dt] = None 112 | else: 113 | avg = sum(values) / self.period 114 | self.values[dt] = (self.series[dt] - avg) / stddev 115 | 116 | class BBandLower(StdDev): 117 | def __init__(self, name, series, period, deviations, ma_series, **kwargs): 118 | super(BBandLower, self).__init__(name, series, period, **kwargs) 119 | self.deviations = deviations 120 | self.ma_series = ma_series 121 | 122 | def calculate(self): 123 | super(BBandLower, self).calculate() 124 | 125 | if not self.ma_series.ready: 126 | self.algorithm.setup_indicator(self.ma_series) 127 | 128 | for dt in self.dates(): 129 | stddev = self.values[dt] 130 | ma_val = self.ma_series[dt] 131 | if stddev is not None and ma_val is not None: 132 | self.values[dt] = ma_val - (self.deviations * stddev) 133 | else: 134 | self.values[dt] = None 135 | 136 | class BBandUpper(StdDev): 137 | def __init__(self, name, series, period, deviations, ma_series, **kwargs): 138 | super(BBandUpper, self).__init__(name, series, period, **kwargs) 139 | self.deviations = deviations 140 | self.ma_series = ma_series 141 | 142 | def calculate(self): 143 | super(BBandUpper, self).calculate() 144 | 145 | if not self.ma_series.ready: 146 | self.algorithm.setup_indicator(self.ma_series) 147 | 148 | for dt in self.dates(): 149 | stddev = self.values[dt] 150 | ma_val = self.ma_series[dt] 151 | if stddev is not None and ma_val is not None: 152 | self.values[dt] = ma_val + (self.deviations * stddev) 153 | else: 154 | self.values[dt] = None 155 | 156 | class ROC(Indicator): 157 | def __init__(self, name, series, **kwargs): 158 | super(ROC, self).__init__(name, series, **kwargs) 159 | 160 | def calculate(self): 161 | super(ROC, self).calculate() 162 | 163 | last_dt = None 164 | for dt in self.dates(): 165 | if last_dt is None: 166 | self.values[dt] = None 167 | else: 168 | if self.series[dt] and self.series[last_dt]: 169 | self.values[dt] = self.series[dt] - self.series[last_dt] 170 | else: 171 | self.values[dt] = None 172 | last_dt = dt 173 | 174 | class VWAP(Indicator): 175 | def __init__(self, name, price_series, volume_series, period, **kwargs): 176 | super(VWAP, self).__init__(name, price_series, **kwargs) 177 | self.price_series = price_series 178 | self.volume_series = volume_series 179 | self.period = period 180 | 181 | def calculate(self): 182 | super(VWAP, self).calculate() 183 | 184 | dates = self.dates() 185 | for i, dt in enumerate(dates): 186 | if i >= 0 and i < min(len(dates), self.period-1): 187 | self.values[dt] = None 188 | else: 189 | values = [self.series[x] for x in dates[i-self.period+1:i+1]] 190 | if None in values: 191 | self.values[dt] = None 192 | else: 193 | numerator = sum([self.price_series[a] * self.volume_series[a] for a in dates[i-self.period+1:i+1]]) 194 | denominator = sum([self.volume_series[a] for a in dates[i-self.period+1:i+1]]) 195 | self.values[dt] = numerator / denominator 196 | 197 | class DV(Indicator): 198 | def __init__(self, name, price_series, volume_series, **kwargs): 199 | super(DV, self).__init__(name, price_series, **kwargs) 200 | self.price_series = price_series 201 | self.volume_series = volume_series 202 | 203 | def calculate(self): 204 | super(DV, self).calculate() 205 | 206 | dates = self.dates() 207 | for i, dt in enumerate(dates): 208 | self.values[dt] = self.price_series[dt] * self.volume_series[dt] 209 | 210 | class TR(Indicator): 211 | def __init__(self, name, high_series, low_series, close_series, **kwargs): 212 | super(TR, self).__init__(name, high_series, **kwargs) 213 | self.high_series = high_series 214 | self.low_series = low_series 215 | self.close_series = close_series 216 | 217 | def calculate(self): 218 | super(TR, self).calculate() 219 | 220 | dates = self.dates() 221 | yesterday = None 222 | for i, dt in enumerate(dates): 223 | high = self.high_series[dt] 224 | low = self.low_series[dt] 225 | h_minus_l = abs(high-low) 226 | 227 | if yesterday is None: 228 | self.values[dt] = h_minus_l 229 | else: 230 | prev_close = self.close_series[yesterday] 231 | h_minus_pc = abs(high-prev_close) 232 | l_minus_pc = abs(low-prev_close) 233 | tr = max(h_minus_l, h_minus_pc, l_minus_pc) 234 | self.values[dt] = tr 235 | yesterday = dt 236 | 237 | class ATR(TR): 238 | def __init__(self, name, period, high_series, low_series, close_series, **kwargs): 239 | super(ATR, self).__init__(name, high_series, low_series, close_series, **kwargs) 240 | self.period = period 241 | 242 | def calculate(self): 243 | super(ATR, self).calculate() 244 | 245 | dates = self.dates() 246 | initial_tr_sum = 0 247 | yesterday = None 248 | for i, dt in enumerate(dates): 249 | if i >= 0 and i < min(len(dates), self.period-1): 250 | initial_tr_sum += self.values[dt] 251 | self.values[dt] = None 252 | elif i == self.period-1: 253 | initial_tr_sum += self.values[dt] 254 | avg_tr = initial_tr_sum / self.period 255 | self.values[dt] = avg_tr 256 | else: 257 | prior_atr = self.values[yesterday] 258 | current_tr = self.values[dt] 259 | current_atr = ((prior_atr * (self.period - 1)) + current_tr) / self.period 260 | self.values[dt] = current_atr 261 | yesterday = dt 262 | 263 | class KeltnerLower(ATR): 264 | def __init__(self, name, period, ema_series, deviations, high_series, low_series, close_series, **kwargs): 265 | super(KeltnerLower, self).__init__(name, period, high_series, low_series, close_series, **kwargs) 266 | self.ema_series = ema_series 267 | self.deviations = deviations 268 | 269 | def calculate(self): 270 | super(KeltnerLower, self).calculate() 271 | 272 | if not self.ema_series.ready: 273 | self.algorithm.setup_indicator(self.ema_series) 274 | 275 | for dt in self.dates(): 276 | atr_val = self.values[dt] 277 | ema_val = self.ema_series[dt] 278 | if atr_val is not None and ema_val is not None: 279 | self.values[dt] = ema_val - (self.deviations * atr_val) 280 | 281 | class KeltnerUpper(ATR): 282 | def __init__(self, name, period, ema_series, deviations, high_series, low_series, close_series, **kwargs): 283 | super(KeltnerUpper, self).__init__(name, period, high_series, low_series, close_series, **kwargs) 284 | self.ema_series = ema_series 285 | self.deviations = deviations 286 | 287 | def calculate(self): 288 | super(KeltnerUpper, self).calculate() 289 | 290 | if not self.ema_series.ready: 291 | self.algorithm.setup_indicator(self.ema_series) 292 | 293 | for dt in self.dates(): 294 | atr_val = self.values[dt] 295 | ema_val = self.ema_series[dt] 296 | if atr_val is not None and ema_val is not None: 297 | self.values[dt] = ema_val + (self.deviations * atr_val) 298 | 299 | class DM(Indicator): 300 | def __init__(self, name, high_series, low_series, **kwargs): 301 | super(DM, self).__init__(name, high_series, **kwargs) 302 | self.high_series = high_series 303 | self.low_series = low_series 304 | 305 | def calculate(self): 306 | super(DM, self).calculate() 307 | 308 | class PlusDM(DM): 309 | def __init__(self, name, high_series, low_series, **kwargs): 310 | super(PlusDM, self).__init__(name, high_series, low_series, **kwargs) 311 | 312 | def calculate(self): 313 | super(PlusDM, self).calculate() 314 | dates = self.dates() 315 | yesterday = None 316 | for i, dt in enumerate(dates): 317 | if yesterday: 318 | high = self.high_series[dt] 319 | low = self.low_series[dt] 320 | prev_high = self.high_series[yesterday] 321 | prev_low = self.low_series[yesterday] 322 | h_minus_ph = high - prev_high 323 | pl_minus_l = prev_low - low 324 | 325 | dm = 0 326 | if h_minus_ph > pl_minus_l: 327 | dm = max(0, h_minus_ph) 328 | self.values[dt] = dm 329 | else: 330 | self.values[dt] = None 331 | yesterday = dt 332 | 333 | class MinusDM(DM): 334 | def __init__(self, name, high_series, low_series, **kwargs): 335 | super(MinusDM, self).__init__(name, high_series, low_series, **kwargs) 336 | 337 | def calculate(self): 338 | super(MinusDM, self).calculate() 339 | dates = self.dates() 340 | yesterday = None 341 | for i, dt in enumerate(dates): 342 | if yesterday: 343 | high = self.high_series[dt] 344 | low = self.low_series[dt] 345 | prev_high = self.high_series[yesterday] 346 | prev_low = self.low_series[yesterday] 347 | h_minus_ph = high - prev_high 348 | pl_minus_l = prev_low - low 349 | 350 | dm = 0 351 | if pl_minus_l > h_minus_ph: 352 | dm = max(0, pl_minus_l) 353 | self.values[dt] = dm 354 | else: 355 | self.values[dt] = None 356 | yesterday = dt 357 | 358 | 359 | class Smooth(Indicator): 360 | def __init__(self, name, series, period, **kwargs): 361 | super(Smooth, self).__init__(name, series, **kwargs) 362 | self.period = period 363 | 364 | def calculate(self): 365 | super(Smooth, self).calculate() 366 | 367 | dates = self.dates() 368 | yesterday = None 369 | for i, dt in enumerate(dates): 370 | if self.series[dt] is not None: 371 | prior = 0.0 372 | if yesterday is not None: 373 | prior = self.values[yesterday] if yesterday else 0.0 374 | if prior is None: 375 | prior = 0.0 376 | 377 | v = self.series[dt] 378 | self.values[dt] = prior - (prior / self.period) + v 379 | else: 380 | self.values[dt] = None 381 | yesterday = dt 382 | 383 | class DI(Indicator): 384 | def __init__(self, name, dm_series, tr_series, **kwargs): 385 | super(DI, self).__init__(name, dm_series, **kwargs) 386 | self.dm_series = dm_series 387 | self.tr_series = tr_series 388 | 389 | def calculate(self): 390 | super(DI, self).calculate() 391 | if not self.tr_series.ready: 392 | self.algorithm.setup_indicator(self.tr_series) 393 | 394 | dates = self.dates() 395 | for i, dt in enumerate(dates): 396 | dm = self.dm_series[dt] 397 | tr = self.tr_series[dt] 398 | if dm is not None and tr is not None: 399 | self.values[dt] = dm / tr * 100.0 400 | else: 401 | self.values[dt] = None 402 | 403 | class DX(Indicator): 404 | def __init__(self, name, pos_di_series, neg_di_series, **kwargs): 405 | super(DX, self).__init__(name, pos_di_series) 406 | self.pos_di_series = pos_di_series 407 | self.neg_di_series = neg_di_series 408 | 409 | def calculate(self): 410 | super(DX, self).calculate() 411 | if not self.neg_di_series.ready: 412 | self.algorithm.setup_indicator(self.neg_di_series) 413 | 414 | dates = self.dates() 415 | for i, dt in enumerate(dates): 416 | pos_di = self.pos_di_series[dt] 417 | neg_di = self.neg_di_series[dt] 418 | if pos_di is not None and neg_di is not None: 419 | d = pos_di - neg_di 420 | s = pos_di + neg_di 421 | if s != 0: 422 | dx = abs(d / s) * 100 423 | else: 424 | dx = 0 425 | self.values[dt] = dx 426 | else: 427 | self.values[dt] = None 428 | 429 | class ADX(DX): 430 | def __init__(self, name, pos_di_series, neg_di_series, period, **kwargs): 431 | super(ADX, self).__init__(name, pos_di_series, neg_di_series) 432 | self.period = period 433 | 434 | def calculate(self): 435 | super(ADX, self).calculate() 436 | 437 | dates = self.dates() 438 | yesterday = None 439 | for i, dt in enumerate(dates): 440 | if self.series[dt] is not None: 441 | prior = 0.0 442 | if yesterday is not None: 443 | prior = self.values[yesterday] if yesterday else 0.0 444 | if prior is None: 445 | prior = 0.0 446 | 447 | v = self.values[dt] 448 | self.values[dt] = ((prior * (self.period - 1)) + v) / self.period 449 | else: 450 | self.values[dt] = None 451 | yesterday = dt 452 | 453 | class Squeeze(Indicator): 454 | def __init__(self, name, bband_lower, bband_upper, keltner_lower, keltner_upper, **kwargs): 455 | super(Squeeze, self).__init__(name, bband_lower, **kwargs) 456 | self.bband_lower = bband_lower 457 | self.bband_upper = bband_upper 458 | self.keltner_lower = keltner_lower 459 | self.keltner_upper = keltner_upper 460 | 461 | def calculate(self): 462 | super(Squeeze, self).calculate() 463 | 464 | if not self.bband_lower.ready: 465 | self.algorithm.setup_indicator(self.bband_lower) 466 | if not self.bband_upper.ready: 467 | self.algorithm.setup_indicator(self.bband_upper) 468 | if not self.keltner_lower.ready: 469 | self.algorithm.setup_indicator(self.keltner_lower) 470 | if not self.keltner_upper.ready: 471 | self.algorithm.setup_indicator(self.keltner_upper) 472 | 473 | dates = self.dates() 474 | yesterday = None 475 | for dt in dates: 476 | bband_lower_val = self.bband_lower[dt] 477 | bband_upper_val = self.bband_upper[dt] 478 | keltner_lower_val = self.keltner_lower[dt] 479 | keltner_upper_val = self.keltner_upper[dt] 480 | if bband_lower_val and bband_upper_val and keltner_lower_val and keltner_upper_val: 481 | prior_squeeze = 0 482 | if yesterday: 483 | prior_squeeze = self.values[yesterday] 484 | 485 | if bband_lower_val > keltner_lower_val and bband_upper_val < keltner_upper_val: 486 | self.values[dt] = prior_squeeze + 1 if prior_squeeze > 0 else 1 487 | else: 488 | self.values[dt] = 0 #prior_squeeze -1 if prior_squeeze < 0 else -1 489 | else: 490 | self.values[dt] = 0 491 | yesterday = dt 492 | 493 | class HeikinAshi(Indicator): 494 | class HeikinAshiFrame(object): 495 | def __init__(self, dt, o, c, h, l): 496 | self.dt = dt 497 | self.o = o 498 | self.c = c 499 | self.h = h 500 | self.l = l 501 | 502 | def __init__(self, name, open_series, close_series, high_series, low_series, **kwargs): 503 | super(HeikinAshi, self).__init__(name, close_series, **kwargs) 504 | self.open_series = open_series 505 | self.close_series = close_series 506 | self.high_series = high_series 507 | self.low_series = low_series 508 | 509 | def calculate(self): 510 | super(HeikinAshi, self).calculate() 511 | 512 | dates = self.dates() 513 | yesterday = None 514 | for dt in dates: 515 | o = self.open_series[dt] 516 | c = self.close_series[dt] 517 | h = self.high_series[dt] 518 | l = self.low_series[dt] 519 | 520 | prior_ha_o = o 521 | prior_ha_c = c 522 | 523 | if yesterday: 524 | prior_ha_o = self.values[yesterday].o 525 | prior_ha_c = self.values[yesterday].c 526 | 527 | ha_c = (o + h + l + c) / 4.0 528 | ha_o = (prior_ha_o + prior_ha_c) / 2.0 529 | ha_h = max(h, ha_o, ha_c) 530 | ha_l = min(l, ha_o, ha_c) 531 | 532 | ha = HeikinAshi.HeikinAshiFrame(dt, ha_o, ha_c, ha_h, ha_l) 533 | self.values[dt] = ha 534 | yesterday = dt 535 | 536 | class AverageGain(Indicator): 537 | def __init__(self, name, close_series, period, **kwargs): 538 | super(AverageGain, self).__init__(name, close_series, **kwargs) 539 | self.period = period 540 | 541 | def calculate(self): 542 | super(AverageGain, self).calculate() 543 | 544 | dates = self.dates() 545 | initial_gain = 0 546 | yesterday = None 547 | for i, dt in enumerate(dates): 548 | current_px = self.series[dt] 549 | prior_px = self.series[yesterday] if yesterday else current_px 550 | gain = max(0, current_px - prior_px) 551 | 552 | if i >= 0 and i < min(len(dates), self.period-1): 553 | initial_gain += gain 554 | self.values[dt] = None 555 | elif i == self.period-1: 556 | avg_gain = initial_gain / self.period 557 | self.values[dt] = float(avg_gain) 558 | else: 559 | prior_gain = self.values[yesterday] 560 | avg_gain = ((prior_gain * (self.period - 1)) + gain) / self.period 561 | self.values[dt] = float(avg_gain) 562 | yesterday = dt 563 | 564 | class AverageLoss(Indicator): 565 | def __init__(self, name, close_series, period, **kwargs): 566 | super(AverageLoss, self).__init__(name, close_series, **kwargs) 567 | self.period = period 568 | 569 | def calculate(self): 570 | super(AverageLoss, self).calculate() 571 | 572 | dates = self.dates() 573 | initial_loss = 0 574 | yesterday = None 575 | for i, dt in enumerate(dates): 576 | current_px = self.series[dt] 577 | prior_px = self.series[yesterday] if yesterday else current_px 578 | loss = abs(min(0, current_px - prior_px)) 579 | 580 | if i >= 0 and i < min(len(dates), self.period-1): 581 | initial_loss += loss 582 | self.values[dt] = None 583 | elif i == self.period-1: 584 | avg_loss = initial_loss / self.period 585 | self.values[dt] = float(avg_loss) 586 | else: 587 | prior_loss = self.values[yesterday] 588 | avg_loss = ((prior_loss * (self.period - 1)) + loss) / self.period 589 | self.values[dt] = float(avg_loss) 590 | yesterday = dt 591 | 592 | class RSI(Indicator): 593 | def __init__(self, name, ag_series, al_series, **kwargs): 594 | super(RSI, self).__init__(name, ag_series, **kwargs) 595 | self.ag_series = ag_series 596 | self.al_series = al_series 597 | 598 | def calculate(self): 599 | super(RSI, self).calculate() 600 | 601 | if not self.ag_series.ready: 602 | self.algorithm.setup_indicator(self.ag_series) 603 | if not self.al_series.ready: 604 | self.algorithm.setup_indicator(self.al_series) 605 | 606 | dates = self.dates() 607 | is_first = True 608 | for dt in dates: 609 | ag_val = self.ag_series[dt] 610 | al_val = self.al_series[dt] 611 | 612 | if ag_val is not None and al_val is not None: 613 | rs = ag_val / al_val 614 | rsi = 100.0 - (100.0 / (1 + rs)) 615 | self.values[dt] = rsi 616 | else: 617 | self.values[dt] = None 618 | 619 | class Streak(Indicator): 620 | def __init__(self, name, series, **kwargs): 621 | super(Streak, self).__init__(name, series, **kwargs) 622 | 623 | def calculate(self): 624 | super(Streak, self).calculate() 625 | sorted_dates = self.dates() 626 | 627 | dates = self.dates() 628 | 629 | prior = None 630 | prior_value = None 631 | for dt in dates: 632 | current = self.series[dt] 633 | if prior: 634 | if current > prior: 635 | if prior_value < 0: 636 | self.values[dt] = 1 637 | else: 638 | self.values[dt] = prior_value + 1 639 | elif current < prior: 640 | if prior_value < 0: 641 | self.values[dt] = prior_value - 1 642 | else: 643 | self.values[dt] = -1 644 | else: 645 | self.values[dt] = 0 646 | else: 647 | self.values[dt] = 0 648 | 649 | prior = current 650 | prior_value = self.values[dt] 651 | 652 | class PercentChange(Indicator): 653 | def __init__(self, name, series, **kwargs): 654 | super(PercentChange, self).__init__(name, series, **kwargs) 655 | 656 | def calculate(self): 657 | super(PercentChange, self).calculate() 658 | 659 | last_dt = None 660 | for dt in self.dates(): 661 | if last_dt is None: 662 | self.values[dt] = None 663 | else: 664 | if self.series[dt] and self.series[last_dt]: 665 | self.values[dt] = 100 * ((self.series[dt] - self.series[last_dt]) / float(self.series[dt])) 666 | else: 667 | self.values[dt] = None 668 | last_dt = dt 669 | 670 | class PercentRank(PercentChange): 671 | def __init__(self, name, series, period, **kwargs): 672 | super(PercentRank, self).__init__(name, series, **kwargs) 673 | self.period = period 674 | 675 | def calculate(self): 676 | super(PercentRank, self).calculate() 677 | 678 | dates = self.dates() 679 | rank_values = OrderedDict() 680 | for i, dt in enumerate(dates): 681 | current_change = self.values[dt] 682 | rank = None 683 | 684 | if i >= self.period: 685 | rank = 0 686 | for j, dt2 in enumerate(dates): 687 | if j >= max(0, i-self.period) and j < i: 688 | percent_change = self.values[dt2] 689 | if percent_change is None: percent_change = 0 690 | if current_change > percent_change: 691 | rank += 1 692 | rank_values[dt] = rank if rank is None else 100 * (rank / float(self.period)) 693 | self.values = rank_values 694 | 695 | class ConnorsRSI(Indicator): 696 | def __init__(self, name, series, rsi_series, streak_series, percent_rank_series, **kwargs): 697 | super(ConnorsRSI, self).__init__(name, series, **kwargs) 698 | self.rsi_series = rsi_series 699 | self.streak_series = streak_series 700 | self.percent_rank_series = percent_rank_series 701 | 702 | def calculate(self): 703 | super(ConnorsRSI, self).calculate() 704 | 705 | if not self.rsi_series.ready: 706 | self.algorithm.setup_indicator(self.rsi_series) 707 | if not self.streak_series.ready: 708 | self.algorithm.setup_indicator(self.streak_series) 709 | if not self.percent_rank_series.ready: 710 | self.algorithm.setup_indicator(self.percent_rank_series) 711 | 712 | dates = self.dates() 713 | for i, dt in enumerate(dates): 714 | rsi = self.rsi_series[dt] 715 | streak = self.streak_series[dt] 716 | percent_rank = self.percent_rank_series[dt] 717 | 718 | current = None 719 | if rsi is not None and streak is not None and percent_rank is not None: 720 | current = (rsi + streak + percent_rank) / 3.0 721 | self.values[dt] = current 722 | 723 | class MACD(Indicator): 724 | def __init__(self, name, series, fast_ema_series, slow_ema_series, **kwargs): 725 | super(MACD, self).__init__(name, series, **kwargs) 726 | self.fast_ema_series = fast_ema_series 727 | self.slow_ema_series = slow_ema_series 728 | 729 | def calculate(self): 730 | super(MACD, self).calculate() 731 | 732 | if not self.fast_ema_series.ready: 733 | self.algorithm.setup_indicator(self.fast_ema_series) 734 | if not self.slow_ema_series.ready: 735 | self.algorithm.setup_indicator(self.slow_ema_series) 736 | 737 | for dt in self.dates(): 738 | fast_ema = self.fast_ema_series[dt] 739 | slow_ema = self.slow_ema_series[dt] 740 | if fast_ema is not None and slow_ema is not None: 741 | self.values[dt] = fast_ema - slow_ema 742 | else: 743 | self.values[dt] = None 744 | 745 | class IBS(Indicator): 746 | def __init__(self, name, open_series, close_series, high_series, low_series, **kwargs): 747 | super(IBS, self).__init__(name, close_series, **kwargs) 748 | self.open_series = open_series 749 | self.close_series = close_series 750 | self.high_series = high_series 751 | self.low_series = low_series 752 | 753 | def calculate(self): 754 | super(IBS, self).calculate() 755 | 756 | dates = self.dates() 757 | 758 | for dt in dates: 759 | o = self.open_series[dt] 760 | c = self.close_series[dt] 761 | h = self.high_series[dt] 762 | l = self.low_series[dt] 763 | 764 | self.values[dt] = ((c - l) / (h - l)) * 100 -------------------------------------------------------------------------------- /macd.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from indicators import * 5 | from plot import * 6 | import pprint 7 | 8 | stocks = ['SPY', 'VXX', 9 | # nasdaq 10 | 'ATVI','ADBE','AKAM','ALXN','ALTR','AMZN','AMGN','ADI','AAPL','AMAT','ADSK','ADP','AVGO','BIDU','BBBY','BIIB','BRCM','CHRW','CA','CTRX','CELG','CERN','CHTR','CHKP','CSCO','CTXS','CTSH','CMCSA','COST','XRAY','DTV','DISCA','DLTR','EBAY','EQIX','EXPE','EXPD','ESRX','FFIV','FB','FAST','FISV','FOSL','GRMN','GILD','GOOG','GMCR','HSIC','INTC','INTU','ISRG','KLAC','KRFT','LBTYA','LINTA','LMCA','LLTC','MAR','MAT','MXIM','MCHP','MU','MSFT','MDLZ','MNST','MYL','NTAP','NFLX','NUAN','NVDA','ORLY','PCAR','PAYX','PCLN','QCOM','REGN','ROST','SNDK','SBAC','STX','SHLD','SIAL','SIRI','SPLS','SBUX','SRCL','SYMC','TSLA','TXN','FOXA','VRSK','VRTX','VIAB','VIP','VOD','WDC','WFM','WYNN','XLNX','YHOO', 11 | # s&P 12 | 'A','AA','AAPL','ABBV','ABC','ABT','ACE','ACN','ACT','ADBE','ADI','ADM','ADP','ADSK','ADT','AEE','AEP','AES','AET','AFL','AGN','AIG','AIV','AIZ','AKAM','ALL','ALTR','ALXN','AMAT','AME','AMGN','AMP','AMT','AMZN','AN','ANF','AON','APA','APC','APD','APH','ARG','ATI','AVB','AVP','AVY','AXP','AZO','BA','BAC','BAX','BBBY','BBT','BBY','BCR','BDX','BEAM','BEN','BF.B','BHI','BIIB','BK','BLK','BLL','BMS','BMY','BRCM','BRK.B','BSX','BTU','BWA','BXP','C','CA','CAG','CAH','CAM','CAT','CB','CBG','CBS','CCE','CCI','CCL','CELG','CERN','CF','CFN','CHK','CHRW','CI','CINF','CL','CLF','CLX','CMA','CMCSA','CME','CMG','CMI','CMS','CNP','CNX','COF','COG','COH','COL','COP','COST','COV','CPB','CRM','CSC','CSCO','CSX','CTAS','CTL','CTSH','CTXS','CVC','CVS','CVX','D','DAL','DD','DE','DFS','DG','DGX','DHI','DHR','DIS','DISCA','DLPH','DLTR','DNB','DNR','DO','DOV','DOW','DPS','DRI','DTE','DTV','DUK','DVA','DVN','EA','EBAY','ECL','ED','EFX','EIX','EL','EMC','EMN','EMR','EOG','EQR','EQT','ESRX','ESV','ETFC','ETN','ETR','EW','EXC','EXPD','EXPE','F','FAST','FCX','FDO','FDX','FE','FFIV','FIS','FISV','FITB','FLIR','FLR','FLS','FMC','FOSL','FOXA','FRX','FSLR','FTI','FTR','GAS','GCI','GD','GE','GILD','GIS','GLW','GM','GME','GNW','GOOG','GPC','GPS','GRMN','GS','GT','GWW','HAL','HAR','HAS','HBAN','HCBK','HCN','HCP','HD','HES','HIG','HOG','HON','HOT','HP','HPQ','HRB','HRL','HRS','HSP','HST','HSY','HUM','IBM','ICE','IFF','IGT','INTC','INTU','IP','IPG','IR','IRM','ISRG','ITW','IVZ','JBL','JCI','JCP','JDSU','JEC','JNJ','JNPR','JOY','JPM','JWN','K','KEY','KIM','KLAC','KMB','KMI','KMX','KO','KR','KRFT','KSS','KSU','L','LEG','LEN','LH','LIFE','LLL','LLTC','LLY','LM','LMT','LNC','LO','LOW','LRCX','LSI','LUK','LUV','LYB','M','MA','MAC','MAR','MAS','MAT','MCD','MCHP','MCK','MCO','MDLZ','MDT','MET','MHFI','MJN','MKC','MMC','MMM','MNST','MO','MOLX','MON','MOS','MPC','MRK','MRO','MS','MSFT','MSI','MTB','MU','MUR','MWV','MYL','NBL','NBR','NDAQ','NE','NEE','NEM','NFLX','NFX','NI','NKE','NLSN','NOC','NOV','NRG','NSC','NTAP','NTRS','NU','NUE','NVDA','NWL','NWSA','OI','OKE','OMC','ORCL','ORLY','OXY','PAYX','PBCT','PBI','PCAR','PCG','PCL','PCLN','PCP','PDCO','PEG','PEP','PETM','PFE','PFG','PG','PGR','PH','PHM','PKI','PLD','PLL','PM','PNC','PNR','PNW','POM','PPG','PPL','PRGO','PRU','PSA','PSX','PVH','PWR','PX','PXD','QCOM','QEP','R','RAI','RDC','REGN','RF','RHI','RHT','RL','ROK','ROP','ROST','RRC','RSG','RTN','SBUX','SCG','SCHW','SE','SEE','SHW','SIAL','SJM','SLB','SLM','SNA','SNDK','SNI','SO','SPG','SPLS','SRCL','SRE','STI','STJ','STT','STX','STZ','SWK','SWN','SWY','SYK','SYMC','SYY','T','TAP','TDC','TE','TEG','TEL','TER','TGT','THC','TIF','TJX','TMK','TMO','TRIP','TROW','TRV','TSN','TSO','TSS','TWC','TWX','TXN','TXT','TYC','UNH','UNM','UNP','UPS','URBN','USB','UTX','V','VAR','VFC','VIAB','VLO','VMC','VNO','VRSN','VRTX','VTR','VZ','WAG','WAT','WDC','WEC','WFC','WFM','WHR','WIN','WLP','WM','WMB','WMT','WPX','WU','WY','WYN','WYNN','X','XEL','XL','XLNX','XOM','XRAY','XRX','XYL','YHOO','YUM','ZION','ZMH','ZTS', 13 | #dow 14 | 'AXP','BA','CAT','CSCO','CVX','DD','DIS','GE','GS','HD','IBM','INTC','JNJ','JPM','KO','MCD','MMM','MRK','MSFT','NKE','PFE','PG','T','TRV','UNH','UTX','V','VZ','WMT','XOM'] 15 | 16 | stocks = ['SPY'] 17 | 18 | class ADXTest(Algorithm): 19 | def __init__(self, symbols, start_date, end_date): 20 | super(ADXTest, self).__init__(symbols, start_date, end_date) 21 | self.cash = 10000 22 | 23 | def pre_run(self): 24 | super(ADXTest, self).pre_run() 25 | 26 | for symbol in self.symbols: 27 | close_series = self.cube.data[(symbol, 'close')] 28 | self.add_indicator(EMA('EMA12-'+symbol, close_series, 12)) 29 | self.add_indicator(EMA('EMA26-'+symbol, close_series, 26)) 30 | self.add_indicator(EMA('EMA55-'+symbol, close_series, 55)) 31 | self.add_indicator(MACD('MACD-'+symbol, close_series, self.i('EMA12-'+symbol), self.i('EMA26-'+symbol))) 32 | self.add_indicator(EMA('MACD_Signal-'+symbol, self.i('MACD-'+symbol), 9)) 33 | 34 | def handle_data(self, dt, symbols, keys, data): 35 | for symbol in symbols: 36 | try: 37 | yesterday = self.cube.go_back(dt, 1) 38 | 39 | macd_yesterday = self.i('MACD-'+symbol)[yesterday] 40 | macd = self.i('MACD-'+symbol)[dt] 41 | signal_yesterday = self.i('MACD_Signal-'+symbol)[dt] 42 | signal = self.i('MACD_Signal-'+symbol)[dt] 43 | 44 | ema26 = self.i('EMA26-'+symbol)[dt] 45 | ema55 = self.i('EMA55-'+symbol)[dt] 46 | 47 | px = data[(symbol, 'close')] 48 | 49 | v_yesterday = None 50 | v = None 51 | if macd_yesterday is not None and signal_yesterday is not None: 52 | v_yesterday = macd_yesterday - signal_yesterday 53 | v = macd - signal 54 | 55 | if v_yesterday is not None: 56 | if v < 2 and v > 0 and v_yesterday < 0 and v - v_yesterday > .25: 57 | if dt == datetime.datetime(2014,1,17): 58 | print(dt, 'BUY', symbol) 59 | '''if symbol not in self.oms.portfolio.positions or not self.oms.portfolio.positions[symbol].is_open(): 60 | qty = 100 #int(self.cash / px) 61 | self.oms.add(Transaction(symbol, dt, px, qty)) 62 | self.cash = 0 63 | ''' 64 | 65 | elif v > 0 and v < v_yesterday and v_yesterday > 0: 66 | pass 67 | '''if dt == datetime.datetime(2013,12,19): 68 | print dt, 'SELL', symbol 69 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 70 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 71 | self.cash += gains_cash 72 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 73 | ''' 74 | 75 | except: 76 | pass 77 | 78 | test = ADXTest(stocks, '20120101', '20140117') 79 | test.run() 80 | test.results() 81 | 82 | #test.write_to_csv('adx.csv', indicator_list=['TR', 'PlusDM', 'MinusDM', 'ATR', 'PlusDM14', 'MinusDM14', 'PlusDI', 'MinusDI', 'DX', 'ADX']) 83 | ''' 84 | stock = stocks[0] 85 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 86 | [[test.cube.get_values(stock, 'close')],[test.i('MACD').as_series(), test.i('MACD_Signal').as_series()]], 87 | 'Date', 88 | ['Price','Value'], 89 | '-', 90 | [['Close'],['MACD', 'Signal']], 91 | stock) 92 | for t in test.oms.blotter.all(symbols=stock): 93 | dt = t.dt 94 | high = test.cube.data[(stock, 'high')][dt] 95 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.05), xytext=(dt, high*1.08), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 96 | plt.show() 97 | ''' -------------------------------------------------------------------------------- /momentum.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | 8 | stock = 'SPY' 9 | results = {} 10 | for period in [5]: 11 | class SMATest(Algorithm): 12 | def __init__(self, symbols, start_date, end_date): 13 | super(SMATest, self).__init__(symbols, start_date, end_date) 14 | self.cash = 10000 15 | 16 | def pre_run(self): 17 | super(SMATest, self).pre_run() 18 | 19 | for symbol in self.symbols: 20 | close_series = self.cube.data[(symbol, 'close')] 21 | self.add_indicator(SMA('SMA-' + symbol, close_series, period)) 22 | self.add_indicator(RSMA('RSMA-' + symbol, close_series, period)) 23 | self.add_indicator(SMA('SSS-' + symbol, self.i('RSMA-' + symbol), period)) 24 | self.add_indicator(BBandLower('BBandLower-20-' + symbol, close_series, 20, 2)) 25 | self.add_indicator(BBandUpper('BBandUpper-20-' + symbol, close_series, 20, 2)) 26 | self.add_indicator(ROC('ROC-' + symbol, self.i('SSS-' + symbol))) 27 | self.add_indicator(VWAP('VWAP-' + symbol, close_series, self.cube.data[(symbol, 'volume')], period)) 28 | 29 | def handle_data(self, dt, symbols, keys, data): 30 | for symbol in symbols: 31 | vwap = self.i('VWAP-' + symbol) 32 | px = data[(symbol, 'close')] 33 | 34 | if vwap[dt] is not None: 35 | if px < vwap[dt] * 1.005: 36 | shares = self.cash / px 37 | if shares > 0: 38 | self.oms.add(Transaction(symbol, dt, px, shares)) 39 | self.cash = 0 40 | elif px > vwap[dt] * .995: 41 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 42 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 43 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 44 | self.cash += gains_cash 45 | 46 | def post_run(self): 47 | self.results() 48 | for symbol in self.symbols: 49 | self.plot(symbol=symbol, indicator_list=['VWAP-' + symbol, 'BBandLower-20-' + symbol, 'BBandUpper-20-' + symbol, 'SMA-' + symbol, 'RSMA-'+ symbol, 'SSS-' + symbol, 'ROC-' + symbol]).show() 50 | 51 | test = SMATest([stock], '20130101', '20131017') 52 | test.run() 53 | results[period] = test.results() 54 | 55 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 56 | [[test.cube.get_values(stock, 'close'), test.i('VWAP-' + stock).as_series(), test.i('SMA-' + stock).as_series(), test.i('BBandLower-20-' + stock).as_series(), test.i('BBandUpper-20-' + stock).as_series()],[test.i('RSMA-' + stock).as_series(), test.i('SSS-' + stock).as_series()],[test.i('ROC-' + stock).as_series()]], 57 | 'Date', 58 | ['Price','Value', 'Value'], 59 | '-', 60 | [['Close', 'VWAP', 'SMA', 'BBandLower', 'BBandUpper'],['RSMA', 'SSS'],['ROC']], 61 | stock) 62 | for t in test.oms.blotter.all(symbols=stock): 63 | dt = t.dt 64 | high = test.cube.data[(stock, 'high')][dt] 65 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.05), xytext=(dt, high*1.08), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 66 | plt.show() 67 | pp = pprint.PrettyPrinter(indent=4) 68 | pp.pprint(results) -------------------------------------------------------------------------------- /nn.py: -------------------------------------------------------------------------------- 1 | # Back-Propagation Neural Networks 2 | # 3 | # Written in Python. See http://www.python.org/ 4 | # Placed in the public domain. 5 | # Neil Schemenauer 6 | 7 | import math 8 | import random 9 | import string 10 | import data 11 | import pprint 12 | random.seed(0) 13 | 14 | # calculate a random number where: a <= rand < b 15 | def rand(a, b): 16 | return (b-a)*random.random() + a 17 | 18 | # Make a matrix (we could use NumPy to speed this up) 19 | def makeMatrix(I, J, fill=0.0): 20 | m = [] 21 | for i in range(I): 22 | m.append([fill]*J) 23 | return m 24 | 25 | # our sigmoid function, tanh is a little nicer than the standard 1/(1+e^-x) 26 | def sigmoid(x): 27 | return math.tanh(x) 28 | 29 | # derivative of our sigmoid function, in terms of the output (i.e. y) 30 | def dsigmoid(y): 31 | return 1.0 - y**2 32 | 33 | class NN: 34 | def __init__(self, ni, nh, no): 35 | # number of input, hidden, and output nodes 36 | self.ni = ni + 1 # +1 for bias node 37 | self.nh = nh 38 | self.no = no 39 | 40 | # activations for nodes 41 | self.ai = [1.0]*self.ni 42 | self.ah = [1.0]*self.nh 43 | self.ao = [1.0]*self.no 44 | 45 | # create weights 46 | self.wi = makeMatrix(self.ni, self.nh) 47 | self.wo = makeMatrix(self.nh, self.no) 48 | # set them to random vaules 49 | for i in range(self.ni): 50 | for j in range(self.nh): 51 | self.wi[i][j] = rand(-0.2, 0.2) 52 | for j in range(self.nh): 53 | for k in range(self.no): 54 | self.wo[j][k] = rand(-2.0, 2.0) 55 | 56 | # last change in weights for momentum 57 | self.ci = makeMatrix(self.ni, self.nh) 58 | self.co = makeMatrix(self.nh, self.no) 59 | 60 | def update(self, inputs): 61 | if len(inputs) != self.ni-1: 62 | raise ValueError('wrong number of inputs') 63 | 64 | # input activations 65 | for i in range(self.ni-1): 66 | #self.ai[i] = sigmoid(inputs[i]) 67 | self.ai[i] = inputs[i] 68 | 69 | # hidden activations 70 | for j in range(self.nh): 71 | sum = 0.0 72 | for i in range(self.ni): 73 | sum = sum + self.ai[i] * self.wi[i][j] 74 | self.ah[j] = sigmoid(sum) 75 | 76 | # output activations 77 | for k in range(self.no): 78 | sum = 0.0 79 | for j in range(self.nh): 80 | sum = sum + self.ah[j] * self.wo[j][k] 81 | self.ao[k] = sigmoid(sum) 82 | 83 | return self.ao[:] 84 | 85 | 86 | def backPropagate(self, targets, N, M): 87 | if len(targets) != self.no: 88 | raise ValueError('wrong number of target values') 89 | 90 | # calculate error terms for output 91 | output_deltas = [0.0] * self.no 92 | for k in range(self.no): 93 | error = targets[k]-self.ao[k] 94 | output_deltas[k] = dsigmoid(self.ao[k]) * error 95 | 96 | # calculate error terms for hidden 97 | hidden_deltas = [0.0] * self.nh 98 | for j in range(self.nh): 99 | error = 0.0 100 | for k in range(self.no): 101 | error = error + output_deltas[k]*self.wo[j][k] 102 | hidden_deltas[j] = dsigmoid(self.ah[j]) * error 103 | 104 | # update output weights 105 | for j in range(self.nh): 106 | for k in range(self.no): 107 | change = output_deltas[k]*self.ah[j] 108 | self.wo[j][k] = self.wo[j][k] + N*change + M*self.co[j][k] 109 | self.co[j][k] = change 110 | #print N*change, M*self.co[j][k] 111 | 112 | # update input weights 113 | for i in range(self.ni): 114 | for j in range(self.nh): 115 | change = hidden_deltas[j]*self.ai[i] 116 | self.wi[i][j] = self.wi[i][j] + N*change + M*self.ci[i][j] 117 | self.ci[i][j] = change 118 | 119 | # calculate error 120 | error = 0.0 121 | for k in range(len(targets)): 122 | error = error + 0.5*(targets[k]-self.ao[k])**2 123 | return error 124 | 125 | 126 | def test(self, patterns): 127 | results = [] 128 | for p in patterns: 129 | results.append((p[0], self.update(p[0]))) 130 | return results 131 | 132 | def weights(self): 133 | print('Input weights:') 134 | for i in range(self.ni): 135 | print(self.wi[i]) 136 | print() 137 | print('Output weights:') 138 | for j in range(self.nh): 139 | print(self.wo[j]) 140 | 141 | def train(self, patterns, iterations=300, N=0.5, M=0.1): 142 | # N: learning rate 143 | # M: momentum factor 144 | last_error = 0 145 | for i in range(iterations): 146 | error = 0.0 147 | for p in patterns: 148 | inputs = p[0] 149 | targets = p[1] 150 | self.update(inputs) 151 | error = error + self.backPropagate(targets, N, M) 152 | if i % 100 == 0: 153 | print(error) 154 | if last_error == error: 155 | print('Error hasn\'t changed - breaking.') 156 | break 157 | last_error = error 158 | 159 | def demo(): 160 | cube = data.load(['SPY', 'QQQ'], '20100101', '20130204') 161 | 162 | spy_px = [cube.data[('SPY', 'adjclose')][dt] for dt in cube.get_dates()] 163 | qqq_px = [cube.data[('QQQ', 'adjclose')][dt] for dt in cube.get_dates()] 164 | minspy = min(spy_px) 165 | maxspy = max(spy_px) 166 | minqqq = min(qqq_px) 167 | maxqqq = max(qqq_px) 168 | spy_px = [(px - minspy) / (maxspy - minspy) for px in spy_px] 169 | qqq_px = [(px - minqqq) / (maxqqq - minqqq) for px in qqq_px] 170 | 171 | spy_inp = [[spy_px[j-i] for i in range(10, 0, -1)] for j in range(10, len(spy_px))] 172 | spy_tar = [spy_px[i] for i in range(10, len(spy_px))] 173 | qqq_inp = [[qqq_px[j-i] for i in range(10, 0, -1)] for j in range(10, len(qqq_px))] 174 | qqq_tar = [qqq_px[i] for i in range(10, len(qqq_px))] 175 | inp = np.array([z[0] + z[1] for z in zip(spy_inp, qqq_inp)]) 176 | tar = np.array([[z[0]] + [z[1]] for z in zip(spy_tar, qqq_tar)]) 177 | net = nl.net.newff([[0,1]]*20, [41,40,2]) 178 | #inp = np.array(spy_inp) 179 | #tar = np.array([spy_tar]).reshape(len(inp), 1) 180 | #net = nl.net.newff([[0,1]]*10, [51,2,1]) 181 | error = net.train(inp,tar,epochs=500, show=100, goal=0.02) 182 | 183 | 184 | returns = {} 185 | for dt in cube.get_dates()[1:]: 186 | yesterday = cube.go_back(dt, 1) 187 | px_T = cube.data[('SPY', 'adjclose')][dt] 188 | px_Tm1 = cube.data[('SPY', 'adjclose')][yesterday] 189 | r = px_T / px_Tm1 190 | returns[dt] = px_T 191 | maxreturn = max(returns.values()) 192 | minreturn = min(returns.values()) 193 | for k, v in returns.items(): 194 | returns[k] = (v - minreturn) / (maxreturn - minreturn) 195 | 196 | xs = [] 197 | ys = [] 198 | pat = [] 199 | dates = cube.get_dates() 200 | for dt in dates[11:]: 201 | contents = [returns[cube.go_back(dt, x)] for x in range(10, 0, -1)] 202 | target = returns[dt] 203 | xs.append(contents) 204 | ys.append([target]) 205 | pat.append([contents, [target]]) 206 | 207 | import neurolab as nl 208 | import numpy as np 209 | inp = np.array(xs) 210 | 211 | tar = np.array(ys) 212 | 213 | net = nl.net.newp([[-1,1],[-1,1],[-1,1],[-1,1],[-1,1],[-1,1],[-1,1],[-1,1],[-1,1],[-1,1]],1) 214 | error = net.train(inp, tar, epochs=500, show=100) 215 | print 'error', error 216 | 217 | out = net.sim([inp[-1]]) 218 | print 'out', out 219 | 220 | 221 | if __name__ == '__main__': 222 | demo() -------------------------------------------------------------------------------- /nn2.py: -------------------------------------------------------------------------------- 1 | from math import tanh 2 | 3 | def dtanh(y): 4 | return 1.0 - y * s 5 | 6 | class NN: 7 | def __init__(self, topography): 8 | self.topography = topography 9 | self.nodes_per_layer = {} 10 | for layer, num_nodes in enumerate(self.topography): 11 | self.nodes_per_layer[layer] = [1.0] * num_nodes 12 | self.strengths={} 13 | for layer in range(0, len(self.topography)-1): 14 | for node_from in range(0, len(self.nodes_per_layer[layer])): 15 | for node_to in range(0, len(self.nodes_per_layer[layer+1])): 16 | if layer+1 == len(self.topography)-1: 17 | self.strengths[((layer, node_from), (layer+1, node_to))] = 0.1 18 | else: 19 | self.strengths[((layer, node_from), (layer+1, node_to))] = 1.0 20 | 21 | def feedforward(self): 22 | 23 | 24 | sample_data = [100 + i for i in range(0, 50)] 25 | 26 | def main(): 27 | 28 | 29 | 30 | if __name__ == '__main__': 31 | main() -------------------------------------------------------------------------------- /pennant.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | 8 | stocks = ['SPY', 'VXX', 9 | # nasdaq 10 | 'ATVI','ADBE','AKAM','ALXN','ALTR','AMZN','AMGN','ADI','AAPL','AMAT','ADSK','ADP','AVGO','BIDU','BBBY','BIIB','BRCM','CHRW','CA','CTRX','CELG','CERN','CHTR','CHKP','CSCO','CTXS','CTSH','CMCSA','COST','XRAY','DTV','DISCA','DLTR','EBAY','EQIX','EXPE','EXPD','ESRX','FFIV','FB','FAST','FISV','FOSL','GRMN','GILD','GOOG','GMCR','HSIC','INTC','INTU','ISRG','KLAC','KRFT','LBTYA','LINTA','LMCA','LLTC','MAR','MAT','MXIM','MCHP','MU','MSFT','MDLZ','MNST','MYL','NTAP','NFLX','NUAN','NVDA','ORLY','PCAR','PAYX','PCLN','QCOM','REGN','ROST','SNDK','SBAC','STX','SHLD','SIAL','SIRI','SPLS','SBUX','SRCL','SYMC','TSLA','TXN','FOXA','VRSK','VRTX','VIAB','VIP','VOD','WDC','WFM','WYNN','XLNX','YHOO', 11 | # s&P 12 | 'A','AA','AAPL','ABBV','ABC','ABT','ACE','ACN','ACT','ADBE','ADI','ADM','ADP','ADSK','ADT','AEE','AEP','AES','AET','AFL','AGN','AIG','AIV','AIZ','AKAM','ALL','ALTR','ALXN','AMAT','AME','AMGN','AMP','AMT','AMZN','AN','ANF','AON','APA','APC','APD','APH','ARG','ATI','AVB','AVP','AVY','AXP','AZO','BA','BAC','BAX','BBBY','BBT','BBY','BCR','BDX','BEAM','BEN','BF.B','BHI','BIIB','BK','BLK','BLL','BMS','BMY','BRCM','BRK.B','BSX','BTU','BWA','BXP','C','CA','CAG','CAH','CAM','CAT','CB','CBG','CBS','CCE','CCI','CCL','CELG','CERN','CF','CFN','CHK','CHRW','CI','CINF','CL','CLF','CLX','CMA','CMCSA','CME','CMG','CMI','CMS','CNP','CNX','COF','COG','COH','COL','COP','COST','COV','CPB','CRM','CSC','CSCO','CSX','CTAS','CTL','CTSH','CTXS','CVC','CVS','CVX','D','DAL','DD','DE','DFS','DG','DGX','DHI','DHR','DIS','DISCA','DLPH','DLTR','DNB','DNR','DO','DOV','DOW','DPS','DRI','DTE','DTV','DUK','DVA','DVN','EA','EBAY','ECL','ED','EFX','EIX','EL','EMC','EMN','EMR','EOG','EQR','EQT','ESRX','ESV','ETFC','ETN','ETR','EW','EXC','EXPD','EXPE','F','FAST','FCX','FDO','FDX','FE','FFIV','FIS','FISV','FITB','FLIR','FLR','FLS','FMC','FOSL','FOXA','FRX','FSLR','FTI','FTR','GAS','GCI','GD','GE','GILD','GIS','GLW','GM','GME','GNW','GOOG','GPC','GPS','GRMN','GS','GT','GWW','HAL','HAR','HAS','HBAN','HCBK','HCN','HCP','HD','HES','HIG','HOG','HON','HOT','HP','HPQ','HRB','HRL','HRS','HSP','HST','HSY','HUM','IBM','ICE','IFF','IGT','INTC','INTU','IP','IPG','IR','IRM','ISRG','ITW','IVZ','JBL','JCI','JCP','JDSU','JEC','JNJ','JNPR','JOY','JPM','JWN','K','KEY','KIM','KLAC','KMB','KMI','KMX','KO','KR','KRFT','KSS','KSU','L','LEG','LEN','LH','LIFE','LLL','LLTC','LLY','LM','LMT','LNC','LO','LOW','LRCX','LSI','LUK','LUV','LYB','M','MA','MAC','MAR','MAS','MAT','MCD','MCHP','MCK','MCO','MDLZ','MDT','MET','MHFI','MJN','MKC','MMC','MMM','MNST','MO','MOLX','MON','MOS','MPC','MRK','MRO','MS','MSFT','MSI','MTB','MU','MUR','MWV','MYL','NBL','NBR','NDAQ','NE','NEE','NEM','NFLX','NFX','NI','NKE','NLSN','NOC','NOV','NRG','NSC','NTAP','NTRS','NU','NUE','NVDA','NWL','NWSA','OI','OKE','OMC','ORCL','ORLY','OXY','PAYX','PBCT','PBI','PCAR','PCG','PCL','PCLN','PCP','PDCO','PEG','PEP','PETM','PFE','PFG','PG','PGR','PH','PHM','PKI','PLD','PLL','PM','PNC','PNR','PNW','POM','PPG','PPL','PRGO','PRU','PSA','PSX','PVH','PWR','PX','PXD','QCOM','QEP','R','RAI','RDC','REGN','RF','RHI','RHT','RL','ROK','ROP','ROST','RRC','RSG','RTN','SBUX','SCG','SCHW','SE','SEE','SHW','SIAL','SJM','SLB','SLM','SNA','SNDK','SNI','SO','SPG','SPLS','SRCL','SRE','STI','STJ','STT','STX','STZ','SWK','SWN','SWY','SYK','SYMC','SYY','T','TAP','TDC','TE','TEG','TEL','TER','TGT','THC','TIF','TJX','TMK','TMO','TRIP','TROW','TRV','TSN','TSO','TSS','TWC','TWX','TXN','TXT','TYC','UNH','UNM','UNP','UPS','URBN','USB','UTX','V','VAR','VFC','VIAB','VLO','VMC','VNO','VRSN','VRTX','VTR','VZ','WAG','WAT','WDC','WEC','WFC','WFM','WHR','WIN','WLP','WM','WMB','WMT','WPX','WU','WY','WYN','WYNN','X','XEL','XL','XLNX','XOM','XRAY','XRX','XYL','YHOO','YUM','ZION','ZMH','ZTS', 13 | #dow 14 | 'AXP','BA','CAT','CSCO','CVX','DD','DIS','GE','GS','HD','IBM','INTC','JNJ','JPM','KO','MCD','MMM','MRK','MSFT','NKE','PFE','PG','T','TRV','UNH','UTX','V','VZ','WMT','XOM'] 15 | 16 | class Pennant(Algorithm): 17 | def __init__(self, symbols, start_date, end_date): 18 | super(Pennant, self).__init__(symbols, start_date, end_date) 19 | self.cash = 10000 20 | self.buys = {} 21 | self.stops = {} 22 | 23 | def pre_run(self): 24 | super(Pennant, self).pre_run() 25 | 26 | for symbol in self.symbols: 27 | close_series = self.cube.data[(symbol, 'close')] 28 | 29 | self.add_indicator(SMA('SMA200-' + symbol, close_series, 200)) 30 | self.add_indicator(SMA('SMA50-' + symbol, close_series, 50)) 31 | self.add_indicator(SMA('SMA13-' + symbol, close_series, 13)) 32 | self.add_indicator(SMA('SMA10-' + symbol, close_series, 10)) 33 | 34 | def handle_data(self, dt, symbols, keys, data): 35 | back20 = self.cube.go_back(dt, 20) 36 | back10 = self.cube.go_back(dt, 10) 37 | back5 = self.cube.go_back(dt, 5) 38 | 39 | for symbol in symbols: 40 | try: 41 | px = data[(symbol, 'close')] 42 | sma200 = self.i('SMA200-'+symbol)[dt] 43 | sma50 = self.i('SMA50-'+symbol)[dt] 44 | sma13 = self.i('SMA13-'+symbol)[dt] 45 | sma10 = self.i('SMA10-'+symbol)[dt] 46 | 47 | sma200_back20 = self.i('SMA200-'+symbol)[back20] 48 | sma50_back10 = self.i('SMA50-'+symbol)[back10] 49 | sma13_back5 = self.i('SMA13-'+symbol)[back5] 50 | 51 | rising_market = sma200 > sma200_back20 and sma50 > sma50_back10 and sma50 > sma200 52 | 53 | min_close = px 54 | max_sma50 = sma50 55 | for i in range(1, 6): 56 | j = self.cube.go_back(dt, i) 57 | min_close = min(min_close, self.cube.data[(symbol, 'close')][j]) 58 | max_sma50 = max(max_sma50, self.i('SMA50-'+symbol)[j]) 59 | 60 | falling_prices = sma13 < sma13_back5 and min_close > max_sma50 61 | 62 | entry_condition = (px < sma10) and falling_prices and rising_market 63 | 64 | if dt == datetime.datetime(2014, 1, 17): 65 | if entry_condition: 66 | print 'BUY', dt, symbol 67 | except: 68 | pass 69 | 70 | test = Pennant(stocks, '20120101', '20140117') 71 | test.run() 72 | test.results() -------------------------------------------------------------------------------- /plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | from numpy import nan 3 | from pylab import * 4 | import numpy as np 5 | import matplotlib.ticker as ticker 6 | import matplotlib.dates as mdates 7 | from mpl_toolkits.axes_grid1 import host_subplot 8 | import mpl_toolkits.axisartist as AA 9 | import matplotlib.gridspec as gridspec 10 | 11 | def plot_data_with_dates(x_list, y_list, x_label, y_label, format, label_list, title): 12 | if len(y_list) != len(label_list): 13 | raise Exception('# of series to plot does not match # of labels for legend.') 14 | 15 | fig = plt.figure(figsize=(6*3.13,4*3.13)) 16 | graph = fig.add_subplot(111) 17 | data = zip(x_list, y_list, label_list) 18 | 19 | for x, y, label in data: 20 | y_values = y 21 | if type(y).__name__ == 'OrderedDict': 22 | y_values = y.values() 23 | plt.plot_date(x, y_values, format, label=label) 24 | plt.legend(loc=3, prop={'size':8}) 25 | plt.title(title) 26 | plt.xlabel(x_label) 27 | plt.ylabel(y_label) 28 | plt.grid(True) 29 | return plt 30 | 31 | def multi_plot_data_with_dates(x_list, y_lists, x_label, y_labels, format, label_lists, title): 32 | if len(y_lists) != len(label_lists): 33 | raise Exception('subplot mismatch') 34 | for y_list, label_list in zip(y_lists, label_lists): 35 | if len(y_list) != len(label_list): 36 | raise Exception('# of series to plot does not match # of labels for legend.') 37 | 38 | subplots = [] 39 | fig = plt.figure(figsize=(6*3.13,4*3.13)) 40 | for i in range(0, len(y_lists)): 41 | data = zip([x_list] * len(y_lists[i]), y_lists[i], label_lists[i]) 42 | if i == 0: 43 | graph = plt.subplot2grid((len(y_lists) + 2, 1), (i, 0), rowspan=3) 44 | else: 45 | graph = plt.subplot2grid((len(y_lists) + 2, 1), (i+2, 0)) 46 | subplots.append(graph) 47 | sum_y = 0 48 | num_y = 0 49 | for x, y, label in data: 50 | y_values = y 51 | if type(y).__name__ == 'OrderedDict': 52 | y_values = y.values() 53 | 54 | sum_y += sum([y for y in y_values if y]) 55 | num_y += len(y_values) 56 | plt.plot_date(x, y_values, format, label=label) 57 | 58 | plt.plot_date(x_list, [sum_y / num_y] * len(x_list), visible=False) 59 | plt.legend(loc=3, prop={'size':8}) 60 | if i == 0: 61 | plt.title(title) 62 | if i == len(y_lists)-1: 63 | plt.xlabel(x_label) 64 | plt.ylabel(y_labels[i]) 65 | plt.grid(True) 66 | return (plt, subplots) 67 | 68 | def candlestick(ax, quotes, width=0.2, colorup='k', colordown='r', alpha=1.0): 69 | OFFSET = width/2.0 70 | 71 | lines = [] 72 | patches = [] 73 | idx = 0 74 | for q in quotes: 75 | _, t, open, close, high, low = q[:6] 76 | 77 | if close>=open : 78 | color = colorup 79 | lower = open 80 | height = close-open 81 | else : 82 | color = colordown 83 | lower = close 84 | height = open-close 85 | 86 | vline = Line2D( 87 | xdata=(idx, idx), ydata=(low, high), 88 | color='k', 89 | linewidth=0.5, 90 | antialiased=True, 91 | ) 92 | 93 | rect = Rectangle( 94 | xy = (idx-OFFSET, lower), 95 | width = width, 96 | height = height, 97 | facecolor = color, 98 | edgecolor = color, 99 | ) 100 | rect.set_alpha(alpha) 101 | 102 | 103 | lines.append(vline) 104 | patches.append(rect) 105 | ax.add_line(vline) 106 | ax.add_patch(rect) 107 | idx += 1 108 | ax.autoscale_view() 109 | 110 | return lines, patches 111 | 112 | def candles(dates, quotes): 113 | N = len(dates) 114 | r = quotes 115 | def format_date(x, pos=None): 116 | if x < 0: 117 | return (mdates.num2date(mdates.date2num(r[0][0])+x)).strftime('%Y-%m-%d') 118 | else: 119 | thisind = np.clip(int(x+0.5), 0, N-1) 120 | return r[thisind][0].strftime('%Y-%m-%d') 121 | 122 | fig = plt.figure(figsize=(6*3.13,4*3.13)) 123 | graph = fig.add_subplot(111) 124 | ind = range(N) 125 | candlestick(graph, quotes) 126 | #graph.plot(ind, [q[2] for q in quotes], '-') 127 | graph.xaxis.set_minor_formatter(ticker.FuncFormatter(format_date)) 128 | graph.xaxis.set_major_formatter(ticker.FuncFormatter(format_date)) 129 | setp(gca().get_xticklabels(), rotation=45, horizontalalignment='right') 130 | return plt 131 | 132 | def plot_candles(cube): 133 | time = [mdates.date2num(dt) for dt in cube.get_dates()] 134 | open = cube.get_values('GOOG', 'open') 135 | close = cube.get_values('GOOG', 'close') 136 | low = cube.get_values('GOOG', 'low') 137 | high = cube.get_values('GOOG', 'high') 138 | return candles(time, zip(cube.get_dates(), time, open, close, low, high)) 139 | -------------------------------------------------------------------------------- /positions.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from collections import defaultdict 3 | from util import enum, flexfilter 4 | 5 | class Transaction(object): 6 | Side = enum(BUY='buy', SELL='sell') 7 | 8 | def __init__(self, symbol, dt, px, qty): 9 | if qty == 0: 10 | raise Exception('Cannot transact in 0-value quantity.') 11 | 12 | self.symbol = symbol 13 | self.dt = dt 14 | self.px = px 15 | self.qty = qty 16 | 17 | @staticmethod 18 | def sort(txns): 19 | # TODO: sort by multiple keys (dt - symbol - px - qty) 20 | sorted_txns = sorted(txns, key=lambda txn: txn.dt) 21 | for i in range(0, len(sorted_txns)): 22 | yield sorted_txns[i] 23 | 24 | def cost(self): 25 | return self.px * self.qty 26 | 27 | def side(self): 28 | return Transaction.Side.SELL if self.qty < 0 else Transaction.Side.BUY 29 | 30 | def __repr__(self): 31 | return 'Transaction({}, {}, {}, {})'.format(self.symbol, self.dt, self.px, self.qty) 32 | 33 | def __str__(self): 34 | return '[{}] {} {} of {} @ {}'.format(datetime.strftime(self.dt, '%Y-%m-%d'), self.side(), abs(self.qty), self.symbol, self.px) 35 | 36 | class Blotter(object): 37 | def __init__(self): 38 | self.txns = [] 39 | 40 | def add(self, txn): 41 | self.txns.append(txn) 42 | 43 | def all(self, symbols=None, start=None, end=None): 44 | return Transaction.sort([txn for txn in flexfilter(self.txns, 'symbol', symbols) 45 | if (start is None or txn.dt >= start) and (end is None or txn.dt < end)]) 46 | 47 | def calculate_pandl(self, symbols=None): 48 | transactions = self.all(symbols=symbols) 49 | pandl = 0.0 50 | for t in transactions: 51 | pandl += t.px * -t.qty 52 | return pandl 53 | 54 | class Position(object): 55 | def __init__(self, symbol): 56 | self.symbol = symbol 57 | self.txns = [] 58 | self.amount = 0.0 59 | self.cost_basis = 0.0 60 | 61 | def cost(self): 62 | return self.cost_basis * self.amount 63 | 64 | def add(self, txn): 65 | if self.symbol != txn.symbol: 66 | raise Exception('Attempt to add a transaction to a wrong position!') 67 | 68 | self.txns.append(txn) 69 | if self.amount + txn.qty == 0: 70 | self.cost_basis = 0.0 71 | self.amount = 0 72 | else: 73 | total_cost = self.cost() + txn.cost() 74 | self.amount = self.amount + txn.qty 75 | self.cost_basis = total_cost / self.amount 76 | 77 | def is_open(self): 78 | return self.amount != 0.0 79 | 80 | def transactions(self): 81 | return Transaction.sort(self.txns) 82 | 83 | def __repr__(self): 84 | return 'Position({}, {}, {})'.format(self.symbol, self.amount, self.cost_basis) 85 | 86 | class Portfolio(object): 87 | def __init__(self): 88 | self.positions = {} 89 | 90 | def add(self, txn): 91 | if txn.symbol not in self.positions: 92 | self.positions[txn.symbol] = Position(txn.symbol) 93 | self.positions[txn.symbol].add(txn) 94 | 95 | def all(self, only_open=False, only_closed=False): 96 | return [position for _, position in self.positions.items() if 97 | not(only_open or only_closed) or 98 | (only_open and position.is_open()) or 99 | (only_closed and not position.is_open())] 100 | 101 | class OMS(object): 102 | def __init__(self): 103 | self.blotter = Blotter() 104 | self.portfolio = Portfolio() 105 | 106 | def add(self, txn): 107 | self.blotter.add(txn) 108 | self.portfolio.add(txn) -------------------------------------------------------------------------------- /pxcross.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | 8 | stocks = ["MMM","AA","MO","AXP","AIG","T","BA","CAT","C","KO","DD","XOM","GE","GM","HPQ","HD","HON","IBM","INTC","JNJ","JPM","MCD","MRK","MSFT","PFE","PG","UTX","VZ","WMT","DIS", "SPY"] 9 | #stocks = ['SPY'] 10 | results = {} 11 | stocks =['AXP'] 12 | for stock in stocks: 13 | for period in [10]:#[2,3,5,10,15,20,30,50,100,200]: 14 | for start_date in ['20050101']:#['20050101','20060101','20070101','20080101','20090101','20100101','20110101','20120101']: 15 | class SMATest(Algorithm): 16 | def __init__(self, symbols, start_date, end_date): 17 | super(SMATest, self).__init__(symbols, start_date, end_date) 18 | self.cash = 10000 19 | 20 | def pre_run(self): 21 | super(SMATest, self).pre_run() 22 | 23 | for symbol in self.symbols: 24 | close_series = self.cube.data[(symbol, 'adjclose')] 25 | self.add_indicator(SMA('SMA-' + symbol, close_series, period)) 26 | self.add_indicator(BBandLower('BBandLower-' + symbol, close_series, period, 2)) 27 | self.add_indicator(BBandUpper('BBandUpper-' + symbol, close_series, period, 2)) 28 | 29 | def handle_data(self, dt, symbols, keys, data): 30 | yesterday = self.cube.go_back(dt, 1) 31 | for symbol in symbols: 32 | px = data[(symbol, 'adjclose')] 33 | px_yesterday = self.cube.data[(symbol, 'adjclose')][yesterday] 34 | sma = self.i('SMA-' + symbol) 35 | sma_yesterday = sma[yesterday] 36 | sma_today = sma[dt] 37 | 38 | if sma_yesterday and px_yesterday: 39 | if sma_yesterday < px_yesterday and sma_today > px: 40 | if self.cash > 0: 41 | self.oms.add(Transaction(symbol, dt, px, (self.cash-5) / px)) 42 | self.cash = 0 43 | elif sma_yesterday > px_yesterday and sma_today < px: 44 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 45 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 46 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 47 | self.cash += (gains_cash-5) 48 | 49 | def post_run(self): 50 | self.results() 51 | for symbol in self.symbols: 52 | self.plot(symbol=symbol, indicator_list=['SMA-' + symbol]).show() 53 | 54 | test = SMATest([stock], start_date, '20130101') 55 | test.run() 56 | results[(stock, period, start_date)] = test.results() 57 | #file = open('pxcross.out', 'w') 58 | #pp = pprint.PrettyPrinter(indent=4, stream=file) 59 | #pp = pprint.PrettyPrinter(indent=4) 60 | #pp.pprint(results) -------------------------------------------------------------------------------- /sellinmay.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from indicators import * 5 | import pprint 6 | 7 | stocks = ["MMM","AA","MO","AXP","AIG","T","BA","CAT","C","KO","DD","XOM","GE","GM","HPQ","HD","HON","IBM","INTC","JNJ","JPM","MCD","MRK","MSFT","PFE","PG","UTX","VZ","WMT","DIS"] 8 | 9 | class SellInMayTest(Algorithm): 10 | def __init__(self, symbols, start_date, end_date, ): 11 | super(SellInMayTest, self).__init__(symbols, start_date, end_date) 12 | 13 | def pre_run(self): 14 | super(SellInMayTest, self).pre_run() 15 | 16 | def handle_data(self, dt, symbols, keys, data): 17 | 18 | for symbol in symbols: 19 | px = data[(symbol, 'adjclose')] 20 | if px: 21 | if dt.month == 5: 22 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 23 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 24 | elif dt.month == 10: 25 | if symbol not in self.oms.portfolio.positions or not self.oms.portfolio.positions[symbol].is_open(): 26 | self.oms.add(Transaction(symbol, dt, px, 10000.0/px)) 27 | 28 | def post_run(self): 29 | self.results() 30 | 31 | test = SellInMayTest(stocks, '20100101', '20130131') 32 | test.run() -------------------------------------------------------------------------------- /spy.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from indicators import * 5 | import pprint 6 | 7 | stocks = ['SPY'] 8 | 9 | class SPYReversion(Algorithm): 10 | def __init__(self, symbols, start_date, end_date): 11 | super(SPYReversion, self).__init__(symbols, start_date, end_date) 12 | 13 | def pre_run(self): 14 | super(SPYReversion, self).pre_run() 15 | 16 | for symbol in self.symbols: 17 | close_series = self.cube.data[(symbol, 'close')] 18 | high_series = self.cube.data[(symbol, 'high')] 19 | low_series = self.cube.data[(symbol, 'low')] 20 | self.add_indicator(ATR('ATR-' + symbol, 25, high_series, low_series, close_series)) 21 | 22 | def high_from_range(self, starting_dt, symbol, period): 23 | high = self.cube.data[(symbol, 'high')][starting_dt] 24 | for i in range(1, period): 25 | dt = self.cube.go_back(starting_dt, i) 26 | high = max(high, self.cube.data[(symbol, 'high')][dt]) 27 | return high 28 | 29 | def handle_data(self, dt, symbols, keys, data): 30 | for symbol in symbols: 31 | atr = self.i('ATR-' + symbol) 32 | atr_today = atr[dt] # 1. 25 day average of ATR 33 | 34 | px = data[(symbol, 'close')] 35 | high = data[(symbol, 'high')] 36 | low = data[(symbol, 'low')] 37 | 38 | recent_high = self.high_from_range(dt, symbol, 10) # 2. 10 day low 39 | 40 | ibs_ratio = (px - low) / (high - low) # 3. IBS ratio (whatever that is) 41 | 42 | if atr_today is not None: 43 | band_below = recent_high - (2.5 * atr_today) # 4. 44 | 45 | if px < band_below: 46 | if symbol not in self.oms.portfolio.positions or not self.oms.portfolio.positions[symbol].is_open(): 47 | self.oms.add(Transaction(symbol, dt, px, 10000.0/px)) 48 | else: 49 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 50 | self.oms.add(Transaction(symbol, dt, px, self.oms.portfolio.positions[symbol].amount)) 51 | 52 | def post_run(self): 53 | self.results() 54 | for symbol in self.symbols: 55 | self.plot(symbol=symbol, indicator_list=['ATR-' + symbol]).show() 56 | 57 | for stock in stocks: 58 | test = SPYReversion([stock], '20000101', '20130131') 59 | test.run() 60 | result = test.results() -------------------------------------------------------------------------------- /squeeze.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | stocks = ["MMM","AA","MO","AXP","AIG","T","BA","CAT","KO","DD","XOM","GE","GM","HPQ","HD","HON","IBM","INTC","JNJ","JPM","MCD","MRK","MSFT","PFE","PG","UTX","VZ","WMT","DIS", "SPY"] 8 | stocks = ['ATVI','ADBE','AKAM','ALXN','ALTR','AMZN','AMGN','ADI','AAPL','AMAT','ADSK','ADP','AVGO','BIDU','BBBY','BIIB','BRCM','CHRW','CA','CTRX','CELG','CERN','CHTR','CHKP','CSCO','CTXS','CTSH','CMCSA','COST','XRAY','DTV','DISCA','DLTR','EBAY','EQIX','EXPE','EXPD','ESRX','FFIV','FB','FAST','FISV','FOSL','GRMN','GILD','GOOG','GMCR','HSIC','INTC','INTU','ISRG','KLAC','KRFT','LBTYA','LINTA','LLTC','MAT','MXIM','MCHP','MU','MSFT','MDLZ','MNST','MYL','NTAP','NFLX','NUAN','NVDA','ORLY','PCAR','PAYX','PCLN','QCOM','GOLD','REGN','ROST','SNDK','SBAC','STX','SHLD','SIAL','SIRI','SPLS','SBUX','SRCL','SYMC','TSLA','TXN','FOXA','VRSK','VRTX','VIAB','VIP','VOD','WDC','WFM','WYNN','XLNX','YHOO','SPY','EEM','GDX','XLF','IWM','QQQ','EWJ','FXI','VWO','EWZ','EFA','XIV','VXX','TZA','IYR','XLU','SDS','SLV','TNA','XLE','GLD','XLI','TLT','XLP','UVXY','DIA','XLK','ITB','FAZ','USO','EWT','SSO','XHB','XLV','XLY','SPXU','FAS','XLB','DXJ','DUST','JNK','EPI','XOP','NUGT','IVV','UNG','IAU','VGK','HYG','EZU','TVIX','SH','OIH','TBT','RSX','QID','VEA','VNQ','EWW','EWH','XRT','AMLP','XME','KRE','MDY','BKLN','EWG','SQQQ','EWY','EWU','VTI','TWM','DBC','UPRO','QLD','AGQ','LQD','IWF','PFF','SPXL','EWM','SPXS','EDC','FEZ','SCO','IJH','EWA','RWM','REM','EWS','IWD','EWI','UGAZ','KBE','EWC','SPLV','TQQQ','IEF'] 9 | 10 | stocks = ['SPY', 'VXX', 11 | # nasdaq 12 | 'ATVI','ADBE','AKAM','ALXN','ALTR','AMZN','AMGN','ADI','AAPL','AMAT','ADSK','ADP','AVGO','BIDU','BBBY','BIIB','BRCM','CHRW','CA','CTRX','CELG','CERN','CHTR','CHKP','CSCO','CTXS','CTSH','CMCSA','COST','XRAY','DTV','DISCA','DLTR','EBAY','EQIX','EXPE','EXPD','ESRX','FFIV','FB','FAST','FISV','FOSL','GRMN','GILD','GOOG','GMCR','HSIC','INTC','INTU','ISRG','KLAC','KRFT','LBTYA','LINTA','LMCA','LLTC','MAR','MAT','MXIM','MCHP','MU','MSFT','MDLZ','MNST','MYL','NTAP','NFLX','NUAN','NVDA','ORLY','PCAR','PAYX','PCLN','QCOM','REGN','ROST','SNDK','SBAC','STX','SHLD','SIAL','SIRI','SPLS','SBUX','SRCL','SYMC','TSLA','TXN','FOXA','VRSK','VRTX','VIAB','VIP','VOD','WDC','WFM','WYNN','XLNX','YHOO', 13 | # s&P 14 | 'A','AA','AAPL','ABBV','ABC','ABT','ACE','ACN','ACT','ADBE','ADI','ADM','ADP','ADSK','ADT','AEE','AEP','AES','AET','AFL','AGN','AIG','AIV','AIZ','AKAM','ALL','ALTR','ALXN','AMAT','AME','AMGN','AMP','AMT','AMZN','AN','ANF','AON','APA','APC','APD','APH','ARG','ATI','AVB','AVP','AVY','AXP','AZO','BA','BAC','BAX','BBBY','BBT','BBY','BCR','BDX','BEAM','BEN','BF.B','BHI','BIIB','BK','BLK','BLL','BMS','BMY','BRCM','BRK.B','BSX','BTU','BWA','BXP','C','CA','CAG','CAH','CAM','CAT','CB','CBG','CBS','CCE','CCI','CCL','CELG','CERN','CF','CFN','CHK','CHRW','CI','CINF','CL','CLF','CLX','CMA','CMCSA','CME','CMG','CMI','CMS','CNP','CNX','COF','COG','COH','COL','COP','COST','COV','CPB','CRM','CSC','CSCO','CSX','CTAS','CTL','CTSH','CTXS','CVC','CVS','CVX','D','DAL','DD','DE','DFS','DG','DGX','DHI','DHR','DIS','DISCA','DLPH','DLTR','DNB','DNR','DO','DOV','DOW','DPS','DRI','DTE','DTV','DUK','DVA','DVN','EA','EBAY','ECL','ED','EFX','EIX','EL','EMC','EMN','EMR','EOG','EQR','EQT','ESRX','ESV','ETFC','ETN','ETR','EW','EXC','EXPD','EXPE','F','FAST','FCX','FDO','FDX','FE','FFIV','FIS','FISV','FITB','FLIR','FLR','FLS','FMC','FOSL','FOXA','FRX','FSLR','FTI','FTR','GAS','GCI','GD','GE','GILD','GIS','GLW','GM','GME','GNW','GOOG','GPC','GPS','GRMN','GS','GT','GWW','HAL','HAR','HAS','HBAN','HCBK','HCN','HCP','HD','HES','HIG','HOG','HON','HOT','HP','HPQ','HRB','HRL','HRS','HSP','HST','HSY','HUM','IBM','ICE','IFF','IGT','INTC','INTU','IP','IPG','IR','IRM','ISRG','ITW','IVZ','JBL','JCI','JCP','JDSU','JEC','JNJ','JNPR','JOY','JPM','JWN','K','KEY','KIM','KLAC','KMB','KMI','KMX','KO','KR','KRFT','KSS','KSU','L','LEG','LEN','LH','LIFE','LLL','LLTC','LLY','LM','LMT','LNC','LO','LOW','LRCX','LSI','LUK','LUV','LYB','M','MA','MAC','MAR','MAS','MAT','MCD','MCHP','MCK','MCO','MDLZ','MDT','MET','MHFI','MJN','MKC','MMC','MMM','MNST','MO','MOLX','MON','MOS','MPC','MRK','MRO','MS','MSFT','MSI','MTB','MU','MUR','MWV','MYL','NBL','NBR','NDAQ','NE','NEE','NEM','NFLX','NFX','NI','NKE','NLSN','NOC','NOV','NRG','NSC','NTAP','NTRS','NU','NUE','NVDA','NWL','NWSA','OI','OKE','OMC','ORCL','ORLY','OXY','PAYX','PBCT','PBI','PCAR','PCG','PCL','PCLN','PCP','PDCO','PEG','PEP','PETM','PFE','PFG','PG','PGR','PH','PHM','PKI','PLD','PLL','PM','PNC','PNR','PNW','POM','PPG','PPL','PRGO','PRU','PSA','PSX','PVH','PWR','PX','PXD','QCOM','QEP','R','RAI','RDC','REGN','RF','RHI','RHT','RL','ROK','ROP','ROST','RRC','RSG','RTN','SBUX','SCG','SCHW','SE','SEE','SHW','SIAL','SJM','SLB','SLM','SNA','SNDK','SNI','SO','SPG','SPLS','SRCL','SRE','STI','STJ','STT','STX','STZ','SWK','SWN','SWY','SYK','SYMC','SYY','T','TAP','TDC','TE','TEG','TEL','TER','TGT','THC','TIF','TJX','TMK','TMO','TRIP','TROW','TRV','TSN','TSO','TSS','TWC','TWX','TXN','TXT','TYC','UNH','UNM','UNP','UPS','URBN','USB','UTX','V','VAR','VFC','VIAB','VLO','VMC','VNO','VRSN','VRTX','VTR','VZ','WAG','WAT','WDC','WEC','WFC','WFM','WHR','WIN','WLP','WM','WMB','WMT','WPX','WU','WY','WYN','WYNN','X','XEL','XL','XLNX','XOM','XRAY','XRX','XYL','YHOO','YUM','ZION','ZMH','ZTS', 15 | #dow 16 | 'AXP','BA','CAT','CSCO','CVX','DD','DIS','GE','GS','HD','IBM','INTC','JNJ','JPM','KO','MCD','MMM','MRK','MSFT','NKE','PFE','PG','T','TRV','UNH','UTX','V','VZ','WMT','XOM'] 17 | 18 | 19 | class SqueezeAlgo(Algorithm): 20 | def __init__(self, symbols, start_date, end_date): 21 | super(SqueezeAlgo, self).__init__(symbols, start_date, end_date) 22 | self.cash = 10000 23 | self.buys = {} 24 | self.stops = {} 25 | 26 | def pre_run(self): 27 | super(SqueezeAlgo, self).pre_run() 28 | 29 | for symbol in self.symbols: 30 | open_series = self.cube.data[(symbol, 'open')] 31 | close_series = self.cube.data[(symbol, 'adjclose')] 32 | high_series = self.cube.data[(symbol, 'high')] 33 | low_series = self.cube.data[(symbol, 'low')] 34 | 35 | self.add_indicator(EMA('EMA-' + symbol, close_series, 20)) 36 | self.add_indicator(SMA('SMA-' + symbol, close_series, 20)) 37 | self.add_indicator(BBandLower('BBandLower-' + symbol, close_series, 20, 2, self.i('SMA-'+symbol))) 38 | self.add_indicator(BBandUpper('BBandUpper-' + symbol, close_series, 20, 2, self.i('SMA-'+symbol))) 39 | self.add_indicator(KeltnerLower('KeltnerLower-' + symbol, 20, self.i('EMA-' + symbol), 1.5, high_series, low_series, close_series)) 40 | self.add_indicator(KeltnerUpper('KeltnerUpper-' + symbol, 20, self.i('EMA-' + symbol), 1.5, high_series, low_series, close_series)) 41 | self.add_indicator(Squeeze('Squeeze-' + symbol, self.i('BBandLower-' + symbol), self.i('BBandUpper-' + symbol), self.i('KeltnerLower-' + symbol), self.i('KeltnerUpper-' + symbol))) 42 | 43 | self.add_indicator(AverageGain('AG3-' + symbol, close_series, 3)) 44 | self.add_indicator(AverageLoss('AL3-' + symbol, close_series, 3)) 45 | self.add_indicator(RSI('RSI3-' + symbol, self.i('AG3-' + symbol), self.i('AL3-' + symbol))) 46 | self.add_indicator(Streak('Streak-' + symbol, close_series)) 47 | self.add_indicator(AverageGain('AGStreak-' + symbol, self.i('Streak-' + symbol), 2)) 48 | self.add_indicator(AverageLoss('ALStreak-' + symbol, self.i('Streak-' + symbol), 2)) 49 | self.add_indicator(RSI('RSIStreak-' + symbol, self.i('AGStreak-' + symbol), self.i('ALStreak-' + symbol))) 50 | self.add_indicator(PercentRank('PercentRank-' + symbol, close_series, 100)) 51 | self.add_indicator(ConnorsRSI('ConnorsRSI-'+symbol, close_series, self.i('RSI3-'+symbol), self.i('RSIStreak-'+symbol), self.i('PercentRank-'+symbol))) 52 | 53 | self.add_indicator(EMA('EMA13-' + symbol, close_series, 13)) 54 | self.add_indicator(EMA('EMA21-' + symbol, close_series, 21)) 55 | self.add_indicator(EMA('EMA55-' + symbol, close_series, 55)) 56 | 57 | self.add_indicator(HeikinAshi('HA-' + symbol, open_series, close_series, high_series, low_series)) 58 | 59 | self.add_indicator(AverageGain('AG-'+symbol, close_series, 12)) 60 | self.add_indicator(AverageLoss('AL-'+symbol, close_series, 12)) 61 | self.add_indicator(RSI('RSI-' + symbol, self.i('AG-' + symbol), self.i('AL-' + symbol))) 62 | 63 | self.add_indicator(TR('TR-' + symbol, high_series, low_series, close_series)) 64 | self.add_indicator(ATR('ATR-' + symbol, 14, high_series, low_series, close_series)) 65 | 66 | def handle_data(self, dt, symbols, keys, data): 67 | yesterday = self.cube.go_back(dt, 1) 68 | two_days_ago = self.cube.go_back(dt, 2) 69 | 70 | for symbol in symbols: 71 | px = data[(symbol, 'adjclose')] 72 | try: 73 | prior_px = self.cube.data[(symbol, 'adjclose')][yesterday] 74 | 75 | h = data[(symbol, 'high')] 76 | l = data[(symbol, 'low')] 77 | o = data[(symbol, 'open')] 78 | c = data[(symbol, 'close')] 79 | prior_h = self.cube.data[(symbol, 'high')][yesterday] 80 | prior_l = self.cube.data[(symbol, 'low')][yesterday] 81 | 82 | squeeze = self.i('Squeeze-' + symbol)[dt] 83 | prior_squeeze = self.i('Squeeze-' + symbol)[yesterday] 84 | squeeze_two_days_ago = self.i('Squeeze-' + symbol)[two_days_ago] 85 | 86 | ema13 = self.i('EMA13-' + symbol)[dt] 87 | ema21 = self.i('EMA21-' + symbol)[dt] 88 | ema55 = self.i('EMA55-' + symbol)[dt] 89 | 90 | bbandl = self.i('BBandLower-'+symbol)[dt] 91 | keltl = self.i('KeltnerLower-'+symbol)[dt] 92 | bbandu = self.i('BBandUpper-'+symbol)[dt] 93 | keltu = self.i('KeltnerUpper-'+symbol)[dt] 94 | 95 | ha = self.i('HA-' + symbol)[dt] 96 | prior_ha = self.i('HA-' + symbol)[yesterday] 97 | ha_two_days_ago = self.i('HA-' + symbol)[two_days_ago] 98 | 99 | ha_doji = ((abs(ha.o - ha.c) <= ((ha.h - ha.l) * 0.1))) 100 | prior_ha_doji = ((abs(prior_ha.o - prior_ha.c) <= ((prior_ha.h - prior_ha.l) * 0.1))) 101 | 102 | rsi = self.i('RSI-'+symbol)[dt] 103 | prior_rsi = self.i('RSI-'+symbol)[yesterday] 104 | 105 | tr = self.i('TR-' + symbol)[dt] 106 | atr = self.i('ATR-' + symbol)[dt] 107 | 108 | in_squeeze = (prior_squeeze > 0 and squeeze >= 0) or (squeeze_two_days_ago > 0 and prior_squeeze >= 0 and squeeze == 0) 109 | up_trend = ema13 > ema21 and ema21 > ema55 110 | down_trend = ema13 < ema21 and ema21 < ema55 111 | rising_ha = ha.c > prior_ha.c and prior_ha.c > ha_two_days_ago.c and ha.c > ha.o and prior_ha.c > prior_ha.o and prior_ha.l == prior_ha.o and ha.o == ha.l 112 | rising_momentum = rsi > prior_rsi 113 | rising_atr = tr > atr 114 | 115 | entry_condition = in_squeeze and up_trend and rising_ha and rising_momentum and rising_atr 116 | stop_condition = symbol in self.stops and l <= self.stops[symbol] 117 | move_stop_condition = h > prior_h or l < prior_l 118 | exit_condition = rsi < prior_rsi and in_squeeze and (ha_doji or prior_ha_doji) 119 | 120 | if dt == datetime.datetime(2014, 1, 17) and in_squeeze: 121 | connors_rsi = self.i('ConnorsRSI-'+symbol)[dt] 122 | if up_trend and rising_ha: 123 | print 'BUY', dt, symbol, connors_rsi 124 | #elif down_trend: 125 | # print 'SELL', dt, symbol, connors_rsi 126 | except: 127 | continue 128 | 129 | ''' 130 | if symbol in self.buys: 131 | buy_limit_px = self.buys[symbol] 132 | if self.cash > 0 and l <= buy_limit_px and ha.o > prior_ha.o: 133 | print '{} limit to buy {} in range ({}, {})'.format(dt, buy_limit_px, l, h) 134 | buy_px = min(buy_limit_px, h) 135 | qty = int(self.cash / buy_px) 136 | print 'buying {} at {}; adding stop at {}'.format(qty, buy_px, prior_ha.l) 137 | self.oms.add(Transaction(symbol, dt, buy_px, qty)) 138 | self.cash = 0 139 | self.stops[symbol] = prior_ha.l 140 | print 'removing limit to buy {}'.format(buy_limit_px) 141 | del self.buys[symbol] 142 | elif entry_condition: 143 | buy_limit_px = round((ha.h + ha.l) / 2.0, 2) 144 | self.buys[symbol] = buy_limit_px 145 | print '{} setting limit px at {}'.format(dt, buy_limit_px) 146 | elif stop_condition: 147 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].amount > 0: 148 | stop_px = self.stops[symbol] 149 | adj_stop_px = min(h, stop_px) 150 | print '{} stop px ({} -> {}) in range ({}, {})'.format(dt, stop_px, adj_stop_px, l, h) 151 | gains_cash = adj_stop_px * self.oms.portfolio.positions[symbol].amount 152 | print 'selling {} at {}'.format(-self.oms.portfolio.positions[symbol].amount, adj_stop_px) 153 | self.oms.add(Transaction(symbol, dt, adj_stop_px, -self.oms.portfolio.positions[symbol].amount)) 154 | self.cash += gains_cash 155 | print 'removing stop px {}'.format(stop_px) 156 | del self.stops[symbol] 157 | elif symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].amount > 0: 158 | if exit_condition: 159 | print 'exiting {} at {}'.format(self.oms.portfolio.positions[symbol].amount, px) 160 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 161 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 162 | self.cash += gains_cash 163 | del self.stops[symbol] 164 | elif symbol in self.stops and move_stop_condition and self.stops[symbol] != prior_px: 165 | print 'moving stop from {} to {}'.format(self.stops[symbol], prior_ha.l) 166 | self.stops[symbol] = prior_ha.l 167 | ''' 168 | 169 | test = SqueezeAlgo(stocks, '20120101', '20140117') 170 | test.run() 171 | test.results() 172 | 173 | stock = stocks[0] 174 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 175 | [[test.cube.get_values(stock, 'adjclose'), test.i('BBandLower-' + stock).as_series(), test.i('BBandUpper-' + stock).as_series(), test.i('KeltnerUpper-' + stock).as_series(), test.i('KeltnerLower-' + stock).as_series()], [test.i('Squeeze-' + stock).as_series()], [test.i('RSI-' + stock).as_series()]], 176 | 'Date', 177 | ['Price', 'Value', 'Value'], 178 | '-', 179 | [['Close', 'BBandLower', 'BBandUpper', 'KeltnerUpper', 'KeltnerLower'], ['Squeeze'], ['RSI']], 180 | stock) 181 | for t in test.oms.blotter.all(symbols=stock): 182 | dt = t.dt 183 | high = test.cube.data[(stock, 'high')][dt] 184 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.02), xytext=(dt, high*1.03), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 185 | plt.show() -------------------------------------------------------------------------------- /util.py: -------------------------------------------------------------------------------- 1 | try: import urllib.request as urllib2 2 | except ImportError: import urllib2 3 | import urllib 4 | import os 5 | import pickle 6 | import logging 7 | 8 | DATA_PATH = '.\\data\\' 9 | 10 | # http://stackoverflow.com/questions/36932/whats-the-best-way-to-implement-an-enum-in-python 11 | def enum(*sequential, **named): 12 | enums = dict(zip(sequential, range(len(sequential))), **named) 13 | reverse = dict((value, key) for key, value in enums.items()) 14 | enums['reverse_mapping'] = reverse 15 | return type('Enum', (), enums) 16 | 17 | def flexfilter(items, key, values): 18 | if values is None: 19 | return items 20 | if type(values) is not list: 21 | values = [values] 22 | # TODO: use zip to handle multiple k/v pairs 23 | return filter(lambda item: getattr(item, key, None) in values, items) 24 | 25 | def write_to_file(filename, content, path=DATA_PATH): 26 | location = path + filename 27 | logging.debug('Writing to file: {}'.format(location)) 28 | file = open(location, 'w') 29 | file.write(content) 30 | file.close() 31 | 32 | def read_from_file(filename, path=DATA_PATH): 33 | location = path + filename 34 | logging.debug('Reading from file: {}'.format(location)) 35 | file = open(location, 'r') 36 | contents = file.read() 37 | return contents 38 | 39 | def pickle_it(filename, content, path=DATA_PATH): 40 | location = path + filename 41 | logging.debug('Pickling to file: {}'.format(location)) 42 | file = open(location, 'wb') 43 | pickle.dump(content, file) 44 | file.close() 45 | 46 | def pickle_load(filename, path=DATA_PATH): 47 | location = path + filename 48 | logging.debug('Loading pickle from file: {}'.format(location)) 49 | file = open(location, 'rb') 50 | contents = pickle.load(file) 51 | file.close() 52 | return contents 53 | 54 | def file_exists(filename, path=DATA_PATH): 55 | location = path + filename 56 | logging.debug('Looking up file: {}'.format(location)) 57 | try: 58 | with open(location, 'r') as f: 59 | logging.debug('File {} exists.'.format(location)) 60 | return True 61 | except IOError as e: 62 | logging.error('File {} does not exist.'.format(location)) 63 | return False 64 | 65 | def get_page(url): 66 | logging.debug('Loading data from {}.'.format(url)) 67 | try: 68 | request = urllib2.urlopen(url) 69 | response = str(request.read()) 70 | return response 71 | except urllib2.URLError as e: 72 | logging.error('Error accessing web page {}.'.format(url)) 73 | raise e -------------------------------------------------------------------------------- /vwap.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | 8 | stocks = ["MMM","AA","MO","AXP","AIG","T","BA","CAT","C","KO","DD","XOM","GE","GM","HPQ","HD","HON","IBM","INTC","JNJ","JPM","MCD","MRK","MSFT","PFE","PG","UTX","VZ","WMT","DIS", "SPY"] 9 | results = {} 10 | for stock in stocks: 11 | for period in [2,3,5,10,15,20,30,50,100,200]: 12 | class SMATest(Algorithm): 13 | def __init__(self, symbols, start_date, end_date): 14 | super(SMATest, self).__init__(symbols, start_date, end_date) 15 | self.cash = 10000 16 | 17 | def pre_run(self): 18 | super(SMATest, self).pre_run() 19 | 20 | for symbol in self.symbols: 21 | close_series = self.cube.data[(symbol, 'adjclose')] 22 | self.add_indicator(SMA('SMA-' + symbol, close_series, period)) 23 | self.add_indicator(RSMA('RSMA-' + symbol, close_series, period)) 24 | self.add_indicator(SMA('SSS-' + symbol, self.i('RSMA-' + symbol), period)) 25 | self.add_indicator(BBandLower('BBandLower-' + symbol, close_series, period, 2)) 26 | self.add_indicator(BBandUpper('BBandUpper-' + symbol, close_series, period, 2)) 27 | self.add_indicator(ROC('ROC-' + symbol, self.i('SSS-' + symbol))) 28 | self.add_indicator(VWAP('VWAP-' + symbol, close_series, self.cube.data[(symbol, 'volume')], period)) 29 | 30 | def handle_data(self, dt, symbols, keys, data): 31 | yesterday = self.cube.go_back(dt, 1) 32 | for symbol in symbols: 33 | vwap = self.i('VWAP-' + symbol) 34 | px = data[(symbol, 'adjclose')] 35 | px_yesterday = self.cube.data[(symbol, 'adjclose')][yesterday] 36 | shortsma = self.i('SMA-' + symbol) 37 | shortsma_yesterday = shortsma[yesterday] 38 | shortsma_today = shortsma[dt] 39 | 40 | if shortsma_yesterday and px_yesterday: 41 | if shortsma_yesterday < px_yesterday and shortsma_today > px: 42 | if self.cash > 0: 43 | self.oms.add(Transaction(symbol, dt, px, self.cash / px)) 44 | self.cash = 0 45 | elif shortsma_yesterday > px_yesterday and shortsma_today < px: 46 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 47 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 48 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 49 | self.cash += gains_cash 50 | 51 | def post_run(self): 52 | pass 53 | #self.results() 54 | #for symbol in self.symbols: 55 | # self.plot(symbol=symbol, indicator_list=['VWAP-' + symbol, 'BBandLower-' + symbol, 'BBandUpper-' + symbol, 'SMA-' + symbol, 'LSMA-' + symbol, 'RSMA-'+ symbol, 'SSS-' + symbol, 'ROC-' + symbol]).show() 56 | 57 | test = SMATest([stock], '20050101', '20130131') 58 | test.run() 59 | results[(stock, period)] = test.results() 60 | ''' 61 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 62 | [[test.cube.get_values(stock, 'adjclose'), test.i('VWAP-' + stock).as_series(), test.i('SMA-' + stock).as_series(), test.i('LSMA-' + stock).as_series(), test.i('BBandLower-' + stock).as_series(), test.i('BBandUpper-' + stock).as_series()],[test.i('RSMA-' + stock).as_series(), test.i('SSS-' + stock).as_series()],[test.i('ROC-' + stock).as_series()]], 63 | 'Date', 64 | ['Price','Value', 'Value'], 65 | '-', 66 | [['Close', 'VWAP', 'SMA', 'LSMA', 'BBandLower', 'BBandUpper'],['RSMA', 'SSS'],['ROC']], 67 | stock) 68 | for t in test.oms.blotter.all(symbols=stock): 69 | dt = t.dt 70 | high = test.cube.data[(stock, 'high')][dt] 71 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.05), xytext=(dt, high*1.08), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 72 | #plt.show() 73 | ''' 74 | file = open('pxcross.out', 'w') 75 | pp = pprint.PrettyPrinter(indent=4, stream=file) 76 | pp.pprint(results) -------------------------------------------------------------------------------- /vwapcross.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from positions import * 3 | from algorithm import Algorithm 4 | from plot import * 5 | from indicators import * 6 | import pprint 7 | 8 | stocks = ["MMM","AA","MO","AXP","AIG","T","BA","CAT","C","KO","DD","XOM","GE","GM","HPQ","HD","HON","IBM","INTC","JNJ","JPM","MCD","MRK","MSFT","PFE","PG","UTX","VZ","WMT","DIS", "SPY"] 9 | results = {} 10 | for stock in stocks: 11 | for period in [2,3,5,10,15,20,30,50,100,200]: 12 | class SMATest(Algorithm): 13 | def __init__(self, symbols, start_date, end_date): 14 | super(SMATest, self).__init__(symbols, start_date, end_date) 15 | self.cash = 10000 16 | 17 | def pre_run(self): 18 | super(SMATest, self).pre_run() 19 | 20 | for symbol in self.symbols: 21 | close_series = self.cube.data[(symbol, 'close')] 22 | self.add_indicator(SMA('SMA-' + symbol, close_series, period)) 23 | self.add_indicator(RSMA('RSMA-' + symbol, close_series, period)) 24 | self.add_indicator(SMA('SSS-' + symbol, self.i('RSMA-' + symbol), period)) 25 | self.add_indicator(BBandLower('BBandLower-' + symbol, close_series, period, 2)) 26 | self.add_indicator(BBandUpper('BBandUpper-' + symbol, close_series, period, 2)) 27 | self.add_indicator(ROC('ROC-' + symbol, self.i('SSS-' + symbol))) 28 | self.add_indicator(VWAP('VWAP-' + symbol, close_series, self.cube.data[(symbol, 'volume')], period)) 29 | 30 | def handle_data(self, dt, symbols, keys, data): 31 | yesterday = self.cube.go_back(dt, 1) 32 | for symbol in symbols: 33 | vwap = self.i('VWAP-' + symbol) 34 | vwap_yesterday = vwap[yesterday] 35 | vwap_today = vwap[dt] 36 | px = data[(symbol, 'close')] 37 | px_yesterday = self.cube.data[(symbol, 'close')][yesterday] 38 | 39 | if vwap_yesterday and px_yesterday: 40 | if vwap_yesterday < px_yesterday and vwap_today > px: 41 | if self.cash > 0: 42 | self.oms.add(Transaction(symbol, dt, px, self.cash / px)) 43 | self.cash = 0 44 | elif vwap_yesterday > px_yesterday and vwap_today < px: 45 | if symbol in self.oms.portfolio.positions and self.oms.portfolio.positions[symbol].is_open(): 46 | gains_cash = px * self.oms.portfolio.positions[symbol].amount 47 | self.oms.add(Transaction(symbol, dt, px, -self.oms.portfolio.positions[symbol].amount)) 48 | self.cash += gains_cash 49 | 50 | def post_run(self): 51 | pass 52 | #self.results() 53 | #for symbol in self.symbols: 54 | # self.plot(symbol=symbol, indicator_list=['VWAP-' + symbol, 'BBandLower-' + symbol, 'BBandUpper-' + symbol, 'SMA-' + symbol, 'LSMA-' + symbol, 'RSMA-'+ symbol, 'SSS-' + symbol, 'ROC-' + symbol]).show() 55 | 56 | test = SMATest([stock], '20050101', '20130131') 57 | test.run() 58 | results[(stock, period)] = test.results() 59 | ''' 60 | plt, subplots = multi_plot_data_with_dates(test.cube.get_dates(), 61 | [[test.cube.get_values(stock, 'close'), test.i('VWAP-' + stock).as_series(), test.i('SMA-' + stock).as_series(), test.i('LSMA-' + stock).as_series(), test.i('BBandLower-' + stock).as_series(), test.i('BBandUpper-' + stock).as_series()],[test.i('RSMA-' + stock).as_series(), test.i('SSS-' + stock).as_series()],[test.i('ROC-' + stock).as_series()]], 62 | 'Date', 63 | ['Price','Value', 'Value'], 64 | '-', 65 | [['Close', 'VWAP', 'SMA', 'LSMA', 'BBandLower', 'BBandUpper'],['RSMA', 'SSS'],['ROC']], 66 | stock) 67 | for t in test.oms.blotter.all(symbols=stock): 68 | dt = t.dt 69 | high = test.cube.data[(stock, 'high')][dt] 70 | subplots[0].annotate('BUY' if t.qty > 0 else 'SELL', xy=(dt, high*1.05), xytext=(dt, high*1.08), arrowprops=dict(facecolor='green' if t.qty > 0 else 'red', shrink=0.05)) 71 | #plt.show() 72 | ''' 73 | file = open('pxcross.out', 'w') 74 | pp = pprint.PrettyPrinter(indent=4, stream=file) 75 | pp.pprint(results) -------------------------------------------------------------------------------- /yf.py: -------------------------------------------------------------------------------- 1 | import yfinance 2 | 3 | def get_historical_prices(symbol, start, end): 4 | ticker = yfinance.Ticker(symbol) 5 | return ticker.history(start=start, end=end) 6 | -------------------------------------------------------------------------------- /ystockquote.py: -------------------------------------------------------------------------------- 1 | import urllib 2 | import time 3 | 4 | 5 | """ 6 | This is the "ystockquote" module. 7 | 8 | This module provides a Python API for retrieving stock data from Yahoo Finance. 9 | 10 | sample usage: 11 | >>> import ystockquote 12 | >>> print ystockquote.get_price('GOOG') 13 | 529.46 14 | """ 15 | 16 | 17 | def __request(symbol, stat): 18 | url = 'http://finance.yahoo.com/d/quotes.csv?s=%s&f=%s' % (symbol, stat) 19 | return urllib.urlopen(url).read().strip().strip('"') 20 | 21 | 22 | def get_all(symbol): 23 | """ 24 | Get all available quote data for the given ticker symbol. 25 | 26 | Returns a dictionary. 27 | """ 28 | values = __request(symbol, 'l1c1va2xj1b4j4dyekjm3m4rr5p5p6s7').split(',') 29 | data = {} 30 | data['price'] = values[0] 31 | data['change'] = values[1] 32 | data['volume'] = values[2] 33 | data['avg_daily_volume'] = values[3] 34 | data['stock_exchange'] = values[4] 35 | data['market_cap'] = values[5] 36 | data['book_value'] = values[6] 37 | data['ebitda'] = values[7] 38 | data['dividend_per_share'] = values[8] 39 | data['dividend_yield'] = values[9] 40 | data['earnings_per_share'] = values[10] 41 | data['52_week_high'] = values[11] 42 | data['52_week_low'] = values[12] 43 | data['50day_moving_avg'] = values[13] 44 | data['200day_moving_avg'] = values[14] 45 | data['price_earnings_ratio'] = values[15] 46 | data['price_earnings_growth_ratio'] = values[16] 47 | data['price_sales_ratio'] = values[17] 48 | data['price_book_ratio'] = values[18] 49 | data['short_ratio'] = values[19] 50 | return data 51 | 52 | 53 | def get_price(symbol): 54 | return __request(symbol, 'l1') 55 | 56 | 57 | def get_change(symbol): 58 | return __request(symbol, 'c1') 59 | 60 | 61 | def get_volume(symbol): 62 | return __request(symbol, 'v') 63 | 64 | 65 | def get_avg_daily_volume(symbol): 66 | return __request(symbol, 'a2') 67 | 68 | 69 | def get_stock_exchange(symbol): 70 | return __request(symbol, 'x') 71 | 72 | 73 | def get_market_cap(symbol): 74 | return __request(symbol, 'j1') 75 | 76 | 77 | def get_book_value(symbol): 78 | return __request(symbol, 'b4') 79 | 80 | 81 | def get_ebitda(symbol): 82 | return __request(symbol, 'j4') 83 | 84 | 85 | def get_dividend_per_share(symbol): 86 | return __request(symbol, 'd') 87 | 88 | 89 | def get_dividend_yield(symbol): 90 | return __request(symbol, 'y') 91 | 92 | 93 | def get_earnings_per_share(symbol): 94 | return __request(symbol, 'e') 95 | 96 | 97 | def get_52_week_high(symbol): 98 | return __request(symbol, 'k') 99 | 100 | 101 | def get_52_week_low(symbol): 102 | return __request(symbol, 'j') 103 | 104 | 105 | def get_50day_moving_avg(symbol): 106 | return __request(symbol, 'm3') 107 | 108 | 109 | def get_200day_moving_avg(symbol): 110 | return __request(symbol, 'm4') 111 | 112 | 113 | def get_price_earnings_ratio(symbol): 114 | return __request(symbol, 'r') 115 | 116 | 117 | def get_price_earnings_growth_ratio(symbol): 118 | return __request(symbol, 'r5') 119 | 120 | 121 | def get_price_sales_ratio(symbol): 122 | return __request(symbol, 'p5') 123 | 124 | 125 | def get_price_book_ratio(symbol): 126 | return __request(symbol, 'p6') 127 | 128 | 129 | def get_short_ratio(symbol): 130 | return __request(symbol, 's7') 131 | 132 | 133 | def get_historical_prices(symbol, start_date, end_date): 134 | """ 135 | Get historical prices for the given ticker symbol. 136 | Date format is 'YYYYMMDD' 137 | 138 | Returns a nested list. 139 | """ 140 | url = 'http://ichart.finance.yahoo.com/table.csv?s=%s&' % symbol + \ 141 | 'd=%s&' % str(int(end_date[4:6]) - 1) + \ 142 | 'e=%s&' % str(int(end_date[6:8])) + \ 143 | 'f=%s&' % str(int(end_date[0:4])) + \ 144 | 'g=d&' + \ 145 | 'a=%s&' % str(int(start_date[4:6]) - 1) + \ 146 | 'b=%s&' % str(int(start_date[6:8])) + \ 147 | 'c=%s&' % str(int(start_date[0:4])) + \ 148 | 'ignore=.csv' 149 | retry=True 150 | sleep_for = 1 151 | while retry: 152 | try: 153 | print url 154 | days = urllib.urlopen(url).readlines() 155 | retry = False 156 | except Exception as e: 157 | print 'failed.. {}'.format(e) 158 | #time.sleep(sleep_for) 159 | #sleep_for *= 2 160 | 161 | data = [day[:-2].split(',') for day in days] 162 | return data --------------------------------------------------------------------------------