def test(): xdf = tstool.get_cont_data('rb1701', datetime.date(2016,1,1), datetime.date(2016,8,19), freq = '30m', nearby = 0, rollrule = '-10b') xdf['WPR'] = dh.WPR(xdf, 9) xdf["SAR"] = dh.SAR(xdf, incr = 0.01, maxaf = 0.1) xdf['RSI'] = dh.RSI(xdf, 14) xdf['MA10'] = dh.MA(xdf, 10) xdf['MA120'] = dh.MA(xdf, 120) ind_fields = [['SAR'], \ ['WPR', 'RSI'], \ ['close', 'MA10', 'MA120']] ind_levels = [[],\ [70, 30],\ []] plot_indicators(xdf, ind_fields, ind_levels)
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['ATR'] = dh.ATR(xdf, n=self.atr_len) xdf['ATRMA'] = dh.MA(xdf, n=self.atrma_len, field='ATR') xdf['RSI'] = dh.RSI(xdf, n=self.rsi_len) self.df = xdf self.df['datetime'] = self.df.index self.df['cost'] = 0.0 self.df['pos'] = 0.0 self.df['traded_price'] = self.df['open']
def process_data(self, mdf): xdf = self.proc_func(mdf, **self.proc_args) if self.win == -1: tr = pd.concat( [xdf.high - xdf.low, abs(xdf.close - xdf.close.shift(1))], join='outer', axis=1).max(axis=1) elif self.win == 0: tr = pd.concat( [(pd.rolling_max(xdf.high, 2) - pd.rolling_min(xdf.close, 2)) * self.multiplier, (pd.rolling_max(xdf.close, 2) - pd.rolling_min(xdf.low, 2)) * self.multiplier, xdf.high - xdf.close, xdf.close - xdf.low], join='outer', axis=1).max(axis=1) else: tr = pd.concat([ pd.rolling_max(xdf.high, self.win) - pd.rolling_min(xdf.close, self.win), pd.rolling_max(xdf.close, self.win) - pd.rolling_min(xdf.low, self.win) ], join='outer', axis=1).max(axis=1) xdf['TR'] = tr xdf['chanh'] = self.chan_high(xdf['high'], self.chan, **self.chan_func['high']['args']) xdf['chanl'] = self.chan_low(xdf['low'], self.chan, **self.chan_func['low']['args']) xdf['ATR'] = dh.ATR(xdf, n=self.atr_len) xdf['MA'] = dh.MA(xdf, n=self.atr_len, field='close') xdata = pd.concat([ xdf['TR'].shift(1), xdf['MA'].shift(1), xdf['ATR'].shift(1), xdf['chanh'].shift(1), xdf['chanl'].shift(1), xdf['open'] ], axis=1, keys=['tr', 'ma', 'atr', 'chanh', 'chanl', 'dopen']).fillna(0) self.df = mdf.join(xdata, how='left').fillna(method='ffill') self.df['datetime'] = self.df.index self.df['cost'] = 0 self.df['pos'] = 0 self.df['traded_price'] = self.df['open']
def bband_chan_sim(mdf, config): start_equity = config['capital'] marginrate = config['marginrate'] offset = config['offset'] pos_class = config['pos_class'] pos_args = config['pos_args'] param = config['param'] #tick_base = config['tick_base'] close_daily = config['close_daily'] win = param[0] k = param[1] chan = param[2] if chan > 0: chan_func = config['chan_func'] tcost = config['trans_cost'] filter_func = config['filter_func']['func'] filter_args = config['filter_func']['args'] filter_param = config['filter_func']['param'] unit = config['unit'] freq = config['freq'] xdf = dh.conv_ohlc_freq(mdf, freq) xdf['boll_ma'] = dh.MA(xdf, win).shift(1) boll_std = dh.STDEV(xdf, win).shift(1) xdf['upbnd'] = xdf['boll_ma'] + boll_std * k xdf['lowbnd'] = xdf['boll_ma'] - boll_std * k if chan > 0: xdf['chan_h'] = eval(chan_func['high']['func'])( xdf, chan, **chan_func['high']['args']).shift(1) xdf['chan_l'] = eval(chan_func['low']['func'])( xdf, chan, **chan_func['low']['args']).shift(1) else: xdf['chan_h'] = 0 xdf['chan_l'] = 10000000 xdf['high_band'] = xdf[['chan_h', 'upbnd']].max(axis=1) xdf['low_band'] = xdf[['chan_l', 'lowbnd']].min(axis=1) xdf['filter'] = eval(filter_func)(xdf, filter_param[0], **filter_args) xdf['filter_ma'] = pd.rolling_mean(xdf['filter'], filter_param[1]) xdf['filter_ind'] = xdf['filter_ma'] >= filter_param[2] xdf['prev_close'] = xdf['close'].shift(1) xdf['close_ind'] = np.isnan(xdf['close'].shift(-1)) if close_daily: daily_end = (xdf['date'] != xdf['date'].shift(-1)) xdf['close_ind'] = xdf['close_ind'] | daily_end ll = xdf.shape[0] xdf['pos'] = 0 xdf['cost'] = 0 xdf['traded_price'] = xdf.open curr_pos = [] closed_trades = [] tradeid = 0 for idx, dd in enumerate(xdf.index): mslice = xdf.loc[dd] if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos xdf.set_value(dd, 'pos', pos) if np.isnan(mslice.boll_ma) or np.isnan(mslice.chan_h): continue if mslice.close_ind: if pos != 0: curr_pos[0].close(mslice.open - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] xdf.set_value( dd, 'cost', xdf.at[dd, 'cost'] - abs(pos) * (mslice.open * tcost)) xdf.set_value(dd, 'traded_price', mslice.open - misc.sign(pos) * offset) pos = 0 else: if ((mslice.open > mslice.boll_ma) and (pos < 0)) or ((mslice.open < mslice.boll_ma) and (pos > 0)): curr_pos[0].close(mslice.open - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] xdf.set_value( dd, 'cost', xdf.at[dd, 'cost'] - abs(pos) * (mslice.open * tcost)) xdf.set_value(dd, 'traded_price', mslice.open - misc.sign(pos) * offset) pos = 0 if ((mslice.open >= mslice.high_band) or (mslice.open <= mslice.low_band)) and (pos == 0): target_pos = (mslice.open >= mslice.high_band) * unit - ( mslice.open <= mslice.low_band) * unit new_pos = pos_class([mslice.contract], [1], target_pos, mslice.open, mslice.open, **pos_args) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.open + misc.sign(target_pos) * offset, dd) curr_pos.append(new_pos) pos = target_pos xdf.set_value( dd, 'cost', xdf.at[dd, 'cost'] - abs(target_pos) * (mslice.open * tcost)) xdf.set_value(dd, 'traded_price', mslice.open + misc.sign(target_pos) * offset) xdf.set_value(dd, 'pos', pos) return (xdf, closed_trades)
def turtle_sim(mdf, config): ddf = config['ddf'] marginrate = config['marginrate'] offset = config['offset'] start_equity = config['capital'] tcost = config['trans_cost'] chan = config['chan'] unit = config['unit'] param = config['param'] max_pos = param[1] max_loss = param[0] ma_ratio = config['ma_ratio'] use_ma = config['use_ma'] chan_func = config['chan_func'] pos_update = config['pos_update'] ddf['ATR'] = dh.ATR(ddf, n=chan[0]).shift(1) ddf['OL_1'] = eval(chan_func['high']['func'])(ddf, chan[0]).shift(1) ddf['OS_1'] = eval(chan_func['low']['func'])(ddf, chan[0]).shift(1) ddf['CL_1'] = eval(chan_func['low']['func'])(ddf, chan[1]).shift(1) ddf['CS_1'] = eval(chan_func['high']['func'])(ddf, chan[1]).shift(1) ddf['MA1'] = dh.MA(ddf, ma_ratio * chan[0]).shift(1) ddf['MA2'] = dh.MA(ddf, chan[1]).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 = [] end_d = mdf.index[-1].date() curr_atr = 0 for idx, dd in enumerate(mdf.index): mslice = mdf.ix[dd] min_id = mslice.min_id d = mslice.date dslice = ddf.ix[d] tot_pos = sum([trade.pos for trade in curr_pos]) mdf.ix[dd, 'pos'] = tot_pos if np.isnan(dslice.ATR): continue if (min_id >= config['exit_min']): if (tot_pos != 0) and (d == end_d): 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 = [] tot_pos = 0 else: if tot_pos == 0: curr_atr = dslice.ATR direction = 0 dol = dslice.OL_1 dos = dslice.OS_1 if (mslice.close >= dol) and ((use_ma == False) or (mslice.MA1 >= mslice.MA2)): direction = 1 elif (mslice.close <= dos) and ((use_ma == False) or (mslice.MA1 <= mslice.MA2)): direction = -1 pos = direction * unit if direction != 0: new_pos = strat.TradePos([mslice.contract], [1], pos, mslice.close, mslice.close) 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) 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].check_exit(mslice.close, curr_atr * max_loss): for trade_pos in curr_pos: if trade_pos.check_exit(mslice.close, curr_atr * max_loss): 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 * max_loss: for trade_pos in curr_pos: #trade.exit_target += curr_atr/max_pos*max_loss * direction trade_pos.set_exit(mslice.close) new_pos = strat.TradePos([mslice.contract], [1], direction * unit, mslice.close, mslice.close) 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) if (len(curr_pos) > 0) and pos_update: for trade_pos in curr_pos: trade_pos.update_price(mslice.close) mdf.ix[dd, 'pos'] = sum([trade.pos for trade in curr_pos]) return (mdf, closed_trades)
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)
def aberration_sim(df, config): marginrate = config['marginrate'] offset = config['offset'] win = config['win'] start_equity = config['capital'] tcost = config['trans_cost'] unit = config['unit'] k = config['scaler'] df['ma'] = dh.MA(df, win).shift(1) std = dh.STDDEV(df, win).shift(1) df['upbnd'] = df['ma'] + std * k[0] df['lowbnd'] = df['ma'] - std * k[0] ll = df.shape[0] df['pos'] = pd.Series([0] * ll, index=df.index) df['cost'] = pd.Series([0] * ll, index=df.index) curr_pos = [] closed_trades = [] start_d = df.index[0].date() end_d = df.index[-1].date() tradeid = 0 for idx, dd in enumerate(df.index): mslice = df.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos df.ix[dd, 'pos'] = pos if np.isnan(mslice.ma): continue if (min_id >= config['exit_min']): if (pos != 0) and (d == end_d): curr_pos[0].close(mslice.close - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] df.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) continue else: if ((mslice.close >= mslice.ma) and (pos < 0)) or (mslice.close <= mslice.ma) and (pos > 0): curr_pos[0].close(mslice.close - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] df.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) pos = 0 if (mslice.close >= mslice.upbnd) or (mslice.close <= mslice.lowbnd): if (pos == 0): target_pos = (mslice.close >= mslice.upbnd) * unit - ( mslice.close <= mslice.lowbnd) * unit target = (mslice.close >= mslice.upbnd) * mslice.upbnd + ( mslice.close <= mslice.lowbnd) * mslice.lowbnd new_pos = strat.TradePos([mslice.contract], [1], target_pos, target, mslice.upbnd + mslice.lowbnd - target) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + misc.sign(target_pos) * offset, dd) curr_pos.append(new_pos) df.ix[dd, 'cost'] -= abs(target_pos) * (offset + mslice.close * tcost) df.ix[dd, 'pos'] = pos else: print "something wrong with position=%s, close =%s, MA=%s, upBnd=%s, lowBnd=%s" % ( pos, mslice.close, mslice.ma, mslice.upbnd, mslice.lowbnd) (res_pnl, ts) = backtest.get_pnl_stats(df, 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)
def bband_chan_sim(mdf, config): offset = config['offset'] pos_class = config['pos_class'] pos_args = config['pos_args'] pos_update = config.get('pos_update', False) stoploss = config.get('stoploss', 0.0) param = config['param'] bar_func = config.get('bar_conv_func', 'dh.bar_conv_func2') bar_func = eval(bar_func) std_func = eval(config['std_func']) #tick_base = config['tick_base'] close_daily = config['close_daily'] win = param[0] k = param[1] chan = param[2] stop_ratio = config.get('exit_stop', 0.0) k_e = k * stop_ratio if chan > 0: chan_func = config['chan_func'] tcost = config['trans_cost'] unit = config['unit'] freq = config['freq'] xdf = dh.conv_ohlc_freq(mdf, freq, extra_cols=['contract'], bar_func=bar_func) xdf['boll_ma'] = dh.MA(xdf, win).shift(1) xdf['boll_std'] = std_func(xdf, win).shift(1) xdf['upbnd'] = xdf['boll_ma'] + xdf['boll_std'] * k xdf['lowbnd'] = xdf['boll_ma'] - xdf['boll_std'] * k xdf['up_exit'] = xdf['boll_ma'] + xdf['boll_std'] * k_e xdf['dn_exit'] = xdf['boll_ma'] - xdf['boll_std'] * k_e if chan > 0: xdf['chan_h'] = eval(chan_func['high']['func'])( xdf, chan, **chan_func['high']['args']).shift(2) xdf['chan_l'] = eval(chan_func['low']['func'])( xdf, chan, **chan_func['low']['args']).shift(2) else: xdf['chan_h'] = -10000000 xdf['chan_l'] = 10000000 xdf['high_band'] = xdf[['chan_h', 'upbnd']].max(axis=1) xdf['low_band'] = xdf[['chan_l', 'lowbnd']].min(axis=1) xdf['prev_close'] = xdf['close'].shift(1) xdf['close_ind'] = np.isnan(xdf['close'].shift(-1)) if close_daily: daily_end = (xdf['date'] != xdf['date'].shift(-1)) xdf['close_ind'] = xdf['close_ind'] | daily_end long_signal = pd.Series(np.nan, index=xdf.index) long_signal[(xdf['open'] >= xdf['high_band']) & (xdf['boll_ma'].notnull())] = 1 long_signal[(xdf['open'] <= xdf['dn_exit']) & (xdf['boll_ma'].notnull())] = 0 long_signal[xdf['close_ind']] = 0 long_signal = long_signal.fillna(method='ffill').fillna(0) short_signal = pd.Series(np.nan, index=xdf.index) short_signal[(xdf['open'] <= xdf['low_band']) & (xdf['boll_ma'].notnull())] = -1 short_signal[(xdf['open'] >= xdf['up_exit']) & (xdf['boll_ma'].notnull())] = 0 short_signal[xdf['close_ind']] = 0 short_signal = short_signal.fillna(method='ffill').fillna(0) if len(xdf[(long_signal > 0) & (short_signal < 0)]) > 0: print xdf[(long_signal > 0) & (short_signal < 0)] print "something wrong with the position as long signal and short signal happen the same time" xdf['pos'] = long_signal + short_signal xdf['cost'] = abs(xdf['pos'] - xdf['pos'].shift(1)) * (offset + xdf['open'] * tcost) xdf['cost'] = xdf['cost'].fillna(0.0) xdf['traded_price'] = xdf.open + (xdf['pos'] - xdf['pos'].shift(1)) * offset closed_trades = backtest.simdf_to_trades1(xdf, slippage=offset) return (xdf, closed_trades)
def aberration_sim(mdf, config): start_equity = config['capital'] marginrate = config['marginrate'] offset = config['offset'] pos_class = config['pos_class'] pos_args = config['pos_args'] param = config['param'] tick_base = config['tick_base'] close_daily = config['close_daily'] win = param[0] k = param[1] chan = param[2] if chan > 0: chan_func = config['chan_func'] tcost = config['trans_cost'] unit = config['unit'] freq = config['freq'] #freq_min = int(freq[:-3]) mode = config.get('mode', 'close') xdf = dh.conv_ohlc_freq(mdf, freq) boll_ma = dh.MA(xdf, win).shift(1) boll_std = dh.STDDEV(xdf, win).shift(1) upbnd = np.ceil((boll_ma + boll_std * k) / tick_base) * tick_base lowbnd = np.floor((boll_ma - boll_std * k) / tick_base) * tick_base boll_ma = np.floor(boll_ma / tick_base + 0.5) * tick_base xdata = [boll_ma, boll_std, upbnd, lowbnd, xdf['min_id']] xkeys = ['ma', 'stdev', 'upbnd', 'lowbnd', 'xmin_id'] if chan > 0: chan_h = eval(chan_func['high']['func'])(xdf, chan, **chan_func['high']['args']) chan_l = eval(chan_func['low']['func'])(xdf, chan, **chan_func['low']['args']) xdata = xdata + [chan_h, chan_l] xkeys = xkeys + ['chan_h', 'chan_l'] xdf = pd.concat(xdata, axis=1, keys=xkeys).fillna(0) mdf = mdf.join(xdf, how='left').fillna(method='ffill') mdf['is_new'] = (mdf['xmin_id'].shift(1) != mdf['xmin_id']) ll = mdf.shape[0] mdf['pos'] = pd.Series([0] * ll, index=mdf.index) mdf['cost'] = pd.Series([0] * ll, index=mdf.index) curr_pos = [] closed_trades = [] start_d = mdf.date[0] end_d = mdf.date[-1] tradeid = 0 for idx, dd in enumerate(mdf.index): mslice = mdf.ix[dd] min_id = mslice.min_id d = mslice.date if len(curr_pos) == 0: pos = 0 start_pos = 0 else: pos = curr_pos[0].pos start_pos = pos mdf.ix[dd, 'pos'] = pos if mslice.ma == 0: continue upbnd = mslice.upbnd lowbnd = mslice.lowbnd if chan > 0: if mslice.chan_h == 0: continue else: upbnd = max(mslice.chan_h, upbnd) lowbnd = min(mslice.chan_l, lowbnd) if min_id >= config['exit_min']: if (pos != 0) and ((d == end_d) or close_daily): curr_pos[0].close(mslice.close - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) pos = 0 else: if mode == 'close': high_trig = mslice.close low_trig = mslice.close trade_price = mslice.close else: high_trig = mslice.high low_trig = mslice.low trade_price = mslice.open if ((high_trig >= mslice.ma) and (pos < 0)) or ((low_trig <= mslice.ma) and (pos > 0)): if pos < 0: exec_price = max(trade_price, mslice.ma) else: exec_price = min(trade_price, mslice.ma) curr_pos[0].close(exec_price - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + exec_price * tcost) pos = 0 if ((high_trig > upbnd) and (pos <= 0)) or ((low_trig < lowbnd) and (pos >= 0)): target_pos = (high_trig > upbnd) * unit - (low_trig < lowbnd) * unit if target_pos == 0: print "the min bar hit both up and low bounds, need to think about how to handle it", start_pos, mslice if mslice.close > mslice.ma: target_pos = (high_trig > upbnd) * unit target = max(trade_price, upbnd) else: trade_pos = -(low_trig < lowbnd) * unit target = min(trade_price, lowbnd) else: target = (high_trig > upbnd) * max(trade_price, upbnd) + ( low_trig < lowbnd) * min(trade_price, lowbnd) new_pos = pos_class([mslice.contract], [1], target_pos, target, target, **pos_args) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(target + misc.sign(target_pos) * offset, dd) curr_pos.append(new_pos) pos = target_pos mdf.ix[dd, 'cost'] -= abs(target_pos) * (offset + target * tcost) mdf.ix[dd, 'pos'] = pos return (mdf, closed_trades)
def bband_chan_sim(mdf, config): offset = config['offset'] pos_class = config['pos_class'] pos_args = config['pos_args'] pos_update = config.get('pos_update', False) stoploss = config.get('stoploss', 0.0) param = config['param'] bar_func = eval(config['bar_conv_func']) std_func = eval(config['std_func']) #tick_base = config['tick_base'] close_daily = config['close_daily'] win = param[0] k = param[1] chan = param[2] stop_ratio = config.get('exit_stop', 0.0) k_e = k * stop_ratio if chan > 0: chan_func = config['chan_func'] tcost = config['trans_cost'] unit = config['unit'] freq = config['freq'] xdf = dh.conv_ohlc_freq(mdf, freq, extra_cols=['contract'], bar_func=bar_func) xdf['boll_ma'] = dh.MA(xdf, win).shift(1) xdf['boll_std'] = std_func(xdf, win).shift(1) xdf['upbnd'] = xdf['boll_ma'] + xdf['boll_std'] * k xdf['lowbnd'] = xdf['boll_ma'] - xdf['boll_std'] * k xdf['up_exit'] = xdf['boll_ma'] + xdf['boll_std'] * k_e xdf['dn_exit'] = xdf['boll_ma'] - xdf['boll_std'] * k_e if chan > 0: xdf['chan_h'] = eval(chan_func['high']['func'])( xdf, chan, **chan_func['high']['args']).shift(2) xdf['chan_l'] = eval(chan_func['low']['func'])( xdf, chan, **chan_func['low']['args']).shift(2) else: xdf['chan_h'] = 0 xdf['chan_l'] = 10000000 xdf['high_band'] = xdf[['chan_h', 'upbnd']].max(axis=1) xdf['low_band'] = xdf[['chan_l', 'lowbnd']].min(axis=1) xdf['prev_close'] = xdf['close'].shift(1) xdf['close_ind'] = np.isnan(xdf['close'].shift(-1)) if close_daily: daily_end = (xdf['date'] != xdf['date'].shift(-1)) xdf['close_ind'] = xdf['close_ind'] | daily_end ll = xdf.shape[0] xdf['pos'] = 0 xdf['cost'] = 0 xdf['traded_price'] = xdf.open curr_pos = [] closed_trades = [] tradeid = 0 for idx, dd in enumerate(xdf.index): mslice = xdf.loc[dd] if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos xdf.set_value(dd, 'pos', pos) if np.isnan(mslice.boll_ma) or np.isnan(mslice.chan_h): continue if mslice.close_ind: if pos != 0: curr_pos[0].close(mslice.open - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] xdf.set_value( dd, 'cost', xdf.at[dd, 'cost'] - abs(pos) * (mslice.open * tcost)) xdf.set_value(dd, 'traded_price', mslice.open - misc.sign(pos) * offset) pos = 0 else: if ((mslice.open > mslice.up_exit) and (pos < 0)) or ((mslice.open < mslice.dn_exit) and (pos > 0)): curr_pos[0].close(mslice.open - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] xdf.set_value( dd, 'cost', xdf.at[dd, 'cost'] - abs(pos) * (mslice.open * tcost)) xdf.set_value(dd, 'traded_price', mslice.open - misc.sign(pos) * offset) pos = 0 if ((mslice.open >= mslice.high_band) or (mslice.open <= mslice.low_band)) and (pos == 0): target_pos = (mslice.open >= mslice.high_band) * unit - ( mslice.open <= mslice.low_band) * unit new_pos = pos_class([mslice.contract], [1], target_pos, mslice.open, mslice.open, **pos_args) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.open + misc.sign(target_pos) * offset, dd) curr_pos.append(new_pos) pos = target_pos xdf.set_value( dd, 'cost', xdf.at[dd, 'cost'] - abs(target_pos) * (mslice.open * tcost)) xdf.set_value(dd, 'traded_price', mslice.open + misc.sign(target_pos) * offset) if pos_update and pos != 0: if curr_pos[0].check_exit(mslice.open, stoploss * mslice.boll_std): curr_pos[0].close(mslice.open - misc.sign(pos) * offset, dd) tradeid += 1 curr_pos[0].exit_tradeid = tradeid closed_trades.append(curr_pos[0]) curr_pos = [] xdf.set_value( dd, 'cost', xdf.at[dd, 'cost'] - abs(pos) * (mslice.open * tcost)) xdf.set_value(dd, 'traded_price', mslice.open - misc.sign(pos) * offset) pos = 0 else: curr_pos[0].update_bar(mslice) xdf.set_value(dd, 'pos', pos) return (xdf, closed_trades)
trades.to_csv(fname) fname = file_prefix + str(idx) + '_dailydata.csv' ts.to_csv(fname) fname = file_prefix + 'stats.csv' res = pd.DataFrame.from_dict(output) res.to_csv(fname) return def aberration_sim( xdf, mdf, config): marginrate = config['marginrate'] offset = config['offset'] win = config['win'] start_equity = config['capital'] tcost = config['trans_cost'] unit = config['unit'] df['ma'] = dh.MA(df, win).shift(1) std = dh.STDDEV(df, win).shift(1) df['upbnd'] = df['ma'] + std df['lowbnd'] = df['ma'] - std ll = df.shape[0] df['pos'] = pd.Series([0]*ll, index = mdf.index) df['cost'] = pd.Series([0]*ll, index = mdf.index) curr_pos = [] closed_trades = [] start_d = df.index[0].date() end_d = df.index[-1].date() tradeid = 0 for idx, dd in enumerate(df.index): mslice = df.ix[dd] min_id = agent.get_min_id(dd) d = dd.date()