Ejemplo n.º 1
0
 def __init__(self, rsiPeriod, streakrsiPeriod, percentRankPeriod):
     MultiMetricMetric.__init__(self)
     self.close = AdjustedClose()
     self.rsi = RSI(metric=self.close, period=rsiPeriod)
     self.streak = Streak(metric=self.close)
     self.streakrsi = RSI(period=streakrsiPeriod, metric=self.streak)
     self.percentRank = PercentRank(metric=self.close,
                                    period=percentRankPeriod)
     self.average = AverageMetric(self.rsi, self.streakrsi,
                                  self.percentRank)
     self._addMetric(self.close)
     self._addMetric(self.rsi)
     self._addMetric(self.streak)
     self._addMetric(self.streakrsi)
     self._addMetric(self.percentRank)
     self._addMetric(self.average)
Ejemplo n.º 2
0
 def __init__(self, period, rsiPeriod):
     MultiMetricMetric.__init__(self)
     self.rsis = list()
     rsi = RSI(rsiPeriod)
     self.rsis.append(rsi)
     self._addMetric(rsi)
     for i in range(1, period):
         hist = HistoricMetric(metric=rsi, period=i)
         self._addMetric(hist)
         self.rsis.append(hist)
Ejemplo n.º 3
0
def features(data, target):
    """
    Given a standard yfinance data dataframe, add features that will help
    the balanced scorecard to recognize buy and sell signals in the data.
    The features are added as columns in the data dataframe. 
    
    The original hist dataframe from yfinance is provided, so we can copy
    the target to the data dataframe. The data dataframe with the extra 
    features is returned. The target argument contains the name of the 
    column that contains the the target.
    """
    # windows = [3, 5, 10, 15, 20, 30] #, 45, 60]
    windows = [ 10, 20, 30 ] 

    for i in windows:
        ma = data.Close.rolling(i).mean()
        if 'MACD' in comb:    
           data[f'MACD_{i}']    = ma - data.Close
        if 'PctDiff' in comb: 
           data[f'PctDiff_{i}'] = data.Close.diff(i)
        if 'StdDev' in comb:  
           data[f'StdDev_{i}']  = data.Close.rolling(i).std()

    # exclude_cols = [target, 'smooth', 'Close', 'Date', 'Volume', 'Dividends', 'Stock Splits'] 
    exclude_cols = [target, 'smooth', 'Close', 'Low', 'High', 'Open', 'Date', 'Volume', 'Dividends', 'Stock Splits'] 
    factor = data.Close.copy()
    for c in data.columns.tolist():
        if c in exclude_cols:
           continue
        data[c] = data[c] / factor

    for i in windows:
        if 'RSI' in comb:
           data[f'RSI_{i}']     = RSI(data, i) / 100
        if 'WPR' in comb:
           data[f'WPR_{i}']     = WPR(data, i) / 100
        if 'MFI' in comb:
           data[f'MFI_{i}']     = MFI(data, i) / 100
        if 'BBP' in comb:
           data[f'BBP_{i}']     = BBP(data, i)


    if 'P/E Ratio' in data.columns:
       if 'P/E Ratio' not in comb:
          log(f'Deleting P/E Ratio feature: comb={comb}')
          del data['P/E Ratio']
       else:
          log(f'Keeping P/E Ratio feature: comb={comb}')

    data = data.dropna()
    
    return data
Ejemplo n.º 4
0
def compute_data(token):
    global one_hour_rsi
    #enddate = datetime.datetime(2020, 5, 4, 15,30,0,0)
    enddate = datetime.datetime.today()
    startdate = enddate - datetime.timedelta(3)
    try:
        df = historical_data.get(kite, token, startdate, enddate, candlesize)
        df = SuperTrend.calc(df, supertrend_period, supertrend_multiplier)
        df = MACD.calc(df)
        rsi = historical_data.get(kite, token, startdate, enddate, "60minute")
        rsi = RSI.calc(rsi)
        one_hour_rsi = rsi.RSI_14.values[-1]
    except Exception as e:
        print("******* ERROR Computing Historical Data ********", token, e)
    return df
Ejemplo n.º 5
0
def compute_data(token):
    global one_hour_rsi
    #enddate = datetime.datetime(2020, 5, 4, 15,30,0,0)
    enddate = datetime.datetime.today()
    startdate = enddate - datetime.timedelta(15)
    try:
        df = historical_data.get(kite, token, startdate, enddate, candlesize)
        df = EMA.calc(df, 'close', 'ema_5', 5)
        df = EMA.calc(df, 'close', 'ema_20', 20)
        df = MACD.calc(df)
        df = MFI.calc(df)
        df = VWAP.calc(df)
        rsi = historical_data.get(kite, token, startdate, enddate, "60minute")
        rsi = RSI.calc(rsi)
        one_hour_rsi = rsi.RSI_14.values[-2]
    except Exception as e:
        print("******* ERROR Computing Historical Data ********", token, e)
    return df
Ejemplo n.º 6
0
    def __init__(self, close, rsi: indicators.RSI, fee=0.0):
        Strategy.__init__(self, close.index, fee=0.0)

        lowthreshpassed = False
        lowlowthreshpassed = False
        hithreshpassed = False
        hihithreshpassed = False
        hasbought = False
        close['rsi'] = rsi.data()
        for index, row in close.iterrows():
            # achat en fonction du RSI
            if row['rsi'] < 33:
                lowthreshpassed = True
            if row['rsi'] < 20:
                lowlowthreshpassed = True
            if row['rsi'] > 66:
                hithreshpassed = True
            if row['rsi'] > 80:
                hihithreshpassed = True

            if row['rsi'] > 20 and lowlowthreshpassed == True:
                lowlowthreshpassed = False
                if hasbought == False:
                    hasbought = True
            if row['rsi'] > 33 and lowthreshpassed == True:
                lowthreshpassed = False
                if hasbought == False:
                    hasbought = True
            # on revend par RSI seulement si c'est le seul signal qui a généré l'achat
            if row['rsi'] < 80 and hihithreshpassed == True:
                hihithreshpassed = False
                if hasbought == True:
                    hasbought = False
            if row['rsi'] < 66 and hithreshpassed == True:
                hithreshpassed = False
                if hasbought == True:
                    hasbought = False

            if hasbought == True:
                self.signals['signal'].loc[index] = 1.0

        self.signals['positions'] = self.signals['signal'].diff()
def test_run():
    Traindates = pd.date_range('2008-1-1', '2009-12-31')
    TestDates = pd.date_range('2010-1-1', '2011-12-31')
    syms = ['AAPL']
    prices_train = get_data(syms, Traindates)
    prices_test = get_data(syms, TestDates)
    prices_train = prices_train[syms]
    prices_test = prices_test[syms]

    bb_train = BB(prices_train, lookback=20)
    bb_train = bb_train.fillna(method='bfill')
    bb_test = BB(prices_test, lookback=20)
    bb_test = bb_test.fillna(method='bfill')

    macd_train = MACD(prices_train)
    macd_test = MACD(prices_test)

    rsi_train = RSI(prices_train, lookback=14)
    rsi_test = RSI(prices_test, lookback=14)
    df_train = pd.concat([prices_train, bb_train, macd_train, rsi_train],
                         axis=1)
    df_train = df_train.fillna(method='bfill')
    df_test = pd.concat([prices_test, bb_test, macd_test, rsi_test], axis=1)
    df_test = df_test.fillna(method='bfill')

    indicators_train = pd.DataFrame(columns=[
        'MACD_ZERO', 'MACD_SIGNAL', 'ACROSS_BAND', 'BB_value', 'RSI',
        'Decision'
    ])
    indicators_test = pd.DataFrame(columns=[
        'MACD_ZERO', 'MACD_SIGNAL', 'ACROSS_BAND', 'BB_value', 'RSI',
        'Decision'
    ])

    indicators_train['BB_value'] = (df_train[syms[0]] - bb_train['Middle Band']
                                    ) / (bb_train['Upper Band'] -
                                         bb_train['Middle Band'])
    indicators_train['MACD_ZERO'] = macd_train['MACD Line']
    indicators_train['MACD_SIGNAL'] = macd_train['Signal Line']
    indicators_train['ACROSS_BAND'] = bb_train['Middle Band']
    indicators_train['RSI'] = rsi_train['RSI']
    indicators_train = (indicators_train - indicators_train.mean(axis=0)
                        ) / indicators_train.std(axis=0)

    indicators_test['BB_value'] = (
        df_test[syms[0]] - bb_test['Middle Band']) / (bb_test['Upper Band'] -
                                                      bb_test['Middle Band'])
    indicators_test['MACD_ZERO'] = macd_test['MACD Line']
    indicators_test['MACD_SIGNAL'] = macd_test['Signal Line']
    indicators_test['ACROSS_BAND'] = bb_test['Middle Band']
    indicators_test['RSI'] = rsi_test['RSI']
    indicators_test = (indicators_test - indicators_test.mean(axis=0)
                       ) / indicators_test.std(axis=0)

    YBUY = 0.05
    YSELL = -0.05
    for (i_row, row), (i_future,
                       future) in zip(df_train.iterrows(),
                                      df_train.shift(-21).iterrows()):
        if (future[syms[0]] / row[syms[0]] - 1
            ) > YBUY:  # if 21 days return exceed YBUY, then BUY Decision=1
            indicators_train.ix[i_row, 'Decision'] = 1
        if (
                future[syms[0]] / row[syms[0]] - 1
        ) < YSELL:  # if 21 days return less than YSELL, then SELL Decision=-1
            indicators_train.ix[i_row, 'Decision'] = -1

    indicators_train = indicators_train.fillna(0)

    for (i_row, row), (i_future, future) in zip(df_test.iterrows(),
                                                df_test.shift(-21).iterrows()):
        if (future[syms[0]] / row[syms[0]] - 1
            ) > YBUY:  # if 21 days return exceed YBUY, then BUY Decision=1
            indicators_test.ix[i_row, 'Decision'] = 1
        if (
                future[syms[0]] / row[syms[0]] - 1
        ) < YSELL:  # if 21 days return less than YSELL, then SELL Decision=-1
            indicators_test.ix[i_row, 'Decision'] = -1

    indicators_test = indicators_test.fillna(0)

    #print indicators
    file_dir_train = os.path.join('orders', 'indicators_train.csv')
    file_dir_test = os.path.join('orders', 'indicators_test.csv')
    indicators_train.to_csv(file_dir_train, header=False, index=False)
    indicators_test.to_csv(file_dir_test, header=False, index=False)

    inf_train = open('orders/indicators_train.csv')
    inf_test = open('orders/indicators_test.csv')
    data_train = np.array(
        [map(float,
             s.strip().split(',')) for s in inf_train.readlines()])
    data_test = np.array(
        [map(float,
             s.strip().split(',')) for s in inf_test.readlines()])
    predY_list = [0] * data_test.shape[0]

    for i in range(10):  # bag 10 times
        learner = dt.DTclass(leaf_size=5, verbose=False)
        train_rows = int(round(1.0 * data_train.shape[0]))
        test_rows = int(round(1.0 * data_test.shape[0]))
        Xtrain = data_train[:train_rows, 0:-1]
        Ytrain = data_train[:train_rows, -1]
        Xtest = data_test[:train_rows, 0:-1]
        Ytest = data_test[:train_rows, -1]
        learner.addEvidence(Xtrain, Ytrain)  # training step
        predY = learner.query(Xtest)  # query
        predY_list = predY_list + predY
    predY = predY_list / 10.0

    prices_test['decision'] = predY
    #print prices_port
    orders = pd.DataFrame(columns=['Date', 'Symbol', 'Order', 'Shares'])
    holding = 0  # holding =200 long; holding=-200 short
    window = date.datetime(2008, 1, 1)  # window should more than 21
    for (i_row, row) in prices_test.iterrows():
        if row['decision'] < 0 and (i_row -
                                    window).days > 21 and holding > -200:
            orders.loc[len(orders)] = [
                i_row, syms[0], 'SELL',
                str(200 + holding)
            ]
            holding -= 200 + holding
            window = i_row
            plt.axvline(i_row, color='r')
        if row['decision'] > 0 and (i_row -
                                    window).days > 21 and holding < 200:
            orders.loc[len(orders)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding)
            ]  # max buy
            holding += 200 - holding
            window = i_row
            plt.axvline(i_row, color='g')

    file_dir = os.path.join('orders', 'orders_ML_test.csv')
    orders.to_csv(file_dir)

    of_ML_test = "./orders/orders_ML_test.csv"
    #of = "./orders/orders.csv"
    sv = 100000

    #calculate benchmark of testing data
    dfprices = pd.DataFrame(prices_test)
    dfprices['Cash'] = sv - 200 * dfprices.ix[0, 'AAPL']
    dfprices['Holding'] = 200
    dfprices['Stock values'] = dfprices['Holding'] * dfprices['AAPL']
    dfprices['Port_val'] = dfprices['Cash'] + dfprices['Stock values']
    dfprices['Benchmark'] = dfprices['Port_val'] / dfprices['Port_val'].ix[
        0, :]
    benchmark = dfprices['Benchmark']

    #calculate rule based on test period
    orders_test = pd.DataFrame(columns=['Date', 'Symbol', 'Order', 'Shares'])

    holding_RB = 0  # holding =200 long; holding=-200 short
    window_RB = date.datetime(2010, 1, 1)  # window should more than 21
    for (i_row, row), (i_prev, prev) in zip(df_test.iterrows(),
                                            df_test.shift(1).iterrows()):
        if prev['MACD Line'] >= 0 and row['MACD Line'] < 0 and (
                i_row - window_RB).days > 21 and holding_RB > -200:
            orders_test.loc[len(orders_test)] = [
                i_row, syms[0], 'SELL',
                str(200 + holding_RB)
            ]
            holding_RB -= 200 + holding_RB
            window_RB = i_row
        if prev['MACD Line'] <= 0 and row['MACD Line'] > 0 and (
                i_row - window_RB).days > 21 and holding_RB < 200:
            orders_test.loc[len(orders_test)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding_RB)
            ]  # max buy
            holding_RB += 200 - holding_RB
            window_RB = i_row
        if prev['MACD Line'] >= prev['Signal Line'] and row['MACD Line'] < row[
                'Signal Line'] and (
                    i_row - window_RB
                ).days > 21 and holding_RB > -200 and row['RSI'] > 70:
            orders_test.loc[len(orders_test)] = [
                i_row, syms[0], 'SELL',
                str(200 + holding_RB)
            ]
            holding_RB -= 200 + holding_RB
            window_RB = i_row
        if prev['MACD Line'] <= prev['Signal Line'] and row['MACD Line'] > row[
                'Signal Line'] and (i_row -
                                    window_RB).days > 21 and holding_RB < 200:
            orders_test.loc[len(orders_test)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding_RB)
            ]  # max buy
            holding_RB += 200 - holding_RB
            window_RB = i_row

        if prev[syms[0]] <= prev['Lower Band'] and row[
                syms[0]] > row['Lower Band'] and (
                    i_row - window_RB
                ).days > 21 and holding_RB < 200:  # cross up Lower Band
            orders_test.loc[len(orders_test)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding_RB)
            ]  # max buy
            holding_RB += 200 - holding_RB
            window_RB = i_row
        if prev[syms[0]] <= prev['Middle Band'] and row[
                syms[0]] > row['Middle Band'] and (
                    i_row - window_RB).days > 21 and holding_RB > -200 and row[
                        'RSI'] > 70:  # cross up Middle Band
            orders_test.loc[len(orders_test)] = [
                i_row, syms[0], 'SELL',
                str(200 + holding_RB)
            ]
            holding_RB -= 200 + holding_RB
            window_RB = i_row
        # if prev[syms[0]] >= prev['Upper Band'] and row[syms[0]] < row['Upper Band'] and (i_row-window).days>21 and holding>-200 and row['RSI']>70: # cross down Upper Band
        #     orders.loc[len(orders)] = [i_row, syms[0], 'SELL', str(200+holding)]
        #     holding -= 200+holding
        #     window = i_row
        #     plt.axvline(i_row, color='r')
        if prev[syms[0]] >= prev['Middle Band'] and row[
                syms[0]] < row['Middle Band'] and (
                    i_row - window_RB
                ).days > 21 and holding_RB < 200:  # cross down Middle Band
            orders_test.loc[len(orders_test)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding_RB)
            ]
            holding_RB += 200 - holding_RB
            window_RB = i_row

    file_dir_RB_test = os.path.join('orders', 'orders_RB_test.csv')
    orders_test.to_csv(file_dir_RB_test)

    portvals_RB = compute_portvals(start_date=date.datetime(2010, 1, 1),
                                   end_date=date.datetime(2011, 12, 31),
                                   orders_file=file_dir_RB_test,
                                   start_val=sv)
    portvals_RB = portvals_RB / portvals_RB.ix[0, :]
    benchmark = benchmark / benchmark.ix[0, :]
    portvals_ML = compute_portvals(start_date=date.datetime(2010, 1, 1),
                                   end_date=date.datetime(2011, 12, 31),
                                   orders_file=of_ML_test,
                                   start_val=sv)
    portvals_ML = portvals_ML / portvals_ML.ix[0, :]
    prices_test = prices_test / prices_test.ix[0, :]
    plt.plot(prices_test.index,
             portvals_RB,
             label='Rule-based portfolio',
             color='b')
    plt.plot(prices_test.index,
             portvals_ML,
             label='ML-based portfolio Out of Sample',
             color='g')
    #plt.plot(prices_port.index, prices_port, label='APPL', color='m')
    plt.plot(benchmark.index, benchmark, label='Benchmark', color='k')
    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.legend(loc='upper left')
    plt.show()
Ejemplo n.º 8
0
    investor = Investor(models=[mr], world=w, live=False)
    # livetrade with investor
    investor.routine()
    '''

    # --- workflow 3 ---

    # build base world
    from indicators import Moving_Average, RSI
    from world import world_from_live
    w = world_from_live(
        basket,
        cash=10000,
        indicators=[Moving_Average(n=200),
                    Moving_Average(n=10),
                    RSI(2)])
    # get model
    from models import Mean_Reversion
    mr = Mean_Reversion('Mean Reversion', 200, 10, 2)
    # build investor
    from investor import Investor
    i = Investor(models=[mr], world=w, live=False)
    # set up backtest
    from backtest import Backtest
    b = Backtest(name='mean_reversion_backtest_000', investor=i, base_world=w)
    # show/export results
    b.do_backtest()
    b.export_history(path='backtests/')

    # --- workflow 4 ---
def test_run():
    # Read data
    dates = pd.date_range('2008-1-1', '2009-12-31')
    syms = ['AAPL']
    prices_all = get_data(syms, dates)
    prices_port = prices_all[syms]  # only price of each stock in portfolio
    prices_SPY = prices_all['SPY']  # only SPY, for comparison later

    bb = BB(prices_port, lookback=20)
    macd = MACD(prices_port)
    rsi = RSI(prices_port, lookback=14)
    df = pd.concat([prices_port, bb, macd, rsi], axis=1)
    df = df.fillna(method='bfill')
    #print df
    #plot_data(df, title="Bollinger Bands and stock price", ylabel="Stock price", xlabel="Date")
    orders = pd.DataFrame(columns=['Date', 'Symbol', 'Order', 'Shares'])

    holding = 0  #holding =200 long; holding=-200 short
    window = dt.datetime(2008, 1, 1)  # window should more than 21
    for (i_row, row), (i_prev, prev) in zip(df.iterrows(),
                                            df.shift(1).iterrows()):
        if prev['MACD Line'] >= 0 and row['MACD Line'] < 0 and (
                i_row - window).days > 21 and holding > -200:
            orders.loc[len(orders)] = [
                i_row, syms[0], 'SELL',
                str(200 + holding)
            ]
            holding -= 200 + holding
            window = i_row
            plt.axvline(i_row, color='r')
        if prev['MACD Line'] <= 0 and row['MACD Line'] > 0 and (
                i_row - window).days > 21 and holding < 200:
            orders.loc[len(orders)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding)
            ]  #max buy
            holding += 200 - holding
            window = i_row
            plt.axvline(i_row, color='g')
        if prev['MACD Line'] >= prev['Signal Line'] and row['MACD Line'] < row[
                'Signal Line'] and (
                    i_row -
                    window).days > 21 and holding > -200 and row['RSI'] > 70:
            orders.loc[len(orders)] = [
                i_row, syms[0], 'SELL',
                str(200 + holding)
            ]
            holding -= 200 + holding
            window = i_row
            plt.axvline(i_row, color='r')
        if prev['MACD Line'] <= prev['Signal Line'] and row['MACD Line'] > row[
                'Signal Line'] and (i_row -
                                    window).days > 21 and holding < 200:
            orders.loc[len(orders)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding)
            ]  #max buy
            holding += 200 - holding
            window = i_row
            plt.axvline(i_row, color='g')

        if prev[syms[0]] <= prev['Lower Band'] and row[
                syms[0]] > row['Lower Band'] and (
                    i_row -
                    window).days > 21 and holding < 200:  # cross up Lower Band
            orders.loc[len(orders)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding)
            ]  #max buy
            holding += 200 - holding
            window = i_row
            plt.axvline(i_row, color='g')
        if prev[syms[0]] <= prev['Middle Band'] and row[
                syms[0]] > row['Middle Band'] and (
                    i_row - window).days > 21 and holding > -200 and row[
                        'RSI'] > 70:  # cross up Middle Band
            orders.loc[len(orders)] = [
                i_row, syms[0], 'SELL',
                str(200 + holding)
            ]
            holding -= 200 + holding
            window = i_row
            plt.axvline(i_row, color='r')
        # if prev[syms[0]] >= prev['Upper Band'] and row[syms[0]] < row['Upper Band'] and (i_row-window).days>21 and holding>-200 and row['RSI']>70: # cross down Upper Band
        #     orders.loc[len(orders)] = [i_row, syms[0], 'SELL', str(200+holding)]
        #     holding -= 200+holding
        #     window = i_row
        #     plt.axvline(i_row, color='r')
        if prev[syms[0]] >= prev['Middle Band'] and row[
                syms[0]] < row['Middle Band'] and (
                    i_row - window
                ).days > 21 and holding < 200:  # cross down Middle Band
            orders.loc[len(orders)] = [
                i_row, syms[0], 'BUY',
                str(200 - holding)
            ]
            holding += 200 - holding
            window = i_row
            plt.axvline(i_row, color='g')

    file_dir = os.path.join('orders', 'orders.csv')
    orders.to_csv(file_dir)

    Compare_df = BestPossible()
    benchmark = Compare_df['Benchmark']
    of = "./orders/orders.csv"
    sv = 100000
    portvals = compute_portvals(orders_file=of, start_val=sv)
    portvals = portvals / portvals.ix[0, :]
    benchmark = benchmark / benchmark.ix[0, :]
    #plot_data(plot_df, title="Benchmark vs. Rule-based portfolio", ylabel="Normalized price", xlabel="Date")
    prices_port = prices_port / prices_port.ix[0, :]
    plt.plot(prices_port.index,
             portvals,
             label='Rule-based portfolio',
             color='b')
    plt.plot(prices_port.index, prices_port, label='APPL', color='m')
    plt.plot(benchmark.index, benchmark, label='Benchmark', color='k')
    plt.title('Benchmark vs. Rule-based portfolio')
    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.legend(loc='lower right')
    plt.show()
Ejemplo n.º 10
0
    def __init__(self,
                 fitting_file='BTC-USD_2019-04-07.csv.xz',
                 testing_file='BTC-USD_2019-04-08.csv.xz',
                 step_size=1,
                 max_position=5,
                 window_size=10,
                 seed=1,
                 action_repeats=10,
                 training=True,
                 format_3d=True,
                 z_score=True,
                 reward_type='default',
                 scale_rewards=True,
                 ema_alpha=EMA_ALPHA):
        """
        Base class for creating environments extending OpenAI's GYM framework.

        :param fitting_file: historical data used to fit environment data (i.e.,
            previous trading day)
        :param testing_file: historical data used in environment
        :param step_size: increment size for steps (NOTE: leave a 1, otherwise market
            transaction data will be overlooked)
        :param max_position: maximum number of positions able to hold in inventory
        :param window_size: number of lags to include in observation space
        :param seed: random seed number
        :param action_repeats: number of steps to take in environment after a given action
        :param training: if TRUE, then randomize starting point in environment
        :param format_3d: if TRUE, reshape observation space from matrix to tensor
        :param z_score: if TRUE, normalize data set with Z-Score, otherwise use Min-Max
            (i.e., range of 0 to 1)
        :param reward_type: method for calculating the environment's reward:
            1) 'trade_completion' --> reward is generated per trade's round trip
            2) 'continuous_total_pnl' --> change in realized & unrealized pnl between
                                            time steps
            3) 'continuous_realized_pnl' --> change in realized pnl between time steps
            4) 'continuous_unrealized_pnl' --> change in unrealized pnl between time steps
            5) 'normed' --> refer to https://arxiv.org/abs/1804.04216v1
            6) 'div' --> reward is generated per trade's round trip divided by
                inventory count (again, refer to https://arxiv.org/abs/1804.04216v1)
            7) 'asymmetrical' --> extended version of *default* and enhanced
                with a reward for being filled above/below midpoint,
                and returns only negative rewards for Unrealized PnL to
                discourage long-term speculation.
            8) 'asymmetrical_adj' --> extended version of *default* and enhanced
                with a reward for being filled above/below midpoint,
                and weighted up/down unrealized returns.
            9) 'default' --> Pct change in Unrealized PnL + Realized PnL of
                respective time step.
        :param ema_alpha: decay factor for EMA, usually between 0.9 and 0.9999; if NONE,
            raw values are returned in place of smoothed values
        """
        # properties required for instantiation
        self.action_repeats = action_repeats
        self._seed = seed
        self._random_state = np.random.RandomState(seed=self._seed)
        self.training = training
        self.step_size = step_size
        self.max_position = max_position
        self.window_size = window_size
        self.reward_type = reward_type
        self.format_3d = format_3d  # e.g., [window, features, *NEW_AXIS*]
        self.sym = testing_file[:7]  # slice the CCY from the filename
        self.scale_rewards = scale_rewards

        # properties that get reset()
        self.reward = 0.0
        self.done = False
        self.local_step_number = 0
        self.midpoint = 0.0
        self.observation = None
        self.action = 0
        self.last_pnl = 0.
        self.last_midpoint = None
        self.midpoint_change = None

        # properties to override in sub-classes
        self.actions = None
        self.broker = None
        self.action_space = None
        self.observation_space = None

        # get historical data for simulations
        self.sim = Sim(z_score=z_score, alpha=ema_alpha)

        self.prices_, self.data, self.normalized_data = self.sim.load_environment_data(
            fitting_file=fitting_file,
            testing_file=testing_file,
            include_imbalances=True,
            as_pandas=False)
        self.best_bid = self.best_ask = None

        self.max_steps = self.data.shape[
            0] - self.step_size * self.action_repeats - 1

        # load indicators into the indicator manager
        self.tns = IndicatorManager()
        self.rsi = IndicatorManager()
        for window in INDICATOR_WINDOW:
            self.tns.add(
                ('tns_{}'.format(window), TnS(window=window, alpha=ema_alpha)))
            self.rsi.add(
                ('rsi_{}'.format(window), RSI(window=window, alpha=ema_alpha)))

        # conditionally load PnlNorm, since it calculates in O(n) time complexity
        self.pnl_norm = PnlNorm(
            window=INDICATOR_WINDOW[0],
            alpha=None) if self.reward_type == 'normed' else None

        # rendering class
        self._render = TradingGraph(sym=self.sym)

        # graph midpoint prices
        self._render.reset_render_data(
            y_vec=self.prices_[:np.shape(self._render.x_vec)[0]])

        # buffer for appending lags
        self.data_buffer = list()
Ejemplo n.º 11
0
def myTradingSystem(
        DATE, OPEN, HIGH, LOW, CLOSE, VOL, USA_ADP, USA_EARN, USA_HRS, USA_BOT,
        USA_BC, USA_BI, USA_CU, USA_CF, USA_CHJC, USA_CFNAI, USA_CP, USA_CCR,
        USA_CPI, USA_CCPI, USA_CINF, USA_DFMI, USA_DUR, USA_DURET, USA_EXPX,
        USA_EXVOL, USA_FRET, USA_FBI, USA_GBVL, USA_GPAY, USA_HI, USA_IMPX,
        USA_IMVOL, USA_IP, USA_IPMOM, USA_CPIC, USA_CPICM, USA_JBO, USA_LFPR,
        USA_LEI, USA_MPAY, USA_MP, USA_NAHB, USA_NLTTF, USA_NFIB, USA_NFP,
        USA_NMPMI, USA_NPP, USA_EMPST, USA_PHS, USA_PFED, USA_PP, USA_PPIC,
        USA_RSM, USA_RSY, USA_RSEA, USA_RFMI, USA_TVS, USA_UNR, USA_WINV,
        exposure, equity, settings):

    nMarkets = CLOSE.shape[1]
    lookback = settings['lookback']
    pos = np.zeros(nMarkets)
    markets = settings['markets']
    w = settings['market_factor_weights']
    lweights, sweights = econ_long_short_allocation(
        markets,
        DATE[0],
        DATE[-1],
        w,
        activate=settings['dynamic_portfolio_allocation'])
    sentiment_data = settings['sentiment_data']
    covid_data = settings['covid_data']

    # to understand how this system works
    print("Using data from {} onwards to predict/take position in {}".format(
        DATE[0], DATE[-1]))

    OPEN = np.transpose(OPEN)[1:]
    HIGH = np.transpose(HIGH)[1:]
    LOW = np.transpose(LOW)[1:]
    CLOSE = np.transpose(CLOSE)[1:]
    VOL = np.transpose(VOL)[1:]

    if settings['model'] == 'TA':
        '''
        Based on factors from https://www.investing.com/technical/us-spx-500-futures-technical-analysis

        ################ TREND FOLOWING ################
        Simple Moving Average (SMA) crosses, period 5,10,20,50,100,200
        '''
        # indicators
        SMA5s = [SMA(close, 5) for close in CLOSE]
        SMA10s = [SMA(close, 10) for close in CLOSE]
        SMA20s = [SMA(close, 20) for close in CLOSE]
        SMA50s = [SMA(close, 50) for close in CLOSE]
        SMA100s = [SMA(close, 100) for close in CLOSE]
        SMA200s = [SMA(close, 200) for close in CLOSE]

        # signals
        def buy_condition(close, sma):
            return (close[-1] > sma[-1]) and (close[-2] <= sma[-2])

        def sell_condition(close, sma):
            return (close[-1] < sma[-1]) and (close[-2] >= sma[-2])

        SMA5_cross_buys = [
            True if buy_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA5s)
        ]
        SMA5_cross_sells = [
            True if sell_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA5s)
        ]
        SMA10_cross_buys = [
            True if buy_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA10s)
        ]
        SMA10_cross_sells = [
            True if sell_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA10s)
        ]
        SMA20_cross_buys = [
            True if buy_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA20s)
        ]
        SMA20_cross_sells = [
            True if sell_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA20s)
        ]
        SMA50_cross_buys = [
            True if buy_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA50s)
        ]
        SMA50_cross_sells = [
            True if sell_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA50s)
        ]
        SMA100_cross_buys = [
            True if buy_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA100s)
        ]
        SMA100_cross_sells = [
            True if sell_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA100s)
        ]
        SMA200_cross_buys = [
            True if buy_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA200s)
        ]
        SMA200_cross_sells = [
            True if sell_condition(close, sma) else False
            for close, sma in zip(CLOSE, SMA200s)
        ]
        '''
        Exponential Moving Average (EMA) crosses, period 5,10,20,50,100,200
        '''
        # indicators
        EMA5s = [EMA(close, 5) for close in CLOSE]
        EMA10s = [EMA(close, 10) for close in CLOSE]
        EMA20s = [EMA(close, 20) for close in CLOSE]
        EMA50s = [EMA(close, 50) for close in CLOSE]
        EMA100s = [EMA(close, 100) for close in CLOSE]
        EMA200s = [EMA(close, 200) for close in CLOSE]

        # signals
        # def condition(close, ema):
        #     return (close[-1] > ema[-1]) and (close[-2] <= ema[-2])
        def buy_condition(close, ema):
            return (close[-1] > ema[-1]) and (close[-2] <= ema[-2])

        def sell_condition(close, ema):
            return (close[-1] < ema[-1]) and (close[-2] >= ema[-2])

        EMA5_cross_buys = [
            True if buy_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA5s)
        ]
        EMA5_cross_sells = [
            True if sell_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA5s)
        ]
        EMA10_cross_buys = [
            True if buy_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA10s)
        ]
        EMA10_cross_sells = [
            True if sell_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA10s)
        ]
        EMA20_cross_buys = [
            True if buy_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA20s)
        ]
        EMA20_cross_sells = [
            True if sell_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA20s)
        ]
        EMA50_cross_buys = [
            True if buy_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA50s)
        ]
        EMA50_cross_sells = [
            True if sell_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA50s)
        ]
        EMA100_cross_buys = [
            True if buy_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA100s)
        ]
        EMA100_cross_sells = [
            True if sell_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA100s)
        ]
        EMA200_cross_buys = [
            True if buy_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA200s)
        ]
        EMA200_cross_sells = [
            True if sell_condition(close, ema) else False
            for close, ema in zip(CLOSE, EMA200s)
        ]
        '''
        Average Directional Movement Index (ADX), period 14
        '''
        # indicators
        ADXs = [
            ADX(high, low, close, 14)
            for high, low, close in zip(HIGH, LOW, CLOSE)
        ]

        # signals
        # adx[0] is mDI, adx[1] is pDI, adx[2] is actual ADX
        def bullish_condition(adx):
            # Bullish strong trend cross
            return (adx[2][-1] > 20) and (adx[1][-1] > adx[0][-1]) and (
                adx[1][-2] <= adx[0][-2])

        def bearish_condition(adx):
            # Bearish strong trend cross
            return (adx[2][-1] > 20) and (adx[1][-1] < adx[0][-1]) and (
                adx[1][-2] >= adx[0][-2])

        ADX_bullish_crosses = [
            True if bullish_condition(adx) else False for adx in ADXs
        ]
        ADX_bearish_crosses = [
            True if bearish_condition(adx) else False for adx in ADXs
        ]
        '''
        Moving Average Convergence Divergence (MACD) fast=12, slow=26
        '''
        # indicator
        EMA12s = [EMA(close, 12) for close in CLOSE]
        EMA26s = [EMA(close, 26) for close in CLOSE]
        MACDs = [[(a - b) if b is not None else None
                  for a, b in zip(EMA12, EMA26)]
                 for EMA12, EMA26 in zip(EMA12s, EMA26s)]

        # signals
        def bullish_condition(MACD):
            # Bullish zero cross which sustains for 2 days (reduce false signals)
            return (MACD[-3] <= 0) and (MACD[-2] > 0) and (MACD[-1] > 0)

        def bearish_condition(MACD):
            # Bearish zero cross
            return (MACD[-3] >= 0) and (MACD[-2] < 0) and (MACD[-1] < 0)

        MACD_bullish_zero_cross = [
            True if bullish_condition(MACD) else False for MACD in MACDs
        ]
        MACD_bearish_zero_cross = [
            True if bearish_condition(MACD) else False for MACD in MACDs
        ]
        '''
        Commodity Channel Index (CCI), period 14
        '''
        # indicator
        CCIs = [
            CCI(high, low, close, 14)
            for high, low, close in zip(HIGH, LOW, CLOSE)
        ]

        # signals
        def bullish_condition(CCI):
            return (CCI[-1] > 100) and (CCI[-2] <= 100)

        def bearish_condition(CCI):
            return (CCI[-1] < -100) and (CCI[-2] >= -100)

        CCI_emerging_bulls = [
            True if bullish_condition(CCI) else False for CCI in CCIs
        ]
        CCI_emerging_bears = [
            True if bearish_condition(CCI) else False for CCI in CCIs
        ]
        '''
        ################ MOMENTUM ################
        Relative Strength Index (RSI), period 14
        '''
        # indicator
        RSIs = [RSI(close) for close in CLOSE]

        # signals
        def bullish_reversal(rsi, sma200, close):
            # Uptrend and cross 30 to become oversold (Bullish)
            return (close[-1] > sma200[-1]) and (rsi[-2] >= 30) and (rsi[-1] <
                                                                     30)

        def bearish_reversal(rsi, sma200, close):
            # Downtrend and cross 70 to become overbought (Bearish)
            return (close[-1] < sma200[-1]) and (rsi[-2] <= 70) and (rsi[-1] >
                                                                     70)

        def underbought_uptrend(rsi, sma200, close):
            # Uptrend and underbought
            return (close[-1] > sma200[-1]) and (rsi[-1] < 50)

        def undersold_downtrend(rsi, sma200, close):
            # Downtrend and undersold
            return (close[-1] < sma200[-1]) and (rsi[-1] > 50)

        RSI_bullish_reversal = [
            True if bullish_reversal(rsi, sma200, close) else False
            for rsi, sma200, close in zip(RSIs, SMA200s, CLOSE)
        ]
        RSI_bearish_reversal = [
            True if bearish_reversal(rsi, sma200, close) else False
            for rsi, sma200, close in zip(RSIs, SMA200s, CLOSE)
        ]
        RSI_underbought_uptrend = [
            True if underbought_uptrend(rsi, sma200, close) else False
            for rsi, sma200, close in zip(RSIs, SMA200s, CLOSE)
        ]
        RSI_undersold_downtrend = [
            True if undersold_downtrend(rsi, sma200, close) else False
            for rsi, sma200, close in zip(RSIs, SMA200s, CLOSE)
        ]
        '''
        Stochastic Oscillator, fast 14, slow 3
        '''
        # indicators
        StochOscs = [
            StochOsc(close, high, low, 14, 3)
            for close, high, low in zip(CLOSE, HIGH, LOW)
        ]

        # signals
        # stochosc[0] is Ks, stochosc[1] is Ds
        def bullish_cross(stochosc):
            # K (fast) cross D (slow) from below
            return (stochosc[0][-2] <= stochosc[1][-2]) and (stochosc[0][-1] >
                                                             stochosc[1][-1])

        def bearish_cross(stochosc):
            # K (fast) cross D (slow) from above
            return (stochosc[0][-2] >= stochosc[1][-2]) and (stochosc[0][-1] <
                                                             stochosc[1][-1])

        StochOsc_bullish_cross = [
            True if bullish_cross(stochosc) else False
            for stochosc in StochOscs
        ]
        StochOsc_bearish_cross = [
            True if bearish_cross(stochosc) else False
            for stochosc in StochOscs
        ]
        '''
        Williams %R, 14 period
        '''
        # indicator
        WilliamsRs = [
            WilliamsR(high, low, close)
            for high, low, close in zip(HIGH, LOW, CLOSE)
        ]

        # signals
        def bullish(wr, close, sma100):
            # Overbought price action
            return (wr[-1] > -20) and (close[-1] > sma100[-1]) and (
                close[-2] <= sma100[-2])

        def bearish(wr, close, sma100):
            # Oversold price action
            return (wr[-1] < -80) and (close[-1] < sma100[-1]) and (
                close[-2] >= sma100[-2])

        WilliamsR_uptrend = [
            True if bullish(wr, close, sma100) else False
            for wr, close, sma100 in zip(WilliamsRs, CLOSE, SMA100s)
        ]
        WilliamsR_downtrend = [
            True if bearish(wr, close, sma100) else False
            for wr, close, sma100 in zip(WilliamsRs, CLOSE, SMA100s)
        ]
        ''' 
        Ultimate Oscillator, periods 20,40,80
        '''
        # indicator
        UltiOscs = [
            UltiOsc(high, low, close, 20, 40, 80)
            for high, low, close in zip(HIGH, LOW, CLOSE)
        ]

        # signals
        def bullish_cross(ultiosc):
            # Bullish center cross
            return (ultiosc[-1] > 50) and (ultiosc[-2] <= 50)

        def bearish_cross(ultiosc):
            # Bearish center cross
            return (ultiosc[-1] < 50) and (ultiosc[-2] >= 50)

        def bullish_reversal(ultiosc):
            # Bullish reversal from oversold
            return (ultiosc[-1] < 30) and (ultiosc[-2] >= 30)

        def bearish_reversal(ultiosc):
            # Bearish reversal from overbought
            return (ultiosc[-1] > 70) and (ultiosc[-2] >= 70)

        UltiOsc_bullish_cross = [
            True if bullish_cross(ultiosc) else False for ultiosc in UltiOscs
        ]
        UltiOsc_bearish_cross = [
            True if bearish_cross(ultiosc) else False for ultiosc in UltiOscs
        ]
        UltiOsc_bullish_reversal = [
            True if bullish_reversal(ultiosc) else False
            for ultiosc in UltiOscs
        ]
        UltiOsc_bearish_reversal = [
            True if bearish_reversal(ultiosc) else False
            for ultiosc in UltiOscs
        ]
        '''
        ################ VOLUME ################
        Accumulation / Distribution Index (ADI)
        '''
        # indicator
        ADIs = [
            ADI(high, low, close, vol)
            for high, low, close, vol in zip(HIGH, LOW, CLOSE, VOL)
        ]

        def bullish_trend(close, adi, sma200):
            # bullish trend confirmation
            return (close[-1] > sma200[-1]) and (close[-2] <= sma200[-2]) and (
                adi[-1] > adi[-2])

        def bearish_trend(close, adi, sma200):
            # bearish trend confirmation
            return (close[-1] < sma200[-1]) and (close[-2] >= sma200[-2]) and (
                adi[-1] < adi[-2])

        ADI_bullish_trend_confo = [
            True if bullish_trend(close, adi, sma200) else False
            for close, adi, sma200 in zip(CLOSE, ADIs, SMA200s)
        ]
        ADI_bearish_trend_confo = [
            True if bearish_trend(close, adi, sma200) else False
            for close, adi, sma200 in zip(CLOSE, ADIs, SMA200s)
        ]
        '''
        On-Balance Volume (OBV)
        '''
        # indicator
        OBVs = [OBV(close, vol) for close, vol in zip(CLOSE, VOL)]

        # signals
        def bullish_trend(obv):
            return (obv[-1] > obv[-2]) and (obv[-2] > obv[-3])

        def bearish_trend(obv):
            return (obv[-1] < obv[-2]) and (obv[-2] < obv[-3])

        OBV_bullish_trend_confo = [
            True if bullish_trend(obv) else False for obv in OBVs
        ]
        OBV_bearish_trend_confo = [
            True if bearish_trend(obv) else False for obv in OBVs
        ]
        '''
        ################ VOLATILITY ################
        Bollinger Bands (BB), 20 period
        '''
        # indicator + signal
        BBs = [BB(close, 20) for close in CLOSE]
        BB_bullish_reversal = [True if bb[1][-1] == 1 else False for bb in BBs]
        BB_bearish_reversal = [True if bb[0][-1] == 1 else False for bb in BBs]
        '''
        Execution
        '''
        for i in range(0, nMarkets - 1):
            future_name = markets[i + 1]
            # # Trend following
            # if (SMA5_cross_buys[i] == True) or (SMA10_cross_buys[i] == True) or (SMA20_cross_buys[i] == True) or (SMA50_cross_buys[i] == True) or (SMA100_cross_buys[i] == True) or (SMA200_cross_buys == True):
            #     pos[i+1] = 1
            # if (SMA5_cross_sells[i] == True) or (SMA10_cross_sells[i] == True) or (SMA20_cross_sells[i] == True) or (SMA50_cross_sells[i] == True) or (SMA100_cross_sells[i] == True) or (SMA200_cross_sells == True):
            #     pos[i+1] = -1

            # Mean reverting
            # if (SMA5_cross_buys[i] == True) or (SMA10_cross_buys[i] == True) or (SMA20_cross_buys[i] == True) or (SMA50_cross_buys[i] == True) or (SMA100_cross_buys[i] == True) or (SMA200_cross_buys == True):
            #     pos[i+1] = -1
            # if (SMA5_cross_sells[i] == True) or (SMA10_cross_sells[i] == True) or (SMA20_cross_sells[i] == True) or (SMA50_cross_sells[i] == True) or (SMA100_cross_sells[i] == True) or (SMA200_cross_sells == True):
            #     pos[i+1] = 1

            # # Trend following
            # if (EMA5_cross_buys[i] == True) or (EMA10_cross_buys[i] == True) or (EMA20_cross_buys[i] == True) or (EMA50_cross_buys[i] == True) or (EMA100_cross_buys[i] == True) or (EMA200_cross_buys == True):
            #     pos[i+1] = 1
            # if (EMA5_cross_sells[i] == True) or (EMA10_cross_sells[i] == True) or (EMA20_cross_sells[i] == True) or (EMA50_cross_sells[i] == True) or (EMA100_cross_sells[i] == True) or (EMA200_cross_sells == True):
            #     pos[i+1] = -1

            # # Mean-reverting
            # if (EMA5_cross_buys[i] == True) or (EMA10_cross_buys[i] == True) or (EMA20_cross_buys[i] == True) or (EMA50_cross_buys[i] == True) or (EMA100_cross_buys[i] == True) or (EMA200_cross_buys == True):
            #     pos[i+1] = -1
            # if (EMA5_cross_sells[i] == True) or (EMA10_cross_sells[i] == True) or (EMA20_cross_sells[i] == True) or (EMA50_cross_sells[i] == True) or (EMA100_cross_sells[i] == True) or (EMA200_cross_sells == True):
            #     pos[i+1] = 1

            # if ADX_bullish_crosses[i] == True:
            #     pos[i+1] = 1
            # elif ADX_bearish_crosses[i] == True:
            #     pos[i+1] = -1

            # if MACD_bullish_zero_cross[i] == True:
            #     pos[i+1] = 1
            # elif MACD_bearish_zero_cross[i] == True:
            #     pos[i+1] = -1

            # if CCI_emerging_bulls[i] == True:
            #     pos[i+1] = 1
            # elif CCI_emerging_bears[i] == True:
            #     pos[i+1] = -1

            # if RSI_bullish_reversal[i] == True:
            #     pos[i+1] = 1
            # elif RSI_bearish_reversal[i] == True:
            #     pos[i+1] = -1

            # if StochOsc_bullish_cross[i] == True:
            #     pos[i+1] = 1
            # elif StochOsc_bearish_cross[i] == True:
            #     pos[i+1] = -1

            # if WilliamsR_uptrend[i] == True:
            #     pos[i+1] = 1
            # elif WilliamsR_downtrend[i] == True:
            #     pos[i+1] = -1

            # if UltiOsc_bullish_cross[i] == True:
            #     pos[i+1] = 1
            # elif UltiOsc_bearish_cross[i] == True:
            #     pos[i+1] = -1

            # if UltiOsc_bullish_reversal[i] == True:
            #     pos[i+1] = 1
            # elif UltiOsc_bearish_reversal[i] == True:
            #     pos[i+1] = -1

            # if ADI_bullish_trend_confo[i] == True:
            #     pos[i+1] = lweights[future_name]
            # elif ADI_bearish_trend_confo[i] == True:
            #     pos[i+1] = sweights[future_name]

            # if OBV_bullish_trend_confo[i] == True:
            #     pos[i+1] = 1
            # elif OBV_bearish_trend_confo[i] == True:
            #     pos[i+1] = -1

            # # Mean-reverting
            # if BB_bullish_reversal[i] == True:
            #     pos[i+1] = 1
            # elif BB_bearish_reversal[i] == True:
            #     pos[i+1] = -1

            # # Trend-following
            if BB_bullish_reversal[i] == True:
                pos[i + 1] = sweights[future_name]
            elif BB_bearish_reversal[i] == True:
                pos[i + 1] = lweights[future_name]

    elif settings['model'] == 'LIGHTGBM':
        for i in range(0, nMarkets - 1):
            future_name = markets[i + 1]
            if future_name in [
                    "CASH", "F_ED", "F_UZ", "F_SS", "F_ZQ", "F_EB", "F_VW",
                    "F_F"
            ]:
                feature_ADI = ADI(HIGH[i], LOW[i], CLOSE[i], VOL[i])
                feature_WilliamsR = WilliamsR(HIGH[i], LOW[i], CLOSE[i])
                feature_BB_high_crosses, feature_BB_low_crosses = BB(
                    CLOSE[i], 10)
                feature_CCI = CCI(LOW[i], CLOSE[i], VOL[i], 10)
                features = np.array([[
                    OPEN[i][-1],
                    HIGH[i][-1],
                    LOW[i][-1],
                    CLOSE[i][-1],
                    VOL[i][-1],
                    feature_ADI[-1],
                    feature_WilliamsR[-1],
                    feature_BB_high_crosses[-1],
                    feature_BB_low_crosses[-1],
                    feature_CCI[-1],
                    CLOSE[i][-2],
                    CLOSE[i][-3],
                ]])
                model_dir = f"./data/lgb_models/{markets[i+1]}_model"
                prediction = get_lgb_prediction(model_dir, features)[0]
                if prediction == 1:
                    pos[i + 1] = lweights[future_name]
                elif prediction == -1:
                    pos[i + 1] = sweights[future_name]

    elif settings['model'] == 'sentiment':
        '''
        How sentiment of tweets from Bloomberg/Trump affect VIX, Gold and Treasuries
        '''
        for i in range(0, nMarkets - 1):
            future_name = markets[i + 1]
            if future_name in ['F_GC']:  #'F_VX','F_GC','F_TU'
                sentiment = sentiment_data[future_name]
                today = datetime.strptime(str(DATE[-1]), '%Y%m%d').date()
                if (today - sentiment['DATE'].tolist()[0]
                    ).days > 30:  # at least 30 days for training
                    train = sentiment[sentiment['DATE'] < today]
                    test = sentiment[sentiment['DATE'] == today]
                    trainY = train['CLOSE']
                    del train['DATE'], train['CLOSE']
                    trainX = train
                    del test['DATE'], test['CLOSE']
                    model = RandomForestRegressor()
                    model.fit(trainX, trainY)
                    pred_CLOSE = model.predict(test)[0]
                    if pred_CLOSE > CLOSE[i][-2]:
                        pos[i + 1] = 1
                    else:
                        pos[i + 1] = -1

    elif settings['model'] == 'covid':
        '''
        How no. of covid cases in each country affects their overall markets
        'sharpe': 1.3048, 'sortino': 2.3477,
        avg longs per day: 1.35 , avg shorts per day: 6.6
        '''
        for i in range(0, nMarkets - 1):
            country = None
            future_name = markets[i + 1]
            if future_name in ['F_ES', 'F_MD', 'F_NQ', 'F_RU', 'F_XX', 'F_YM']:
                country = 'US'
            elif future_name in ['F_AX', 'F_DM', 'F_DZ']:
                country = 'Germany'
            elif future_name == 'F_CA':
                country = 'France'
            elif future_name == 'F_LX':
                country = 'United Kingdom'
            elif future_name == 'F_FP':
                country = 'Finland'
            elif future_name == 'F_NY':
                country = 'Japan'
            elif future_name == 'F_PQ':
                country = 'Portugal'
            elif future_name in ['F_SH', 'F_SX']:
                country = 'Switzerland'

            if country:
                df = covid_data[covid_data['Country/Region'] == country].T.sum(
                    axis=1).reset_index()
                df = df.iloc[1:]
                df['index'] = df['index'].apply(lambda x: x + "20")
                df['index'] = df['index'].apply(
                    lambda x: datetime.strptime(x, '%m/%d/%Y').date())
                future = pd.DataFrame({'DATE': DATE, 'CLOSE': CLOSE[i]})
                future['CLOSE'] = future['CLOSE'].shift(-1)
                future['DATE'] = future['DATE'].apply(
                    lambda x: datetime.strptime(str(x), '%Y%m%d').date())
                df = pd.merge(df, future, left_on='index', right_on='DATE')
                df = df[df[0] != 0][[0, 'CLOSE']].rename(columns={0: "count"})
                if len(df) > 10:
                    reg = LinearRegression().fit(
                        np.array(df['count'].values[:-1]).reshape(-1, 1),
                        df['CLOSE'].values[:-1])
                    pred_CLOSE = reg.predict(
                        np.array(df['count'].values[-1]).reshape(1, -1))[0]
                    if pred_CLOSE > CLOSE[i][-2]:
                        pos[i + 1] = 1
                    else:
                        pos[i + 1] = -1

    elif settings['model'] == 'ARIMA':
        for i in range(0, nMarkets - 1):
            try:
                if markets[i + 1] not in ARIMA_MODELS:
                    model = auto_arima(np.log(CLOSE[i][:-1]),
                                       trace=False,
                                       error_action='ignore',
                                       suppress_warnings=True)
                    ARIMA_MODELS[markets[i + 1]] = model.fit(
                        np.log(CLOSE[i][:-1]))
                model = ARIMA_MODELS[markets[i + 1]].fit(np.log(CLOSE[i][:-1]))
                pred = model.predict(n_periods=1)[0]
                # print(markets[i+1],pred, np.log(CLOSE[i][-1]))
                pos[i + 1] = 1 if pred > np.log(CLOSE[i][-1]) else -1
            except:
                pos[i + 1] = 0
        print(f"Today's position in the {len(markets)} futures: {pos}")

    elif settings['model'] == 'GARCH':
        # Log return of the closing data
        #Prameters
        bound1 = 1
        bound2 = 1
        cor_dir = f'./data/garch_models/correlation.txt'
        with open(cor_dir) as f:
            cor_dict = json.load(f)
        log_return = np.diff(np.log(CLOSE))
        #print(log_return)
        #log_return = log_return[~np.isnan(log_return)]
        #print(log_return[1])
        for i in range(0, nMarkets - 1):
            train_Xs = log_return[i][:-1]
            #test_Xs = log_return[i][-1]
            sd = np.var(train_Xs)
            # define model
            model_dir = f'./data/garch_models/{markets[i+1]}_garch_model.txt'
            with open(model_dir) as f:
                params_dict = json.load(f)
            p = params_dict['order'][0]
            q = params_dict['order'][1]
            model = arch_model(train_Xs, p=p, q=q)
            model_fixed = model.fix(params_dict['params'])
            # forecast the test set
            forecasts = model_fixed.forecast()
            #expected = forecasts.mean.iloc[-1:]['h.1']
            var = forecasts.variance.iloc[-1:]['h.1']
            #print(type(variance))

            if (cor_dict[markets[i + 1]] > 0.03):
                if (float(np.sqrt(var)) > bound1 * np.std(train_Xs)):
                    pos[i] = 1
                elif (float(np.sqrt(var)) < bound2 * np.std(train_Xs)):
                    pos[i] = -1
                else:
                    pos[i] = 0
            elif (cor_dict[markets[i + 1]] < -0.03):
                if (float(np.sqrt(var)) > bound1 * np.std(train_Xs)):
                    pos[i] = -1
                elif (float(np.sqrt(var)) < bound2 * np.std(train_Xs)):
                    pos[i] = 1
                else:
                    pos[i] = 0
            else:
                pos[i] = 0
        # With the estimated return and variance, we can apply portfolio optimization
        #print((np.array(result) * np.array(truth)).sum() / len(result))

    elif settings['model'] == 'fourier':
        #Parameters that filter the signal with specific range of signals
        #Note that the lower bound should be larger than 0 and upper bound smaller than 1
        filter_type = 'customed'
        my_frequency_bound = [0.05, 0.2]
        filter_type = 'low'  #Specify high/mid/low/customed for weekly signals, weekly to monthly signals, above monthly signals or customed frequency range
        if filter_type == 'high':
            frequency_bound = [0.2, 1]
        elif filter_type == 'mid':
            frequency_bound = [0.05, 0.2]
        elif filter_type == 'low':
            frequency_bound = [0, 0.05]
        elif filter_type == 'customed':
            frequency_bound = my_frequency_bound

        #Transform the close data by fourier filtering, only signals within the specific range remains
        transformed_close = []
        for i in range(0, nMarkets - 1):
            signal = CLOSE[i][:-1]
            fft = np.fft.rfft(signal)
            T = 1  # sampling interval
            N = len(signal)
            f = np.linspace(0, 1 / T, N)
            fft_filtered = []
            for j in range(int(N / 2)):
                if f[j] > frequency_bound[0] and f[j] < frequency_bound[1]:
                    fft_filtered.append(fft[j])
                else:
                    fft_filtered.append(0)
            signal_filtered = np.fft.irfft(fft_filtered)
            transformed_close.append(list(signal_filtered))

        periodLonger = 200
        periodShorter = 40
        smaLongerPeriod = np.nansum(
            np.array(transformed_close)[:,
                                        -periodLonger:], axis=1) / periodLonger
        smaShorterPeriod = np.nansum(
            np.array(transformed_close)[:, -periodShorter:],
            axis=1) / periodShorter
        longEquity = smaShorterPeriod > smaLongerPeriod
        shortEquity = ~longEquity
        pos_1 = np.zeros(nMarkets - 1)
        pos_1[longEquity] = 1
        pos_1[shortEquity] = -1
        pos = np.array([0] + list(pos_1))

    elif settings['model'] == 'pearson':
        '''
        Pairwise correlation, taking position based on the greatest variation from
        average of the past 50 periods of 50 days
        '''
        #'sharpe': 0.57939, 'sortino': 0.9027189, 'returnYearly': 0.076509, 'volaYearly': 0.13205
        # with allocation
        #avg longs per day: 6.343 , avg shorts per day: 6.746
        d = {}  ##Name of future : Close of all 88 futures
        names = []  ##names of all 88 future
        for i in range(0, nMarkets - 1):
            n = markets[i + 1]
            names.append(n)
            d[n] = (CLOSE[i])
        d_corr = settings['historic_corr']

        ## key = tuple of name of 2 futures, value = position to take for ((future1,future2),difference)
        d_position = {}
        for i in list(d_corr.keys()):
            f = i[0]
            s = i[1]
            tup = d_corr[i]
            l1 = d[f][-49:-1]  ##take last 50 close
            l2 = d[s][-49:-1]  ##take last 50 close
            corr, _ = pearsonr(l1, l2)
            change_f = d[f][-2] - d[f][-49]
            change_s = d[s][-2] - d[s][-49]
            diff = tup - corr
            if diff > 0.3:
                if change_f > change_s:
                    d_position[i] = (
                        (-1, 1), diff
                    )  ##assuming -1 means short while 1 means long
                else:
                    d_position[i] = ((1, -1), diff)

        for i in range(
                len(names)):  ##find position based on greatest variation
            diff = 0
            pair = tuple()
            name = names[i]
            counter = 0
            for k in list(d_position.keys()):
                if name in k:
                    counter += 1
                    pair = k
            if counter == 1:
                if name == k[0]:
                    if d_position[k][0][0] > 0:
                        pos[i + 1] = lweights[name]
                    else:
                        pos[i + 1] = sweights[name]
                else:
                    if d_position[k][0][1] > 0:
                        pos[i + 1] = lweights[name]
                    else:
                        pos[i + 1] = sweights[name]

    elif settings['model'] == 'FASTDTW':
        #'sharpe': 4.8632971, 'sortino': 17.09129, 'returnYearly': 1.216714, 'volaYearly': 0.25018
        # no allocation
        # avg longs per day: 0.328 , avg shorts per day: 0.281
        d = {}  ##Name of future : Close of all 88 futures
        names = []  ##names of all 88 future
        for i in range(0, nMarkets - 1):
            n = markets[i + 1]
            names.append(n)
            d[n] = (CLOSE[i])

        d_dist = settings[
            'historic_dist']  ## key = tuple of name of 2 futures, value = average distance

        d_position = {}
        for i in list(d_dist.keys()):
            f = i[0]
            s = i[1]
            tup = d_dist[i]
            l1 = d[f][-49:-1]  ##take last 50 close
            l2 = d[s][-49:-1]  ##take last 50 close
            distance, _ = fastdtw(l1, l2)
            distance = distance / 50
            change_f = d[f][-2] - d[f][-49]
            change_s = d[s][-2] - d[s][-49]
            diff = distance - tup
            threshold = 16 * tup
            if distance > threshold:
                if change_f > change_s:
                    d_position[i] = (
                        (-1, 1), diff
                    )  ##assuming -1 means short while 1 means long
                else:
                    d_position[i] = ((1, -1), diff)

        for i in range(
                len(names)):  ##find position based on greatest variation
            diff = 0
            name = names[i]
            for k in list(d_position.keys()):
                if name in k:
                    if d_position[k][1] > diff:
                        diff = d_position[k][1]
                        if name == k[0]:
                            if d_position[k][0][0] > 0:
                                pos[i + 1] = lweights[name]
                            else:
                                pos[i + 1] = sweights[name]
                        else:
                            if d_position[k][0][1] > 0:
                                pos[i + 1] = lweights[name]
                            else:
                                pos[i + 1] = sweights[name]

    # check if latest economic data suggests downturn then activate short only strats
    print("Positions:", pos)
    if np.nansum(pos) > 0:
        pos = pos / np.nansum(abs(pos))

    settings['longs'] = settings['longs'] + sum(1 for x in pos if x > 0)
    settings['shorts'] = settings['shorts'] + sum(1 for x in pos if x < 0)
    settings['days'] = settings['days'] + 1
    return pos, settings
Ejemplo n.º 12
0
def application():

    if request.method == 'POST':

        new_request = request.get_json(force=True)
        new_ticker = get_ticker(new_request)

        private_client = AuthenticatedClient(Data.API_Public_Key,
                                             Data.API_Secret_Key,
                                             Data.Passphrase)

        new_order = Order(private_client)
        position = OpenPosition(new_order)
        funds = Capital(private_client)

        indicator = Indicator()
        macd = MACD()

        candle_ticker: str
        stop_time: int
        candle_gra = int

        if position.get_position() and last_instance():

            candle_ticker = new_order.get_key("product_id")
            stop_time = get_time(27976)
            candle_gra = 300

            writer = open(Data.Time, "w")
            writer.write(str(time.time() + 5.0))
            writer.close()

        elif position.get_position() is False:

            candle_ticker = new_ticker
            stop_time = get_time(83925)
            candle_gra = 900

        try:
            indicator.set_candles(product=candle_ticker,
                                  callback=stop_time,
                                  begin=get_time(0),
                                  granularity=candle_gra)
        except ValueError as ve:
            print(ve.with_traceback())
        except NameError as ne:
            print(ne.with_traceback())

        indicator_list = [indicator, macd]
        try:
            for value in indicator_list:
                value.candles = indicator.candles
                value.set_indicator()
                value.set_dates()
        except Exception as e:
            print(e.with_traceback())

        indicator_5m = Indicator()
        macd_5m = MACD()

        if position.get_position() is False:

            if macd.hist[-1] > macd.hist[-2]:
                try:
                    indicator_5m.set_candles(product=new_ticker,
                                             callback=get_time(27976),
                                             begin=get_time(0),
                                             granularity=900)
                except ValueError as ve:
                    print(ve.with_traceback())
        else:
            indicator_5m = indicator
            macd_5m = macd

        volume_5m = VolSMA(timeperiod=20)
        bands2dev_5m = BB()
        bands1dev_5m = BB(ndbevup=1, nbdevdn=1)
        rsi_5m = RSI()
        ema_5m = EMA()
        momentum_5m = Momentum()

        indicators = [
            indicator_5m, macd_5m, volume_5m, bands1dev_5m, bands2dev_5m,
            rsi_5m, ema_5m, momentum_5m
        ]

        try:
            for value in indicators:
                value.candles = indicator_5m.candles
                value.set_indicator()
                value.set_dates()
        except Exception as e:
            print(e.with_traceback())

        strategy_5m = Strategy(indicator_5m, macd_5m, bands1dev_5m,
                               bands2dev_5m, volume_5m, rsi_5m, ema_5m,
                               new_order)

        try:
            strategy_5m.strategy(-1)
        except Exception as e:
            print(e.with_traceback())

        trade_side: str
        trade_product: str
        trade_funds: str

        if (new_order.is_bottom()) and (position.get_position() is False):
            trade_side = "buy"
            trade_product = new_ticker
            trade_funds = funds.get_capital()
        elif (new_order.is_top()) and (position.get_position()):
            trade_side = "sell"
            trade_product = new_order.get_key("product_id")
            trade_funds = get_size(trade_product,
                                   new_order.get_key("filled_size"))

        try:
            new_trade = private_client.place_market_order(
                product_id=trade_product, side=trade_side, funds=trade_funds)
            writer = open(Data.Path, "w")
            writer.write(new_trade['id'])
            writer.close()
            writer = open(Data.Time, "w")
            writer.write(new_trade['done_at'])
            writer.close()
        except NameError as ne:
            print(ne.with_traceback())
        except KeyError as ke:
            print(ke.with_traceback())

        return 'success', 200

    elif request.method == 'GET':
        return redirect('http://3.218.228.129/login')

    else:
        abort(400)
Ejemplo n.º 13
0
 def __init__(self, rsi=RSI(), order=Order()):
     super(RSISTrategy, self).__init__(rsi=rsi, order=order)
Ejemplo n.º 14
0
    bbp = BBP(pdf, lookback)
    print('BBP:')
    print("====")
    print('')
    print(bbp.tail(30))
    print('')
    plot_BBP(sym, bbp, pdf)

    # rsi = RSI_indicator_v1(pdf, lookback)
    # rsi = RSI_indicator_v2(pdf, lookback)
    # rsi = RSI_indicator_v3(pdf, lookback)
    # rsi = RSI_indicator_v4(pdf, lookback)
    # rsi = RSI_indicator_v5(pdf, lookback)
    # rsi = RSI_indicator_v6(pdf, lookback)
    rsi = RSI(pdf, lookback)
    print('RSI:')
    print("====")
    print('')
    print(rsi.tail(30))
    print('')

    plot_RSI(sym, rsi, pdf)

    mfi = MFI(vdf, hdf, ldf, pdf, lookback)
    print('MFI:')
    print("====")
    print('')
    print(mfi.tail(30))
    print('')
    plot_MFI(sym, mfi, pdf)
def test_run():
    #construct indicator and decision
    dates = pd.date_range('2008-1-1', '2009-12-31')
    syms = ['AAPL']
    prices_all = get_data(syms, dates)
    prices_port = prices_all[syms]  # only price of each stock in portfolio

    bb = BB(prices_port, lookback=20)
    bb=bb.fillna(method='bfill')
    macd = MACD(prices_port)
    rsi = RSI(prices_port, lookback=14)
    df = pd.concat([prices_port, bb, macd, rsi], axis=1)
    df = df.fillna(method='bfill')

    indicators = pd.DataFrame(columns=['MACD_ZERO', 'MACD_SIGNAL', 'ACROSS_BAND', 'BB_value', 'RSI','Decision'])

    indicators['BB_value'] = (df[syms[0]] - bb['Middle Band']) / (bb['Upper Band'] - bb['Middle Band'])
    indicators['MACD_ZERO']=macd['MACD Line']
    indicators['MACD_SIGNAL'] = macd['Signal Line']
    indicators['ACROSS_BAND'] = bb['Middle Band']
    indicators['RSI'] = rsi['RSI']
    indicators2 = indicators[['MACD_SIGNAL', 'MACD_ZERO']]
    indicators2 = (indicators2 - indicators2.mean(axis=0)) / indicators2.std(axis=0)
    indicators2['Color']='k'
    # construct indicators
    # for (i_row, row), (i_prev, prev) in zip(df.iterrows(), df.shift(1).iterrows()):
    #     if prev['MACD Line'] >= 0 and row['MACD Line'] < 0:  # MACD prev>0,now<0, SELL MACD_ZERO=-1
    #         indicators.ix[i_row,'MACD_ZERO']=-1
    #     if prev['MACD Line'] <= 0 and row['MACD Line'] > 0:  # MACD prev<0,now>0, BUY MACD_ZERO=1
    #         indicators.ix[i_row, 'MACD_ZERO'] = 1
    #     if prev['MACD Line'] >= prev['Signal Line'] and row['MACD Line'] < row['Signal Line']: # MACD prev>Signal Line,now<Signal line, SELL MACD_Signal=-1
    #         indicators.ix[i_row,'MACD_SIGNAL']=-1
    #     if prev['MACD Line'] <= prev['Signal Line'] and row['MACD Line'] > row['Signal Line']:  # MACD prev<Signal Line,now>Signal line, BUY MACD_Signal=1
    #         indicators.ix[i_row, 'MACD_SIGNAL'] = 1
    #     if prev[syms[0]] <= prev['Lower Band'] and row[syms[0]] > row['Lower Band']:  # cross up Lower Band, BUY Acroo_band=1
    #         indicators.ix[i_row, 'ACROSS_BAND'] = 1
    #     if prev[syms[0]] >= prev['Upper Band'] and row[syms[0]] < row['Upper Band']: # cross down Upper Band SELL Acroo_band=-1
    #         indicators.ix[i_row, 'ACROSS_BAND'] = -1
    #     if row['RSI']>70:     #RSI>70 overbought, likely to sell it
    #         indicators.ix[i_row, 'RSI'] = -1
    #     if row['RSI'] < 30:   #RSI<30, oversold, likely to buy it.
    #         indicators.ix[i_row, 'RSI'] = 1
    # construct decision

    indicators = (indicators - indicators.mean(axis=0)) / indicators.std(axis=0)

    YBUY=0.05
    YSELL=-0.05
    for (i_row, row), (i_future, future) in zip(df.iterrows(), df.shift(-21).iterrows()):
        if (future[syms[0]]/row[syms[0]]-1)> YBUY: # if 21 days return exceed YBUY, then BUY Decision=1
            indicators.ix[i_row, 'Decision'] = 1
            indicators2.ix[i_row, 'Color'] = 'g'
        if (future[syms[0]] / row[syms[0]] - 1) < YSELL:  # if 21 days return less than YSELL, then SELL Decision=-1
            indicators.ix[i_row, 'Decision'] = -1
            indicators2.ix[i_row, 'Color'] = 'r'

    indicators=indicators.fillna(0)


    #print indicators
    file_dir = os.path.join('orders', 'indicators.csv')
    file_dir2 = os.path.join('orders', 'Training data.csv')
    indicators.to_csv(file_dir, header=False, index=False)

    indicators2.to_csv(file_dir2)
Ejemplo n.º 16
0
    def __init__(self,
                 symbol: str,
                 fitting_file: str,
                 testing_file: str,
                 max_position: int = 10,
                 window_size: int = 100,
                 seed: int = 1,
                 action_repeats: int = 5,
                 training: bool = True,
                 format_3d: bool = False,
                 reward_type: str = 'default',
                 transaction_fee: bool = True,
                 ema_alpha: list or float or None = EMA_ALPHA):
        """
        Base class for creating environments extending OpenAI's GYM framework.

        :param symbol: currency pair to trade / experiment
        :param fitting_file: prior trading day (e.g., T-1)
        :param testing_file: current trading day (e.g., T)
        :param max_position: maximum number of positions able to hold in inventory
        :param window_size: number of lags to include in observation space
        :param seed: random seed number
        :param action_repeats: number of steps to take in environment after a given action
        :param training: if TRUE, then randomize starting point in environment
        :param format_3d: if TRUE, reshape observation space from matrix to tensor
        :param reward_type: method for calculating the environment's reward:
            1) 'default' --> inventory count * change in midpoint price returns
            2) 'default_with_fills' --> inventory count * change in midpoint price returns
                + closed trade PnL
            3) 'realized_pnl' --> change in realized pnl between time steps
            4) 'differential_sharpe_ratio' -->
        http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.1.7210&rep=rep1&type=pdf
            5) 'asymmetrical' --> extended version of *default* and enhanced with a
                    reward for being filled above or below midpoint, and returns only
                    negative rewards for Unrealized PnL to discourage long-term
                    speculation.
            6) 'trade_completion' --> reward is generated per trade's round trip

        :param ema_alpha: decay factor for EMA, usually between 0.9 and 0.9999; if NONE,
            raw values are returned in place of smoothed values
        """
        assert reward_type in VALID_REWARD_TYPES, \
            'Error: {} is not a valid reward type. Value must be in:\n{}'.format(
                reward_type, VALID_REWARD_TYPES)

        self.viz = Visualize(
            columns=['midpoint', 'buys', 'sells', 'inventory', 'realized_pnl'],
            store_historical_observations=True)

        # get Broker class to keep track of PnL and orders
        self.broker = Broker(max_position=max_position,
                             transaction_fee=transaction_fee)

        # properties required for instantiation
        self.symbol = symbol
        self.action_repeats = action_repeats
        self._seed = seed
        self._random_state = np.random.RandomState(seed=self._seed)
        self.training = training
        self.max_position = max_position
        self.window_size = window_size
        self.reward_type = reward_type
        self.format_3d = format_3d  # e.g., [window, features, *NEW_AXIS*]
        self.testing_file = testing_file

        # properties that get reset()
        self.reward = np.array([0.0], dtype=np.float32)
        self.step_reward = np.array([0.0], dtype=np.float32)
        self.done = False
        self.local_step_number = 0
        self.midpoint = 0.0
        self.observation = None
        self.action = 0
        self.last_pnl = 0.
        self.last_midpoint = None
        self.midpoint_change = None
        self.A_t, self.B_t = 0., 0.  # variables for Differential Sharpe Ratio
        self.episode_stats = ExperimentStatistics()
        self.best_bid = self.best_ask = None

        # properties to override in sub-classes
        self.actions = None
        self.action_space = None
        self.observation_space = None

        # get historical data for simulations
        self.data_pipeline = DataPipeline(alpha=ema_alpha)

        # three different data sets, for different purposes:
        #   1) midpoint_prices - midpoint prices that have not been transformed
        #   2) raw_data - raw limit order book data, not including imbalances
        #   3) normalized_data - z-scored limit order book and order flow imbalance
        #       data, also midpoint price feature is replace by midpoint log price change
        self._midpoint_prices, self._raw_data, self._normalized_data = \
            self.data_pipeline.load_environment_data(
                fitting_file=fitting_file,
                testing_file=testing_file,
                include_imbalances=True,
                as_pandas=True,
            )
        # derive best bid and offer
        self._best_bids = self._raw_data['midpoint'] - (
            self._raw_data['spread'] / 2)
        self._best_asks = self._raw_data['midpoint'] + (
            self._raw_data['spread'] / 2)

        self.max_steps = self._raw_data.shape[0] - self.action_repeats - 1

        # load indicators into the indicator manager
        self.tns = IndicatorManager()
        self.rsi = IndicatorManager()
        for window in INDICATOR_WINDOW:
            self.tns.add(
                ('tns_{}'.format(window), TnS(window=window, alpha=ema_alpha)))
            self.rsi.add(
                ('rsi_{}'.format(window), RSI(window=window, alpha=ema_alpha)))

        # buffer for appending lags
        self.data_buffer = deque(maxlen=self.window_size)

        # Index of specific data points used to generate the observation space
        features = self._raw_data.columns.tolist()
        self.best_bid_index = features.index('bids_distance_0')
        self.best_ask_index = features.index('asks_distance_0')
        self.notional_bid_index = features.index('bids_notional_0')
        self.notional_ask_index = features.index('asks_notional_0')
        self.buy_trade_index = features.index('buys')
        self.sell_trade_index = features.index('sells')

        # typecast all data sets to numpy
        self._raw_data = self._raw_data.to_numpy(dtype=np.float32)
        self._normalized_data = self._normalized_data.to_numpy(
            dtype=np.float32)
        self._midpoint_prices = self._midpoint_prices.to_numpy(
            dtype=np.float64)
        self._best_bids = self._best_bids.to_numpy(dtype=np.float32)
        self._best_asks = self._best_asks.to_numpy(dtype=np.float32)

        # rendering class
        self._render = TradingGraph(sym=self.symbol)

        # graph midpoint prices
        self._render.reset_render_data(
            y_vec=self._midpoint_prices[:np.shape(self._render.x_vec)[0]])
Ejemplo n.º 17
0
    def __init__(self,
                 close,
                 rsi: indicators.RSI,
                 macd: indicators.MACD,
                 fee=0.0):
        Strategy.__init__(self, close.index, fee=0.0)

        # indique le signal en cours sachant que MACD > RSI
        buysignalstrat = None

        macdcrossedfromdown = False
        macdcrossedfromtop = False

        lowthreshpassed = False
        lowlowthreshpassed = False
        hithreshpassed = False
        hihithreshpassed = False
        hasbought = False
        self.signals['rsi'] = rsi.data()
        self.signals['macd'], self.signals['macd_signal'] = macd.data()
        for index, row in self.signals.iterrows():
            # achat en fonction du RSI
            if row['rsi'] < 33:
                lowthreshpassed = True
            if row['rsi'] < 20:
                lowlowthreshpassed = True
            if row['rsi'] > 66:
                hithreshpassed = True
            if row['rsi'] > 80:
                hihithreshpassed = True

            if row['rsi'] > 20 and lowlowthreshpassed == True:
                lowlowthreshpassed = False
                if hasbought == False:
                    hasbought = True
                    buysignalstrat = "RSI"
            if row['rsi'] > 33 and lowthreshpassed == True:
                lowthreshpassed = False
                if hasbought == False:
                    hasbought = True
                    buysignalstrat = "RSI"
            # on revend par RSI seulement si c'est le seul signal qui a généré l'achat
            if row['rsi'] < 80 and hihithreshpassed == True:
                hihithreshpassed = False
                if hasbought == True and buysignalstrat == "RSI":
                    hasbought = False
                    buysignalstrat = None
            if row['rsi'] < 66 and hithreshpassed == True:
                hithreshpassed = False
                if hasbought == True and buysignalstrat == "RSI":
                    hasbought = False
                    buysignalstrat = None

            # achat en fonction de la MACD
            # TODO : lorsque le marché stagne, la MACD génère beaucoup de faux signaux, comment les éviter ?
            if row['macd'] > row[
                    'macd_signal'] and macdcrossedfromdown == False:
                macdcrossedfromdown = True
                macdcrossedfromtop = False
                if hasbought == False:
                    hasbought = True
                # même si nous avions acheté avec le RSI, si le signal est confirmé par la MACD
                # il sera considéré comme étant prévalant
                buysignalstrat = "MACD"
            if row['macd'] < row['macd_signal'] and macdcrossedfromtop == False:
                macdcrossedfromtop = True
                macdcrossedfromdown = False
                if hasbought == True:
                    hasbought = False
                    buysignalstrat = None

            if hasbought == True:
                self.signals['signal'].loc[index] = 1.0

        self.signals['positions'] = self.signals['signal'].diff()
Ejemplo n.º 18
0
    windowSize = 2

    #Get full dataset
    dfPrices = get_data_google(
        stockSym, pd.date_range(before_start_date, end_sample_date))
    dfSPY = dfPrices[['SPY']]
    dfPrices = dfPrices[stockSym]

    #Normalize Price
    priceNormed = dfPrices / dfPrices.ix[0]
    SPYNormed = dfSPY / dfSPY.ix[0]

    #Call indicators
    topBand, bottomBand, bbValue, bbp = Bollinger_Bands(
        stockSym, dfPrices, windowSize)
    RSIValueSMA, RSIValueEWM = RSI(stockSym, dfPrices, windowSize)
    MACDValue, signal, MACDIndicator = MACD(stockSym, dfPrices)

    SPYInd = SPYIndicator(dfSPY)

    #Standardize
    bbp = (bbp - bbp.mean()) / (bbp.std())
    RSIValueEWM = (RSIValueEWM - RSIValueEWM.mean()) / (RSIValueEWM.std())
    MACDValue = (MACDValue - MACDValue.mean()) / (MACDValue.std())
    signal = (signal - signal.mean()) / (signal.std())
    MACDIndicator = (MACDIndicator -
                     MACDIndicator.mean()) / (MACDIndicator.std())

    #5 Day Future Returns
    futureReturn = (dfPrices / dfPrices.shift(windowSize)) - 1.0
    futureReturn = futureReturn.shift(-windowSize)