diff --git a/Examples/Basic/tutorial1.py b/Examples/Basic/tutorial1.py index 7ea254f96..8e183d0a7 100644 --- a/Examples/Basic/tutorial1.py +++ b/Examples/Basic/tutorial1.py @@ -51,6 +51,12 @@ def main(): ldf_data = c_dataobj.get_data(ldt_timestamps, ls_symbols, ls_keys) d_data = dict(zip(ls_keys, ldf_data)) + # Filling the data for NAN + for s_key in ls_keys: + d_data[s_key] = d_data[s_key].fillna(method='ffill') + d_data[s_key] = d_data[s_key].fillna(method='bfill') + d_data[s_key] = d_data[s_key].fillna(1.0) + # Getting the numpy ndarray of close prices. na_price = d_data['close'].values diff --git a/Examples/Basic/tutorial3.py b/Examples/Basic/tutorial3.py index 12d08f20f..422fce947 100644 --- a/Examples/Basic/tutorial3.py +++ b/Examples/Basic/tutorial3.py @@ -77,6 +77,7 @@ def main(): # Filling the data. df_rets = df_rets.fillna(method='ffill') df_rets = df_rets.fillna(method='bfill') + df_rets = df_rets.fillna(1.0) # Numpy matrix of filled data values na_rets = df_rets.values diff --git a/Examples/Basic/tutorial5.py b/Examples/Basic/tutorial5.py index 877ae20b2..50bec0827 100644 --- a/Examples/Basic/tutorial5.py +++ b/Examples/Basic/tutorial5.py @@ -46,6 +46,9 @@ def main(): # Reading just the close prices df_close = c_dataobj.get_data(ldt_timestamps, ls_symbols, "close") + df_close = df_close.fillna(method='ffill') + df_close = df_close.fillna(method='bfill') + df_close = df_close.fillna(1.0) # Creating the allocation dataframe # We offset the time for the simulator to have atleast one diff --git a/Examples/Basic/tutorial6.py b/Examples/Basic/tutorial6.py deleted file mode 100644 index e61bf72dc..000000000 --- a/Examples/Basic/tutorial6.py +++ /dev/null @@ -1,114 +0,0 @@ -''' -(c) 2011, 2012 Georgia Tech Research Corporation -This source code is released under the New BSD license. Please see -http://wiki.quantsoftware.org/index.php?title=QSTK_License -for license details. - -Created on June 1, 2011 - -@author: John Cornwell -@contact: JohnWCornwellV@gmail.com -@summary: Demonstrates the retrieval and use of Compustat data from the DataAccess object. -''' - -### You'll need compustat data license for this tutorial. - -import QSTK.qstkutil.qsdateutil as du -import QSTK.qstkutil.tsutil as tsu -import QSTK.qstkutil.DataAccess as da -import datetime as dt -import matplotlib.pyplot as plt -from pylab import * -from math import isnan -from copy import copy - - -symbols = ['GE','MSFT','XOM','PFE','C','WMT','INTC','AAPL','GOOG'] - -''' Create compustat object and query it for some information ''' - -compustatObj = da.DataAccess('Compustat') -compustatObj.get_info() - - -''' Get data items and create dictionary to translate between string and index ''' -lsItems = compustatObj.get_data_labels() -dLabel = dict( zip(lsItems,range(len(lsItems))) ) -print 'Valid data items (sorted):\n', sort(lsItems[:]) - - - -''' Create timestamps for 5 year period, must include all days, financial report may have been filed on non-NYSE day ''' -''' get todays date, time = 16:00:00 ''' -dtEnd = dt.datetime.combine( dt.datetime.now().date(), dt.time(16) ) -dtStart = dtEnd.replace( year=dtEnd.year-5 ) - -tsAll = [ dtStart ] -while( tsAll[-1] != dtEnd ): - tsAll.append( tsAll[-1] + dt.timedelta(days=1) ) - - -''' Query data object ''' -dmValues = compustatObj.get_data( tsAll, symbols, lsItems) - - -''' Keep track of non-nan data entries ''' -llTotal = [0] * len(lsItems) -llValid = [0] * len(lsItems) - -for lStock in range(len(symbols)): - - dmKeys = dmValues[ dLabel['gvkey'] ] - - ''' Loop through all time indexes ''' - for i, row in enumerate( dmKeys.values ): - - ''' Check nan gvkey value, indicating an invalid entry row skip ''' - if( isnan(row[lStock]) ): - continue - - ''' check for other valid entries in the other data types ''' - for lInd in range( len(lsItems) ): - llTotal[lInd] = llTotal[lInd] + 1 - if( not isnan(dmValues[lInd].values[i,lStock]) ): - llValid[lInd] = llValid[lInd] + 1 - -''' sort and print results by percentage valid data ''' - -ltBoth = [] -lNonZero = 0 -lHundred = 0 -for i, sLabel in enumerate( lsItems ): - ltBoth.append( ( (llValid[i] * 100.0 / llTotal[i]), sLabel ) ) - if not llValid[i] == 0: - lNonZero = lNonZero + 1 - if llValid[i] == llTotal[i]: - lHundred = lHundred + 1 - -ltBoth.sort() -ltBoth.reverse() - -for tRes in ltBoth: - print '%10s: %.02lf%%'%( tRes[1], tRes[0] ) - -print '\n%i out of %i elemenets non-zero.'%(lNonZero, len(lsItems)) -print '%i out of %i elemenets have 100%% participation.'%(lHundred, len(lsItems)) - - -''' Retrieve and plot quarterly earnings per share ''' - -dmEps = dmKeys = dmValues[ dLabel['EPSPIQ'] ] -naEps = dmEps.values -tsu.fillforward( naEps ) - -plt.clf() - -for i, sStock in enumerate( symbols ): - plt.plot( tsAll, naEps[:,i] ) - -plt.gcf().autofmt_xdate(rotation=45) -plt.legend( symbols, loc='upper left' ) -plt.title('EPS of various stocks') - -savefig('tutorial6.pdf',format='pdf') - diff --git a/Examples/Basic/tutorial7.py b/Examples/Basic/tutorial7.py deleted file mode 100644 index cef95bb32..000000000 --- a/Examples/Basic/tutorial7.py +++ /dev/null @@ -1,135 +0,0 @@ -''' -(c) 2011, 2012 Georgia Tech Research Corporation -This source code is released under the New BSD license. Please see -http://wiki.quantsoftware.org/index.php?title=QSTK_License -for license details. - -Created on August 29, 2011 - -@author: John Cornwell -@contact: JohnWCornwellV@gmail.com -@summary: Demonstrates the use of the NAG portfolio optimization call. -''' - -# You'll need NAG license for this tutorial - Please use tutorial8 instead. - -import QSTK.qstkutil.qsdateutil as du -import QSTK.qstkutil.tsutil as tsu -import QSTK.qstkutil.DataAccess as da -import datetime as dt - -import matplotlib.pyplot as plt -from pylab import * -from math import isnan -from copy import copy - -''' Function gets a 100 sample point frontier for given returns ''' -def getFrontier(naData, lPeriod): - ''' Special case for fTarget = None, just get average returns ''' - (naAvgRets, naStd) = tsu.getOptPort( naData, None, lPeriod ) - fMin = np.min(naAvgRets) - fMax = np.max(naAvgRets) - - fStep = (fMax - fMin) / 100.0 - - lfReturn = [fMin + x * fStep for x in range(101)] - lfStd = [] - lnaPortfolios = [] - - ''' Call the function 100 times for the given range ''' - for fTarget in lfReturn: - (naWeights, fStd) = tsu.getOptPort( naData, fTarget, lPeriod ) - lfStd.append(fStd) - lnaPortfolios.append( naWeights ) - - return (lfReturn, lfStd, lnaPortfolios, naAvgRets, naStd) - - - -''' ******************************************************* ''' -''' ******************** MAIN SCRIPT ********************** ''' -''' ******************************************************* ''' - -''' S&P100 ''' -lsSymbols = [ 'AA', 'AAPL', 'ABT', 'AEP', 'ALL', 'AMGN', 'AMZN', 'AVP', 'AXP', 'BA', 'BAC', 'BAX', 'BHI', 'BK', 'BMY', 'BNI', 'C', 'CAT', 'CL', 'CMCSA', 'COF', 'COP', 'COST', 'COV', 'CPB', 'CSCO', 'CVS', 'CVX', 'DD', 'DELL', 'DIS', 'DOW', 'DVN', 'EMC', 'ETR', 'EXC', 'F', 'FDX', 'GD', 'GE', 'GILD', 'GOOG', 'GS', 'HAL', 'HD', 'HNZ', 'HON', 'HPQ', 'IBM', 'INTC', 'JNJ', 'JPM', 'KFT', 'KO', 'LMT', 'LOW', 'MA', 'MCD', 'MDT', 'MMM', 'MO', 'MRK', 'MS', 'MSFT', 'NKE', 'NOV', 'NSC', 'NYX', 'ORCL', 'OXY', 'PEP', 'PFE', 'PG', 'PM', 'QCOM', 'RF', 'RTN', 'S', 'SGP', 'SLB', 'SLE', 'SO', 'T', 'TGT', 'TWX', 'TXN', 'TYC', 'UNH', 'UPS', 'USB', 'UTX', 'VZ', 'WAG', 'WFC', 'WMB', 'WMT', 'WY', 'WYE', 'XOM', 'XRX'] - -''' Create norgate object and query it for stock data ''' -norgateObj = da.DataAccess('Yahoo') - -lsAll = norgateObj.get_all_symbols() -intersect = set(lsAll) & set(lsSymbols) - -if len(intersect) < len(lsSymbols): - print "Warning: S&P100 contains symbols that do not exist: ", - print set(lsSymbols) - intersect - - lsSymbols = sort(list( intersect )) - -''''Read in historical data''' -lYear = 2009 -dtEnd = dt.datetime(lYear+1,1,1) -dtStart = dtEnd - dt.timedelta(days=365) -dtTest = dtEnd + dt.timedelta(days=365) -timeofday=dt.timedelta(hours=16) - -ldtTimestamps = du.getNYSEdays( dtStart, dtEnd, timeofday ) -ldtTimestampTest = du.getNYSEdays( dtEnd, dtTest, timeofday ) - -dmClose = norgateObj.get_data(ldtTimestamps, lsSymbols, "close") -dmTest = norgateObj.get_data(ldtTimestampTest, lsSymbols, "close") - -naData = dmClose.values.copy() -naDataTest = dmTest.values.copy() - -tsu.fillforward(naData) -tsu.fillbackward(naData) -tsu.returnize1(naData) - -tsu.fillforward(naDataTest) -tsu.fillbackward(naDataTest) -tsu.returnize1(naDataTest) - -lPeriod = 21 - -''' Get efficient frontiers ''' -(lfReturn, lfStd, lnaPortfolios, naAvgRets, naStd) = getFrontier( naData, lPeriod ) -(lfReturnTest, lfStdTest, unused, unused, unused) = getFrontier( naDataTest, lPeriod ) - -plt.clf() -fig = plt.figure() - -''' Plot efficient frontiers ''' -plt.plot(lfStd,lfReturn, 'b') -plt.plot(lfStdTest,lfReturnTest, 'r') - -''' Plot where efficient frontier WOULD be the following year ''' -lfRetTest = [] -lfStdTest = [] -naRetsTest = tsu.getReindexedRets( naDataTest, lPeriod) -for naPortWeights in lnaPortfolios: - naPortRets = np.dot( naRetsTest, naPortWeights) - lfStdTest.append( np.std(naPortRets) ) - lfRetTest.append( np.average(naPortRets) ) - -plt.plot(lfStdTest,lfRetTest,'k') - -''' plot some arrows showing transition of efficient frontier ''' -for i in range(0,101,10): - arrow( lfStd[i],lfReturn[i], lfStdTest[i]-lfStd[i], lfRetTest[i]-lfReturn[i], color='k' ) - -''' Plot indifidual stock risk/return as green + ''' -for i, fReturn in enumerate(naAvgRets): - plt.plot( naStd[i], fReturn, 'g+' ) - -plt.legend( ['2009 Frontier', '2010 Frontier', 'Performance of \'09 Frontier in 2010'], loc='lower right' ) - -plt.title('Efficient Frontier For S&P 100 ' + str(lYear)) -plt.ylabel('Expected Return') -plt.xlabel('StDev') - -savefig('tutorial7.pdf',format='pdf') - - - - - diff --git a/Examples/Validation.py b/Examples/Validation.py index d342015da..7e5986eb1 100644 --- a/Examples/Validation.py +++ b/Examples/Validation.py @@ -151,7 +151,7 @@ ls_symbols = ['MSFT', 'GOOG'] # Creating an object of the dataaccess class with Yahoo as the source. -c_dataobj = da.DataAccess('Yahoo') +c_dataobj = da.DataAccess('Yahoo', verbose=True) # Reading adjusted_close prices df_close = c_dataobj.get_data(ldt_timestamps, ls_symbols, "close") print df_close diff --git a/MANIFEST.in b/MANIFEST.in index 6dbc68350..adc0082aa 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -14,4 +14,5 @@ include QSTK/QSData/Yahoo/*.csv' include QSTK/QSData/Yahoo/Lists/*.txt include QSTK/qstkutil/NYSE_dates.txt include QSTK/qstktest/*.csv -include QSTK/qstkstudy/sp500.txt \ No newline at end of file +include QSTK/qstkstudy/sp500.txt +include QSTK/__init__.py diff --git a/QSTK/QSData/Yahoo/Lists/sp5002008.txt b/QSTK/QSData/Yahoo/Lists/sp5002008.txt index ca4c0e138..dffdac55e 100644 --- a/QSTK/QSData/Yahoo/Lists/sp5002008.txt +++ b/QSTK/QSData/Yahoo/Lists/sp5002008.txt @@ -91,7 +91,6 @@ CBS CCE CCL CCMO -CCTYQ CEG CELG CFC+A @@ -218,7 +217,6 @@ HNZ HOG HON HOT -HPC HPQ HRB HSP diff --git a/QSTK/qstkfeat/features.py b/QSTK/qstkfeat/features.py index 7fd405139..f589caf16 100644 --- a/QSTK/qstkfeat/features.py +++ b/QSTK/qstkfeat/features.py @@ -341,7 +341,8 @@ def featVolumeDelta( dData, lLookback=30, b_human=False ): def featAroon( dData, bDown=False, lLookback=25, b_human=False ): ''' - @summary: Calculate Aroon - indicator indicating days since a 25-day high/low, weighted between 0 and 100 + @summary: Calculate Aroon - indicator indicating days since a 25-day + high/low, weighted between 0 and 100 @param dData: Dictionary of data to use @param bDown: If false, calculates aroonUp (high), else aroonDown (lows) @param lLookback: Days to lookback to calculate high/low from @@ -351,19 +352,21 @@ def featAroon( dData, bDown=False, lLookback=25, b_human=False ): dfPrice = dData['close'] - #''' Feature DataFrame will be 1:1, we can use the price as a template ''' - dfRet = pand.DataFrame( index=dfPrice.index, columns=dfPrice.columns, + #Feature DataFrame will be 1:1, we can use the price as a template + dfRet = pd.DataFrame( index=dfPrice.index, columns=dfPrice.columns, data=np.zeros(dfPrice.shape) ) - #''' Loop through time ''' + #Loop through time for i in range(dfPrice.shape[0]): - if( (i-lLookback)+1 < 0 ): + if( (i-lLookback) < 0 ): dfRet.ix[i,:] = np.NAN else: if bDown: - dfRet.ix[i,:] = dfPrice.values[i+1:(i-lLookback)+1:-1,:].argmin(axis=0) + dfRet.ix[i,:] = dfPrice.values[i:(i-lLookback):-1,:].argmin( + axis=0) else: - dfRet.ix[i,:] = dfPrice.values[i+1:(i-lLookback)+1:-1,:].argmax(axis=0) + dfRet.ix[i,:] = dfPrice.values[i:(i-lLookback):-1,:].argmax( + axis=0) dfRet = ((lLookback - 1.) - dfRet) / (lLookback - 1.) * 100. diff --git a/QSTK/qstkstudy/EventProfiler.py b/QSTK/qstkstudy/EventProfiler.py index 0308c227a..d1aa00979 100644 --- a/QSTK/qstkstudy/EventProfiler.py +++ b/QSTK/qstkstudy/EventProfiler.py @@ -20,12 +20,15 @@ import QSTK.qstkutil.qsdateutil as du -def eventprofiler(df_events, d_data, i_lookback=20, i_lookforward=20, +def eventprofiler(df_events_arg, d_data, i_lookback=20, i_lookforward=20, s_filename='study', b_market_neutral=True, b_errorbars=True, s_market_sym='SPY'): ''' Event Profiler for an event matix''' df_close = d_data['close'].copy() df_rets = df_close.copy() + + # Do not modify the original event dataframe. + df_events = df_events_arg.copy() tsu.returnize0(df_rets.values) if b_market_neutral == True: @@ -40,7 +43,8 @@ def eventprofiler(df_events, d_data, i_lookback=20, i_lookforward=20, df_events.values[-i_lookforward:, :] = np.NaN # Number of events - i_no_events = int(np.nansum(df_events.values)) + i_no_events = int(np.logical_not(np.isnan(df_events.values)).sum()) + assert i_no_events > 0, "Zero events in the event matrix" na_event_rets = "False" # Looking for the events and pushing them to a matrix @@ -53,6 +57,9 @@ def eventprofiler(df_events, d_data, i_lookback=20, i_lookforward=20, else: na_event_rets = np.vstack((na_event_rets, na_ret)) + if len(na_event_rets.shape) == 1: + na_event_rets = np.expand_dims(na_event_rets, axis=0) + # Computing daily rets and retuns na_event_rets = np.cumprod(na_event_rets + 1, axis=1) na_event_rets = (na_event_rets.T / na_event_rets[:, i_lookback]).T diff --git a/QSTK/qstkstudy/stockListGen.py b/QSTK/qstkstudy/stockListGen.py deleted file mode 100644 index d1cffb48e..000000000 --- a/QSTK/qstkstudy/stockListGen.py +++ /dev/null @@ -1,44 +0,0 @@ -# (c) 2011, 2012 Georgia Tech Research Corporation -# This source code is released under the New BSD license. Please see -# http://wiki.quantsoftware.org/index.php?title=QSTK_License -# for license details. -# -# Created on October , 2011 -# -# @author: Vishal Shekhar -# @contact: mailvishalshekhar@gmail.com -# @summary: Utiltiy script to create list of symbols for study. - -import QSTK.qstkutil.DataAccess as da -import QSTK.qstkutil.qsdateutil as du -import datetime as dt - -if __name__ == '__main__': - dataobj = da.DataAccess('Norgate') - delistSymbols = set(dataobj.get_symbols_in_sublist('/US/Delisted Securities')) - allSymbols = set(dataobj.get_all_symbols()) #by default Alive symbols only - aliveSymbols = list(allSymbols - delistSymbols) # set difference is smart - - startday = dt.datetime(2008,1,1) - endday = dt.datetime(2009,12,31) - timeofday=dt.timedelta(hours=16) - timestamps = du.getNYSEdays(startday,endday,timeofday) - - #Actual Close Prices of aliveSymbols and allSymbols - aliveSymbsclose = dataobj.get_data(timestamps, aliveSymbols, 'actual_close') - allSymbsclose = dataobj.get_data(timestamps, allSymbols, 'actual_close') - - file = open('aliveSymbols2','w') - for symbol in aliveSymbols: - belowdollar = len(aliveSymbsclose[symbol][aliveSymbsclose[symbol]<1.0]) - if belowdollar and (len(aliveSymbsclose[symbol]) > belowdollar): - file.write(str(symbol)+'\n') - file.close() - - file = open('allSymbols2','w') - for symbol in allSymbols: - belowdollar = len(allSymbsclose[symbol][allSymbsclose[symbol]<1.0]) - if belowdollar and (len(allSymbsclose[symbol]) > belowdollar): - file.write(str(symbol)+'\n') - file.close() - diff --git a/QSTK/qstktools/YahooDataPull.py b/QSTK/qstktools/YahooDataPull.py index 8b1b063a2..ee0bbf072 100644 --- a/QSTK/qstktools/YahooDataPull.py +++ b/QSTK/qstktools/YahooDataPull.py @@ -8,8 +8,11 @@ import os -def get_data(data_path, ls_symbols): - +def get_yahoo_data(data_path, ls_symbols): + '''Read data from Yahoo + @data_path : string for where to place the output files + @ls_symbols: list of symbols to read from yahoo + ''' # Create path if it doesn't exist if not (os.access(data_path, os.F_OK)): os.makedirs(data_path) @@ -60,7 +63,7 @@ def get_data(data_path, ls_symbols): print "All done. Got {0} stocks. Could not get {1}".format(len(ls_symbols) - miss_ctr, miss_ctr) def read_symbols(s_symbols_file): - + '''Read a list of symbols''' ls_symbols=[] file = open(s_symbols_file, 'r') for line in file.readlines(): @@ -72,9 +75,10 @@ def read_symbols(s_symbols_file): return ls_symbols def main(): + '''Main Function''' path = './' ls_symbols = read_symbols('symbols.txt') - get_data(path, ls_symbols) + get_yahoo_data(path, ls_symbols) if __name__ == '__main__': main() diff --git a/QSTK/qstkutil/DataAccess.py b/QSTK/qstkutil/DataAccess.py index 536f57d84..9e466767a 100644 --- a/QSTK/qstkutil/DataAccess.py +++ b/QSTK/qstkutil/DataAccess.py @@ -22,7 +22,7 @@ import datetime as dt import dircache import tempfile - +import copy class Exchange (object): AMEX = 1 @@ -63,7 +63,7 @@ class DataAccess(object): @note: The earliest time for which this works is platform dependent because the python date functionality is platform dependent. ''' def __init__(self, sourcein=DataSource.YAHOO, s_datapath=None, - s_scratchpath=None, cachestalltime=12): + s_scratchpath=None, cachestalltime=12, verbose=False): ''' @param sourcestr: Specifies the source of the data. Initializes paths based on source. @note: No data is actually read in the constructor. Only paths for the source are initialized @@ -92,8 +92,9 @@ def __init__(self, sourcein=DataSource.YAHOO, s_datapath=None, self.rootdir = os.path.join(os.path.dirname(__file__), '..', 'QSData') self.scratchdir = os.path.join(tempfile.gettempdir(), 'QSScratch') - print "Scratch Directory: ", self.scratchdir - print "Data Directory: ", self.rootdir + if verbose: + print "Scratch Directory: ", self.scratchdir + print "Data Directory: ", self.rootdir if not os.path.isdir(self.rootdir): print "Data path provided is invalid" @@ -432,6 +433,8 @@ def get_data (self, ts_list, symbol_list, data_item, verbose=False, bIncDelist=F # We then check to see if the filename exists already, meaning that # the data has already been created and we can just read that file. + ls_syms_copy = copy.deepcopy(symbol_list) + # Create the hash for the symbols hashsyms = 0 for i in symbol_list: @@ -513,6 +516,12 @@ def get_data (self, ts_list, symbol_list, data_item, verbose=False, bIncDelist=F print "end saving to cache" if verbose: print "reading took " + str(elapsed) + " seconds" + + if type(retval) == type([]): + for i, df_single in enumerate(retval): + retval[i] = df_single.reindex(columns=ls_syms_copy) + else: + retval = retval.reindex(columns=ls_syms_copy) return retval def getPathOfFile(self, symbol_name, bDelisted=False): diff --git a/QSTK/qstkutil/bollinger.py b/QSTK/qstkutil/bollinger.py deleted file mode 100644 index d6e78b9a5..000000000 --- a/QSTK/qstkutil/bollinger.py +++ /dev/null @@ -1,57 +0,0 @@ -''' -(c) 2011, 2012 Georgia Tech Research Corporation -This source code is released under the New BSD license. Please see -http://wiki.quantsoftware.org/index.php?title=QSTK_License -for license details. - -Created on Jan 1, 2011 - -@author:Drew Bratcher -@contact: dbratcher@gatech.edu -@summary: Contains tutorial for backtester and report. - -''' - -# python imports -import cPickle -from pylab import * -from pandas import * -import datetime as dt - -#qstk imports -import qstk.qstkutil.DataAccess as da -import qstk.qstkutil.qsdateutil as du - -def calcavg(period): - sum = zeros(len(period.columns)) - count=0 - for day in period.index: - sum+=period.xs(day) - count+=1 - return(sum/count) - -def calcdev(period): - avg=calcavg(period) - devs=zeros(len(period.columns)) - count=0 - for day in period.index: - devs+=(period.xs(day)-avg*ones(len(period.columns)))*(period.xs(day)-avg*ones(len(period.columns))) - count+=1 - return(sqrt(devs/count)) - -def calcbvals(adjclose, timestamps, stocks, lookback): - for i in adjclose.values: - if i == 'NaN': - adjclose.values[adjclose.values.index(i)]=1; - bvals=DataMatrix(index=[timestamps[0]],columns=stocks,data=[zeros(len(stocks))]) - for i in range(1,len(timestamps)): - s=i-lookback - if s<0: - s=0 - lookbackperiod=adjclose[s:i] - avg = calcavg(lookbackperiod) - stddevs = calcdev(lookbackperiod) - if not(0 in stddevs): - b=(adjclose[i:i+1]-avg*ones(len(lookbackperiod.columns)))/stddevs - bvals=bvals.append(DataMatrix(index=[timestamps[i]],columns=stocks,data=b)) - return(bvals) diff --git a/README.md b/README.md index ed352bca4..0c9ae82a9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ QSTK ==== -QuantSoftware Toolkit 0.2.5 +QuantSoftware Toolkit 0.2.6 Website