Example #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 = strat.TradePos([cont], [1], pos - prev_pos, tprice, tprice)
            tradeid += 1
            new_pos.entry_tradeid = tradeid
            new_pos.open(tprice + misc.sign(pos - prev_pos)*slippage, 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 - misc.sign(tp.pos)*slippage, 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 = strat.TradePos([cont], [1], pos - prev_pos, tprice, tprice)
                    tradeid += 1
                    new_pos.entry_tradeid = tradeid
                    new_pos.open(tprice + misc.sign(pos - prev_pos)*slippage, 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 - misc.sign(tp.pos)*slippage, 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
Example #2
0
 def open_tradepos(self, contracts, price, traded_pos):
     tp = price + misc.sign(traded_pos) * self.offset
     new_pos = self.pos_class(insts = contracts, volumes = self.weights, \
                              pos = self.unit * traded_pos, \
                              entry_target = tp, exit_target = tp, \
                              multiple = 1, **self.pos_args)
     new_pos.entry_tradeid = self.tradeid
     self.tradeid += 1
     new_pos.open(tp, self.unit * traded_pos, self.timestamp)
     self.positions.append(new_pos)
     self.traded_price = (self.traded_price * self.traded_vol + tp * new_pos.pos)/(self.traded_vol + new_pos.pos)
     self.traded_vol += new_pos.pos
     self.traded_cost += abs(new_pos.pos) * (self.offset + tp * self.tcost)
Example #3
0
 def open_tradepos(self, contracts, price, traded_pos):
     tp = price + misc.sign(traded_pos) * self.offset
     new_pos = self.pos_class(insts = contracts, volumes = self.weights, \
                              pos = self.unit * traded_pos, \
                              entry_target = tp, exit_target = tp, \
                              multiple = 1, **self.pos_args)
     new_pos.entry_tradeid = self.tradeid
     self.tradeid += 1
     new_pos.open(tp, self.unit * traded_pos, self.timestamp)
     self.positions.append(new_pos)
     self.traded_price = (self.traded_price * self.traded_vol + tp * new_pos.pos)/(self.traded_vol + new_pos.pos)
     self.traded_vol += new_pos.pos
     self.traded_cost += abs(new_pos.pos) * (self.offset + tp * self.tcost)
Example #4
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 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)
            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
Example #5
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
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)
Example #7
0
    def move_to(self, newpos):
        '''
        Arguments:
            newpos: new position vector, the length of this vector sets which
                channels will be used.
        '''

        channels = len(newpos)
        pos = [self._posins.get_position(i) for i in range(channels)]
        stepspos = [0 for i in range(channels)]
        est = []
        for i in range(channels):
            e = PositionEstimator()
            e.add(pos[i], stepspos[i])
            est.append(e)
        delta = [newpos[i] - pos[i] for i in range(channels)]
        dist = [abs(delta[i]) for i in range(channels)]
        hold = [False for i in range(channels)]
        increase_steps = True
        #        print 'move_to(): start pos = %r, delta = %r, dist = %r' % \
        #            (pos, delta, dist)

        steps = [
            -misc.sign(delta[i]) * self._startstep for i in range(channels)
        ]

        j = 0
        while j < 1000:

            # Move
            for i in range(channels):
                if not hold[i]:
                    self._moveins.move_steps(i + self._channel_ofs, steps[i])
                    stepspos[i] += steps[i]
            time.sleep(self._delay)

            # Update position
            pos2 = [self._posins.get_position(i) for i in range(channels)]
            realpos2 = pos2[0]
            delta2 = [newpos[i] - pos2[i] for i in range(channels)]
            dist2 = [abs(delta2[i]) for i in range(channels)]
            for i in range(channels):
                pos2[i] = est[i].add(pos2[i], stepspos[i])
#            print 'move_to(): pos = %r, delta2 = %r' % (pos2, delta2)

# Increase step size exponentially
            if increase_steps:
                for i in range(channels):
                    if not hold[i]:
                        if misc.sign(delta2[i]) != misc.sign(delta[i]):
                            hold[i] = True
                        elif abs(steps[i]) != self._maxstep:
                            steps[i] = misc.sign(delta2[i]) * min(
                                abs(steps[i]) * 2, self._maxstep)
#                            print 'move_to(): increasing stepsize for ch%d to %f' % (i, steps[i])

                if all_true(hold):
                    #                    print 'move_to(): increase_steps=False'
                    increase_steps = False
                    for i in range(channels):
                        hold[i] = False
                        if self._use_reset:
                            est[i].reset()

            # Immediately reverse if we moved too far
            if not increase_steps:
                for i in range(channels):
                    if not hold[i]:
                        if misc.sign(delta2[i]) != misc.sign(delta[i]):
                            if abs(steps[i]) == self._minstep:
                                hold[i] = True
                            else:
                                steps[i] = int(
                                    misc.sign(delta2[i]) *
                                    max(round(abs(steps[i]) / 2),
                                        self._minstep))
                                if self._use_reset:
                                    est[i].reset()


#                                print 'move_to(): reversing and decreasing stepsize for ch%d to %f' % (i, steps[i])

                if all_true(hold):
                    #                    print 'move_to(): Moved to position!'
                    return realpos2

                # Remember relative position
                delta = delta2

            j += 1
Example #8
0
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)
Example #9
0
def layer_sim(mdf, config):
    tcost = config['trans_cost']
    unit = config['unit']
    offset = config['offset']
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    freq = config['freq']
    signal_func = config['signal_func']
    signal_args = config['signal_args']
    signal_level = config['signal_level']
    close_daily = config['close_daily']
    for idx, (f, sfunc, sargs, slvl) in enumerate(
            zip(freq, signal_func, signal_args, signal_level)):
        df = dh.conv_ohlc_freq(mdf, f, extra_cols=['contract'])
        if idx == 0:
            xdf = df
        farg = tuple(sargs)
        func = eval(sfunc[0])
        sigout = func(df, *farg)
        sig_field = sfunc[1] % farg
        signal = sigout[sig_field]
        long_lvl = slvl[0] + slvl[1]
        short_lvl = slvl[0] - slvl[1]
        if idx > 0:
            long_ind = (signal > long_lvl)
            short_ind = (signal < short_lvl)
        else:
            long_ind = (signal > long_lvl) & (signal.shift(1) <= long_lvl)
            short_ind = (signal < short_lvl) & (signal.shift(1) >= short_lvl)
        xdata = pd.concat([signal, long_ind, short_ind],
                          axis=1,
                          keys=[
                              'signal' + str(idx), 'long_ind' + str(idx),
                              'short_ind' + str(idx)
                          ]).shift(1)
        #print xdata
        xdf = xdf.join(xdata, how='left').fillna(method='ffill')
    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
    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.ix[dd]
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        signal_indlist = [
            np.isnan(getattr(mslice, 'signal' + str(i)))
            for i in range(len(freq))
        ]
        long_indlist = [
            getattr(mslice, 'long_ind' + str(i)) for i in range(len(freq))
        ]
        short_indlist = [
            getattr(mslice, 'short_ind' + str(i)) for i in range(len(freq))
        ]
        if True in signal_indlist:
            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 (pos != 0):
                direction = 0
                long_ind = (True in long_indlist)
                short_ind = (True in short_indlist)
                if ((pos < 0) and long_ind) or ((pos > 0) and short_ind):
                    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
            long_ind = (False not in long_indlist)
            short_ind = (False not in short_indlist)
            if (long_ind or short_ind) and (pos == 0):
                target_pos = long_ind * unit - short_ind * 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)
                #print dd, target_pos, len(curr_pos), curr_pos[0].pos, curr_pos #[getattr(mslice, 'long_ind' + str(i)) for i in range(len(freq))]
                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)
Example #10
0
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 = 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.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 = 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.set_value(
                        dd, 'cost', mdf.at[dd, 'cost'] - abs(pos) *
                        (offset + mslice.close * tcost))
        mdf.set_value(dd, 'pos', pos)
    return (mdf, closed_trades)
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 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)
Example #13
0
def MA_sim(mdf, config):
    offset = config['offset']
    use_chan = config['use_chan']
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    pos_update = config.get('pos_update', False)
    stoploss = config.get('stoploss', 0.0)
    win_list = config['param']
    MA_func = eval(config['MA_func'])
    close_daily = config['close_daily']
    tcost = config['trans_cost']
    unit = config['unit']
    freq = config['freq']
    chan_ratio = config['channel_ratio']
    channel = int(chan_ratio * win_list[-1])
    xdf = dh.conv_ohlc_freq(mdf, freq, extra_cols=['contract'])
    for idx, win in enumerate(win_list):
        xdf['MA' + str(idx)] = MA_func(xdf, win).shift(1)
    if use_chan:
        xdf['chan_high'] = eval(config['channel_func'][0])(
            xdf, channel, **config['channel_args'][0]).shift(2)
        xdf['chan_low'] = eval(config['channel_func'][1])(
            xdf, channel, **config['channel_args'][1]).shift(2)
    else:
        xdf['chan_high'] = pd.Series(index=xdf.index)
        xdf['chan_low'] = pd.Series(index=xdf.index)
    tot_MA = len(win_list)
    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]
        ma_list = [
            getattr(mslice, 'MA' + str(i)) for i in range(len(win_list))
        ]
        ma_short = ma_list[0]
        ma_last = ma_list[-1]
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        xdf.set_value(dd, 'pos', pos)
        if np.isnan(getattr(mslice, "MA" + str(tot_MA - 1))):
            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 (((ma_short >= ma_last) or
                 (mslice.open >= mslice.chan_high)) and
                (pos < 0)) or (((ma_short <= ma_last) or
                                (mslice.open <= mslice.chan_low)) 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 (((ma_short >= ma_list[1]) and (ma_short >= ma_last) and ((use_chan == False) or (mslice.open>=mslice.chan_high))) or \
                        ((ma_short <= ma_list[1]) and (ma_short <= ma_last) and ((use_chan == False) or (mslice.open<=mslice.chan_low)))) and (pos==0):
                target_pos = ((ma_short >= ma_list[1]) and (ma_short >= ma_last) and ((use_chan == False) or (mslice.open>=mslice.chan_high))) * unit \
                             - ((ma_short <= ma_list[1]) and (ma_short <= ma_last) and ((use_chan == False) or (mslice.open<=mslice.chan_low))) * 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)
Example #14
0
def rbreaker_sim( mdf, config):
    if 'ddf' in config:
        ddf = config['ddf']
    else:
        freq = config['freq']
        ddf = dh.conv_ohlc_freq(mdf, freq)
    start_equity = config['capital']
    tcost = config['trans_cost']
    unit = config['unit']
    pos_class = config['pos_class']
    pos_args  = config['pos_args']
    close_daily = config['close_daily']
    marginrate = config['marginrate']
    offset = config['offset']
    min_rng = config['min_rng']
    k = config['params']
    a = k[0]
    b = k[1]
    c = k[2]
    ddf['range'] = ddf.high - ddf.low
    ddf['ssetup'] = ddf.high + a*(ddf.close - ddf.low)
    ddf['bsetup'] = ddf.low  - a*(ddf.high - ddf.close)
    ddf['senter'] = (1+b)*(ddf.high+ddf.close)/2.0 - b * ddf.low
    ddf['benter'] = (1+b)*(ddf.low+ddf.close)/2.0 - b * ddf.high
    ddf['bbreak'] = ddf.ssetup + c * (ddf.ssetup - ddf.bsetup)
    ddf['sbreak'] = ddf.bsetup - c * (ddf.ssetup - ddf.bsetup)
    ddf = ddf.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 = mdf.index[0].date()
    end_d = mdf.index[-1].date()
    prev_d = start_d - datetime.timedelta(days=1)
    tradeid = 0
    cur_high = 0
    cur_low = 0
    rev_flag = True
    dslice = None
    num_trades = 0
    for dd in mdf.index:
        mslice = mdf.ix[dd]
        min_id = mslice.min_id
        d = mslice.date
        if (prev_d < d):
            num_trades = 0
            cur_high = mslice.high
            cur_low = mslice.low
            if d not in ddf.index:
                print d, dd
                continue
            else:
                dslice = ddf.ix[d]
            if np.isnan(dslice.bbreak):
                continue
            if dslice.range < min_rng * dslice.close:
                rev_flag = False
            else:
                rev_flag = True
            prev_d = d
        else:
            cur_high = max(cur_high, mslice.high)
            cur_low = min(cur_low, mslice.low)
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[dd, 'pos'] = pos
        if (min_id <= config['start_min']):
            continue
        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 num_trades >=3:
                continue
            if ((mslice.high >= dslice.bbreak) and (pos <= 0)) or ((mslice.low <= dslice.sbreak) and (pos >= 0)):
                rev_flag = False
                if (mslice.close >= dslice.bbreak):
                    direction = 1
                else:
                    direction = -1
                if pos != 0:
                    curr_pos[0].close(mslice.close + direction*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 = pos_class([mslice.contract], [1], unit*direction, mslice.close, 0, **pos_args)
                tradeid += 1
                new_pos.entry_tradeid = tradeid
                new_pos.open(mslice.close + offset*direction, dd)
                curr_pos.append(new_pos)
                pos = unit*direction
                mdf.ix[dd, 'cost'] -=  abs(direction) * (offset + mslice.close*tcost)
                num_trades += 1
            elif rev_flag and (((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 = pos_class([mslice.contract], [1], -unit*misc.sign(pos), mslice.close, 0, **pos_args)
                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
        mdf.ix[dd, 'pos'] = pos
    return (mdf, closed_trades)
Example #15
0
    def _derivative(self):
        a = self.a
        x = self.x
        u = self.u
        HEB = transformation(x[9],x[10],x[11])
        gb = HEB*matrix([[0.0],[0.0],[9.80665]])
        Va = [x[0],x[1],x[2]]
        V = sqrt(Va[0]**2+Va[1]**2+Va[2]**2)
        alpha = arctan(Va[2] / Va[0])
        beta = arcsin(Va[1] / V)
        T,P = atmosphere(-x[5])
        R = 287.0
        rho = P/R/T
        qbar = .5*rho*V*V
        qbarS = qbar*a.S
        a._calc(Va, x, u)
        CL = a.CL
        CD = a.CD
        CY = a.CY
        Cl = a.Cl
        Cm = a.Cm
        Cn = a.Cn
        thrust = a.thrust 
        Ixx = a.Ixx
        Iyy = a.Iyy
        Izz = a.Izz
        Ixz = a.Ixz

        CX = -CD*cos(alpha) + CL*sin(alpha)
        CZ = -CD*sin(alpha) - CL*cos(alpha)
       
        Xb = (CX*qbarS + thrust)/a.m
        Yb = CY*qbarS/a.m
        Zb = CZ*qbarS/a.m
        Lb = Cl*qbarS*a.b
        Mb = Cm*qbarS*a.c
        Nb = Cn*qbarS*a.b
        nz = -Zb/9.80665
        
        xd0 = Xb + float(gb[0]) + x[8]*x[1] - x[7]*x[2];

	xd1 = Yb + float(gb[1]) - x[8]*x[0] + x[6]*x[2];
	xd2 = Zb + float(gb[2]) + x[7]*x[0] - x[6]*x[1];
	
	y = HEB.transpose()*matrix([[x[0]],[x[1]],[x[2]]])
	xd3 = float(y[0]);
	xd4 = float(y[1]);
	xd5 = float(y[2]);
	
	xd6 = (Izz*Lb + Ixz*Nb - (Ixz*(Iyy - Ixx - Izz)*x[6]+\
                                      (Ixz**2 + Izz*(Izz - Iyy))*x[8]) * x[7]) / (Ixx*Izz - Ixz**2);
	xd7 = 	(Mb - (Ixx - Izz) * x[6] * x[8] - Ixz * (x[6]**2 - x[8]**2)) / Iyy;
	xd8 =	(Ixz*Lb + Ixx*Nb + (Ixz*(Iyy - Ixx - Izz)*x[8] + \
                                        (Ixz**2 + Ixx*(Ixx - Iyy))*x[6])*x[7])/(Ixx*Izz - Ixz**2);

	cosPitch = cos(x[10]);
	if abs(cosPitch) <= 0.00001:
            cosPitch = 0.00001 * sign(cosPitch)
	
	tanPitch	=	sin(x[10]) / cosPitch;
        
	xd9	=	x[6] + (sin(x[9]) * x[7] + cos(x[9]) * x[8]) * tanPitch;
	xd10	=	cos(x[9]) * x[7] - sin(x[9]) * x[8];
	xd11	=	(sin(x[9]) * x[7] + cos(x[9]) * x[8]) / cosPitch;
	
	return array([xd0,xd1,xd2,xd3,xd4,xd5,xd6,xd7,xd8,xd9,xd10,xd11]);
Example #16
0
def ttl_soup_sim(mdf, config):
    close_daily = config['close_daily']
    marginrate = config['marginrate']
    offset = config['offset']
    pos_update = config['pos_update']
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    proc_func = config['proc_func']
    proc_args = config['proc_args']
    start_equity = config['capital']
    tcost = config['trans_cost']
    unit = config['unit']
    SL = config['stoploss']
    chan = config['chan']
    exit_ratio = config['exit_ratio']
    exit_chan = int(chan * exit_ratio)
    gap_win = config['gap_win']
    no_trade_set = config['no_trade_set']
    ll = mdf.shape[0]
    xdf = proc_func(mdf, **proc_args)
    donch_data = dh.DONCH_IDX(xdf, chan)
    hh_str = 'DONCH_H%s' % str(chan)
    hidx_str = 'DONIDX_H%s' % str(chan)
    ll_str = 'DONCH_L%s' % str(chan)
    lidx_str = 'DONIDX_L%s' % str(chan)
    xdf['exit_hh'] = pd.rolling_max(xdf.high, exit_chan)
    xdf['exit_ll'] = pd.rolling_min(xdf.low, exit_chan)
    xdf['ssetup'] = (xdf['close'] >= donch_data[hh_str].shift(1)) & (
        donch_data[hidx_str] >= gap_win)
    xdf['bsetup'] = (xdf['close'] <= donch_data[ll_str].shift(1)) & (
        donch_data[lidx_str] >= gap_win)
    atr = dh.ATR(xdf, chan)
    donch_data['prevhh'] = donch_data[hh_str].shift(1)
    donch_data['prevll'] = donch_data[ll_str].shift(1)
    xdata = pd.concat([
        donch_data[hidx_str], donch_data[hh_str], donch_data[lidx_str],
        donch_data[ll_str], xdf['ssetup'], xdf['bsetup'], atr,
        donch_data[hh_str].shift(1), donch_data[ll_str].shift(1)
    ],
                      axis=1,
                      keys=[
                          'hh_idx', 'hh', 'll_idx', 'll', 'ssetup', 'bsetup',
                          'ATR', 'prev_hh', 'prev_ll'
                      ]).fillna(0)
    xdata = xdata.shift(1)
    mdf = mdf.join(xdata, 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 = []
    end_d = mdf.index[-1].date
    #prev_d = start_d - datetime.timedelta(days=1)
    tradeid = 0
    for idx, dd in enumerate(mdf.index):
        mslice = mdf.ix[dd]
        min_id = mslice.min_id
        min_cnt = (min_id - 300) / 100 * 60 + min_id % 100 + 1
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[dd, 'pos'] = pos
        if (mslice.prev_hh == 0):
            continue
        if (min_id >= config['exit_min']) and (close_daily or
                                               (mslice.datetime.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
        elif min_id not in no_trade_set:
            if (pos != 0):
                exit_flag = False
                if ((pos > 0) and (mslice.close <= mslice.exit_ll)) or (
                    (pos < 0) and (mslice.close >= mslice.exit_hh)):
                    exit_flag = True
                if exit_flag or curr_pos[0].check_exit(mslice.close, 0):
                    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
                elif pos_update and (min_cnt % config['pos_freq'] == 0):
                    curr_pos[0].update_price(mslice.close)
            if mslice.bsetup and (pos
                                  == 0) and (mslice.close >= mslice.prev_ll):
                new_pos = pos_class([mslice.contract], [1], unit,
                                    mslice.close + offset, mslice.low,
                                    **pos_args)
                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.ssetup and (pos
                                    == 0) and mslice.close <= mslice.prev_hh:
                new_pos = pos_class([mslice.contract], [1], -unit,
                                    mslice.close - offset, mslice.high,
                                    **pos_args)
                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)
Example #17
0
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)
Example #19
0
def dual_thrust_sim( mdf, config):
    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]
    pos_update = config['pos_update']
    pos_class = config['pos_class']
    pos_args  = config['pos_args']
    proc_func = config['proc_func']
    proc_args = config['proc_args']
    start_equity = config['capital']
    chan_func = config['chan_func']
    chan_high = eval(chan_func['high']['func'])
    chan_low  = eval(chan_func['low']['func'])
    tcost = config['trans_cost']
    unit = config['unit']
    SL = config['stoploss']
    min_rng = config['min_range']
    chan = config['chan']
    use_chan = config['use_chan']
    no_trade_set = config['no_trade_set']
    ll = mdf.shape[0]
    xdf = proc_func(mdf, **proc_args)
    if win == -1:
        tr= pd.concat([xdf.high - xdf.low, abs(xdf.close - xdf.close.shift(1))], 
                       join='outer', axis=1).max(axis=1)
    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)
    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)
    xdf['TR'] = tr
    xdf['chan_h'] = chan_high(xdf, chan, **chan_func['high']['args'])
    xdf['chan_l'] = chan_low(xdf, chan, **chan_func['low']['args'])
    xdf['MA'] = pd.rolling_mean(xdf.close, chan)
    xdata = pd.concat([xdf['TR'].shift(1), xdf['MA'].shift(1),
                       xdf['chan_h'].shift(1), xdf['chan_l'].shift(1),
                       xdf['open']], axis=1, keys=['TR','MA', 'chanH', 'chanL', 'dopen']).fillna(0)
    mdf = mdf.join(xdata, 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 = []
    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 = mslice.min_id
        min_cnt = (min_id-300)/100 * 60 + min_id % 100 + 1
        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
        rng = max(min_rng * d_open, k * mslice.TR)
        if (d_open <= 0):
            continue
        buytrig  = d_open + rng
        selltrig = d_open - rng
        if 'reset_margin' in pos_args:
            pos_args['reset_margin'] = mslice.TR * SL
        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
        elif min_id not in no_trade_set:
            if (pos!=0) and pos_update:
                curr_pos[0].update_price(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 (use_chan == False) or (mslice.high > mslice.chanH):
                    new_pos = pos_class([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset, **pos_args)
                    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 (use_chan == False) or (mslice.low < mslice.chanL):
                    new_pos = pos_class([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset, **pos_args)
                    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)
Example #20
0
def ttl_soup_sim( mdf, config):
    close_daily = config['close_daily']
    marginrate = config['marginrate']
    offset = config['offset']
    pos_update = config['pos_update']
    pos_class = config['pos_class']
    pos_args  = config['pos_args']
    proc_func = config['proc_func']
    proc_args = config['proc_args']
    start_equity = config['capital']
    tcost = config['trans_cost']
    unit = config['unit']
    SL = config['stoploss']
    chan = config['chan']
    exit_ratio = config['exit_ratio']
    exit_chan = int(chan * exit_ratio)
    gap_win = config['gap_win']
    no_trade_set = config['no_trade_set']
    ll = mdf.shape[0]
    xdf = proc_func(mdf, **proc_args)
    donch_data = dh.DONCH_IDX(xdf, chan)
    hh_str = 'DONCH_H%s' % str(chan)
    hidx_str = 'DONIDX_H%s' % str(chan)
    ll_str = 'DONCH_L%s' % str(chan)
    lidx_str = 'DONIDX_L%s' % str(chan)
    xdf['exit_hh'] = pd.rolling_max(xdf.high, exit_chan)
    xdf['exit_ll'] = pd.rolling_min(xdf.low, exit_chan)
    xdf['ssetup'] = (xdf['close'] >= donch_data[hh_str].shift(1)) & (donch_data[hidx_str]>=gap_win)
    xdf['bsetup'] = (xdf['close'] <= donch_data[ll_str].shift(1)) & (donch_data[lidx_str]>=gap_win)
    atr = dh.ATR(xdf, chan)
    donch_data['prevhh'] = donch_data[hh_str].shift(1)
    donch_data['prevll'] = donch_data[ll_str].shift(1)
    xdata = pd.concat([donch_data[hidx_str], donch_data[hh_str],
                       donch_data[lidx_str], donch_data[ll_str],
                       xdf['ssetup'], xdf['bsetup'],atr,
                       donch_data[hh_str].shift(1), donch_data[ll_str].shift(1)],
                       axis=1, keys=['hh_idx', 'hh', 'll_idx', 'll', 'ssetup', 'bsetup', 'ATR', 'prev_hh', 'prev_ll']).fillna(0)
    xdata = xdata.shift(1)
    mdf = mdf.join(xdata, 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 = []
    end_d = mdf.index[-1].date
    #prev_d = start_d - datetime.timedelta(days=1)
    tradeid = 0
    for idx, dd in enumerate(mdf.index):
        mslice = mdf.ix[dd]
        min_id = mslice.min_id
        min_cnt = (min_id-300)/100 * 60 + min_id % 100 + 1
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[dd, 'pos'] = pos
        if (mslice.prev_hh == 0):
            continue
        if (min_id >= config['exit_min']) and (close_daily or (mslice.datetime.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
        elif min_id not in no_trade_set:
            if (pos!=0):
                exit_flag = False
                if ((pos > 0) and (mslice.close <= mslice.exit_ll)) or ((pos < 0) and (mslice.close >= mslice.exit_hh)):
                    exit_flag = True
                if exit_flag or curr_pos[0].check_exit( mslice.close, 0):
                    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
                elif pos_update and (min_cnt % config['pos_freq'] == 0):
                    curr_pos[0].update_price(mslice.close)
            if mslice.bsetup and (pos == 0) and (mslice.close>=mslice.prev_ll):
                new_pos = pos_class([mslice.contract], [1], unit, mslice.close + offset, mslice.low, **pos_args)
                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.ssetup and (pos == 0) and mslice.close<=mslice.prev_hh:
                new_pos = pos_class([mslice.contract], [1], -unit, mslice.close - offset, mslice.high, **pos_args)
                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)
Example #21
0
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)
Example #22
0
def dual_thrust_sim(mdf, config):
    (pos_class, pos_args) = config['pos_param']
    update_freq = config.get('update_freq', 0)
    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]
    chan = config['chan']
    chan_func = config['chan_func']
    use_chan = config['use_chan']
    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['ATR'] = dh.ATR(ddf, win)
    if use_chan:
        ddf['CH_H'] = eval(chan_func['high']['func'])(
            ddf, chan, **chan_func['high']['args']).shift(1)
        ddf['CH_L'] = eval(chan_func['low']['func'])(
            ddf, chan, **chan_func['low']['args']).shift(1)
    if update_freq > 1:
        xdf = dh.conv_ohlc_freq(mdf, str(update_freq) + 'Min')
    else:
        xdf = mdf
    xdata = pd.concat([xdf['open'], xdf['high'], xdf['low'], xdf['close']],
                      axis=1,
                      keys=['xopen', 'xhigh', 'xlow', 'xclose'])
    mdf = mdf.join(xdata, how='left').fillna(method='ffill')
    ll = mdf.shape[0]
    mdf['pos'] = 0
    mdf['cost'] = 0
    start_d = ddf.index[0]
    end_d = mdf.index[-1].date()
    prev_d = start_d - datetime.timedelta(days=1)
    curr_pos = []
    closed_trades = []
    tradeid = 0
    for idx, dd in enumerate(mdf.index):
        mslice = mdf.ix[dd]
        min_id = mslice.min_id
        d = mslice.date
        dslice = ddf.ix[d]
        if np.isnan(dslice.TR) or (mslice.close == 0):
            continue
        if use_chan and np.isnan(dslice.CH_H):
            continue
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[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
        else:
            d_open = dslice.open
        prev_d = d
        buytrig = d_open + rng
        selltrig = d_open - rng
        stoploss = SL * dslice.ATR
        tmp_args = pos_args.copy()
        if 'reset_margin' in pos_args:
            tmp_args['reset_margin'] = dslice.ATR * pos_args['reset_margin']
            stoploss = tmp_args['reset_margin'] * stoploss
        close_pos = False
        if pos != 0:
            if ((pos > 0) and
                (mslice.high < buytrig)) or ((pos < 0) and
                                             (mslice.low > selltrig)):
                close_pos = curr_pos[0].check_exit(mslice.close, stoploss)
            if (close_pos == False) and (update_freq > 0) and (
                (mslice.min_id + 1) % update_freq == 0):
                xslice = conv_xslice(mslice)
                curr_pos[0].update_bar(xslice)
            if close_pos or ((mslice.min_id >= config['exit_min']) 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
        if mslice.min_id < config['exit_min']:
            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 (use_chan == False) or (use_chan and
                                           (mslice.high >= dslice.CH_H)):
                    new_pos = eval(pos_class)([mslice.contract], [1], unit,
                                              mslice.close + offset,
                                              mslice.close + offset,
                                              **tmp_args)
                    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 (use_chan == False) or (use_chan and
                                           (mslice.low <= dslice.CH_L)):
                    new_pos = eval(pos_class)([mslice.contract], [1], -unit,
                                              mslice.close - offset,
                                              mslice.close - offset,
                                              **tmp_args)
                    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
    return (mdf, closed_trades)
def layer_sim( mdf, config):
    tcost = config['trans_cost']
    unit = config['unit']
    offset = config['offset']
    pos_class = config['pos_class']
    pos_args  = config['pos_args']    
    freq = config['freq']
    signal_func = config['signal_func']
    signal_args = config['signal_args']
    signal_level = config['signal_level']
    close_daily = config['close_daily']
    for idx, (f, sfunc, sargs, slvl)  in enumerate(zip(freq, signal_func, signal_args, signal_level)):
        df = dh.conv_ohlc_freq(mdf, f, extra_cols=['contract'])
        if idx == 0:
            xdf = df
        farg = tuple(sargs)
        func = eval(sfunc[0])
        sigout = func(df, *farg)
        sig_field = sfunc[1] % farg
        signal = sigout[sig_field]
        long_lvl  = slvl[0] + slvl[1]
        short_lvl = slvl[0] - slvl[1]
        if idx > 0:
            long_ind = (signal > long_lvl)
            short_ind = (signal < short_lvl)
        else:
            long_ind = (signal > long_lvl) & (signal.shift(1) <= long_lvl)
            short_ind = (signal < short_lvl) & (signal.shift(1) >= short_lvl)
        xdata = pd.concat([signal, long_ind, short_ind], axis = 1, keys = ['signal'+str(idx), 'long_ind'+str(idx), 'short_ind'+str(idx)]).shift(1)
        #print xdata
        xdf = xdf.join(xdata, how = 'left').fillna(method='ffill')
    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        
    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.ix[dd]
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        signal_indlist = [np.isnan(getattr(mslice, 'signal' + str(i))) for i in range(len(freq))]
        long_indlist = [getattr(mslice, 'long_ind' + str(i)) for i in range(len(freq))]
        short_indlist = [ getattr(mslice, 'short_ind'+str(i)) for i in range(len(freq))]
        if True in signal_indlist:
            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 (pos !=0):
                direction = 0
                long_ind = (True in long_indlist)
                short_ind = (True in short_indlist)
                if ((pos < 0) and long_ind) or ((pos > 0) and short_ind):
                    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                
            long_ind = (False not in long_indlist)
            short_ind = (False not in short_indlist)
            if (long_ind or short_ind) and (pos == 0):
                target_pos = long_ind * unit - short_ind * 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)
                #print dd, target_pos, len(curr_pos), curr_pos[0].pos, curr_pos #[getattr(mslice, 'long_ind' + str(i)) for i in range(len(freq))]
                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)
Example #24
0
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)
Example #25
0
def fisher_swing_sim(mdf, config):
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    pos_update = config.get('pos_update', False)
    offset = config['offset']
    close_daily = config['close_daily']
    tcost = config['trans_cost']
    unit = config['unit']
    freq = config['freq']
    param = config['param']
    fisher_n = param[0]
    bband_n = param[1]
    bband_std = param[2]
    heiken_n = param[3]
    xdf = dh.conv_ohlc_freq(mdf, freq, extra_cols=['contract'])
    fisher = dh.FISHER(xdf, win[0])
    xdf['FISHER_I'] = fisher['FISHER_I'].shift(1)
    bbands_stop = dh.BBANDS_STOP(xdf, win[1], 1.0)
    xdf['BBSTOP_upper'] = bbands_stop['BBSTOP_upper'].shift(1)
    xdf['BBSTOP_lower'] = bbands_stop['BBSTOP_lower'].shift(1)
    xdf['BBSTOP_trend'] = bbands_stop['BBSTOP_trend'].shift(1)
    ha_df = dh.HEIKEN_ASHI(xdf, win[2]).shift(1)
    xdf['HAopen'] = ha_df['HAopen'].shift(1)
    xdf['HAclose'] = ha_df['HAclose'].shift(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
    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]
        min_id = mslice.min_id
        d = dd.date()
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        xdf.set_value(dd, 'pos', pos)
        if np.isnan(mslice.BBSTOP_lower) or np.isnan(
                mslice.FISHER_I) or np.isnan(mslice.HAclose):
            continue
        stop_loss = (pos > 0) and ((mslice.open < mslice.BBSTOP_lower) or
                                   (mslice.FISHER_I < 0))
        stop_loss = stop_loss or ((pos < 0) and
                                  ((mslice.open > 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 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 stop_loss:
                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
            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 = pos_class([mslice.contract], [1], pos, mslice.open,
                                    mslice.open, **pos_args)
                tradeid += 1
                new_pos.entry_tradeid = tradeid
                new_pos.open(mslice.open + misc.sign(pos) * offset, dd)
                curr_pos.append(new_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)
        xdf.ix[dd, 'pos'] = pos
    return (xdf, closed_trades)
Example #26
0
def run_sim(config):
    mdf = config['mdf']
    close_daily = config['close_daily']
    offset = config['offset']
    k = config['param'][0]
    win = config['param'][1]
    multiplier = config['param'][2]
    f = config['param'][3]
    price_mode = config.get('price_mode', 'TP')
    pos_update = config['pos_update']
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    proc_func = config['proc_func']
    proc_args = config['proc_args']
    chan_func = config['chan_func']
    chan_high = eval(chan_func['high']['func'])
    chan_low = eval(chan_func['low']['func'])
    tcost = config['trans_cost']
    unit = config['unit']
    SL = config['stoploss']
    min_rng = config['min_range']
    chan = config['chan']
    use_chan = config['use_chan']
    no_trade_set = config['no_trade_set']
    pos_freq = config.get('pos_freq', 1)
    xdf = proc_func(mdf, **proc_args)
    if win == -1:
        tr = pd.concat(
            [xdf.high - xdf.low,
             abs(xdf.close - xdf.close.shift(1))],
            join='outer',
            axis=1).max(axis=1)
    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)
    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)
    xdf['TR'] = tr
    xdf['chan_h'] = chan_high(xdf['high'], chan, **chan_func['high']['args'])
    xdf['chan_l'] = chan_low(xdf['low'], chan, **chan_func['low']['args'])
    xdata = pd.concat([
        xdf['TR'].shift(1), xdf['MA'].shift(1), xdf['chan_h'].shift(1),
        xdf['chan_l'].shift(1), xdf['open']
    ],
                      axis=1,
                      keys=['tr', 'ma', 'chanh', 'chanl', 'dopen']).fillna(0)
    df = mdf.join(xdata, how='left').fillna(method='ffill')
    df['pos'] = 0
    df['cost'] = 0
    df['traded_price'] = df['open']
    sim_data = dh.DynamicRecArray(dataframe=df)
    nlen = len(sim_data)
    positions = []
    closed_trades = []
    tradeid = 0
    curr_date = None
    buytrig = selltrig = 0.0
    for n in range(nlen - 3):
        cost = 0
        pos = sim_data['pos'][n]
        if sim_data['ma'][n] == 0 or sim_data['chan_h'][n] == 0 or sim_data[
                'dopen'][n] == 0:
            continue
        if curr_date != sim_data['date'][n]:
            curr_date = sim_data['date'][n]
            dopen = sim_data['dopen'][n]
            rng = max(min_rng * dopen, k * sim_data['tr'][n])
            buytrig = dopen + rng
            selltrig = dopen - rng
            if sim_data['ma'][n] > dopen:
                buytrig += f * rng
            else:
                selltrig -= f * rng
            continue
        if price_mode == 'TP':
            ref_long = ref_short = (sim_data['close'][n] + sim_data['high'][n]
                                    + sim_data['low'][n]) / 3.0
        elif price_mode == 'HL':
            ref_long = sim_data['high'][n]
            ref_short = sim_data['low'][n]
        elif price_mode == 'CL':
            ref_long = ref_short = sim_data['close'][n]
        else:
            ref_long = ref_short = sim_data['open'][n + 1]
        target_pos = (ref_long > buytrig) - (ref_short < selltrig)
        if len(positions) > 0:
            need_close = (close_daily or
                          (curr_date == sim_data['date'][-1])) and (
                              sim_data['min_id'][n] >= config['exit_min'])
            for tradepos in positions:
                ep = sim_data['low'][n] if tradepos.pos > 0 else sim_data[
                    'high'][n]
                if need_close or tradepos.check_exit(
                        sim_data['open'][n + 1],
                        0) or (tradepos.pos * target_pos < 0):
                    tradepos.close(
                        sim_data['open'][n + 1] -
                        offset * misc.sign(tradepos.pos),
                        sim_data['datetime'][n + 1])
                    tradepos.exit_tradeid = tradeid
                    tradeid += 1
                    pos -= tradepos.pos
                    cost += abs(tradepos.pos) * (
                        offset + sim_data['open'][n + 1] * tcost)
                    closed_trades.append(tradepos)
                elif pos_update:
                    tradepos.update_price(ep)
            positions = [pos for pos in positions if not pos.is_closed]
            if need_close:
                continue
        if target_pos != 0:
            if (not use_chan) or (
                ((ref_long > sim_data['chanh'][n]) and target_pos > 0) or
                ((ref_short < sim_data['chanl'][n]) and target_pos < 0)):
                new_pos = pos_class(
                    [sim_data['contract'][n]], [1], unit * target_pos,
                    sim_data['open'][n + 1] + target_pos * offset, buytrig,
                    **pos_args)
                tradeid += 1
                new_pos.entry_tradeid = tradeid
                new_pos.open(sim_data['open'][n + 1] + target_pos * offset,
                             sim_data['datetime'][n + 1])
                positions.append(new_pos)
                pos += unit * target_pos
                cost += abs(target_pos) * (offset +
                                           sim_data['open'][n + 1] * tcost)
        sim_data['cost'][n + 1] = cost
        sim_data['pos'][n + 1] = pos
    out_df = pd.concat([])
    return out_df, 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)
Example #28
0
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)
Example #29
0
def asctrend_sim(mdf, config):
    offset = config['offset']
    tcost = config['trans_cost']
    unit = config['unit']
    stoploss = config['stoploss']
    bar_func = config.get('bar_conv_func', 'dh.bar_conv_func2')
    param = config['param']
    freq = config['freq']
    pos_update = config.get('pos_update', False)
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    close_daily = config['close_daily']
    xdf = dh.conv_ohlc_freq(mdf,
                            freq,
                            extra_cols=['contract'],
                            bar_func=eval(bar_func))
    asc_period = param[0]
    asc_risk = param[1]
    rsi_sig = config['rsi_sig']
    asctrend = dh.ASCTREND(xdf, asc_period, risk=asc_risk)
    xdf['asc_signal'] = asctrend["ASCSIG_%s" % str(asc_period)].shift(1)
    xdf['asc_stop'] = asctrend["ASCSTOP_%s" % str(asc_period)].shift(1)
    rsi_period = param[2]
    rsi_offset = param[3]
    rsi_buy = 50 + rsi_offset
    rsi_sell = 50 - rsi_offset
    rsi = dh.RSI(xdf, n=rsi_period)
    rsi_signal = pd.Series(0, index=rsi.index)
    if rsi_sig:
        rsi_signal[(rsi >= rsi_buy) & (rsi.shift(1) < rsi_buy)] = 1
        rsi_signal[(rsi <= rsi_sell) & (rsi.shift(1) > rsi_sell)] = -1
    else:
        rsi_signal[(rsi >= rsi_buy)] = 1
        rsi_signal[(rsi <= rsi_sell)] = -1
    xdf['rsi_signal'] = rsi_signal.shift(1)
    if len(param) > 4:
        sar_step = param[4]
        sar_max = param[5]
    else:
        sar_step = 0.005
        sar_max = 0.02
    sar = dh.SAR(xdf, incr=sar_step, maxaf=sar_max)
    sar_signal = pd.Series(0, index=sar.index)
    sar_signal[(sar < xdf['close'])] = 1
    sar_signal[(sar > xdf['close'])] = -1
    xdf['sar_signal'] = sar_signal.shift(1)
    xdf['sar_stop'] = sar.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
    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.sar_stop) or np.isnan(mslice.asc_stop):
            continue
        buy_trig = (mslice.asc_signal > 0) and (mslice.rsi_signal >
                                                0) and (mslice.sar_signal > 0)
        sell_trig = (mslice.asc_signal < 0) and (mslice.rsi_signal <
                                                 0) and (mslice.sar_signal < 0)
        buy_close = (mslice.asc_signal < 0) or (mslice.rsi_signal < 0)
        sell_close = (mslice.asc_signal > 0) or (mslice.rsi_signal > 0)
        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 pos_update and pos != 0:
                curr_pos[0].update_price(mslice.asc_stop)
                pos_close = curr_pos[0].check_exit(mslice.open, 0)
            else:
                pos_close = False
            if (buy_close and (pos > 0)) or (sell_close and
                                             (pos < 0)) or pos_close:
                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 (buy_trig or sell_trig) and (pos == 0):
                target_pos = buy_trig * unit - sell_trig * unit
                new_pos = pos_class([mslice.contract], [1], target_pos,
                                    mslice.open, mslice.asc_stop, **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)
Example #30
0
def psar_chan_sim(mdf, config):
    marginrate = config['marginrate']
    offset = config['offset']
    tcost = config['trans_cost']
    unit = config['unit']
    stoploss = config['stoploss']
    bar_func = config.get('bar_conv_func', 'dh.bar_conv_func2')
    param = config['param']
    freq = config['freq']
    use_HL = config.get('use_HL', False)
    use_chan = config['use_chan']
    chan_func = config['chan_func']
    chan_args = config['chan_args']
    chan = param[0]
    sar_param = param[1]
    pos_update = config.get('pos_update', False)
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    close_daily = config['close_daily']

    xdf = dh.conv_ohlc_freq(mdf,
                            freq,
                            extra_cols=['contract'],
                            bar_func=eval(bar_func))
    if use_chan:
        xdf['chanH'] = eval(chan_func[0])(xdf, chan, **chan_args[0]).shift(1)
        xdf['chanL'] = eval(chan_func[1])(xdf, chan, **chan_args[1]).shift(1)
    else:
        xdf['chanH'] = 0
        xdf['chanL'] = 10000000
    psar_data = dh.PSAR(xdf, **sar_param)
    xdf['psar_dir'] = psar_data['PSAR_DIR'].shift(1)
    xdf['psar_val'] = psar_data['PSAR_VAL'].shift(1)
    xdf['prev_high'] = xdf['high'].shift(1)
    xdf['prev_low'] = xdf['low'].shift(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
    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.chanH) or np.isnan(mslice.chanL):
            continue
        if use_HL:
            buy_trig = (mslice.prev_high >= mslice.chanH) and (mslice.psar_dir
                                                               > 0)
            sell_trig = (mslice.prev_low <= mslice.chanL) and (mslice.psar_dir
                                                               < 0)
            long_close = (mslice.prev_low <= mslice.chanL) or (mslice.psar_dir
                                                               < 0)
            short_close = (mslice.prev_high >=
                           mslice.chanH) or (mslice.psar_dir > 0)
        else:
            buy_trig = (mslice.open >= mslice.chanH) and (mslice.psar_dir > 0)
            sell_trig = (mslice.open <= mslice.chanL) and (mslice.psar_dir < 0)
            long_close = (mslice.open <= mslice.chanL) or (mslice.psar_dir < 0)
            short_close = (mslice.open >= mslice.chanH) or (mslice.psar_dir >
                                                            0)
        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 (short_close and (pos > 0)) or (long_close 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 (buy_trig or sell_trig) and (pos == 0):
                target_pos = buy_trig * unit - sell_trig * 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)
Example #31
0
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)
Example #32
0
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 = dd.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] )    

    (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)
Example #33
0
def chanbreak_sim( mdf, 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']
    pos_class = config['pos_class']
    pos_args  = config['pos_args']
    chan_func = config['channel_func']
    upper_chan_func = chan_func[0]
    lower_chan_func = chan_func[1]
    entry_chan = win[0]    
    exit_chan =  win[1]
    xdf['H1'] = upper_chan_func(xdf, entry_chan)
    xdf['L1'] = lower_chan_func(xdf, entry_chan)
    xdf['H2'] = upper_chan_func(xdf, exit_chan)
    xdf['L2'] = lower_chan_func(xdf, exit_chan)
    xdf['ATR'] = dh.ATR(xdf, entry_chan)
    xdata = pd.concat([xdf['H1'], xdf['L1'], xdf['H2'], xdf['L2'], xdf['ATR'], xdf['high'], xdf['low']], \
                      axis=1, keys=['H1', 'L1', 'H2', 'L2', 'ATR', 'xhigh', 'xlow']).shift(1)
    ll = mdf.shape[0]
    mdf = mdf.join(xdata, 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 = []
    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 = mslice.min_id
        cnt_id = count_min_id(dd)
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[dd, 'pos'] = pos
        #if np.isnan(mslice.ATR):
        #    continue
        if (min_id >=config['exit_min']):
            if (pos!=0) and (dd.date() == 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 = []
                pos = 0
                mdf.ix[dd, 'cost'] -=  abs(pos) * (offset + mslice.close*tcost) 
            continue
        else:
            if (pos !=0):
                if (cnt_id % freq) == 0:
                    curr_pos[0].update_bar(mslice)
                check_price = (pos>0) * mslice.low + (pos<0) * mslice.high
                if curr_pos[0].check_exit(check_price, 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.high >= mslice.H2) and (pos<0)) or ((mslice.low <= mslice.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.high >= mslice.H1) and (pos<=0)) or ((mslice.low <= mslice.L1) and (pos>=0)):
                if (pos ==0 ):
                    pos = (mslice.high >= mslice.H1) * unit -(mslice.low <= mslice.L1) * unit
                    exit_target = (mslice.high >= mslice.H1) * mslice.L2 + (mslice.low <= mslice.L1) * mslice.H2
                    new_pos = pos_class([mslice.contract], [1], pos, mslice.close, exit_target, 1, **pos_args)
                    tradeid += 1
                    new_pos.entry_tradeid = tradeid
                    new_pos.open(mslice.close + misc.sign(pos)*offset, dd)
                    curr_pos.append(new_pos)
                    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)
Example #34
0
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)
Example #35
0
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']
    use_MA = False
    if signals[2] > 1:
        use_MA = True        
    start_idx = 0
    trail_loss = config['trail_loss']
    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))
    if use_MA:
        ddf['MA'] = pd.Series(dh.MA(ddf, signals[2]*signals[0]).shift(1))
    else:
        ddf['MA'] = pd.Series(0, index=ddf.index)
    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
            dol = dslice.OL_1
            dos = dslice.OS_1
            if use_MA:
                dol = max(dol, dslice.MA)
                dos = min(dos, dslice.MA)        
            if mslice.close >= dol:
                direction = 1
            elif mslice.close <= dos:
                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)
                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
            if trail_loss:
                for trade_pos in curr_pos:
                    trade_pos.trail_update(mslice.close)
            #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].trail_check( mslice.close, curr_atr * NN ):
                for trade_pos in curr_pos:
                    if trade_pos.trail_check( mslice.close, curr_atr * NN )>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
                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)
        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)
Example #36
0
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)
Example #37
0
def MA_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)
    ma_list = config['ma_list']
    param = config['param']
    corr_entry = param[0]
    corr_exit = param[1]
    pval_entry = param[2]
    pval_exit = param[3]
    if len(param) >= 5:
        channel = param[4]
    else:
        channel = 0
    if channel == 0:
        use_chan = False
    else:
        use_chan = True
    close_daily = config['close_daily']
    tcost = config['trans_cost']
    unit = config['unit']
    freq = config['freq']
    if int(freq[:-3]) == 1:
        xdf = mdf
    else:
        xdf = dh.conv_ohlc_freq(mdf, freq, extra_cols=['contract'])
    if use_chan:
        xdf['chan_high'] = eval(config['channel_func'][0])(
            xdf, channel, **config['channel_args'][0]).shift(2)
        xdf['chan_low'] = eval(config['channel_func'][1])(
            xdf, channel, **config['channel_args'][1]).shift(2)
    else:
        xdf['chan_high'] = pd.Series(index=xdf.index)
        xdf['chan_low'] = pd.Series(index=xdf.index)
    ma_ribbon = dh.MA_RIBBON(xdf, ma_list)
    xdf["ribbon_corr"] = ma_ribbon["MARIBBON_CORR"].shift(1)
    xdf["ribbon_pval"] = ma_ribbon["MARIBBON_PVAL"].shift(1)
    xdf["ribbon_dist"] = ma_ribbon["MARIBBON_DIST"].shift(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.ribbon_corr):
            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.ribbon_corr >= -corr_exit) or (mslice.ribbon_pval >= pval_exit)) and (pos<0)) or \
                    (((mslice.ribbon_corr <= corr_exit) or (mslice.ribbon_pval >= pval_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 (pos==0) and (mslice.ribbon_corr >= corr_entry) and (mslice.ribbon_pval < pval_entry) \
                    and ((use_chan == False) or (mslice.open >= mslice.chan_high)):
                target_pos = unit
            elif (pos==0) and (mslice.ribbon_corr <= -corr_entry) and (mslice.ribbon_pval < pval_entry) \
                    and ((use_chan == False) or (mslice.open <= mslice.chan_low)):
                target_pos = -unit
            else:
                target_pos = 0
            if target_pos != 0:
                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)
Example #38
0
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):
    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 psar_test_sim(mdf, config):
    close_daily = config['close_daily']
    marginrate = config['marginrate']
    offset = config['offset']
    pos_update = config['pos_update']
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    proc_func = config['proc_func']
    proc_args = config['proc_args']
    start_equity = config['capital']
    tcost = config['trans_cost']
    unit = config['unit']
    SL = config['stoploss']
    chan = config['chan']
    no_trade_set = config['no_trade_set']
    ll = mdf.shape[0]
    xdf = proc_func(mdf, **proc_args)
    xdf['chan_h'] = pd.rolling_max(xdf.high, chan)
    xdf['chan_l'] = pd.rolling_min(xdf.low, chan)
    xdf['MA'] = pd.rolling_mean(xdf.close, chan)
    psar_data = dh.PSAR(xdf, **config['sar_params'])
    xdata = pd.concat(
        [
            xdf['MA'], xdf['chan_h'], xdf['chan_l'], psar_data['PSAR_VAL'],
            psar_data['PSAR_DIR'], xdf['date_idx']
        ],
        axis=1,
        keys=['MA', 'chanH', 'chanL', 'psar', 'psar_dir', 'date'])
    xdata = xdata.shift(1).fillna(0)
    mdf = mdf.join(xdata, 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 = []
    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 = mslice.min_id
        min_cnt = (min_id - 300) / 100 * 60 + min_id % 100 + 1
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[dd, 'pos'] = pos
        if (mslice.MA == 0) or (mslice.chanH
                                == 0) or (mslice.chanL
                                          == 0) or (mslice.psar_dir == 0):
            continue
        if (min_id >= config['exit_min']) and (close_daily or
                                               (mslice.datetime.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
        elif min_id not in no_trade_set:
            if (pos != 0) and pos_update:
                curr_pos[0].update_price(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
            long_close = ((mslice.low <= mslice.chanL) or
                          (mslice.psar_dir < 0)) and (pos > 0)
            short_close = ((mslice.high >= mslice.chanH) or
                           (mslice.psar_dir > 0)) and (pos < 0)
            close_price = mslice.close
            if (short_close or long_close):
                if (mslice.psar_dir > 0):
                    close_price = max(mslice.psar, mslice.open)
                elif (mslice.psar_dir < 0):
                    close_price = min(mslice.psar, mslice.open)
                curr_pos[0].close(mslice.close + offset, dd)
                tradeid += 1
                curr_pos[0].exit_tradeid = tradeid
                closed_trades.append(curr_pos[0])
                curr_pos = []
                pos = 0
                mdf.ix[dd,
                       'cost'] -= abs(pos) * (offset + mslice.close * tcost)
            buy_trig = (mslice.high >= mslice.chanH) and (mslice.psar_dir >
                                                          0) and (pos == 0)
            sell_trig = (mslice.low <= mslice.chanL) and (mslice.psar_dir <
                                                          0) and (pos == 0)
            if buy_trig:
                new_pos = pos_class([mslice.contract], [1], unit,
                                    mslice.close + offset,
                                    mslice.close + offset, **pos_args)
                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 sell_trig:
                new_pos = pos_class([mslice.contract], [1], -unit,
                                    mslice.close - offset,
                                    mslice.close - offset, **pos_args)
                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
    return (mdf, closed_trades)
Example #41
0
    def move_to(self, newpos):
        '''
        Arguments:
            newpos: new position vector, the length of this vector sets which
                channels will be used.
        '''

        channels = len(newpos)
        pos = [self._posins.get_position(i) for i in range(channels)]
        stepspos = [0 for i in range(channels)]
        est = []
        for i in range(channels):
            e = PositionEstimator()
            e.add(pos[i], stepspos[i])
            est.append(e)
        delta = [newpos[i] - pos[i] for i in range(channels)]
        dist = [abs(delta[i]) for i in range(channels)]
        hold = [False for i in range(channels)]
        increase_steps = True
#        print 'move_to(): start pos = %r, delta = %r, dist = %r' % \
#            (pos, delta, dist)

        steps = [-misc.sign(delta[i]) * self._startstep for i in range(channels)]

        j = 0
        while j < 1000:

            # Move
            for i in range(channels):
                if not hold[i]:
                    self._moveins.move_steps(i + self._channel_ofs, steps[i])
                    stepspos[i] += steps[i]
            time.sleep(self._delay)

            # Update position
            pos2 = [self._posins.get_position(i) for i in range(channels)]
            realpos2 = pos2[0]
            delta2 = [newpos[i] - pos2[i] for i in range(channels)]
            dist2 = [abs(delta2[i]) for i in range(channels)]
            for i in range(channels):
                pos2[i] = est[i].add(pos2[i], stepspos[i])
#            print 'move_to(): pos = %r, delta2 = %r' % (pos2, delta2)

            # Increase step size exponentially
            if increase_steps:
                for i in range(channels):
                    if not hold[i]:
                        if misc.sign(delta2[i]) != misc.sign(delta[i]):
                            hold[i] = True
                        elif abs(steps[i]) != self._maxstep:
                            steps[i] = misc.sign(delta2[i]) * min(abs(steps[i]) * 2, self._maxstep)
#                            print 'move_to(): increasing stepsize for ch%d to %f' % (i, steps[i]) 

                if all_true(hold):
#                    print 'move_to(): increase_steps=False'
                    increase_steps = False
                    for i in range(channels):
                        hold[i] = False
                        if self._use_reset:
                            est[i].reset()
                    
            # Immediately reverse if we moved too far
            if not increase_steps:
                for i in range(channels):
                    if not hold[i]:
                        if misc.sign(delta2[i]) != misc.sign(delta[i]):
                            if abs(steps[i]) == self._minstep:
                                hold[i] = True
                            else:
                                steps[i] = int(misc.sign(delta2[i]) * max(round(abs(steps[i]) / 2), self._minstep))
                                if self._use_reset:
                                    est[i].reset()
#                                print 'move_to(): reversing and decreasing stepsize for ch%d to %f' % (i, steps[i])

                if all_true(hold):
#                    print 'move_to(): Moved to position!'
                    return realpos2

                # Remember relative position
                delta = delta2

            j += 1
Example #42
0
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)
Example #43
0
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)
Example #44
0
def dual_thrust_sim(mdf, config):
    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]
    pos_update = config['pos_update']
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    proc_func = config['proc_func']
    proc_args = config['proc_args']
    start_equity = config['capital']
    chan_func = config['chan_func']
    chan_high = eval(chan_func['high']['func'])
    chan_low = eval(chan_func['low']['func'])
    tcost = config['trans_cost']
    unit = config['unit']
    SL = config['stoploss']
    min_rng = config['min_range']
    chan = config['chan']
    use_chan = config['use_chan']
    no_trade_set = config['no_trade_set']
    ll = mdf.shape[0]
    xdf = proc_func(mdf, **proc_args)
    if win == -1:
        tr = pd.concat(
            [xdf.high - xdf.low,
             abs(xdf.close - xdf.close.shift(1))],
            join='outer',
            axis=1).max(axis=1)
    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)
    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)
    xdf['TR'] = tr
    xdf['chan_h'] = chan_high(xdf['high'], chan, **chan_func['high']['args'])
    xdf['chan_l'] = chan_low(xdf['low'], chan, **chan_func['low']['args'])
    xdf['MA'] = pd.rolling_mean(xdf.close, chan)
    xdata = pd.concat([
        xdf['TR'].shift(1), xdf['MA'].shift(1), xdf['chan_h'].shift(1),
        xdf['chan_l'].shift(1), xdf['open']
    ],
                      axis=1,
                      keys=['TR', 'MA', 'chanH', 'chanL', 'dopen']).fillna(0)
    mdf = mdf.join(xdata, 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 = []
    end_d = mdf.index[-1].date
    #prev_d = start_d - datetime.timedelta(days=1)
    tradeid = 0
    pos_update_idx = 0
    for idx, dd in enumerate(mdf.index):
        mslice = mdf.ix[dd]
        min_id = mslice.min_id
        min_cnt = (min_id - 300) / 100 * 60 + min_id % 100 + 1
        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
        rng = max(min_rng * d_open, k * mslice.TR)
        if (d_open <= 0):
            continue
        buytrig = d_open + rng
        selltrig = d_open - rng
        if 'reset_margin' in pos_args:
            pos_args['reset_margin'] = mslice.TR * SL
        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
        elif min_id not in no_trade_set:
            if (pos != 0):
                exit_flag = False
                if (curr_pos[0].check_exit(mslice.close, 0)):
                    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
                elif pos_update and (min_cnt % config['pos_freq'] == 0):
                    if pos > 0:
                        ep = max(mdf['high'][pos_update_idx:idx])
                    else:
                        ep = max(mdf['low'][pos_update_idx:idx])
                    curr_pos[0].update_price(ep)
                    pos_update_idx = idx
            if (mslice.high >= buytrig) and (pos <= 0):
                if 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)
                    pos = 0
                if (use_chan == False) or (mslice.high > mslice.chanH):
                    new_pos = pos_class([mslice.contract], [1], unit,
                                        mslice.close + offset, selltrig,
                                        **pos_args)
                    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)
                    pos_update_idx = idx
            elif (mslice.low <= selltrig) and (pos >= 0):
                if 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)
                    pos = 0
                if (use_chan == False) or (mslice.low < mslice.chanL):
                    new_pos = pos_class([mslice.contract], [1], -unit,
                                        mslice.close - offset, buytrig,
                                        **pos_args)
                    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)
                    pos_update_idx = idx
        mdf.ix[dd, 'pos'] = pos
    return (mdf, closed_trades)
Example #45
0
def psar_test_sim( mdf, config):
    close_daily = config['close_daily']
    marginrate = config['marginrate']
    offset = config['offset']
    pos_update = config['pos_update']
    pos_class = config['pos_class']
    pos_args  = config['pos_args']
    proc_func = config['proc_func']
    proc_args = config['proc_args']
    start_equity = config['capital']
    tcost = config['trans_cost']
    unit = config['unit']
    SL = config['stoploss']
    chan = config['chan']
    no_trade_set = config['no_trade_set']
    ll = mdf.shape[0]
    xdf = proc_func(mdf, **proc_args)
    xdf['chan_h'] = pd.rolling_max(xdf.high, chan)
    xdf['chan_l'] = pd.rolling_min(xdf.low, chan)
    xdf['MA'] = pd.rolling_mean(xdf.close, chan)
    psar_data = dh.PSAR(xdf, **config['sar_params'])
    xdata = pd.concat([xdf['MA'], xdf['chan_h'], xdf['chan_l'], psar_data['PSAR_VAL'], psar_data['PSAR_DIR'], xdf['date_idx']],
                       axis=1, keys=['MA', 'chanH', 'chanL', 'psar', 'psar_dir', 'date'])
    xdata = xdata.shift(1).fillna(0)
    mdf = mdf.join(xdata, 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 = []
    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 = mslice.min_id
        min_cnt = (min_id-300)/100 * 60 + min_id % 100 + 1
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[dd, 'pos'] = pos
        if (mslice.MA == 0) or (mslice.chanH == 0) or (mslice.chanL == 0) or (mslice.psar_dir ==0):
            continue
        if (min_id >= config['exit_min']) and (close_daily or (mslice.datetime.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
        elif min_id not in no_trade_set:
            if (pos!=0) and pos_update:
                curr_pos[0].update_price(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
            long_close  = ((mslice.low <= mslice.chanL) or (mslice.psar_dir < 0)) and (pos >0)
            short_close = ((mslice.high >= mslice.chanH) or (mslice.psar_dir > 0)) and (pos <0)
            close_price = mslice.close
            if (short_close or long_close):
                if (mslice.psar_dir > 0):
                    close_price = max(mslice.psar, mslice.open)
                elif (mslice.psar_dir < 0):
                    close_price = min(mslice.psar, mslice.open)
                curr_pos[0].close(mslice.close+offset, dd)
                tradeid += 1
                curr_pos[0].exit_tradeid = tradeid
                closed_trades.append(curr_pos[0])
                curr_pos = []
                pos = 0
                mdf.ix[dd, 'cost'] -=  abs(pos) * (offset + mslice.close*tcost)
            buy_trig  = (mslice.high >= mslice.chanH) and (mslice.psar_dir > 0) and (pos ==0)
            sell_trig = (mslice.low <= mslice.chanL) and (mslice.psar_dir < 0) and (pos == 0)
            if buy_trig:
                new_pos = pos_class([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset, **pos_args)
                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 sell_trig:
                new_pos = pos_class([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset, **pos_args)
                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)
Example #46
0
def psar_chan_sim( mdf, config):
    marginrate = config['marginrate']
    offset = config['offset']
    tcost = config['trans_cost']
    unit = config['unit']
    stoploss = config['stoploss']
    bar_func = config.get('bar_conv_func', 'dh.bar_conv_func2')
    param = config['param']
    freq = config['freq']
    use_HL = config.get('use_HL',False)
    use_chan = config['use_chan']    
    chan_func = config['chan_func']
    chan_args = config['chan_args']
    chan = param[0]
    sar_param = param[1]
    pos_update = config.get('pos_update', False)
    pos_class = config['pos_class']
    pos_args  = config['pos_args']    
    close_daily = config['close_daily']
    
    xdf = dh.conv_ohlc_freq(mdf, freq, extra_cols = ['contract'], bar_func = eval(bar_func))
    if use_chan:
        xdf['chanH'] = eval(chan_func[0])(xdf, chan, **chan_args[0]).shift(1)
        xdf['chanL'] = eval(chan_func[1])(xdf, chan, **chan_args[1]).shift(1)
    else:
        xdf['chanH'] = 0
        xdf['chanL'] = 10000000
    psar_data = dh.PSAR(xdf, **sar_param)
    xdf['psar_dir'] = psar_data['PSAR_DIR'].shift(1)
    xdf['psar_val'] = psar_data['PSAR_VAL'].shift(1)
    xdf['prev_high'] = xdf['high'].shift(1)
    xdf['prev_low'] = xdf['low'].shift(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    
    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.chanH) or np.isnan(mslice.chanL):
            continue
        if use_HL:
            buy_trig  = (mslice.prev_high >= mslice.chanH) and (mslice.psar_dir > 0)
            sell_trig = (mslice.prev_low <= mslice.chanL) and (mslice.psar_dir < 0)
            long_close  = (mslice.prev_low <= mslice.chanL) or (mslice.psar_dir < 0)
            short_close = (mslice.prev_high >= mslice.chanH) or (mslice.psar_dir > 0)
        else:
            buy_trig  = (mslice.open >= mslice.chanH) and (mslice.psar_dir > 0)
            sell_trig = (mslice.open <= mslice.chanL) and (mslice.psar_dir < 0)
            long_close  = (mslice.open <= mslice.chanL) or (mslice.psar_dir < 0)
            short_close = (mslice.open >= mslice.chanH) or (mslice.psar_dir > 0)
        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 (short_close and (pos > 0)) or (long_close 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 (buy_trig or sell_trig) and (pos==0):
                target_pos = buy_trig * unit - sell_trig * 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)
Example #47
0
def dual_thrust_sim( mdf, config):
    (pos_class, pos_args) = config['pos_param']
    update_freq = config.get('update_freq', 0)
    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]
    chan = config['chan']
    chan_func = config['chan_func']
    use_chan = config['use_chan']
    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['ATR'] = dh.ATR(ddf, win)
    if use_chan:
        ddf['CH_H'] = eval(chan_func['high']['func'])(ddf, chan, **chan_func['high']['args']).shift(1)
        ddf['CH_L'] = eval(chan_func['low']['func'])(ddf, chan, **chan_func['low']['args']).shift(1)
    if update_freq > 1:
        xdf = dh.conv_ohlc_freq(mdf, str(update_freq)+'Min')
    else:
        xdf = mdf
    xdata = pd.concat([xdf['open'], xdf['high'], xdf['low'], xdf['close']], axis=1, keys=['xopen','xhigh', 'xlow', 'xclose'])
    mdf = mdf.join(xdata, how = 'left').fillna(method='ffill')
    ll = mdf.shape[0]
    mdf['pos'] = 0
    mdf['cost'] = 0
    start_d = ddf.index[0]
    end_d = mdf.index[-1].date()
    prev_d = start_d - datetime.timedelta(days=1)
    curr_pos = []
    closed_trades = []
    tradeid = 0
    for idx, dd in enumerate(mdf.index):
        mslice = mdf.ix[dd]
        min_id = mslice.min_id
        d = mslice.date
        dslice = ddf.ix[d]
        if np.isnan(dslice.TR) or (mslice.close == 0):
            continue
        if use_chan and np.isnan(dslice.CH_H):
            continue
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[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
        else:
            d_open = dslice.open
        prev_d = d
        buytrig  = d_open + rng
        selltrig = d_open - rng
        stoploss = SL * dslice.ATR
        tmp_args = pos_args.copy()
        if 'reset_margin' in pos_args:
            tmp_args['reset_margin'] = dslice.ATR * pos_args['reset_margin']
            stoploss =  tmp_args['reset_margin'] * stoploss
        close_pos = False
        if pos != 0:
            if ((pos > 0) and (mslice.high < buytrig)) or ((pos < 0) and (mslice.low > selltrig)):
                close_pos = curr_pos[0].check_exit(mslice.close, stoploss)
            if (close_pos == False) and (update_freq > 0) and ((mslice.min_id + 1) % update_freq == 0):
                xslice = conv_xslice(mslice)
                curr_pos[0].update_bar(xslice)
            if close_pos or ((mslice.min_id >= config['exit_min']) 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
        if mslice.min_id < config['exit_min']:
            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 (use_chan == False) or (use_chan and (mslice.high >= dslice.CH_H)):
                    new_pos = eval(pos_class)([mslice.contract], [1], unit, mslice.close + offset, mslice.close + offset, **tmp_args)
                    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 (use_chan == False) or (use_chan and (mslice.low <= dslice.CH_L)):
                    new_pos = eval(pos_class)([mslice.contract], [1], -unit, mslice.close - offset, mslice.close - offset, **tmp_args)
                    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
    return (mdf, closed_trades)
Example #48
0
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)
Example #49
0
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)
Example #50
0
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)
Example #51
0
def chanbreak_sim(mdf, config):
    freq = config['freq']
    str_freq = str(freq) + 'Min'
    xdf = dh.conv_ohlc_freq(mdf, str_freq)
    tcost = config['trans_cost']
    unit = config['unit']
    offset = config['offset']
    win = config['win']
    pos_class = config['pos_class']
    pos_args = config['pos_args']
    chan_func = config['channel_func']
    upper_chan_func = chan_func[0]
    lower_chan_func = chan_func[1]
    entry_chan = win[0]
    exit_chan = win[1]
    xdf['H1'] = upper_chan_func(xdf, entry_chan)
    xdf['L1'] = lower_chan_func(xdf, entry_chan)
    xdf['H2'] = upper_chan_func(xdf, exit_chan)
    xdf['L2'] = lower_chan_func(xdf, exit_chan)
    xdf['ATR'] = dh.ATR(xdf, entry_chan)
    xdata = pd.concat([xdf['H1'], xdf['L1'], xdf['H2'], xdf['L2'], xdf['ATR'], xdf['high'], xdf['low']], \
                      axis=1, keys=['H1', 'L1', 'H2', 'L2', 'ATR', 'xhigh', 'xlow']).shift(1)
    ll = mdf.shape[0]
    mdf = mdf.join(xdata, 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 = []
    end_d = mdf.index[-1].date()
    tradeid = 0
    for idx, dd in enumerate(mdf.index):
        mslice = mdf.ix[dd]
        min_id = mslice.min_id
        cnt_id = count_min_id(dd)
        if len(curr_pos) == 0:
            pos = 0
        else:
            pos = curr_pos[0].pos
        mdf.ix[dd, 'pos'] = pos
        #if np.isnan(mslice.ATR):
        #    continue
        if (min_id >= config['exit_min']):
            if (pos != 0) and (dd.date() == 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 = []
                pos = 0
                mdf.ix[dd,
                       'cost'] -= abs(pos) * (offset + mslice.close * tcost)
            continue
        else:
            if (pos != 0):
                if (cnt_id % freq) == 0:
                    curr_pos[0].update_bar(mslice)
                check_price = (pos > 0) * mslice.low + (pos < 0) * mslice.high
                if curr_pos[0].check_exit(check_price, 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.high >= mslice.H2) and
                (pos < 0)) or ((mslice.low <= mslice.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.high >= mslice.H1) and
                (pos <= 0)) or ((mslice.low <= mslice.L1) and (pos >= 0)):
                if (pos == 0):
                    pos = (mslice.high >=
                           mslice.H1) * unit - (mslice.low <= mslice.L1) * unit
                    exit_target = (mslice.high >= mslice.H1) * mslice.L2 + (
                        mslice.low <= mslice.L1) * mslice.H2
                    new_pos = pos_class([mslice.contract], [1], pos,
                                        mslice.close, exit_target, 1,
                                        **pos_args)
                    tradeid += 1
                    new_pos.entry_tradeid = tradeid
                    new_pos.open(mslice.close + misc.sign(pos) * offset, dd)
                    curr_pos.append(new_pos)
                    mdf.ix[dd, 'cost'] -= abs(pos) * (offset +
                                                      mslice.close * tcost)
            mdf.ix[dd, 'pos'] = pos
    return (mdf, closed_trades)
Example #52
0
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 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)
Example #54
0
 def run_loop_sim(self):
     sim_data = dh.DynamicRecArray(dataframe=self.df)
     nlen = len(sim_data)
     positions = []
     closed_trades = []
     tradeid = 0
     curr_date = None
     for n in range(nlen - 3):
         cost = 0
         pos = sim_data['pos'][n]
         if sim_data['ma'][n] == 0 or sim_data['chan_h'][
                 n] == 0 or sim_data['dopen'][n] == 0:
             continue
         if curr_date != sim_data['date'][n]:
             curr_date = sim_data['date'][n]
             dopen = sim_data['dopen'][n]
             rng = max(self.min_rng * dopen, self.k * sim_data['tr'][n])
             buytrig = dopen + rng
             selltrig = dopen - rng
             if sim_data['ma'][n] > dopen:
                 buytrig += self.f * rng
             else:
                 selltrig -= self.f * rng
             continue
         if self.price_mode == 'TP':
             ref_long = ref_short = (sim_data['close'][n] +
                                     sim_data['high'][n] +
                                     sim_data['low'][n]) / 3.0
         elif self.price_mode == 'HL':
             ref_long = sim_data['high'][n]
             ref_short = sim_data['low'][n]
         elif self.price_mode == 'CL':
             ref_long = ref_short = sim_data['close'][n]
         else:
             ref_long = ref_short = sim_data['open'][n + 1]
         target_pos = (ref_long > buytrig) - (ref_short < selltrig)
         if len(positions) > 0:
             need_close = (self.close_daily or
                           (curr_date == sim_data['date'][-1])) and (
                               sim_data['min_id'][n] >= config['exit_min'])
             for tradepos in positions:
                 ep = sim_data['low'][n] if tradepos.pos > 0 else sim_data[
                     'high'][n]
                 if need_close or tradepos.check_exit(
                         sim_data['open'][n + 1],
                         0) or (tradepos.pos * target_pos < 0):
                     tradepos.close(
                         sim_data['open'][n + 1] -
                         self.offset * misc.sign(tradepos.pos),
                         sim_data['datetime'][n + 1])
                     tradepos.exit_tradeid = tradeid
                     tradeid += 1
                     pos -= tradepos.pos
                     cost += abs(tradepos.pos) * (
                         self.offset + sim_data['open'][n + 1] * self.tcost)
                     closed_trades.append(tradepos)
                 elif self.pos_update:
                     tradepos.update_price(ep)
             positions = [pos for pos in positions if not pos.is_closed]
             if need_close:
                 continue
         if target_pos != 0:
             if (not self.use_chan) or (
                 ((ref_long > sim_data['chanh'][n]) and target_pos > 0) or
                 ((ref_short < sim_data['chanl'][n]) and target_pos < 0)):
                 new_pos = self.pos_class(
                     [sim_data['contract'][n]], [1], self.unit * target_pos,
                     sim_data['open'][n + 1] + target_pos * self.offset,
                     buytrig, **self.pos_args)
                 tradeid += 1
                 new_pos.entry_tradeid = tradeid
                 new_pos.open(
                     sim_data['open'][n + 1] + target_pos * self.offset,
                     sim_data['datetime'][n + 1])
                 positions.append(new_pos)
                 pos += self.unit * target_pos
                 cost += abs(target_pos) * (
                     self.offset + sim_data['open'][n + 1] * self.tcost)
         sim_data['cost'][n + 1] = cost
         sim_data['pos'][n + 1] = pos
     out_df = pd.concat([])
     return out_df, closed_trades
Example #55
0
    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 = []
                mdf.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+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