def __init__(self, sym='SPY', sd=dt.datetime(2008,1, 1), \ ed=dt.datetime(2009,12,31),sv=100000,verbose=False): self.sym = sym self.verbose = verbose self.shares = 0 self.position = 0 self.sv = sv self.cash = sv self.pp = 0 #period n = 28 chart = False #take in, normalize data df = ut.get_data([sym], pd.date_range(sd - dt.timedelta(100), ed))[sym] normed = df / df.ix[0] #get features sma = ind.SMA(normed, n) smap = ind.standardize(normed / sma) bbp = ind.standardize(ind.bband(normed, n, chart)[0]) stdev = ind.standardize(normed.rolling(window=n, min_periods=n).std()) mom = ind.standardize(ind.momentum(normed, n, chart)) momvol = ind.standardize(mom / stdev) #daily returns & combined features rets = pd.DataFrame(df) daily_rets = rets[sym].copy() daily_rets[1:] = (rets[sym].ix[1:] / rets[sym].ix[:-1].values) - 1 daily_rets.ix[0] = 0 #print df #df = pd.DataFrame(df).assign(normed = normed).assign(smap=smap).\ # assign(stdev=stdev).assign(bbp=bbp).assign(mom=mom)[sd:] df = pd.DataFrame(df).assign(normed = normed).assign(smap=smap).\ assign(bbp=bbp).assign(mom=mom)[sd:] #print df daily_rets.ix[0] = 0 df = df.assign(dr=daily_rets) #print df self.df = df self.market = df.iterrows() self.curr = self.market.next() self.action = self.Action() #self.features = ['smap', 'stdev', 'bbp', 'mom'] self.features = ['smap', 'bbp', 'mom']
def testPolicy(symbol = "AAPL", sd=dt.datetime(2010,1,1), \ ed = dt.datetime(2011,12,31), sv=100000): chart = False n = 14 #symbol = [symbol] prices = get_data(symbol, pd.date_range(sd, ed)) #print prices #ffill and drop SPY prices.fillna(method='ffill', inplace=True) prices.fillna(method='bfill', inplace=True) prices = prices[symbol] #Generate indicators sma = ind.SMA(prices, n) smap = ind.standardize(prices / sma) bbp = ind.standardize(ind.bband(prices, n, chart)[0]) stdev = ind.standardize(prices.rolling(window=n, min_periods=n).std()) mom = ind.standardize(ind.momentum(prices, n, chart)) momvol = ind.standardize(mom / stdev) orders = prices.copy() orders.ix[:, :] = np.nan smap_cross = pd.DataFrame(0, index=smap.index, columns=smap.columns) smap_cross[smap >= 1] = 1 smap_cross[1:] = smap_cross.diff() smap_cross.ix[0] = 0 orders[(smap < 0.95) & (bbp < 0) & (stdev < 0.1) & (mom < 0)] = 1000 orders[(smap > 1.05) & (bbp > 1) & (stdev > 0.3) & (mom > 0)] = -1000 orders[(smap_cross != 0)] = 0 orders.ffill(inplace=True) orders.fillna(0, inplace=True) orders[1:] = orders.diff() #orders.ix[0] = 1000 #orders.ix[-1] = -1000 #orders = orders.loc[(orders!=0).any(axis=1)] #orders.ix[0] = 0 #orders.ix[-1] = orders.ix[-2]*-1 #print orders return orders
def __init__(self, sym='SPY', sd=dt.datetime(2008,1, 1), \ ed=dt.datetime(2009,12,31),sv=100000,verbose=False, experiment=False, impact=0.0): self.sym = sym self.verbose = verbose self.shares = 0 self.position = 2 self.sv = sv self.cash = sv self.pp = 0 self.impact = impact self.experiment = experiment #n = 3 #period chart = False #take in, normalize data df = ut.get_data([sym], pd.date_range(sd - dt.timedelta(100), ed))[sym] #print df #print sd, ed normed = df / df.ix[0] #print normed #daily returns & combined features rets = pd.DataFrame(df) daily_rets = rets[sym].copy() daily_rets[1:] = (rets[sym].ix[1:] / rets[sym].ix[:-1].values) - 1 daily_rets.ix[0] = 0 #Simple moving average sma5 = normed.rolling(5).mean() sma15 = normed.rolling(15).mean() sma20 = normed.rolling(20).mean() sma25 = normed.rolling(25).mean() sma30 = normed.rolling(30).mean() sma40 = normed.rolling(40).mean() #print sma5 # Volatility vol5 = normed.rolling(5).std() vol10 = normed.rolling(10).std() vol20 = normed.rolling(20).std() vol30 = normed.rolling(30).std() # Bollinger bands sma_bb = normed.rolling(5).mean() sma_bb_std = normed.rolling(5).std() bb = (normed - (sma_bb - 2 * sma_bb_std)) / ((sma_bb + 2 * sma_bb_std) - (sma_bb - 2 * sma_bb_std)) # Moving average convergence/divergence #ema12 = pd.ewma(np.asarray(normed), span=12) #ema26 = pd.ewma(np.asarray(normed), span=26) #macd = ema12 - ema26 # Momentum momentum2 = normed / normed.shift(2) - 1 momentum5 = normed / normed.shift(5) - 1 momentum10 = normed / normed.shift(10) - 1 # Combine into new dataframe df = pd.DataFrame(df).assign(sma5=normed / sma5 - 1).assign(\ bb=bb).assign(momentum2=momentum2).assign(normed=normed).\ assign(vol10=vol10).assign(vol20=vol20).assign(vol30=vol30).assign(vol10=vol10)\ .assign(vol5=vol5).assign(\ momentum5=momentum5).assign(momentum10=momentum10)[sd:] df = df.assign(dr=daily_rets) #print df # Determine optimal features for states corr_df = df.corr().abs() corr = corr_df['dr'][:] corr.ix[0] = 0 corr['normed'] = 0 icorr = np.asarray(corr) scorr = icorr.argsort( )[-4:][::-1] # select top 3 features and daily returns scorr = scorr[1:] # remove daily returns from possible features optimal_ftrs = [] for i in scorr: optimal_ftrs.append(corr_df.columns[i]) if experiment: #print "Experiment 1 ACTIVATED" n = 14 sma = ind.SMA(normed, n) smap = ind.standardize(normed / sma) bbp = ind.standardize(ind.bband(normed, n, chart)[0]) stdev = ind.standardize( normed.rolling(window=n, min_periods=n).std()) mom = ind.standardize(ind.momentum(normed, n, chart)) momvol = ind.standardize(mom / stdev) df = pd.DataFrame(df).assign(normed=normed).assign( smap=smap).assign(stdev=stdev).assign(bbp=bbp).assign( mom=mom)[sd:] optimal_ftrs = ['smap', 'stdev', 'bbp', 'mom'] #df = pd.DataFrame(df).assign(normed = normed).assign(smap=smap).assign(bbp=bbp).assign(mom=mom)[sd:] #df = pd.DataFrame(df).assign(normed = normed)[sd:] self.df = df self.market = df.iterrows() self.curr = self.market.next() self.action = self.Action() self.features = optimal_ftrs
# generate a buy signal (1) if price falls significantly below sma # generate a sell signal (-1) if prices rises significantly above sma smaSignal = 1 * (smaIndicator < -smaThreshold) + -1 * (smaIndicator > smaThreshold) momIndicator, momWindow = getMomIndicator(data) momThreshold = 0.06 # 0.055 optimized value on manual trading strategy 1 # generate a buy/sell signal if momentum is greatly positive/negative momSignal = -1 * (momIndicator < -momThreshold) + 1 * (momIndicator > momThreshold) bbWindow = 10 # 48 NOT OPTIMIZED bbIndicator = getBb(data, bbWindow) bbThreshold = 0 # 0.2 NOT OPTIMIZED # generate a buy/sell signal if indicator is below/above the BB and the indicator is rising/falling significantly bbSignal = -1 * ((bbIndicator > 1) & (standardize(data).diff(1) < -bbThreshold)) + \ 1 * ((bbIndicator < -1) & (standardize(data).diff(1) > bbThreshold)) crossIndicator, crossWindow = getCrossIndicator(data) crossThreshold = 0.08 # 0.08 optimized value on manual trading strategy 1 # generate a buy/sell signal if indicator is close to 0.5/-0.5 crossSignal = 1 * ((crossIndicator - 0.5).abs() < crossThreshold) + \ -1 * ((crossIndicator + 0.5).abs() < crossThreshold) # Combine individual signals. bbSignal is neglected here since including it # with the other signals did not result in label-free trading using strategy 1 signal = 1 * ((smaSignal == 1) & (momSignal ==1) & (crossSignal == 1)) \ + -1 * ((smaSignal == -1) & (momSignal == -1) & (crossSignal == -1)) order = tradingStrategy(signal, holdTime) createOrder(order, 'rule_based')
def testcode(): data = defineData() # get AAPL between the in-sample dates set as default holdTime = 21 # in days smaIndicator, smaWindow = getSmaIndicator(data) smaThreshold = 0.012 #0.012 # optimized value on manual trading strategy 1 # generate a buy signal (1) if price falls significantly below sma # generate a sell signal (-1) if prices rises significantly above sma smaSignal = 1 * (smaIndicator < -smaThreshold) + \ -1 * (smaIndicator > smaThreshold) momIndicator, momWindow = getMomIndicator(data) momThreshold = 0.06 #0.055 # optimized value on manual trading strategy 1 # generate a buy/sell signal if momentum is greatly positive/negative momSignal = -1 * (momIndicator < -momThreshold) + \ 1 * (momIndicator > momThreshold) bbWindow = 10 #48 NOT OPTIMIZED bbIndicator = getBb(data, bbWindow) bbThreshold = 0 #0.2 NOT OPTIMIZED # generate a buy/sell signal if indicator is below/above the lower/upper BB # and the indicator is rising/falling significantly bbSignal = -1 * ((bbIndicator > 1) & \ (standardize(data).diff(1) < -bbThreshold)) + \ 1 * ((bbIndicator < -1) & \ (standardize(data).diff(1) > bbThreshold)) crossIndicator, crossWindow = getCrossIndicator(data) crossThreshold = 0.08 #0.08 # optimized value on manual trading strategy 1 # generate a buy/sell signal if indicator is close to 0.5/-0.5 crossSignal = 1 * ( (crossIndicator - 0.5).abs() < crossThreshold) + \ -1 * ( (crossIndicator + 0.5).abs() < crossThreshold ) # Combine individual signals. bbSignal is neglected here since including it # with the other signals did not result in label-free trading using strategy 1 signal = 1 * ( (smaSignal == 1) & (momSignal ==1 ) & (crossSignal == 1) ) \ + -1 * ( (smaSignal == -1) & (momSignal == -1) & (crossSignal == -1) ) order = tradingStrategy(signal, holdTime) createOrder(order, 'rule_based') cumReturn, portVals = testcode_marketsim('rule_based', verbose=False) print('Cumulative return [%]: ', round(cumReturn * 100, 4)) plt.figure(figsize=(10, 10)) plt.subplot(311) plt.plot(data / data[0], label='benchmark', color='k') plt.plot(portVals / portVals[0], label='rule-based') plt.xticks(rotation=30) plotVline(order) plt.title('rule-based with sma + mom + crossover indicators') lg = plt.legend(loc='best') lg.draw_frame(False) plt.ylabel('normalized') plt.subplot(312) plt.plot(smaSignal / 2, label='sma') plt.plot(momSignal / 1.3, '.', label='mom') plt.plot(crossSignal / 1.1, '.', label='crossover') plt.plot(signal, label='overall signal') plt.xticks(rotation=30) plt.ylabel('indicator signals [a.u.]') lg = plt.legend(loc='center right') lg.draw_frame(False) plt.subplot(313) plt.scatter(momIndicator[signal==0], crossIndicator[signal==0], \ color = 'k', label = 'hold') plt.scatter(momIndicator[signal==1], crossIndicator[signal==1], \ color = 'g', label = 'buy') plt.scatter(momIndicator[signal==-1], crossIndicator[signal==-1], \ color = 'r', label = 'sell') lg = plt.legend(loc='best') lg.draw_frame(True) plt.xlabel('Momentum Indicator') plt.ylabel('Crossover Indicator')