Пример #1
0
def train_lgb_model(future_name):
    # Data munging
    df = pd.read_csv(f"./tickerData/{future_name}.txt")
    # Limit to 31st Dec 2019 data
    df['DATE'] = pd.to_datetime(df['DATE'], format='%Y%m%d')
    df = df[df['DATE'] <= '2019-12-31']

    df['ADI'] = ADI(df['HIGH'], df['LOW'], df['CLOSE'], df['VOL'])  # Volume
    df['WilliamsR'] = WilliamsR(df['HIGH'], df['LOW'], df['CLOSE'])  # Momentum
    BBs = BB(df['CLOSE'], 10)
    df['BB_high_crosses'] = BBs[0]  # Volatility
    df['BB_low_crosses'] = BBs[1]  # Volatility
    df['CCI'] = CCI(df['HIGH'], df['LOW'], df['CLOSE'], 10)  # Trend
    df['label'] = np.where(df['CLOSE'].shift(periods=-1) - df['CLOSE'] < 0, -1,
                           1)
    # If change is too small, don't take position
    returns = abs(df['CLOSE'].shift(periods=-1) - df['CLOSE'])
    change_limit = 0.5 * returns.mean()
    df.loc[abs(df['CLOSE'].shift(periods=-1) - df['CLOSE']) < change_limit,
           'label'] = 0
    # Assume stocks have pacf of 2-timestep significance
    df['LAG_1'] = df['CLOSE'].shift(periods=1)
    df['LAG_2'] = df['CLOSE'].shift(periods=2)
    df['LABEL_var'] = df['CLOSE'].shift(periods=-1)
    data = df.iloc[2:][[
        'OPEN', 'HIGH', 'LOW', 'CLOSE', 'VOL', 'ADI', 'WilliamsR',
        'BB_high_crosses', 'BB_low_crosses', 'CCI', 'LAG_1', 'LAG_2', 'label'
    ]]

    # Split test-train set
    train_df, test_df = train_test_split(data, test_size=0.2, shuffle=False)
    train_X = train_df[[
        'OPEN', 'HIGH', 'LOW', 'CLOSE', 'VOL', 'ADI', 'WilliamsR',
        'BB_high_crosses', 'BB_low_crosses', 'CCI', 'LAG_1', 'LAG_2'
    ]].to_numpy()
    train_Y = train_df['label'].to_numpy()
    test_X = test_df[[
        'OPEN', 'HIGH', 'LOW', 'CLOSE', 'VOL', 'ADI', 'WilliamsR',
        'BB_high_crosses', 'BB_low_crosses', 'CCI', 'LAG_1', 'LAG_2'
    ]].to_numpy()
    test_Y = test_df['label'].to_numpy()

    # Create lgb model
    lgb_clf = lgb.LGBMClassifier(objective='multiclass',
                                 num_leaves=75,
                                 learning_rate=0.05,
                                 max_depth=10,
                                 n_estimators=100)
    lgb_clf.fit(train_X,
                train_Y,
                eval_set=[(test_X, test_Y)],
                early_stopping_rounds=50,
                verbose=False)
    test_accuracy = np.sum(lgb_clf.predict(test_X) == test_Y) / len(test_Y)
    if test_accuracy > 0.65:
        lgb_clf.booster_.save_model(f'./data/lgb_models/{future_name}_model')
        print(
            f"Successfully trained {future_name}. Test accuracy: {test_accuracy:.3f}"
        )
        print(f"Saved as {future_name}_model under /data/lgb_models.")
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()
Пример #3
0
    except FileNotFoundError as fnfe:
        continue

    listener = open("../txt_files/data.txt", "w")
    listener.close()

    candles = []
    for line in new_reader:
        candles.append(line)

    capital = 100
    private_client = AuthenticatedClient(Data.API_Public_Key, Data.API_Secret_Key, Data.Passphrase)
    new_order = Order(private_client)
    position = OpenPosition(new_order)
    indicator = Indicator()
    bands_1dev = BB(ndbevup=1, nbdevdn=1)

    indicator_list = [indicator, bands_1dev]
    for new_indicator in indicator_list:
        new_indicator.candles = candles[1:]
        new_indicator.get_data_set()
        new_indicator.reverse_data()
        new_indicator.get_dates()
        new_indicator.get_np_array()
        new_indicator.set_indicator()

    # verifies that the data and dates was extracted successfully
    h = 0
    y = -1
    while h < len(indicator.candles):
        if indicator.date_array[h] == indicator.candles[y][0]:
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()
Пример #5
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
Пример #6
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)
Пример #7
0
 def __init__(self, indicator=Indicator(), bol=BB(), order=Order()):
     super(Bollinger, self).__init__(indicator=indicator,
                                     bands_2dev=bol,
                                     order=order)
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)