def process_data(self, df): if self.freq == 1: xdf = df else: freq_str = str(self.freq) + "min" xdf = dh.conv_ohlc_freq(df, freq_str, extra_cols=['contract']) xdf['band_wth'] = self.band_func( xdf, n=self.boll_len).fillna(method='bfill') xdf['band_mid'] = self.ma_func(xdf, n=self.boll_len) xdf['band_up'] = xdf['band_mid'] + xdf['band_wth'] * self.band_ratio xdf['band_dn'] = xdf['band_mid'] - xdf['band_wth'] * self.band_ratio xdf['filter_ind'] = self.filter_func(xdf, self.filter_len) xdf['chan_h'] = dh.DONCH_H(xdf, self.channel) xdf['chan_l'] = dh.DONCH_L(xdf, self.channel) xdf['tr_stop_h'] = xdf['chan_h'] - ( xdf['band_wth'] * self.SL / self.tick_base).astype('int') * self.tick_base xdf['tr_stop_l'] = xdf['chan_l'] + ( xdf['band_wth'] * self.SL / self.tick_base).astype('int') * self.tick_base xdata = pd.concat([xdf['band_up'].shift(1), xdf['band_dn'].shift(1), \ xdf['tr_stop_h'].shift(1), xdf['tr_stop_l'].shift(1), xdf['filter_ind'].shift(1)], axis=1, \ keys=['band_up','band_dn', 'tr_stop_h', 'tr_stop_l', 'filter_ind']) self.df = df.join(xdata, how='left').fillna(method='ffill').dropna() self.df['cost'] = 0.0 self.df['pos'] = 0.0 self.df['closeout'] = 0.0 self.df['traded_price'] = self.df['open']
def process_data(self, mdf): if self.freq == 1: xdf = mdf else: freq_str = str(self.freq) + "min" xdf = dh.conv_ohlc_freq(mdf, freq_str, extra_cols = ['contract']) xdf['band_wth'] = self.band_func(xdf, n = self.boll_len) * self.band_ratio xdf['band_mid'] = self.ma_func(xdf, n=self.boll_len) xdf['band_up'] = xdf['band_mid'] + xdf['band_wth'] xdf['band_dn'] = xdf['band_mid'] - xdf['band_wth'] if (self.chan_len > 0): xdf['chan_h'] = dh.DONCH_H(xdf, n = self.chan_len, field = 'high') xdf['chan_l'] = dh.DONCH_L(xdf, n = self.chan_len, field = 'low') else: xdf['chan_h'] = -10000000 xdf['chan_l'] = 10000000 xdata = pd.concat([xdf['band_up'].shift(1), xdf['band_dn'].shift(1), \ xdf['band_mid'].shift(1), xdf['band_wth'].shift(1), \ xdf['chan_h'].shift(1), xdf['chan_l'].shift(1)], axis=1, \ keys=['band_up','band_dn', 'band_mid', 'band_wth', \ 'chan_h', 'chan_l']) self.df = mdf.join(xdata, how = 'left').fillna(method='ffill') self.df['datetime'] = self.df.index self.df['cost'] = 0.0 self.df['pos'] = 0.0 self.df['closeout'] = 0.0 self.df['traded_price'] = self.df['open']
def turtle_sim(ddf, mdf, config): marginrate = config['marginrate'] offset = config['offset'] start_equity = config['capital'] tcost = config['trans_cost'] signals = config['signals'] unit = config['unit'] NN = config['max_loss'] max_pos = config['max_pos'] start_idx = 0 ddf['ATR'] = pd.Series(dh.ATR(ddf, n=signals[0]).shift(1)) ddf['OL_1'] = pd.Series(dh.DONCH_H(ddf, signals[0]).shift(1)) ddf['OS_1'] = pd.Series(dh.DONCH_L(ddf, signals[0]).shift(1)) ddf['CL_1'] = pd.Series(dh.DONCH_L(ddf, signals[1]).shift(1)) ddf['CS_1'] = pd.Series(dh.DONCH_H(ddf, signals[1]).shift(1)) ddf['MA1'] = pd.Series(dh.MA(ddf, signals[2]).shift(1)) ddf['MA2'] = pd.Series(dh.MA(ddf, signals[3]).shift(1)) ll = mdf.shape[0] mdf['pos'] = pd.Series([0] * ll, index=mdf.index) mdf['cost'] = pd.Series([0] * ll, index=mdf.index) curr_pos = [] tradeid = 0 closed_trades = [] curr_atr = 0 for idx, dd in enumerate(mdf.index): mslice = mdf.ix[dd] d = dd.date() dslice = ddf.ix[d] tot_pos = sum([trade.pos for trade in curr_pos]) mdf.ix[dd, 'pos'] = tot_pos if (idx < start_idx) or np.isnan(dslice.ATR): continue if len(curr_pos) == 0 and idx < len(mdf.index) - NO_OPEN_POS_PROTECT: curr_atr = dslice.ATR direction = 0 up_MA = False down_MA = False if np.isnan(dslice.MA1) or (dslice.MA1 < dslice.MA2): up_MA = True if np.isnan(dslice.MA1) or (dslice.MA1 > dslice.MA2): down_MA = True if (mslice.close >= dslice.OL_1) and up_MA: direction = 1 elif (mslice.close <= dslice.OS_1) and down_MA: direction = -1 pos = direction * unit if direction != 0: new_pos = strat.TradePos([mslice.contract], [1], pos, mslice.close, mslice.close - direction * curr_atr * NN) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + direction * offset, dd) mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) curr_pos.append(new_pos) curr_atr = dslice.ATR elif (idx >= len(mdf.index) - NO_OPEN_POS_PROTECT): if len(curr_pos) > 0: for trade_pos in curr_pos: trade_pos.close( mslice.close - misc.sign(trade_pos.pos) * offset, dd) tradeid += 1 trade_pos.exit_tradeid = tradeid closed_trades.append(trade_pos) mdf.ix[dd, 'cost'] -= abs( trade_pos.pos) * (offset + mslice.close * tcost) curr_pos = [] else: direction = curr_pos[0].direction #exit position out of channel if (direction == 1 and mslice.close <= dslice.CL_1) or \ (direction == -1 and mslice.close >= dslice.CS_1): for trade_pos in curr_pos: trade_pos.close( mslice.close - misc.sign(trade_pos.pos) * offset, dd) tradeid += 1 trade_pos.exit_tradeid = tradeid closed_trades.append(trade_pos) mdf.ix[dd, 'cost'] -= abs( trade_pos.pos) * (offset + mslice.close * tcost) curr_pos = [] #stop loss position partially elif (curr_pos[-1].exit_target - mslice.close) * direction >= 0: for trade_pos in curr_pos: if (trade_pos.exit_target - mslice.close) * direction > 0: trade_pos.close( mslice.close - misc.sign(trade_pos.pos) * offset, dd) tradeid += 1 trade_pos.exit_tradeid = tradeid closed_trades.append(trade_pos) mdf.ix[dd, 'cost'] -= abs( trade_pos.pos) * (offset + mslice.close * tcost) curr_pos = [trade for trade in curr_pos if not trade.is_closed] #add positions elif (len(curr_pos) < max_pos) and (mslice.close - curr_pos[-1].entry_price ) * direction > curr_atr / max_pos * NN: for trade_pos in curr_pos: #trade.exit_target += curr_atr/max_pos*NN * direction trade_pos.exit_target = mslice.close - direction * curr_atr * NN new_pos = strat.TradePos( [mslice.contract], [1], direction * unit, mslice.close, mslice.close - direction * curr_atr * NN) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + direction * offset, dd) mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) curr_pos.append(new_pos) mdf.ix[dd, 'pos'] = sum([trade.pos for trade in curr_pos]) (res_pnl, ts) = backtest.get_pnl_stats(mdf, start_equity, marginrate, 'm') res_trade = backtest.get_trade_stats(closed_trades) res = dict(res_pnl.items() + res_trade.items()) return (res, closed_trades, ts)