Beispiel #1
0
def simdf_to_trades1(df, slippage=0):
    xdf = df[df['pos'] != df['pos'].shift(1)]
    prev_pos = 0
    tradeid = 0
    pos_list = []
    closed_trades = []
    for o, c, pos, tprice, cont, dtime in zip(xdf['open'], xdf['close'],
                                              xdf['pos'], xdf['traded_price'],
                                              xdf['contract'], xdf.index):
        if (prev_pos * pos >= 0) and (abs(prev_pos) < abs(pos)):
            if len(pos_list) > 0 and (pos_list[-1].pos * (pos - prev_pos) < 0):
                print "Error: the new trade should be on the same direction of the existing trade cont=%s, prev_pos=%s, pos=%s, time=%s" % (
                    cont, prev_pos, pos, dtime)
            new_pos = trade_position.TradePos(insts=[cont],
                                              volumes=[1],
                                              pos=pos - prev_pos,
                                              entry_target=tprice,
                                              exit_target=tprice)
            tradeid += 1
            new_pos.entry_tradeid = tradeid
            new_pos.open(tprice, pos - prev_pos, dtime)
            pos_list.append(new_pos)
        else:
            for i, tp in enumerate(reversed(pos_list)):
                if (prev_pos - tp.pos - pos) * (prev_pos) < 0:
                    break
                else:
                    tp.close(tprice, dtime)
                    prev_pos -= tp.pos
                    tradeid += 1
                    tp.exit_tradeid = tradeid
                    closed_trades.append(tp)
            pos_list = [tp for tp in pos_list if not tp.is_closed]
            if prev_pos != pos:
                if len(pos_list) == 0:
                    new_pos = trade_position.TradePos(insts=[cont],
                                                      volumes=[1],
                                                      pos=pos - prev_pos,
                                                      entry_target=tprice,
                                                      exit_target=tprice)
                    tradeid += 1
                    new_pos.entry_tradeid = tradeid
                    new_pos.open(tprice, pos - prev_pos, dtime)
                    pos_list.append(new_pos)
                else:
                    print "Warning: handling partial position for prev_pos=%s, pos=%s, cont=%s, time=%s, should avoid this situation!" % (
                        prev_pos, pos, cont, dtime)
                    partial_tp = copy.deepcopy(pos_list[-1])
                    partial_tp.pos = prev_pos - pos
                    partial_tp.close(tprice, dtime)
                    tradeid += 1
                    partial_tp.exit_tradeid = tradeid
                    closed_trades.append(partial_tp)
                    pos_list[-1].pos -= prev_pos - pos
        prev_pos = pos
    if (len(pos_list) != 0) or (prev_pos != 0):
        print "ERROR: something wrong with the backtest position management - there are unclosed positions after the test"
    return closed_trades
def dual_thrust_sim( mdf, config):
    ddf = config['ddf']
    close_daily = config['close_daily']
    offset = config['offset']
    k = config['param'][0]
    win = config['param'][1]
    multiplier = config['param'][2]
    f = config['param'][3]
    ep_enabled = config['EP']
    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['MA'] = pd.rolling_mean(ddf.close, chan).shift(1)
    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'] = 0
    mdf['cost'] = 0
    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.loc[dd]
        min_id = mslice.min_id
        d = mslice.date
        dslice = ddf.loc[d]
        if np.isnan(dslice.TR) or (mslice.close == 0):
            continue
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.set_value(dd, 'pos', pos)
        d_open = dslice.open
        if (d_open <= 0):
            continue
        rng = max(min_rng * d_open, k * dslice.TR)
        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)
        prev_d = d
        buytrig  = d_open + rng
        selltrig = d_open - rng
        if dslice.MA > mslice.close:
            buytrig  += f * rng
        elif dslice.MA < mslice.close:
            selltrig -= f * rng
        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.set_value(dd, 'cost', mdf.at[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.set_value(dd, 'cost', mdf.at[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.set_value(dd, 'cost', mdf.at[dd, 'cost'] - abs(pos) * (offset + mslice.close*tcost))
                if mslice.high >= dslice.H1:
                    new_pos = tradepos.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.set_value(dd, 'cost', mdf.at[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.set_value(dd, 'cost', mdf.at[dd, 'cost'] - abs(pos) * (offset + mslice.close*tcost))
                if mslice.low <= dslice.L1:
                    new_pos = tradepos.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.set_value(dd, 'cost', mdf.at[dd, 'cost'] - abs(pos) * (offset + mslice.close*tcost))
        mdf.set_value(dd, 'pos', pos)
    return (mdf, closed_trades)
Beispiel #3
0
def simdf_to_trades2(df, slippage=0.0):
    xdf = df[df['pos'] != df['pos'].shift(1)]
    prev_pos = 0
    tradeid = 0
    pos_list = []
    closed_trades = []
    for pos, tprice, cont, dtime in zip(xdf['pos'], xdf['traded_price'],
                                        xdf['contract'], xdf.index):
        if (prev_pos * pos >= 0) and (abs(prev_pos) < abs(pos)):
            if len(pos_list) > 0 and (pos_list[-1].pos * (pos - prev_pos) < 0):
                print "Error: the new trade should be on the same direction of the existing trade cont=%s, prev_pos=%s, pos=%s, time=%s" % (
                    cont, prev_pos, pos, dtime)
            npos = int(abs(pos - prev_pos))
            new_pos = [
                trade_position.TradePos(insts=[cont],
                                        volumes=[1],
                                        pos=misc.sign(pos - prev_pos),
                                        entry_target=tprice,
                                        exit_target=tprice)
                for i in range(npos)
            ]
            for tpos in new_pos:
                tradeid += 1
                tpos.entry_tradeid = tradeid
                tpos.open(tprice, misc.sign(pos - prev_pos), dtime)
            pos_list = pos_list + new_pos
            new_pos = [
                trade_position.TradePos(insts=[cont],
                                        volumes=[1],
                                        pos=misc.sign(pos - prev_pos),
                                        entry_target=tprice,
                                        exit_target=tprice)
                for i in range(npos)
            ]
            for tpos in new_pos:
                tradeid += 1
                tpos.entry_tradeid = tradeid
                tpos.open(tprice, misc.sign(pos - prev_pos), dtime)
            pos_list = pos_list + new_pos
        else:
            for i, tp in enumerate(reversed(pos_list)):
                if (prev_pos - tp.pos - pos) * (prev_pos) < 0:
                    break
                else:
                    tp.close(tprice, dtime)
                    prev_pos -= tp.pos
                    tradeid += 1
                    tp.exit_tradeid = tradeid
                    closed_trades.append(tp)
            pos_list = [tp for tp in pos_list if not tp.is_closed]
            if prev_pos != pos:
                if len(pos_list) == 0:
                    npos = int(abs(pos - prev_pos))
                    new_pos = [
                        trade_position.TradePos(insts=[cont],
                                                volumes=[1],
                                                pos=misc.sign(pos - prev_pos),
                                                entry_target=tprice,
                                                exit_target=tprice)
                        for i in range(npos)
                    ]
                    for tpos in new_pos:
                        tradeid += 1
                        tpos.entry_tradeid = tradeid
                        tpos.open(tprice, misc.sign(pos - prev_pos), dtime)
                    pos_list = pos_list + new_pos
                else:
                    print "Warning: This should not happen for unit tradepos for prev_pos=%s, pos=%s, cont=%s, time=%s, should avoid this situation!" % (
                        prev_pos, pos, cont, dtime)
        prev_pos = pos
    if (len(pos_list) != 0) or (prev_pos != 0):
        print "ERROR: something wrong with the backtest position management - there are unclosed positions after the test"
    return closed_trades