def dual_thrust_sim(mdf, config): close_daily = config["close_daily"] marginrate = config["marginrate"] offset = config["offset"] k = config["k"] f = config["f"] start_equity = config["capital"] win = config["win"] multiplier = config["m"] tcost = config["trans_cost"] unit = config["unit"] SL = config["stoploss"] min_rng = config["min_range"] ma_fast = config["MA_fast"] ll = mdf.shape[0] mdf["min_idx"] = pd.Series(1, index=mdf.index) mdf.loc[mdf["min_id"] < 1500, "min_idx"] = 0 mdf["date_idx"] = mdf.index.date xdf = mdf.groupby([mdf["date_idx"], mdf["min_idx"]]).apply(dh.ohlcsum).reset_index().set_index("datetime") if win == -1: tr = ( pd.concat([xdf.high - xdf.low, abs(xdf.close - xdf.close.shift(1))], join="outer", axis=1) .max(axis=1) .shift(1) ) elif win == -2: tr = pd.rolling_max(xdf.high, 2) - pd.rolling_min(xdf.low, 2) elif win == 0: tr = ( pd.concat( [ (pd.rolling_max(xdf.high, 2) - pd.rolling_min(xdf.close, 2)) * multiplier, (pd.rolling_max(xdf.close, 2) - pd.rolling_min(xdf.low, 2)) * multiplier, xdf.high - xdf.close, xdf.close - xdf.low, ], join="outer", axis=1, ) .max(axis=1) .shift(1) ) else: tr = ( pd.concat( [ pd.rolling_max(xdf.high, win) - pd.rolling_min(xdf.close, win), pd.rolling_max(xdf.close, win) - pd.rolling_min(xdf.low, win), ], join="outer", axis=1, ) .max(axis=1) .shift(1) ) xdf["TR"] = tr xdf["MA"] = pd.rolling_mean(xdf.close, ma_fast).shift(1) ddf = pd.concat( [xdf["TR"], xdf["MA"], xdf["open"], xdf["date_idx"]], axis=1, keys=["TR", "MA", "dopen", "date"] ).fillna(0) mdf = mdf.join(ddf, how="left").fillna(method="ffill") mdf["pos"] = pd.Series([0] * ll, index=mdf.index) mdf["cost"] = pd.Series([0] * ll, index=mdf.index) curr_pos = [] closed_trades = [] start_d = ddf.index[0] end_d = mdf.index[-1].date() # prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, "pos"] = pos if mslice.TR == 0 or mslice.MA == 0: continue d_open = mslice.dopen # if (prev_d < d): # d_open = mslice.open # else: # d_open = dslice.open rng = max(min_rng * d_open, k * mslice.TR) if d_open <= 0: continue buytrig = d_open + rng selltrig = d_open - rng if mslice.MA > mslice.close: buytrig += f * rng elif mslice.MA < mslice.close: selltrig -= f * rng if (min_id >= config["exit_min"]) and (close_daily or (mslice.date == end_d)): if 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 = [] mdf.ix[dd, "cost"] -= abs(pos) * (offset + mslice.close * tcost) pos = 0 else: if (pos != 0) and (SL > 0): curr_pos[0].trail_update(mslice.close) if curr_pos[0].trail_check(mslice.close, SL * mslice.close): curr_pos[0].close(mslice.close - offset * misc.sign(pos), 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 if (mslice.high >= buytrig) and (pos <= 0): if len(curr_pos) > 0: curr_pos[0].close(mslice.close + 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) new_pos = strat.TradePos([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset, dd) curr_pos.append(new_pos) pos = unit mdf.ix[dd, "cost"] -= abs(pos) * (offset + mslice.close * tcost) elif (mslice.low <= selltrig) and (pos >= 0): if len(curr_pos) > 0: curr_pos[0].close(mslice.close - 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) new_pos = strat.TradePos([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close - offset, dd) curr_pos.append(new_pos) pos = -unit mdf.ix[dd, "cost"] -= abs(pos) * (offset + mslice.close * tcost) mdf.ix[dd, "pos"] = 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 r_breaker_sim(ddf, mdf, config): marginrate = config['marginrate'] offset = config['offset'] k = config['k'] a = k[0] b = k[1] c = k[2] start_equity = config['capital'] tcost = config['trans_cost'] unit = config['unit'] close_daily = config['close_daily'] ddf['range'] = (ddf.high - ddf.low).shift(1) ddf['ssetup'] = (ddf.high + a * (ddf.close - ddf.low)).shift(1) ddf['bsetup'] = (ddf.low - a * (ddf.high - ddf.close)).shift(1) ddf['senter'] = ((1 + b) * (ddf.high + ddf.close) / 2.0 - b * ddf.low).shift(1) ddf['benter'] = ((1 + b) * (ddf.low + ddf.close) / 2.0 - b * ddf.high).shift(1) ddf['bbreak'] = ddf.ssetup + c * (ddf.ssetup - ddf.bsetup) ddf['sbreak'] = ddf.bsetup - c * (ddf.ssetup - ddf.bsetup) 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 = ddf.index[0] end_d = mdf.index[-1].date() prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 cur_high = 0 cur_low = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() dslice = ddf.ix[d] if np.isnan(dslice.bbreak): continue if (prev_d < d): num_trades = 0 cur_high = mslice.high cur_low = mslice.low else: cur_high = max([cur_high, mslice.high]) cur_low = min([cur_low, mslice.low]) prev_d = d if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos if (min_id >= config['exit_min']): if (pos != 0) and (close_daily or (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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) pos = 0 elif (min_id <= config['start_min']): continue else: if num_trades >= 2: continue if ((cur_high < dslice.bbreak) and (cur_high >= dslice.ssetup) and (mslice.close < dslice.senter) and (pos >=0)) or \ ((cur_low > dslice.sbreak) and (cur_low <= dslice.bsetup) and (mslice.close > dslice.benter) and (pos <=0)): if len(curr_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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) new_pos = strat.TradePos([mslice.contract], [1], -unit * misc.sign(pos), mslice.close, 0) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset * misc.sign(pos), dd) curr_pos.append(new_pos) pos = -unit * misc.sign(pos) mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) num_trades += 1 elif ((mslice.close >= dslice.bbreak) or (mslice.close <= dslice.sbreak)) and (pos == 0): if (mslice.close >= dslice.bbreak): direction = 1 else: direction = -1 new_pos = strat.TradePos([mslice.contract], [1], unit * direction, mslice.close, 0) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset * misc.sign(direction), dd) curr_pos.append(new_pos) pos = unit * direction mdf.ix[dd, 'cost'] -= abs(direction) * (offset + mslice.close * tcost) num_trades += 1 mdf.ix[dd, 'pos'] = 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 dual_thrust_sim( ddf, mdf, config): close_daily = config['close_daily'] marginrate = config['marginrate'] offset = config['offset'] k = config['k'] start_equity = config['capital'] win = config['win'] multiplier = config['m'] tcost = config['trans_cost'] unit = config['unit'] SL = config['stoploss'] min_rng = config['min_range'] if win == -1: tr = (ddf.high - ddf.low).shift(1) elif win == 0: tr = pd.concat([(pd.rolling_max(ddf.high, 2) - pd.rolling_min(ddf.close, 2))*multiplier, (pd.rolling_max(ddf.close, 2) - pd.rolling_min(ddf.low, 2))*multiplier, ddf.high - ddf.close, ddf.close - ddf.low], join='outer', axis=1).max(axis=1).shift(1) else: tr= pd.concat([pd.rolling_max(ddf.high, win) - pd.rolling_min(ddf.close, win), pd.rolling_max(ddf.close, win) - pd.rolling_min(ddf.low, win)], join='outer', axis=1).max(axis=1).shift(1) ddf['TR'] = tr 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 = ddf.index[0] end_d = mdf.index[-1].date() #prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() dslice = ddf.ix[d] if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos if np.isnan(dslice.TR): continue d_open = dslice.open #if (prev_d < d): # d_open = mslice.open #else: # d_open = dslice.open if (d_open <= 0): continue #prev_d = d buytrig = d_open + max(min_rng, dslice.TR * k) selltrig = d_open - max(min_rng, dslice.TR * k) if (min_id >= config['exit_min']): if (pos != 0) and (close_daily or (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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) pos = 0 else: if (pos!=0) and (SL>0) and (curr_pos[0].trail_loss(mslice.close, SL*mslice.close)): curr_pos[0].close(mslice.close-offset*misc.sign(pos), 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 if (mslice.close >= buytrig) and (pos <=0 ): if len(curr_pos) > 0: curr_pos[0].close(mslice.close+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) new_pos = strat.TradePos([mslice.contract], [1], unit, buytrig, 0) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset, dd) curr_pos.append(new_pos) pos = unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) elif (mslice.close <= selltrig) and (pos >=0 ): if len(curr_pos) > 0: curr_pos[0].close(mslice.close-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) new_pos = strat.TradePos([mslice.contract], [1], -unit, selltrig, 0) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close - offset, dd) curr_pos.append(new_pos) pos = -unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) mdf.ix[dd, 'pos'] = 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 fisher_swing_sim(df, xdf, config): marginrate = config["marginrate"] offset = config["offset"] win = config["win"] start_equity = config["capital"] tcost = config["trans_cost"] unit = config["unit"] fisher = dh.FISHER(xdf, win[0]) xdf["FISHER_I"] = fisher["FISHER_I"].shift(1) xdf = xdf.join(dh.BBANDS_STOP(xdf, win[1], 1.0).shift(1)) ha_df = dh.HEIKEN_ASHI(xdf, win[2]).shift(1) xdf["HAopen"] = ha_df["HAopen"] xdf["HAclose"] = ha_df["HAclose"] 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 = [] end_d = df.index[-1].date() tradeid = 0 for dd in 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.BBSTOP_lower) or np.isnan(mslice.FISHER_I) or np.isnan(mslice.HAclose): continue end_trading = (min_id >= config["exit_min"]) and (d == end_d) stop_loss = (pos > 0) and ((mslice.close < mslice.BBSTOP_lower) or (mslice.FISHER_I < 0)) stop_loss = stop_loss or ((pos < 0) and ((mslice.close > mslice.BBSTOP_upper) or (mslice.FISHER_I > 0))) start_long = (mslice.FISHER_I > 0) and (mslice.HAclose > mslice.HAopen) and (mslice.BBSTOP_trend > 0) start_short = (mslice.FISHER_I < 0) and (mslice.HAclose < mslice.HAopen) and (mslice.BBSTOP_trend < 0) if pos != 0: if stop_loss or end_trading: 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 (not end_trading) and (pos == 0): if start_long and start_short: print "warning: get both long and short signal, something is wrong!" print mslice continue pos = (start_long == True) * unit - (start_short == True) * unit if abs(pos) > 0: # target = (start_long == True) * mslice.close +(start_short == True) * mslice.close new_pos = strat.TradePos([mslice.contract], [1], pos, mslice.close, mslice.close) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + misc.sign(pos) * offset, dd) curr_pos.append(new_pos) df.ix[dd, "cost"] -= abs(pos) * (offset + mslice.close * tcost) df.ix[dd, "pos"] = pos (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 dual_thrust_sim( ddf, mdf, config): close_daily = config['close_daily'] marginrate = config['marginrate'] offset = config['offset'] k = config['k'] start_equity = config['capital'] win = config['win'] multiplier = config['m'] tcost = config['trans_cost'] unit = config['unit'] SL = config['stoploss'] min_rng = config['min_range'] if win == -1: tr= pd.concat([ddf.high - ddf.low, ddf.close - ddf.close.shift(1)], join='outer', axis=1).max(axis=1).shift(1) elif win == 0: tr = pd.concat([(pd.rolling_max(ddf.high, 2) - pd.rolling_min(ddf.close, 2))*multiplier, (pd.rolling_max(ddf.close, 2) - pd.rolling_min(ddf.low, 2))*multiplier, ddf.high - ddf.close, ddf.close - ddf.low], join='outer', axis=1).max(axis=1).shift(1) else: tr= pd.concat([pd.rolling_max(ddf.high, win) - pd.rolling_min(ddf.close, win), pd.rolling_max(ddf.close, win) - pd.rolling_min(ddf.low, win)], join='outer', axis=1).max(axis=1).shift(1) ddf['TR'] = tr #ddf['prev_high'] = ddf.high.shift(1) #ddf['prev_low'] = ddf.low.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 = [] closed_trades = [] start_d = ddf.index[0] end_d = mdf.index[-1].date() prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() dslice = ddf.ix[d] if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos if np.isnan(dslice.TR): continue d_open = dslice.open if (prev_d < d): d_open = mslice.open #d_high = mslice.high #d_low = mslice.low else: d_open = dslice.open #d_high = max(d_high, mslice.high) #d_low = min(d_low, mslice.low) if (d_open <= 0): continue prev_d = d buytrig = d_open + max(min_rng * d_open, dslice.TR * k) selltrig = d_open - max(min_rng * d_open, dslice.TR * k) #d_high = max(d_high, dslice.prev_high) #d_low = min(d_low, dslice.prev_low) if (min_id >= config['exit_min']): if (pos != 0) and (close_daily or (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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) pos = 0 else: if (pos!=0) and (SL>0): curr_pos[0].trail_update(mslice.close) if (curr_pos[0].trail_check(mslice.close, SL*mslice.close)): curr_pos[0].close(mslice.close-offset*misc.sign(pos), 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 if (mslice.high >= buytrig) and (pos <=0 ): if len(curr_pos) > 0: curr_pos[0].close(mslice.close+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) new_pos = strat.TradePos([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset, dd) curr_pos.append(new_pos) pos = unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) elif (mslice.low <= selltrig) and (pos >=0 ): if len(curr_pos) > 0: curr_pos[0].close(mslice.close-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) new_pos = strat.TradePos([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close - offset, dd) curr_pos.append(new_pos) pos = -unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) mdf.ix[dd, 'pos'] = 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 dual_thrust_sim( mdf, config): close_daily = config['close_daily'] marginrate = config['marginrate'] offset = config['offset'] k = config['k'] f = config['f'] start_equity = config['capital'] win = config['win'] multiplier = config['m'] tcost = config['trans_cost'] unit = config['unit'] SL = config['stoploss'] min_rng = config['min_range'] ma_fast = config['MA_fast'] ll = mdf.shape[0] mdf['min_idx'] = pd.Series(1, index = mdf.index) mdf.loc[mdf['min_id']<1500, 'min_idx'] = 0 mdf['date_idx'] = mdf.index.date xdf = mdf.groupby([mdf['date_idx'], mdf['min_idx']]).apply(dh.ohlcsum).reset_index().set_index('datetime') if win == -1: tr= pd.concat([xdf.high - xdf.low, abs(xdf.close - xdf.close.shift(1))], join='outer', axis=1).max(axis=1).shift(1) elif win == -2: tr= pd.rolling_max(xdf.high, 2) - pd.rolling_min(xdf.low, 2) elif win == 0: tr = pd.concat([(pd.rolling_max(xdf.high, 2) - pd.rolling_min(xdf.close, 2))*multiplier, (pd.rolling_max(xdf.close, 2) - pd.rolling_min(xdf.low, 2))*multiplier, xdf.high - xdf.close, xdf.close - xdf.low], join='outer', axis=1).max(axis=1).shift(1) else: tr= pd.concat([pd.rolling_max(xdf.high, win) - pd.rolling_min(xdf.close, win), pd.rolling_max(xdf.close, win) - pd.rolling_min(xdf.low, win)], join='outer', axis=1).max(axis=1).shift(1) xdf['TR'] = tr xdf['MA'] = pd.rolling_mean(xdf.close, ma_fast).shift(1) ddf = pd.concat([xdf['TR'], xdf['MA'], xdf['open'], xdf['date_idx']], axis=1, keys=['TR','MA','dopen', 'date']).fillna(0) mdf = mdf.join(ddf, how = 'left').fillna(method='ffill') mdf['pos'] = pd.Series([0]*ll, index = mdf.index) mdf['cost'] = pd.Series([0]*ll, index = mdf.index) curr_pos = [] closed_trades = [] start_d = ddf.index[0] end_d = mdf.index[-1].date() #prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos if mslice.TR == 0 or mslice.MA == 0: continue d_open = mslice.dopen #if (prev_d < d): # d_open = mslice.open #else: # d_open = dslice.open rng = max(min_rng * d_open, k * mslice.TR) if (d_open <= 0): continue buytrig = d_open + rng selltrig = d_open - rng if mslice.MA > mslice.close: buytrig += f * rng elif mslice.MA < mslice.close: selltrig -= f * rng if (min_id >= config['exit_min']) and (close_daily or (mslice.date == end_d)): if (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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) pos = 0 else: if (pos!=0) and (SL>0): curr_pos[0].trail_update(mslice.close) if (curr_pos[0].trail_check(mslice.close, SL*mslice.close)): curr_pos[0].close(mslice.close-offset*misc.sign(pos), 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 if (mslice.high >= buytrig) and (pos <=0 ): if len(curr_pos) > 0: curr_pos[0].close(mslice.close+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) new_pos = strat.TradePos([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset, dd) curr_pos.append(new_pos) pos = unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) elif (mslice.low <= selltrig) and (pos >=0 ): if len(curr_pos) > 0: curr_pos[0].close(mslice.close-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) new_pos = strat.TradePos([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close - offset, dd) curr_pos.append(new_pos) pos = -unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) mdf.ix[dd, 'pos'] = 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 dual_thrust_sim( mdf, config): ddf = config['ddf'] close_daily = config['close_daily'] marginrate = config['marginrate'] offset = config['offset'] k = config['param'][0] win = config['param'][1] multiplier = config['param'][2] f = config['param'][3] ep_enabled = config['EP'] start_equity = config['capital'] chan = config['chan'] chan_func = config['chan_func'] tcost = config['trans_cost'] unit = config['unit'] SL = config['stoploss'] min_rng = config['min_range'] no_trade_set = config['no_trade_set'] if win == -1: tr= pd.concat([ddf.high - ddf.low, ddf.close - ddf.close.shift(1)], join='outer', axis=1).max(axis=1).shift(1) elif win == 0: tr = pd.concat([(pd.rolling_max(ddf.high, 2) - pd.rolling_min(ddf.close, 2))*multiplier, (pd.rolling_max(ddf.close, 2) - pd.rolling_min(ddf.low, 2))*multiplier, ddf.high - ddf.close, ddf.close - ddf.low], join='outer', axis=1).max(axis=1).shift(1) else: tr= pd.concat([pd.rolling_max(ddf.high, win) - pd.rolling_min(ddf.close, win), pd.rolling_max(ddf.close, win) - pd.rolling_min(ddf.low, win)], join='outer', axis=1).max(axis=1).shift(1) ddf['TR'] = tr ddf['H1'] = eval(chan_func['high']['func'])(ddf, chan, **chan_func['high']['args']).shift(1) ddf['L1'] = eval(chan_func['low']['func'])(ddf, chan, **chan_func['low']['args']).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 = [] closed_trades = [] start_d = ddf.index[0] end_d = mdf.index[-1].date() prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() dslice = ddf.ix[d] if np.isnan(dslice.TR) or (mslice.close == 0): continue if (mslice.low == 0): mslice.low = mslice.close if mslice.high >= mslice.open * 1.2: mslice.high = mslice.close if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos d_open = dslice.open if (prev_d < d): d_open = mslice.open d_high = mslice.high d_low = mslice.low else: d_open = dslice.open d_high = max(d_high, mslice.high) d_low = min(d_low, mslice.low) if (d_open <= 0): continue prev_d = d buytrig = d_open + max(min_rng * d_open, dslice.TR * k) selltrig = d_open - max(min_rng * d_open, dslice.TR * k) if ep_enabled: buytrig = max(buytrig, d_high) selltrig = min(selltrig, d_low) if (min_id >= config['exit_min']) : if (pos != 0) and (close_daily or (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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) pos = 0 elif min_id not in no_trade_set: if (pos!=0) and (SL>0): curr_pos[0].trail_update(mslice.close) if curr_pos[0].check_exit(mslice.close, SL*mslice.close): curr_pos[0].close(mslice.close-offset*misc.sign(pos), 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 if (mslice.high >= buytrig) and (pos <=0 ): if len(curr_pos) > 0: curr_pos[0].close(mslice.close+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) if mslice.high >= dslice.H1: new_pos = strat.TradePos([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset, dd) curr_pos.append(new_pos) pos = unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) elif (mslice.low <= selltrig) and (pos >=0 ): if len(curr_pos) > 0: curr_pos[0].close(mslice.close-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) if mslice.low <= dslice.L1: new_pos = strat.TradePos([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close - offset, dd) curr_pos.append(new_pos) pos = -unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) mdf.ix[dd, 'pos'] = 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 chanbreak_sim(mdf, ddf, config): freq = config['freq'] str_freq = str(freq) + 'Min' xdf = dh.conv_ohlc_freq(mdf, str_freq) start_equity = config['capital'] tcost = config['trans_cost'] unit = config['unit'] k = config['scaler'] marginrate = config['marginrate'] offset = config['offset'] win = config['win'] chan_func = config['channel_func'] upper_chan_func = chan_func[0] lower_chan_func = chan_func[1] entry_chan = win exit_chan = int(entry_chan / k[1]) xdf['H1'] = upper_chan_func(xdf, entry_chan).shift(1) xdf['L1'] = lower_chan_func(xdf, entry_chan).shift(1) xdf['H2'] = upper_chan_func(xdf, exit_chan).shift(1) xdf['L2'] = lower_chan_func(xdf, exit_chan).shift(1) ddf['ATR'] = dh.ATR(ddf, entry_chan) 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 = [] end_d = mdf.index[-1].date() tradeid = 0 x_idx = 0 max_idx = len(xdf.index) for idx, dd in enumerate(mdf.index): mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() dslice = ddf.ix[d] while (x_idx < max_idx - 1) and (xdf.index[x_idx + 1] < dd): x_idx += 1 xslice = xdf.iloc[x_idx] if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos if np.isnan(dslice.ATR): 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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) continue else: if (pos != 0): curr_pos[0].trail_update(mslice.close) if curr_pos[0].trail_check(mslice.close, dslice.ATR * k[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]) pos = 0 curr_pos = [] if ((mslice.close >= xslice.H2) and (pos < 0)) or ((mslice.close <= xslice.L2) 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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) pos = 0 if ((mslice.close >= xslice.H1) and (pos <= 0)) or ((mslice.close <= xslice.L1) and (pos >= 0)): if (pos == 0): target_pos = (mslice.close >= xslice.H1) * unit - ( mslice.close <= xslice.L1) * unit new_pos = strat.TradePos([mslice.contract], [1], target_pos, mslice.close, mslice.close) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + misc.sign(target_pos) * offset, dd) curr_pos.append(new_pos) mdf.ix[dd, 'cost'] -= abs(target_pos) * (offset + mslice.close * tcost) mdf.ix[dd, 'pos'] = pos else: print "something wrong with position=%s, close =%s, upBnd=%s, lowBnd=%s" % ( pos, mslice.close, xslice.H1, xslice.L1) (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 r_breaker_sim( ddf, mdf, config): marginrate = config['marginrate'] offset = config['offset'] k = config['k'] a = k[0] b = k[1] c = k[2] start_equity = config['capital'] tcost = config['trans_cost'] unit = config['unit'] close_daily = config['close_daily'] ddf['range'] = (ddf.high - ddf.low).shift(1) ddf['ssetup'] = (ddf.high+a*(ddf.close - ddf.low)).shift(1) ddf['bsetup'] = (ddf.low-a*(ddf.high - ddf.close)).shift(1) ddf['senter'] = ((1+b)*(ddf.high+ddf.close)/2.0 - b * ddf.low).shift(1) ddf['benter'] = ((1+b)*(ddf.low+ddf.close)/2.0 - b * ddf.high).shift(1) ddf['bbreak'] = ddf.ssetup + c * (ddf.ssetup - ddf.bsetup) ddf['sbreak'] = ddf.bsetup - c * (ddf.ssetup - ddf.bsetup) 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 = ddf.index[0] end_d = mdf.index[-1].date() prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 cur_high = 0 cur_low = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() dslice = ddf.ix[d] if np.isnan(dslice.bbreak): continue if (prev_d < d): num_trades = 0 cur_high = mslice.high cur_low = mslice.low else: cur_high = max([cur_high, mslice.high]) cur_low = min([cur_low, mslice.low]) prev_d = d if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos if (min_id >= config['exit_min']): if (pos != 0) and (close_daily or (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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) pos = 0 elif (min_id <= config['start_min']): continue else: if num_trades >=2: continue if ((cur_high < dslice.bbreak) and (cur_high >= dslice.ssetup) and (mslice.close < dslice.senter) and (pos >=0)) or \ ((cur_low > dslice.sbreak) and (cur_low <= dslice.bsetup) and (mslice.close > dslice.benter) and (pos <=0)): if len(curr_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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) new_pos = strat.TradePos([mslice.contract], [1], -unit*misc.sign(pos), mslice.close, 0) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset*misc.sign(pos), dd) curr_pos.append(new_pos) pos = -unit*misc.sign(pos) mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) num_trades += 1 elif ((mslice.close >= dslice.bbreak) or (mslice.close <= dslice.sbreak)) and (pos == 0): if (mslice.close >= dslice.bbreak): direction = 1 else: direction = -1 new_pos = strat.TradePos([mslice.contract], [1], unit*direction, mslice.close, 0) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset*misc.sign(direction), dd) curr_pos.append(new_pos) pos = unit*direction mdf.ix[dd, 'cost'] -= abs(direction) * (offset + mslice.close*tcost) num_trades += 1 mdf.ix[dd, 'pos'] = 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 dual_thrust_sim(mdf, config): close_daily = config['close_daily'] marginrate = config['marginrate'] offset = config['offset'] k = config['k'] f = config['f'] start_equity = config['capital'] win = config['win'] multiplier = config['m'] tcost = config['trans_cost'] unit = config['unit'] SL = config['stoploss'] min_rng = config['min_range'] ma_fast = config['MA_fast'] ll = mdf.shape[0] mdf['min_idx'] = pd.Series(1, index=mdf.index) mdf.loc[mdf['min_id'] < 1500, 'min_idx'] = 0 mdf['date_idx'] = mdf.index.date xdf = mdf.groupby([mdf['date_idx'], mdf['min_idx'] ]).apply(dh.ohlcsum).reset_index().set_index('datetime') if win == -1: tr = pd.concat( [xdf.high - xdf.low, abs(xdf.close - xdf.close.shift(1))], join='outer', axis=1).max(axis=1).shift(1) elif win == -2: tr = pd.rolling_max(xdf.high, 2) - pd.rolling_min(xdf.low, 2) elif win == 0: tr = pd.concat( [(pd.rolling_max(xdf.high, 2) - pd.rolling_min(xdf.close, 2)) * multiplier, (pd.rolling_max(xdf.close, 2) - pd.rolling_min(xdf.low, 2)) * multiplier, xdf.high - xdf.close, xdf.close - xdf.low], join='outer', axis=1).max(axis=1).shift(1) else: tr = pd.concat([ pd.rolling_max(xdf.high, win) - pd.rolling_min(xdf.close, win), pd.rolling_max(xdf.close, win) - pd.rolling_min(xdf.low, win) ], join='outer', axis=1).max(axis=1).shift(1) xdf['TR'] = tr xdf['MA'] = pd.rolling_mean(xdf.close, ma_fast).shift(1) ddf = pd.concat([xdf['TR'], xdf['MA'], xdf['open'], xdf['date_idx']], axis=1, keys=['TR', 'MA', 'dopen', 'date']).fillna(0) mdf = mdf.join(ddf, how='left').fillna(method='ffill') mdf['pos'] = pd.Series([0] * ll, index=mdf.index) mdf['cost'] = pd.Series([0] * ll, index=mdf.index) curr_pos = [] closed_trades = [] start_d = ddf.index[0] end_d = mdf.index[-1].date() #prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos if mslice.TR == 0 or mslice.MA == 0: continue d_open = mslice.dopen #if (prev_d < d): # d_open = mslice.open #else: # d_open = dslice.open rng = max(min_rng * d_open, k * mslice.TR) if (d_open <= 0): continue buytrig = d_open + rng selltrig = d_open - rng if mslice.MA > mslice.close: buytrig += f * rng elif mslice.MA < mslice.close: selltrig -= f * rng if (min_id >= config['exit_min']) and (close_daily or (mslice.date == end_d)): if (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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) pos = 0 else: if (pos != 0) and (SL > 0): curr_pos[0].trail_update(mslice.close) if (curr_pos[0].trail_check(mslice.close, SL * mslice.close)): curr_pos[0].close(mslice.close - offset * misc.sign(pos), 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 if (mslice.high >= buytrig) and (pos <= 0): if len(curr_pos) > 0: curr_pos[0].close(mslice.close + 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) new_pos = strat.TradePos([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset, dd) curr_pos.append(new_pos) pos = unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) elif (mslice.low <= selltrig) and (pos >= 0): if len(curr_pos) > 0: curr_pos[0].close(mslice.close - 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) new_pos = strat.TradePos([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close - offset, dd) curr_pos.append(new_pos) pos = -unit mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) mdf.ix[dd, 'pos'] = 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 fisher_swing_sim(df, xdf, config): marginrate = config['marginrate'] offset = config['offset'] win = config['win'] start_equity = config['capital'] tcost = config['trans_cost'] unit = config['unit'] fisher = dh.FISHER(xdf, win[0]) xdf['FISHER_I'] = fisher['FISHER_I'].shift(1) xdf = xdf.join(dh.BBANDS_STOP(xdf, win[1], 1.0).shift(1)) ha_df = dh.HEIKEN_ASHI(xdf, win[2]).shift(1) xdf['HAopen'] = ha_df['HAopen'] xdf['HAclose'] = ha_df['HAclose'] 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 = [] end_d = df.index[-1].date() tradeid = 0 for dd in 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.BBSTOP_lower) or np.isnan( mslice.FISHER_I) or np.isnan(mslice.HAclose): continue end_trading = (min_id >= config['exit_min']) and (d == end_d) stop_loss = (pos > 0) and ((mslice.close < mslice.BBSTOP_lower) or (mslice.FISHER_I < 0)) stop_loss = stop_loss or ((pos < 0) and ((mslice.close > mslice.BBSTOP_upper) or (mslice.FISHER_I > 0))) start_long = (mslice.FISHER_I > 0) and ( mslice.HAclose > mslice.HAopen) and (mslice.BBSTOP_trend > 0) start_short = (mslice.FISHER_I < 0) and ( mslice.HAclose < mslice.HAopen) and (mslice.BBSTOP_trend < 0) if pos != 0: if stop_loss or end_trading: 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 (not end_trading) and (pos == 0): if start_long and start_short: print "warning: get both long and short signal, something is wrong!" print mslice continue pos = (start_long == True) * unit - (start_short == True) * unit if abs(pos) > 0: #target = (start_long == True) * mslice.close +(start_short == True) * mslice.close new_pos = strat.TradePos([mslice.contract], [1], pos, mslice.close, mslice.close) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + misc.sign(pos) * offset, dd) curr_pos.append(new_pos) df.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close * tcost) df.ix[dd, 'pos'] = pos (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 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 dual_thrust_sim(ddf, mdf, config): close_daily = config["close_daily"] marginrate = config["marginrate"] offset = config["offset"] k = config["k"] start_equity = config["capital"] win = config["win"] multiplier = config["m"] tcost = config["trans_cost"] unit = config["unit"] SL = config["stoploss"] min_rng = config["min_range"] no_trade_set = config["no_trade_set"] if win == -1: tr = pd.concat([ddf.high - ddf.low, ddf.close - ddf.close.shift(1)], join="outer", axis=1).max(axis=1).shift(1) elif win == 0: tr = ( pd.concat( [ (pd.rolling_max(ddf.high, 2) - pd.rolling_min(ddf.close, 2)) * multiplier, (pd.rolling_max(ddf.close, 2) - pd.rolling_min(ddf.low, 2)) * multiplier, ddf.high - ddf.close, ddf.close - ddf.low, ], join="outer", axis=1, ) .max(axis=1) .shift(1) ) else: tr = ( pd.concat( [ pd.rolling_max(ddf.high, win) - pd.rolling_min(ddf.close, win), pd.rolling_max(ddf.close, win) - pd.rolling_min(ddf.low, win), ], join="outer", axis=1, ) .max(axis=1) .shift(1) ) ddf["TR"] = tr # ddf['prev_high'] = ddf.high.shift(1) # ddf['prev_low'] = ddf.low.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 = [] closed_trades = [] start_d = ddf.index[0] end_d = mdf.index[-1].date() prev_d = start_d - datetime.timedelta(days=1) tradeid = 0 for dd in mdf.index: mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() dslice = ddf.ix[d] if min_id in no_trade_set or np.isnan(dslice.TR): continue if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, "pos"] = pos d_open = dslice.open if prev_d < d: d_open = mslice.open # d_high = mslice.high # d_low = mslice.low else: d_open = dslice.open # d_high = max(d_high, mslice.high) # d_low = min(d_low, mslice.low) if d_open <= 0: continue prev_d = d buytrig = d_open + max(min_rng * d_open, dslice.TR * k) selltrig = d_open - max(min_rng * d_open, dslice.TR * k) # d_high = max(d_high, dslice.prev_high) # d_low = min(d_low, dslice.prev_low) if min_id >= config["exit_min"]: if (pos != 0) and (close_daily or (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 = [] mdf.ix[dd, "cost"] -= abs(pos) * (offset + mslice.close * tcost) pos = 0 else: if (pos != 0) and (SL > 0): curr_pos[0].trail_update(mslice.close) if curr_pos[0].trail_check(mslice.close, SL * mslice.close): curr_pos[0].close(mslice.close - offset * misc.sign(pos), 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 if (mslice.high >= buytrig) and (pos <= 0): if len(curr_pos) > 0: curr_pos[0].close(mslice.close + 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) new_pos = strat.TradePos([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + offset, dd) curr_pos.append(new_pos) pos = unit mdf.ix[dd, "cost"] -= abs(pos) * (offset + mslice.close * tcost) elif (mslice.low <= selltrig) and (pos >= 0): if len(curr_pos) > 0: curr_pos[0].close(mslice.close - 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) new_pos = strat.TradePos([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close - offset, dd) curr_pos.append(new_pos) pos = -unit mdf.ix[dd, "cost"] -= abs(pos) * (offset + mslice.close * tcost) mdf.ix[dd, "pos"] = 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 chanbreak_sim( mdf, ddf, config): freq = config['freq'] str_freq = str(freq) + 'Min' xdf = dh.conv_ohlc_freq(mdf, str_freq) start_equity = config['capital'] tcost = config['trans_cost'] unit = config['unit'] k = config['scaler'] marginrate = config['marginrate'] offset = config['offset'] win = config['win'] chan_func = config['channel_func'] upper_chan_func = chan_func[0] lower_chan_func = chan_func[1] entry_chan = win exit_chan = int(entry_chan/k[1]) xdf['H1'] = upper_chan_func(xdf, entry_chan).shift(1) xdf['L1'] = lower_chan_func(xdf, entry_chan).shift(1) xdf['H2'] = upper_chan_func(xdf, exit_chan).shift(1) xdf['L2'] = lower_chan_func(xdf, exit_chan).shift(1) ddf['ATR'] = dh.ATR(ddf, entry_chan) 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 = [] end_d = mdf.index[-1].date() tradeid = 0 x_idx = 0 max_idx = len(xdf.index) for idx, dd in enumerate(mdf.index): mslice = mdf.ix[dd] min_id = agent.get_min_id(dd) d = dd.date() dslice = ddf.ix[d] while (x_idx<max_idx-1) and (xdf.index[x_idx + 1] < dd): x_idx += 1 xslice = xdf.iloc[x_idx] if len(curr_pos) == 0: pos = 0 else: pos = curr_pos[0].pos mdf.ix[dd, 'pos'] = pos if np.isnan(dslice.ATR): 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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) continue else: if (pos !=0): curr_pos[0].trail_update(mslice.close) if curr_pos[0].trail_check(mslice.close, dslice.ATR*k[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]) pos = 0 curr_pos = [] if ((mslice.close >= xslice.H2) and (pos<0)) or ((mslice.close <= xslice.L2) 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 = [] mdf.ix[dd, 'cost'] -= abs(pos) * (offset + mslice.close*tcost) pos = 0 if ((mslice.close>=xslice.H1) and (pos<=0)) or ((mslice.close <= xslice.L1) and (pos>=0)): if (pos ==0 ): target_pos = (mslice.close>=xslice.H1) * unit -(mslice.close<=xslice.L1) * unit new_pos = strat.TradePos([mslice.contract], [1], target_pos, mslice.close, mslice.close) tradeid += 1 new_pos.entry_tradeid = tradeid new_pos.open(mslice.close + misc.sign(target_pos)*offset, dd) curr_pos.append(new_pos) mdf.ix[dd, 'cost'] -= abs(target_pos) * (offset + mslice.close*tcost) mdf.ix[dd, 'pos'] = pos else: print "something wrong with position=%s, close =%s, upBnd=%s, lowBnd=%s" % ( pos, mslice.close, xslice.H1, xslice.L1) (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)
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() 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 >=2054): 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 = []