Esempio n. 1
0
    def discretize(self,
                   symbol="IBM",
                   sd=dt.datetime(2008, 1, 1),
                   ed=dt.datetime(2009, 12, 31)):
        syms = [symbol]
        dates = pd.date_range(sd, ed)
        indicator_dates = pd.date_range(sd - dt.timedelta(days=28), ed)
        prices_all = ut.get_data(syms, dates)  # automatically adds SPY
        prices = prices_all[syms]  # only portfolio symbols
        indicator_prices_all = ut.get_data(
            syms, indicator_dates
        )  #will this be the same size as the number of days traded?
        indicator_prices = indicator_prices_all[syms]
        prices_SPY = prices_all["SPY"]  # only SPY, for comparison later

        #get 3 indicators using passed in start date minus window required for each
        rm = ind.get_rolling_mean(indicator_prices[symbol], window=20)
        percent_bb = ind.get_rolling_std(indicator_prices[symbol],
                                         window=20)  #aka rstd
        upper_band, lower_band = ind.get_bollinger_bands(rm, percent_bb)

        percent_bb = percent_bb.iloc[19:]
        rm = rm.iloc[19:]
        upper_band = upper_band.iloc[19:]
        lower_band = lower_band.iloc[19:]
        for x in range(rm.size):  #did i format that right??
            #print(prices.iloc[x])
            #print(type(rm.iloc[x]))
            if (prices.iloc[x][0] == rm.iloc[x]):
                percent_bb.iloc[x] = 0.0
            elif (prices.iloc[x][0] > rm.iloc[x]):
                percent_bb.iloc[x] = (prices.iloc[x][0] - rm.iloc[x]) / (
                    upper_band.iloc[x] - rm.iloc[x])
            elif (prices.iloc[x][0] < rm.iloc[x]):
                percent_bb.iloc[x] = (rm.iloc[x] - prices.iloc[x][0]) / (
                    lower_band.iloc[x] - rm.iloc[x])

        percent_bb = pd.Series(percent_bb)
        #print(percent_bb)
        indicator_prices = indicator_prices.iloc[9:]
        #print(indicator_prices)
        momentum = pd.Series(
            ind.get_momentum(indicator_prices[symbol], window=10))
        momentum = momentum.iloc[10:]
        #print(momentum)
        volatility = pd.Series(
            ind.get_volatility(indicator_prices[symbol], window=10))
        volatility = volatility.iloc[10:]
        #print(volatility.values.shape)

        uglystupidnobodylikesyouvol, vol = pd.qcut(volatility.values,
                                                   10,
                                                   retbins=True)
        esrfergs, momnt = pd.qcut(momentum.values, 10, retbins=True)
        rgefsegrf, bb = pd.qcut(percent_bb.values, 10, retbins=True)
        vol = vol[1:-1]
        momnt = momnt[1:-1]
        bb = bb[1:-1]

        return vol, momnt, bb
Esempio n. 2
0
    def get_features(self, prices):
        """Compute technical indicators and use them as features to be fed
        into a Q-learner.

        Parameters:
        prices: Adjusted close prices of the given symbol

        Returns:
        df_features: A pandas dataframe of the technical indicators
        """
        window = 10
        # Compute rolling mean
        rolling_mean = prices.rolling(window=window).mean()
        # Compute_rolling_std
        rolling_std = prices.rolling(window=window).std()
        # Compute momentum
        momentum = get_momentum(prices, window)
        # Compute SMA indicator
        sma_indicator = get_sma_indicator(prices, rolling_mean)
        # Compute Bollinger value
        bollinger_val = compute_bollinger_value(prices, rolling_mean, rolling_std)
        # Create a dataframe with three features
        df_features = pd.concat([momentum, sma_indicator], axis=1)
        df_features = pd.concat([df_features, bollinger_val], axis=1)
        df_features.columns = ["ind{}".format(i)
                                for i in range(len(df_features.columns))]
        df_features.dropna(inplace=True)
        return df_features
 def get_features(self, prices):
     """
     Compute the technical features of a position and feed that
     into the Q-Learning process
     
     TODO: Try different parameters to see if you can improve
           the portfolio
           
     Try out different window sizes (right now set to 10 trading days)
     
     prices: Adjusted close prices of the given symbol
     
     df_features: A pandas dataframe of the technical indicators
     """
     
     rolling_mean = prices.rolling(window=self.window_size).mean()
     rolling_std = prices.rolling(window=self.window_size).std()
     
     momentum      = get_momentum(prices, self.window_size)
     sma_indicator = get_sma_indicator(prices, rolling_mean)
     
     bollinger_val = compute_bollinger_value(prices, rolling_mean, rolling_std)
     
     df_features   = pd.concat([momentum, sma_indicator], axis=1)
     df_features   = pd.concat([df_features, bollinger_val], axis=1)
     df_features.columns = ["ind{}".format(i) 
                             for i in range(len(df_features.columns))]
     
     # Perhaps you can come up with a different feature?
     # Try it!
     
     df_features.dropna(inplace=True)
     return df_features
Esempio n. 4
0
    def testPolicy(self,
                   symbol="JPM",
                   sd=dt.datetime(2008, 1, 1),
                   ed=dt.datetime(2009, 1, 31),
                   sv=100000):
        df_prices = get_data([symbol], pd.date_range(sd, ed)).ffill().bfill()
        df_prices_symbol = df_prices[[symbol]]

        momentum = get_momentum(df_prices_symbol)
        sma_r = get_sma_r(df_prices_symbol)
        bbp = get_bbp(df_prices_symbol)

        df_trades = df_prices_symbol.copy()
        df_trades[symbol] = 0

        impact = 0.005
        commission = 9.95
        current_holding = 0

        for i in range(df_prices_symbol.shape[0] - 1):
            price = df_prices_symbol.iloc[i, 0]
            sign = 0
            if (bbp.iloc[i, 0] <= 0.6 and sma_r.iloc[i, 0] < 1) or \
                    (sma_r.iloc[i, 0] < 1 and momentum.iloc[i, 0] > 0.1) or \
                    (bbp.iloc[i, 0] <= 0.6 and momentum.iloc[i, 0] > 0.1):
                sign = 1
                price = price * (1 + impact * sign)
            if (bbp.iloc[i, 0] >= 0.8 and sma_r.iloc[i, 0] > 1) or \
                    (sma_r.iloc[i, 0] > 1 and momentum.iloc[i, 0] < 0) or \
                    (bbp.iloc[i, 0] >= 0.8 and momentum.iloc[i, 0] < 0):
                sign = -1
                price = price * (1 + impact * sign)
            if sign != 0:
                if current_holding == 0:
                    sv -= commission
                    sv = sv - price * 1000 * sign
                    current_holding = 1000 * sign
                    df_trades.iloc[i, 0] = 1000 * sign
                elif current_holding == -1000 * sign:
                    sv -= commission
                    sv = sv - price * 2000 * sign
                    current_holding = 1000 * sign
                    df_trades.iloc[i, 0] = 2000 * sign
                else:
                    pass

        df_trades.index.names = ['Date']
        df_trades.columns = ['Shares']
        df_trades["Symbol"] = "JPM"
        df_trades["Order"] = [
            "BUY" if x > 0 else "SELL" if x < 0 else "NA"
            for x in df_trades['Shares']
        ]
        df_trades.drop(df_trades[df_trades['Shares'] == 0].index, inplace=True)
        df_trades['Shares'] = df_trades['Shares'].abs()
        df_trades = df_trades.reindex(columns=['Symbol', 'Order', 'Shares'])

        return df_trades
Esempio n. 5
0
    def testPolicy(self, symbol = "IBM", \
        sd=dt.datetime(2009,1,1), \
        ed=dt.datetime(2010,1,1), \
        sv = 10000):

        syms = [symbol]

        # here we build a fake set of trades
        # your code should return the same sort of data
        syms = [symbol]
        dates = pd.date_range(sd, ed)
        prices, prices_SPY = id.get_price(syms, dates)

        if self.verbose: print prices

        daily_returns = (prices / prices.shift(1)) - 1
        daily_returns = daily_returns[1:]

        # get indicators and combine them into as a feature data_frame
        lookback = 14

        _, PSR = id.get_SMA(prices, lookback)
        _, _, bb_indicator = id.get_BB(prices, lookback)
        momentum = id.get_momentum(prices, lookback)
        indices = prices.index
        holdings = pd.DataFrame(np.nan, index=indices, columns=['Holdings'])
        holdings.iloc[0] = 0

        for i in range(1, daily_returns.shape[0]):

            state = self.indicators_to_state(PSR.iloc[i], bb_indicator.iloc[i],
                                             momentum.iloc[i])

            # Get action by Query learner with current state and reward to get action
            action = self.learner.querysetstate(state)
            #print("SL 286 action is ", action)

            # Get holdings with the new action.
            holdings.iloc[i], _ = self.apply_action(holdings.iloc[i - 1][0],
                                                    action, 0)

        holdings.ffill(inplace=True)
        holdings.fillna(0, inplace=True)
        trades = holdings.diff()
        trades.iloc[0] = 0

        # buy and sell happens when the difference change direction
        df_trades = pd.DataFrame(data=trades.values,
                                 index=trades.index,
                                 columns=['Trades'])

        #print("293: ", df_trades)
        if self.verbose: print type(df_trades)  # it better be a DataFrame!
        if self.verbose: print trades
        if self.verbose: print prices

        return df_trades
    def addEvidence(self, symbol = "IBM", \
        sd=dt.datetime(2008,1,1), \
        ed=dt.datetime(2009,1,1), \
        sv = 10000):

        # add your code to do learning here

        # example usage of the old backward compatible util function
        syms = [symbol]
        dates = pd.date_range(sd, ed)
        prices_all = ut.get_data(syms, dates)  # automatically adds SPY
        prices = prices_all[syms]  # only portfolio symbols
        prices_SPY = prices_all['SPY']  # only SPY, for comparison later
        if self.verbose: print prices

        # example use with new colname
        volume_all = ut.get_data(syms, dates,
                                 colname="Volume")  # automatically adds SPY
        volume = volume_all[syms]  # only portfolio symbols
        volume_SPY = volume_all['SPY']  # only SPY, for comparison later
        if self.verbose: print volume

        bb_val, upper, lower, rm, rs = get_bb(prices)
        sma = get_sma(prices)
        mom = get_momentum(prices)
        x_train = np.zeros(shape=(len(prices), 7))

        for i in range(20, len(prices) - self.N):
            x_train[i][0] = bb_val[i]
            x_train[i][1] = upper[i]
            x_train[i][2] = lower[i]
            x_train[i][3] = rm[i]
            x_train[i][4] = rs[i]
            x_train[i][5] = sma[i]
            x_train[i][6] = mom[i]

        x_train = pd.DataFrame(x_train)
        x_train = x_train[:-self.N]
        x_train.fillna(0, inplace=True)
        x_train = x_train.values
        y = []

        for i in range(0, len(prices) - self.N):
            if (prices.ix[i + self.N, symbol] /
                    prices.ix[i, symbol]) > 1.0009 + self.impact:
                y.append(1)
            elif (prices.ix[i + self.N, symbol] /
                  prices.ix[i, symbol]) < 0.9991 - self.impact:
                y.append(-1)
            else:
                y.append(0)

        y_train = np.array(y)

        #print y_train
        self.learner.addEvidence(x_train, y_train)
    def trading_strategy(self, sym_price):
        """Create a dataframe of order signals that maximizes portfolio's return.
        This function has been optimized for the symbol and training period in 
        the main function

        Parameters:
        sym_price: The price series of a stock symbol of interest

        Returns:
        df_order_signals: A series that contains 1 for buy, 0 for hold and -1 for sell
        """

        # Get momentum indicator and generate signals
        momentum = get_momentum(sym_price, 40)
        mom_signal = -1 * (momentum < -0.07) + 1 * (momentum > 0.14)

        # Get RSI indicator and generate signals
        rsi_indicator = get_RSI(sym_price)
        rsi_signal = 1 * (rsi_indicator < 50) + -1 * (rsi_indicator > 50)

        # Get SMA indicator and generate signals
        sma_indicator = get_sma_indicator(sym_price,
                                          sym_price.rolling(window=30).mean())
        sma_signal = 1 * (sma_indicator < 0.0) + -1 * (sma_indicator > 0.0)

        # Combine individual signals
        signal = 1 * ((sma_signal == 1) & (rsi_signal == 1) & (mom_signal == 1)) \
            + -1 * ((sma_signal == -1) & (rsi_signal == -1) & (mom_signal == -1))

        # Create an order series with 0 as default values
        self.df_order_signals = signal * 0

        # Keep track of net signals which are constrained to -1, 0, and 1
        net_signals = 0
        for date in self.df_order_signals.index:
            net_signals = self.df_order_signals.loc[:date].sum()

            # If net_signals is not long and signal is to buy
            if (net_signals < 1) and (signal.loc[date] == 1):
                self.df_order_signals.loc[date] = 1

            # If net_signals is not short and signal is to sell
            elif (net_signals > -1) and (signal.loc[date] == -1):
                self.df_order_signals.loc[date] = -1

        # On the last day, close any open positions
        if self.df_order_signals.sum() == -1:
            self.df_order_signals[-1] = 1
        elif self.df_order_signals.sum() == 1:
            self.df_order_signals[-1] = -1

        return self.df_order_signals
Esempio n. 8
0
def testPolicyMomentum(n_days_bb=20,
                       n_days_mtum=20,
                       n_days_std=20,
                       tresh_bb=1,
                       tresh_mmtum=0.2,
                       tresh_std_low=1,
                       tresh_std_high=1,
                       symbol="JPM",
                       sd=dt.datetime(2008, 1, 1),
                       ed=dt.datetime(2009, 12, 31),
                       sv=100000):
    df_prices_all = get_data([symbol], pd.date_range(sd, ed))
    df_prices = df_prices_all[symbol]
    df_trades = pd.DataFrame(data=np.zeros(len(df_prices)),
                             index=df_prices.index,
                             columns=['trades'])

    rstd = idc.get_rolling_stdev(
        pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]),
        n_days_std)
    bband = idc.get_bbands(
        pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]),
        n_days_bb)
    momentum = idc.get_momentum(
        pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]),
        n_days_mtum)
    abs_momentum = momentum.abs()
    # use momentum to confirm sell & buy signal:
    # confirmed if small enough momentum
    # (changes in prices is slowing - time to take action)
    for t in range(1, len(df_prices)):
        df_net_holdings = df_trades.cumsum(axis=0)
        net_holdings = df_net_holdings.values[t]
        if (net_holdings > 1000) | (net_holdings < -1000):
            print("ERROR")
        #if rstd[t] >= tresh_std:
        # buy signal
        if (bband[t - 1] <= -tresh_bb) & (bband[t] > -tresh_bb):
            if (abs_momentum[t] <= tresh_mmtum):
                if (net_holdings == 0):
                    df_trades.iloc[t] = 1000
                elif (net_holdings == -1000):
                    df_trades.iloc[t] = 2000
        # sell signal
        if (bband[t - 1] >= tresh_bb) & (bband[t] < tresh_bb):
            if (abs_momentum[t] <= tresh_mmtum):
                if (net_holdings == 0):
                    df_trades.iloc[t] = -1000
                elif (net_holdings == 1000):
                    df_trades.iloc[t] = -2000
    return df_trades, momentum
Esempio n. 9
0
    def testPolicy(self, symbol, sd, ed, sv=100000):
        # this policy is like this: buy when the price will go up the next day, sell when the price will do down the next day
        # get price data
        dates = pd.date_range(sd, ed)
        prices_all = get_data([symbol],
                              dates,
                              addSPY=True,
                              colname='Adj Close')
        prices = prices_all[symbol]  # only portfolio symbols

        # get indicators
        lookback = 14

        _, PSR = id.get_SMA(prices, lookback)
        _, _, bb_indicator = id.get_BB(prices, lookback)
        momentum = id.get_momentum(prices, lookback)

        holdings = pd.DataFrame(np.nan,
                                index=prices.index,
                                columns=['Holdings'])

        # make sure when PSR (= price / SMA -1) >0.05 and bb_indicator > 1 and momentum > 0.05 SELL or hold -1000
        # when PSR (= price / SMA -1) < -0.05 and bb_indicator < -1 and momentum < -0.05 Buy or hold -1000

        #print("PSR: ", PSR)
        #print("momentum: ", momentum)
        #print("bb_indicator: ", bb_indicator)

        for t in range(prices.shape[0]):
            if PSR.iloc[t] < -0.02 and bb_indicator.iloc[
                    t] < -0.8 and momentum.iloc[t] < -0.03:
                holdings.iloc[t] = 1000
            elif PSR.iloc[t] > 0.02 and bb_indicator.iloc[
                    t] > 0.8 and momentum.iloc[t] > 0.03:
                holdings.iloc[t] = -1000

        # fill the NAN data
        holdings.ffill(inplace=True)
        holdings.fillna(0, inplace=True)
        trades = holdings.diff()
        trades.iloc[0] = 0
        #trades.iloc[-1] = 0
        #trades.columns = 'Trades'

        # buy and sell happens when the difference change direction
        df_trades = pd.DataFrame(data=trades.values,
                                 index=trades.index,
                                 columns=['Trades'])

        return df_trades
Esempio n. 10
0
    def testPolicy(self,
                   symbol="JPM",
                   sd=dt.datetime(2010, 1, 1),
                   ed=dt.datetime(2011, 12, 31),
                   sv=100000):

        df_prices = ut.get_data([symbol], pd.date_range(sd,
                                                        ed)).ffill().bfill()
        df_prices = df_prices[[symbol]]

        # Make indicators df
        indicator_details = df_prices.copy()
        indicator_details.drop([symbol], axis=1, inplace=True)
        indicator_details[self.momentum] = idc.get_momentum(df_prices)
        indicator_details[self.sma_ratio] = idc.get_sma_r(df_prices)
        indicator_details[self.bollinger_percent] = idc.get_bbp(df_prices)

        df_trades = df_prices.copy()
        df_trades[symbol] = 0
        current_holding = 0

        indicators = indicator_details.iloc[self.window - 1]
        s = self.serialize(indicators)
        a = self.learner.querysetstate(s)
        prices_len = df_prices.shape[0]

        for i in range(self.window, prices_len - 1):
            s = self.serialize(indicator_details.iloc[i])
            if a == 1:
                pass
            elif a == 0 and current_holding == 0:
                current_holding = -1000
                df_trades.iloc[i, 0] = current_holding
            elif a == 0 and current_holding == 1000:
                current_holding = -1000
                df_trades.iloc[i, 0] = current_holding * 2
            elif a == 2 and current_holding == 0:
                current_holding = 1000
                df_trades.iloc[i, 0] = current_holding
            elif a == 2 and current_holding == -1000:
                current_holding = 1000
                df_trades.iloc[i, 0] = current_holding * 2

            a = self.learner.querysetstate(s)

        return df_trades
Esempio n. 11
0
    def buildIndicators(self, df_prices, symbol="IBM"):
        """
        Build (panda Series) indicators from the prices dataframe
        @params df_prices: the prices dataframe
        @params symbol: the asset's symbol
        5,10,20,30
        """
        # rolling bollinger band
        self.bband = idc.get_bbands(pd.DataFrame(df_prices,
                                                 index=df_prices.index,
                                                 columns=[symbol]),
                                    self.window_size,
                                    symbol=symbol).dropna()
        # fixing treshold for consistencies before normalization
        self.bband[self.bband < -1] = -1
        self.bband[self.bband > 1] = 1
        self.discretize_bband = self.normalizeIndicators(self.bband)

        # rolling momentum abs
        self.momentum = idc.get_momentum(pd.DataFrame(df_prices,
                                                      index=df_prices.index,
                                                      columns=[symbol]),
                                         self.window_size,
                                         symbol=symbol).dropna()
        self.momentum[self.momentum < -0.3] = -0.3
        self.momentum[self.momentum > 0.3] = 0.3
        self.discretize_momentum = self.normalizeIndicators(self.momentum)

        # rolling standard deviation
        self.rstd = pd.Series(pd.rolling_std(df_prices, window=2),
                              name='rstd').dropna()
        self.rstd[self.rstd < 0.5] = 0.5
        self.rstd[self.rstd > 4] = 4
        self.discretize_rstd = self.normalizeIndicators(self.rstd)

        # rolling rsi
        self.rsi = idc.get_rsi(df_prices, self.window_size).dropna()
        self.rsi[self.rsi < 40] = 40
        self.rsi[self.rsi > 70] = 70
        self.discretize_rsi = self.normalizeIndicators(self.rsi)

        self.discretize_holding = {0: 0, -1000: 1, 1000: 2}
        self.n_states = int(3 * 10**4)
Esempio n. 12
0
    def prepare_indicators(self,
                           symbol="JPM",
                           sd=dt.datetime(2008, 1, 1),
                           ed=dt.datetime(2009, 12, 31)):
        dates = pd.date_range(sd, ed)
        prices = ut.get_data([symbol], dates)
        prices.fillna(method='ffill', inplace=True)
        prices.fillna(method='bfill', inplace=True)
        prices = prices[[symbol]]

        indicators = prices.copy()
        indicators.drop([symbol], axis=1, inplace=True)
        indicators["momentum"] = ind.get_momentum(prices, self.window)
        indicators["sma_ratio"] = ind.get_SMA_ratio(prices, symbol,
                                                    self.window)
        indicators["bollinger_value"] = ind.get_bollinger_band(
            prices, symbol, self.window)

        return prices, indicators
def testPolicy(symbol, sd, ed, sv):
    symbols = ['JPM']
    dates = pd.date_range(sd, ed)
    benchmark = get_data(symbols, dates, addSPY=False).dropna()
    prices = benchmark['JPM'].values
    trades = pd.DataFrame(data=np.zeros(len(prices)),
                          index=benchmark.index,
                          columns=['JPM'])
    print benchmark
    sma = get_sma(benchmark)
    mom = get_momentum(benchmark)
    bbval, upper, lower, rolling_m, rolling_s = get_bb(benchmark)
    holding = 0
    benchmark = pd.DataFrame({'Date': dt.datetime(2008, 1, 2), 'JPM': [1000]})
    benchmark.set_index("Date", inplace=True)
    for i in range(12, len(prices)):
        if sma[i] < 0.95 and bbval[i] < 0:
            trades['JPM'].iloc[i] = 1000 - holding
            holding = 1000
        elif sma[i] > 1.05 and bbval[i] > 1:
            trades['JPM'].iloc[i] = -holding - 1000
            holding = -1000
    return trades, benchmark
Esempio n. 14
0
    def get_features1(self, prices, symbol, print=False):
        '''
        Compute technical indicators and use them as features to be fed
        into a Q-learner.
        :param: prices: Adj Close prices dataframe
        :param: Whether adding data for printing to dataframe or not
        :return: Normalize Features dataframe
        '''

        # Fill NAN values if any
        prices.fillna(method="ffill", inplace=True)
        prices.fillna(method="bfill", inplace=True)
        prices.fillna(1.0, inplace=True)

        # Price
        adj_close = prices[symbol]

        # Compute Momentum
        mom = get_momentum(adj_close, window=10)

        # Compute RSI
        rsi = get_RSI(adj_close)

        # Compute rolling mean
        rm = get_rolling_mean(adj_close, window=10)

        # Compute rolling standard deviation
        rstd = get_rolling_std(adj_close, window=10)

        # Compute upper and lower bands
        upper_band, lower_band = get_bollinger_bands(rm, rstd)



        # Compute SMA
        sma = get_sma_indicator(adj_close, rm)

        df = prices.copy()
        df['Momentum'] = mom
        df['Adj. Close/SMA'] = adj_close/sma
        df['middle_band'] = rm

        # Delete 'Adj Close' column
        del df[symbol]

        if set(['cash']).issubset(df.columns):
            del df['cash']

        # Normalize dataframe
        df_norm = normalize_data(df)

        # Add Adj Close, Bollinrt Bands and RSY if printing
        if print:
            df_norm['Adj Close'] = prices[symbol]
            df_norm['upper_band'] = upper_band
            df_norm['lower_band'] = lower_band
            df_norm['middle_band'] = rm
            df_norm['RSI'] = rsi



        # Drop NaN
        df_norm.dropna(inplace=True)

        return df_norm
Esempio n. 15
0
    def testPolicy(self,
                   symbol="JPM",
                   sd=dt.datetime(2008, 1, 1),
                   ed=dt.datetime(2009, 1, 31),
                   sv=100000):
        # get data
        dates = pd.date_range(sd, ed)
        prices_all = get_data([symbol], dates)  # automatically adds SPY
        prices_all.fillna(method='ffill', inplace=True)
        prices_all.fillna(method='bfill', inplace=True)
        prices = prices_all[[symbol]]
        prices_SPY = prices_all['SPY']

        lookback = 7
        momentum = get_momentum(prices, lookback=lookback)
        sma_r = get_sma_r(prices, lookback=lookback)
        bbp = get_bbp(prices, lookback=lookback)

        commission = 9.95
        impact = 0.005
        holding = 0
        cash = sv

        #print(bbp)
        df_trades = prices.copy()
        df_trades[symbol] = 0

        for i in range(lookback - 1, prices.shape[0] - 1):
            price = prices.iloc[i, 0]
            # BUY
            if (bbp.iloc[i,0] <= 0.6 and sma_r.iloc[i,0] < 1) or \
                (sma_r.iloc[i,0] < 1 and momentum.iloc[i,0] > 0.1) or \
                (bbp.iloc[i,0] <= 0.6 and momentum.iloc[i,0] > 0.1):
                price = price * (1 + impact)

                if holding == 0:
                    cash = cash - price * 1000 - commission
                    holding = 1000
                    df_trades.iloc[i, 0] = 1000
                elif holding == -1000:
                    cash = cash - price * 2000 - commission
                    holding = 1000
                    df_trades.iloc[i, 0] = 2000
                else:
                    pass

            # SELL
            elif (bbp.iloc[i,0] >= 0.8 and sma_r.iloc[i,0] > 1) or \
                (sma_r.iloc[i,0] > 1 and momentum.iloc[i,0] < 0) or \
                (bbp.iloc[i,0] >= 0.8 and momentum.iloc[i,0] < 0):
                price = price * (1 - impact)

                if holding == 0:
                    cash = cash + price * 1000 - commission
                    holding = -1000
                    df_trades.iloc[i, 0] = -1000
                elif holding == 1000:
                    cash = cash + price * 2000 - commission
                    holding = -1000
                    df_trades.iloc[i, 0] = -2000
                else:
                    pass
            else:
                pass

        return df_trades
Esempio n. 16
0
def experiment1():

    ms = ManualStrategy.ManualStrategy()
    sl = StrategyLearner.StrategyLearner()

    commission = 9.95
    impact = 0.005

    # in sample
    start_date = dt.datetime(2008, 1, 1)
    end_date = dt.datetime(2009, 12, 31)
    # dates = pd.date_range(start_date, end_date)
    symbol = 'JPM'

    sl.addEvidence(symbol=symbol,
                   sd=start_date,
                   ed=end_date,
                   sv=100000,
                   n_bins=5)

    df_trades_ms = ms.testPolicy(symbol=symbol,
                                 sd=start_date,
                                 ed=end_date,
                                 sv=100000)
    df_trades_sl = sl.testPolicy(symbol=symbol,
                                 sd=start_date,
                                 ed=end_date,
                                 sv=100000)

    # generate orders based on trades
    df_orders_ms, benchmark_orders = ManualStrategy.generate_orders(
        df_trades_ms, symbol)
    df_orders_sl, _ = ManualStrategy.generate_orders(df_trades_sl, symbol)

    port_vals_ms = ManualStrategy.compute_portvals(df_orders_ms,
                                                   start_val=100000,
                                                   sd=start_date,
                                                   ed=end_date,
                                                   commission=commission,
                                                   impact=impact)
    port_vals_sl = ManualStrategy.compute_portvals(df_orders_sl,
                                                   start_val=100000,
                                                   sd=start_date,
                                                   ed=end_date,
                                                   commission=commission,
                                                   impact=impact)
    #benchmark_orders.loc[benchmark_orders.index[1], 'Shares'] = 0

    benchmark_vals = ManualStrategy.compute_portvals(benchmark_orders,
                                                     sd=start_date,
                                                     ed=end_date,
                                                     start_val=100000,
                                                     commission=commission,
                                                     impact=impact)

    normed_port_ms = port_vals_ms / port_vals_ms.ix[0]
    normed_port_sl = port_vals_sl / port_vals_sl.ix[0]
    normed_bench = benchmark_vals / benchmark_vals.ix[0]

    dates = pd.date_range(start_date, end_date)
    prices_all = get_data([symbol], dates, addSPY=True, colname='Adj Close')
    prices = prices_all[symbol]  # only portfolio symbols

    # get indicators
    lookback = 14

    _, PSR = id.get_SMA(prices, lookback)
    _, _, bb_indicator = id.get_BB(prices, lookback)
    momentum = id.get_momentum(prices, lookback)

    # figure 5.
    plt.figure(figsize=(12, 6.5))
    top = plt.subplot2grid((5, 1), (0, 0), rowspan=3, colspan=1)
    bottom = plt.subplot2grid((5, 1), (3, 0), rowspan=2, colspan=1, sharex=top)

    # plot the Long or short action
    for index, marks in df_trades_sl.iterrows():
        if marks['Trades'] > 0:
            plt.axvline(x=index, color='blue', linestyle='dashed', alpha=.9)
        elif marks['Trades'] < 0:
            plt.axvline(x=index, color='black', linestyle='dashed', alpha=.9)
        else:
            pass

    top.xaxis_date()
    top.grid(True)
    top.plot(normed_port_sl, lw=2, color='red', label='Q-Learning Strategy')
    top.plot(normed_port_ms, lw=1.5, color='black', label='Manual Strategy')
    top.plot(normed_bench, lw=1.2, color='green', label='Benchmark')

    top.set_title(
        'Machine Learning Strategy (MLS), Manual Strategy (MS) - In Sample Analysis'
    )
    top.set_ylabel('Normalized Value')
    for index, marks in df_trades_sl.iterrows():
        if marks['Trades'] > 0:
            top.axvline(x=index, color='blue', linestyle='dashed', alpha=.9)
        elif marks['Trades'] < 0:
            top.axvline(x=index, color='black', linestyle='dashed', alpha=.9)
        else:
            pass

    bottom.plot(momentum, color='olive', lw=1, label="momentum")
    bottom.plot(PSR, color='purple', lw=1, label="PSR")
    #bottom.plot(bb_indicator, color='blue', lw=1, label="Bollinger")
    bottom.set_title('Indicators')

    bottom.axhline(y=-0.2, color='grey', linestyle='--', alpha=0.5)
    bottom.axhline(y=0, color='grey', linestyle='--', alpha=0.5)
    bottom.axhline(y=0.2, color='grey', linestyle='--', alpha=0.5)
    bottom.legend()

    top.legend()
    top.axes.get_xaxis().set_visible(False)
    plt.xlim(start_date, end_date)

    filename = '01_MLS_insample.png'

    plt.savefig(filename)

    plt.close()

    port_cr_sl, port_adr_sl, port_stddr_sl, port_sr_sl = ManualStrategy.get_portfolio_stats(
        port_vals_sl)
    port_cr_ms, port_adr_ms, port_stddr_ms, port_sr_ms = ManualStrategy.get_portfolio_stats(
        port_vals_ms)
    bench_cr, bench_adr, bench_stddr, bench_sr = ManualStrategy.get_portfolio_stats(
        benchmark_vals)

    # Compare portfolio against benchmark
    print "=== Machine Learning Strategy (MLS) V.S. Manual Strategy (MS) In Sample ==="
    print "Date Range: {} to {}".format(start_date, end_date)
    print
    print "Sharpe Ratio of MLS: {}".format(port_sr_sl)
    print "Sharpe Ratio of MS: {}".format(port_sr_ms)
    print "Sharpe Ratio of BenchMark : {}".format(bench_sr)
    print
    print "Cumulative Return of MLS: {}".format(port_cr_sl)
    print "Cumulative Return of MS: {}".format(port_cr_ms)
    print "Cumulative Return of Benchmark : {}".format(bench_cr)
    print
    print "Standard Deviation of MLS: {}".format(port_stddr_sl)
    print "Standard Deviation of MS: {}".format(port_stddr_ms)
    print "Standard Deviation of Benchmark : {}".format(bench_stddr)
    print
    print "Average Daily Return of MLS: {}".format(port_adr_sl)
    print "Average Daily Return of MS: {}".format(port_adr_ms)
    print "Average Daily Return of BenchMark : {}".format(bench_adr)
    print
    print "Final MLS Portfolio Value: {}".format(port_vals_sl[-1])
    print "Final MS Portfolio Value: {}".format(port_vals_ms[-1])
    print "Final Benchmark Portfolio Value: {}".format(benchmark_vals[-1])
    print

    # ========================
    # OUT OF SAMPLE Analysis
    # ========================
    start_date = dt.datetime(2010, 1, 1)
    end_date = dt.datetime(2011, 12, 31)
    # dates = pd.date_range(start_date, end_date)
    symbol = 'JPM'

    df_trades_ms = ms.testPolicy(symbol=symbol,
                                 sd=start_date,
                                 ed=end_date,
                                 sv=100000)
    df_trades_sl = sl.testPolicy(symbol=symbol,
                                 sd=start_date,
                                 ed=end_date,
                                 sv=100000)

    # generate orders based on trades
    df_orders_ms, benchmark_orders = ManualStrategy.generate_orders(
        df_trades_ms, symbol)
    df_orders_sl, _ = ManualStrategy.generate_orders(df_trades_sl, symbol)

    port_vals_ms = ManualStrategy.compute_portvals(df_orders_ms,
                                                   start_val=100000,
                                                   sd=start_date,
                                                   ed=end_date,
                                                   commission=commission,
                                                   impact=impact)
    port_vals_sl = ManualStrategy.compute_portvals(df_orders_sl,
                                                   start_val=100000,
                                                   sd=start_date,
                                                   ed=end_date,
                                                   commission=commission,
                                                   impact=impact)
    #benchmark_orders.loc[benchmark_orders.index[1], 'Shares'] = 0

    benchmark_vals = ManualStrategy.compute_portvals(benchmark_orders,
                                                     sd=start_date,
                                                     ed=end_date,
                                                     start_val=100000,
                                                     commission=commission,
                                                     impact=impact)

    normed_port_ms = port_vals_ms / port_vals_ms.ix[0]
    normed_port_sl = port_vals_sl / port_vals_sl.ix[0]
    normed_bench = benchmark_vals / benchmark_vals.ix[0]

    dates = pd.date_range(start_date, end_date)
    prices_all = get_data([symbol], dates, addSPY=True, colname='Adj Close')
    prices = prices_all[symbol]  # only portfolio symbols

    # get indicators
    lookback = 14

    _, PSR = id.get_SMA(prices, lookback)
    _, _, bb_indicator = id.get_BB(prices, lookback)
    momentum = id.get_momentum(prices, lookback)

    # figure 5.
    plt.figure(figsize=(12, 6.5))
    top = plt.subplot2grid((5, 1), (0, 0), rowspan=3, colspan=1)
    bottom = plt.subplot2grid((5, 1), (3, 0), rowspan=2, colspan=1, sharex=top)

    # plot the Long or short action
    for index, marks in df_trades_sl.iterrows():
        if marks['Trades'] > 0:
            plt.axvline(x=index, color='blue', linestyle='dashed', alpha=.9)
        elif marks['Trades'] < 0:
            plt.axvline(x=index, color='black', linestyle='dashed', alpha=.9)
        else:
            pass

    top.xaxis_date()
    top.grid(True)
    top.plot(normed_port_sl, lw=2, color='red', label='Q-Learning Strategy')
    top.plot(normed_port_ms, lw=1.5, color='black', label='Manual Strategy')
    top.plot(normed_bench, lw=1.2, color='green', label='Benchmark')

    top.set_title(
        'Machine Learning Strategy (MLS) V.S. Manual Strategy (MS) - Out Sample Analysis'
    )
    top.set_ylabel('Normalized Value')
    for index, marks in df_trades_sl.iterrows():
        if marks['Trades'] > 0:
            top.axvline(x=index, color='blue', linestyle='dashed', alpha=.9)
        elif marks['Trades'] < 0:
            top.axvline(x=index, color='black', linestyle='dashed', alpha=.9)
        else:
            pass

    bottom.plot(momentum, color='olive', lw=1, label="momentum")
    bottom.plot(PSR, color='purple', lw=1, label="PSR")
    #bottom.plot(bb_indicator, color='blue', lw=1, label="Bollinger")
    bottom.set_title('Indicators')

    bottom.axhline(y=-0.2, color='grey', linestyle='--', alpha=0.5)
    bottom.axhline(y=0, color='grey', linestyle='--', alpha=0.5)
    bottom.axhline(y=0.2, color='grey', linestyle='--', alpha=0.5)
    bottom.legend()

    top.legend()
    top.axes.get_xaxis().set_visible(False)
    plt.xlim(start_date, end_date)

    filename = '02_MLS_outsample.png'

    plt.savefig(filename)

    plt.close()

    port_cr_sl, port_adr_sl, port_stddr_sl, port_sr_sl = ManualStrategy.get_portfolio_stats(
        port_vals_sl)
    port_cr_ms, port_adr_ms, port_stddr_ms, port_sr_ms = ManualStrategy.get_portfolio_stats(
        port_vals_ms)
    bench_cr, bench_adr, bench_stddr, bench_sr = ManualStrategy.get_portfolio_stats(
        benchmark_vals)

    # Compare portfolio against benchmark
    print "=== Machine Learning Strategy (MLS) V.S. Manual Strategy (MS) OUT Sample ==="
    print "Date Range: {} to {}".format(start_date, end_date)
    print
    print "Sharpe Ratio of MLS: {}".format(port_sr_sl)
    print "Sharpe Ratio of MS: {}".format(port_sr_ms)
    print "Sharpe Ratio of BenchMark : {}".format(bench_sr)
    print
    print "Cumulative Return of MLS: {}".format(port_cr_sl)
    print "Cumulative Return of MS: {}".format(port_cr_ms)
    print "Cumulative Return of Benchmark : {}".format(bench_cr)
    print
    print "Standard Deviation of MLS: {}".format(port_stddr_sl)
    print "Standard Deviation of MS: {}".format(port_stddr_ms)
    print "Standard Deviation of Benchmark : {}".format(bench_stddr)
    print
    print "Average Daily Return of MLS: {}".format(port_adr_sl)
    print "Average Daily Return of MS: {}".format(port_adr_ms)
    print "Average Daily Return of BenchMark : {}".format(bench_adr)
    print
    print "Final MLS Portfolio Value: {}".format(port_vals_sl[-1])
    print "Final MS Portfolio Value: {}".format(port_vals_ms[-1])
    print "Final Benchmark Portfolio Value: {}".format(benchmark_vals[-1])
    print
Esempio n. 17
0
    def testPolicy(  		  	   		   	 			  		 			 	 	 		 		 	
        self,  		  	   		   	 			  		 			 	 	 		 		 	
        symbol="IBM",  		  	   		   	 			  		 			 	 	 		 		 	
        sd=dt.datetime(2009, 1, 1),  		  	   		   	 			  		 			 	 	 		 		 	
        ed=dt.datetime(2010, 1, 1),  		  	   		   	 			  		 			 	 	 		 		 	
        sv=10000,  		  	   		   	 			  		 			 	 	 		 		 	
    ):  		  	   		   	 			  		 			 	 	 		 		 	
        """  		  	   		   	 			  		 			 	 	 		 		 	
        Tests your learner using data outside of the training data  		  	   		   	 			  		 			 	 	 		 		 	
  		  	   		   	 			  		 			 	 	 		 		 	
        :param symbol: The stock symbol that you trained on on  		  	   		   	 			  		 			 	 	 		 		 	
        :type symbol: str  		  	   		   	 			  		 			 	 	 		 		 	
        :param sd: A datetime object that represents the start date, defaults to 1/1/2008  		  	   		   	 			  		 			 	 	 		 		 	
        :type sd: datetime  		  	   		   	 			  		 			 	 	 		 		 	
        :param ed: A datetime object that represents the end date, defaults to 1/1/2009  		  	   		   	 			  		 			 	 	 		 		 	
        :type ed: datetime  		  	   		   	 			  		 			 	 	 		 		 	
        :param sv: The starting value of the portfolio  		  	   		   	 			  		 			 	 	 		 		 	
        :type sv: int  		  	   		   	 			  		 			 	 	 		 		 	
        :return: A DataFrame with values representing trades for each day. Legal values are +1000.0 indicating  		  	   		   	 			  		 			 	 	 		 		 	
            a BUY of 1000 shares, -1000.0 indicating a SELL of 1000 shares, and 0.0 indicating NOTHING.  		  	   		   	 			  		 			 	 	 		 		 	
            Values of +2000 and -2000 for trades are also legal when switching from long to short or short to  		  	   		   	 			  		 			 	 	 		 		 	
            long so long as net holdings are constrained to -1000, 0, and 1000.  		  	   		   	 			  		 			 	 	 		 		 	
        :rtype: pandas.DataFrame  		  	   		   	 			  		 			 	 	 		 		 	
        """  		  	   		   	 			  		 			 	 	 		 		 	
  		  	   		   	 			  		 			 	 	 		 		 	
        dates = pd.date_range(sd,ed)
        df_prices = ind.get_price(symbol, dates)

        daily_rets = (df_prices / df_prices.shift(1)) - 1
        daily_rets = daily_rets[1:]


        sd_older = sd - dt.timedelta(days=365)
        dates_older = pd.date_range(sd_older,ed)
        df_prices_older = ind.get_price(symbol, dates_older)
        sd_key = df_prices.index[0]
        sd_index = df_prices_older.index.get_loc(sd_key)


        df_holdings = df_prices.copy()
        df_holdings['Holdings'] = np.nan
        del df_holdings[symbol]
        # print(df_holdings)


        # Get Indicator Values
        _,_,ind1 = ind.get_BB(df_prices_older, self.lookback)
        ind2 = ind.get_CCI(df_prices_older, self.lookback)
        _,_,ind3 = ind.get_SMA_Cross(self.lookback, 100, df_prices_older)
        ind4 = ind.get_momentum(df_prices_older, self.lookback)
        _,_,ind5 = ind.get_MACD(df_prices_older)
        BB = ind1.iloc[sd_index:].values
        CCI = ind2.iloc[sd_index:].values
        SMA_Cross = ind3.iloc[sd_index:].values
        Momentum = ind4.iloc[sd_index:].values
        MACD = ind5.iloc[sd_index:].values

        df_holdings.iloc[0]['Holdings'] = 0
        action = 2

        # BB_threshold = 1.0
        # MACD_threshold = 0.15
        # Momentum_threshold = 0.1

        # BB_threshold = 0.
        BB_threshold = 0.0
        MACD_threshold = 0.0
        Momentum_threshold = 0


        for day_idx in range(1,daily_rets.shape[0]):

            # BB Logic
            BB_sell = BB[day_idx-1] >= 1-BB_threshold and BB[day_idx] < 1-BB_threshold
            BB_buy = BB[day_idx-1] <= BB_threshold and BB[day_idx] > BB_threshold

            # MACD Logic
            # MACD_sell = MACD[day_idx] > MACD[day_idx-1] and MACD[day_idx] > 0 and MACD[day_idx] < MACD_threshold
            # MACD_buy = MACD[day_idx] < MACD[day_idx-1] and MACD[day_idx] < 0 and MACD[day_idx] > -1*MACD_threshold
            MACD_sell = MACD[day_idx] >= 0 and MACD[day_idx-1] < 0
            MACD_buy = MACD[day_idx] <= 0 and MACD[day_idx-1] > 0

            # Momentum Logic
            Momentum_sell = Momentum[day_idx] > Momentum_threshold
            Momentum_buy = Momentum[day_idx] < -1*Momentum_threshold

            # SMA Cross Logic
            SMA_sell = SMA_Cross[day_idx] <= 0 and SMA_Cross[day_idx-1] > 0
            SMA_buy = SMA_Cross[day_idx] >= 0 and SMA_Cross[day_idx-1] < 0

            # Momentum_sell = True
            # Momentum_buy = True
            # Momentum_buy = Momentum[day_idx] > Momentum_threshold
            # Momentum_sell = Momentum[day_idx] < -1*Momentum_threshold


            action = 2
            if (BB_sell and Momentum_sell) or (MACD_sell and Momentum_sell):
                action = 1 # Sell signal
            if (BB_buy and Momentum_buy) or (MACD_buy and Momentum_buy):
                action = 0 # Buy Signal





            df_holdings.iloc[day_idx]['Holdings'] = self.take_action(df_holdings.iloc[day_idx-1]['Holdings'], action)  

        df_holdings.iloc[-1]['Holdings'] = 0
        df_trades = df_holdings.diff()
        df_trades['Trades'] = df_trades['Holdings']
        del df_trades['Holdings']
        df_trades.iloc[0]['Trades'] = 0
        return df_trades	   		   	 			  		 			 	 	 		 		 	
Esempio n. 18
0
    def addEvidence(self, symbol = "IBM", \
        sd=dt.datetime(2008,1,1), \
        ed=dt.datetime(2009,1,1), \
        sv = 10000,n_bins=6):

        # this method should create a QLearner, and train it for trading

        syms = [symbol]
        dates = pd.date_range(sd, ed)
        prices, prices_SPY = id.get_price(syms, dates)

        if self.verbose: print prices

        daily_returns = (prices / prices.shift(1)) - 1
        daily_returns = daily_returns[1:]

        # get indicators and combine them into as a feature data_frame
        lookback = 14

        _, PSR = id.get_SMA(prices, lookback)
        _, _, bb_indicator = id.get_BB(prices, lookback)
        momentum = id.get_momentum(prices, lookback)

        _, self.pbins = pd.qcut(PSR, n_bins, labels=False, retbins=True)
        _, self.bbins = pd.qcut(bb_indicator,
                                n_bins,
                                labels=False,
                                retbins=True)
        _, self.mbins = pd.qcut(momentum, n_bins, labels=False, retbins=True)
        self.pbins = self.pbins[1:-1]
        self.bbins = self.bbins[1:-1]
        self.mbins = self.mbins[1:-1]

        # start training

        converged = False
        df_trades = None

        count = 0

        old_cum_ret = 0.0
        converge_count = 0
        converged_prev = False

        #print "Total number of states is:", total_states

        # Initialize QLearner,

        self.learner = ql.QLearner(num_states=100 * n_bins,
                                   num_actions=self.num_actions,
                                   alpha=0.5,
                                   gamma=0.9,
                                   rar=0.0,
                                   radr=0.0,
                                   dyna=0,
                                   verbose=self.verbose)

        while (not converged) and (count < 100):
            # Set first state to the first data point (first day)
            indices = daily_returns.index
            holdings = pd.DataFrame(np.nan,
                                    index=indices,
                                    columns=['Holdings'])
            #first_state = self.indicators_to_state(PSR.iloc[0], bb_indicator.iloc[0], momentum.iloc[0])

            #print("SL 152: holdings.iloc[0] = ", holdings.iloc[0][0], "; daily_rets.iloc[1] = ", daily_returns.iloc[1][0])
            holdings.iloc[0] = 0.
            #print("SL 153")

            #df_prices = prices.copy()
            #df_prices['Cash'] = pd.Series(1.0, index=indices)
            #df_trades = df_prices.copy()
            #df_trades[:] = 0.0

            state = self.indicators_to_state(PSR.iloc[0], bb_indicator.iloc[0],
                                             momentum.iloc[0])
            action = self.learner.querysetstate(state)
            holdings.iloc[0], reward = self.apply_action(
                holdings.iloc[0][0], action, daily_returns.iloc[1][0])

            #print("SL 171: PSR.shape[0] = ",PSR.shape[0],"; daily_returns.shape[0] = ",daily_returns.shape[0])

            # Cycle through dates
            for j in range(1, daily_returns.shape[0]):

                state = self.indicators_to_state(PSR.iloc[j],
                                                 bb_indicator.iloc[j],
                                                 momentum.iloc[j])

                # Get action by Query learner with current state and reward to get action

                action = self.learner.query(state, reward)

                # update reward and holdings with the new action.
                holdings.iloc[j], reward = self.apply_action(
                    holdings.iloc[j - 1][0], action, daily_returns.iloc[j][0])
                #print("SL 183: holdings.iloc[j][0] = ",holdings.iloc[j][0])

                # Implement action returned by learner and update portfolio
            #print("SL 206: one learning is done.")
            #print("SL 215, holdings.iloc[0]",holdings.iloc[0])
            holdings.iloc[-1] = 0
            holdings.ffill(inplace=True)
            holdings.fillna(0, inplace=True)
            #print("SL 216 holdings = ",holdings)
            trades = holdings.diff()
            trades.iloc[0] = 0

            # buy and sell happens when the difference change direction
            df_trades = pd.DataFrame(data=trades.values,
                                     index=indices,
                                     columns=['Trades'])

            df_orders, _ = generate_orders(df_trades, symbol)

            port_vals = compute_portvals(df_orders,
                                         sd=sd,
                                         ed=ed,
                                         impact=self.impact,
                                         start_val=sv,
                                         commission=self.commission)

            cum_ret, _, _, _ = get_portfolio_stats(port_vals)

            count += 1

            old_cum_ret,converged_prev,converge_count,converged = \
                check_convergence(old_cum_ret,cum_ret,converged_prev,converge_count)

            # check if converge
            #if converged:
            #print("SL 212: converged at iteration # ",count, "cum_ret is: ", cum_ret)

        return df_trades

        # example use with new colname
        volume_all = ut.get_data(syms, dates,
                                 colname="Volume")  # automatically adds SPY
        volume = volume_all[syms]  # only portfolio symbols
        volume_SPY = volume_all['SPY']  # only SPY, for comparison later
        if self.verbose: print volume
Esempio n. 19
0
    def testPolicy(self, symbol = "JPM", \
        sd=dt.datetime(2010,1,1), \
        ed=dt.datetime(2011,12,31), \
        sv = 100000):

        rand.seed(5)
        LOOKBACK = 10

        # example usage of the old backward compatible util function
        syms = [symbol]
        dates = pd.date_range(sd, ed)
        prices_all = ut.get_data(syms, dates)  # automatically adds SPY
        prices = prices_all[syms]  # only portfolio symbols
        prices.fillna(method='ffill', inplace=True)
        prices.fillna(method='bfill', inplace=True)
        prices_SPY = prices_all['SPY']  # only SPY, for comparison later
        if self.verbose: print(prices)

        # Make indicators df
        X = prices.copy()
        X.drop([symbol], axis=1, inplace=True)
        X['mmt'] = idc.get_momentum(prices)
        X['smar'] = idc.get_sma_r(prices)
        X['bbp'] = idc.get_bbp(prices)

        df_trades = prices.copy()
        df_trades[symbol] = 0
        holding = 0

        # Get initial state
        indicators = X.iloc[LOOKBACK - 1]
        s = self.serialize(indicators)
        a = self.learner.querysetstate(s)
        df_len = prices.shape[0]

        for i in range(LOOKBACK, df_len - 1):
            s = self.serialize(X.iloc[i])

            if a == 2:  # LONG
                if holding == 0:
                    holding = 1000
                    df_trades.iloc[i, 0] = 1000
                elif holding == -1000:
                    holding = 1000
                    df_trades.iloc[i, 0] = 2000
            elif a == 1:
                pass
            elif a == 0:  # SHORT
                if holding == 0:
                    holding = -1000
                    df_trades.iloc[i, 0] = -1000
                elif holding == 1000:
                    holding = -1000
                    df_trades.iloc[i, 0] = -2000
            else:
                raise Exception("ERROR: INVALID ACTION")
            a = self.learner.querysetstate(s)

    # por_vals = ms.compute_portvals(df_trades, start_val = sv, commission=0.0, impact=self.impact)
    # cum_ret = por_vals[-1]/por_vals[0] - 1
        return df_trades

        if self.verbose: print(type(trades))  # it better be a DataFrame!
        if self.verbose: print(trades)
        if self.verbose: print(prices_all)
Esempio n. 20
0
def showvalues():
    # Specify the start and end dates for this period.
    start_d = dt.date(2008, 1, 1)
    #end_d = dt.datetime(2018, 10, 30)
    yesterday = dt.date.today() - dt.timedelta(1)

    # Get portfolio values from Yahoo
    symbol = request.form['symbol']
    portf_value = fetchOnlineData(start_d, yesterday, symbol)

    # ****Stock prices chart****
    plot_prices = plot_stock_prices(portf_value.index,
                                    portf_value['Adj Close'], symbol)

    # ****Momentum chart****
    # Normalize the prices Dataframe
    normed = pd.DataFrame()
    normed['Adj Close'] = portf_value['Adj Close'].values / portf_value[
        'Adj Close'].iloc[0]

    # Compute momentum
    sym_mom = get_momentum(normed['Adj Close'], window=10)

    # Create momentum chart
    plot_mom = plot_momentum(portf_value.index, normed['Adj Close'], sym_mom,
                             "Momentum Indicator", (12, 8))

    # ****Bollinger Bands****
    # Compute rolling mean
    rm_JPM = get_rolling_mean(portf_value['Adj Close'], window=10)

    # Compute rolling standard deviation
    rstd_JPM = get_rolling_std(portf_value['Adj Close'], window=10)

    # Compute upper and lower bands
    upper_band, lower_band = get_bollinger_bands(rm_JPM, rstd_JPM)

    # Plot raw symbol values, rolling mean and Bollinger Bands
    dates = pd.date_range(start_d, yesterday)
    plot_boll = plot_bollinger(dates,
                               portf_value.index,
                               portf_value['Adj Close'],
                               symbol,
                               upper_band,
                               lower_band,
                               rm_JPM,
                               num_std=1,
                               title="Bollinger Indicator",
                               fig_size=(12, 6))

    # ****Simple moving average (SMA)****
    # Compute SMA
    sma_JPM, q = get_sma(normed['Adj Close'], window=10)

    # Plot symbol values, SMA and SMA quality
    plot_sma = plot_sma_indicator(dates, portf_value.index,
                                  normed['Adj Close'], symbol, sma_JPM, q,
                                  "Simple Moving Average (SMA)")

    # ****Relative Strength Index (RSI)****
    # Compute RSI
    rsi_value = get_RSI(portf_value['Adj Close'])

    # Plot RSI
    plot_rsi = plot_rsi_indicator(dates,
                                  portf_value.index,
                                  portf_value['Adj Close'],
                                  symbol,
                                  rsi_value,
                                  window=14,
                                  title="RSI Indicator",
                                  fig_size=(12, 6))

    # Session variables
    session['start_val'] = request.form['start_val']
    session['symbol'] = request.form['symbol']
    session['start_d'] = start_d.strftime('%Y/%m/%d')
    session['num_shares'] = request.form['num_shares']
    session['commission'] = request.form['commission']
    session['impact'] = request.form['impact']

    return render_template(
        # name of template
        "stockpriceschart.html",

        # now we pass in our variables into the template
        start_val=request.form['start_val'],
        symbol=request.form['symbol'],
        commission=request.form['commission'],
        impact=request.form['impact'],
        num_shares=request.form['num_shares'],
        start_date=start_d,
        end_date=yesterday,
        tables=[portf_value.to_html(classes=symbol)],
        titles=['na', 'Stock Prices '],
        div_placeholder_stock_prices=Markup(plot_prices),
        div_placeholder_momentum=Markup(plot_mom),
        div_placeholder_bollinger=Markup(plot_boll),
        div_placeholder_sma=Markup(plot_sma),
        div_placeholder_rsi=Markup(plot_rsi))
Esempio n. 21
0
    def addEvidence(self, symbol = "JPM", \
        sd=dt.datetime(2008,1,1), \
        ed=dt.datetime(2009,12,31), \
        sv = 100000):

        rand.seed(5)
        LOOKBACK = 10
        randomrate = 0.0

        # Getting data
        syms = [symbol]
        dates = pd.date_range(sd, ed)
        prices_all = ut.get_data(syms, dates)  # automatically adds SPY
        prices = prices_all[syms]  # only portfolio symbols
        prices.fillna(method='ffill', inplace=True)
        prices.fillna(method='bfill', inplace=True)
        prices_SPY = prices_all['SPY']  # only SPY, for comparison later

        # Make indicators df
        X = prices.copy()
        X.drop([symbol], axis=1, inplace=True)
        X['mmt'] = idc.get_momentum(prices)
        X['smar'] = idc.get_sma_r(prices)
        X['bbp'] = idc.get_bbp(prices)

        # Get thresholds for 3 indicators
        # Momentum
        sorted_vals = X['mmt'].sort_values()
        sorted_vals = sorted_vals.dropna()
        stepsize = math.floor(sorted_vals.shape[0] / 10)
        for i in range(0, 10):
            self.threshold_mmt.append(sorted_vals[(i + 1) * stepsize])

        # Simple moving average ratio
        sorted_vals = X['smar'].sort_values()
        sorted_vals = sorted_vals.dropna()
        stepsize = math.floor(sorted_vals.shape[0] / 10)
        for i in range(0, 10):
            self.threshold_smar.append(sorted_vals[(i + 1) * stepsize])

        # Bollinger band percentage
        sorted_vals = X['bbp'].sort_values()
        sorted_vals = sorted_vals.dropna()
        stepsize = math.floor(sorted_vals.shape[0] / 10)
        for i in range(0, 10):
            self.threshold_bbp.append(sorted_vals[(i + 1) * stepsize])

        # Get initial state
        indicators = X.iloc[LOOKBACK - 1]
        s = self.serialize(indicators)
        a = self.learner.querysetstate(s)
        df_len = prices.shape[0]

        run_i = 0
        run_results = []
        MAX_RUNS = 50

        while run_i < MAX_RUNS:
            if len(run_results) > 10:  # Check for convergence
                if (round(run_results[-1], 4) == round(run_results[-2], 4)):
                    break
            run_i += 1
            holding = 0
            df_trades = prices.copy()
            df_trades[symbol] = 0

            for i in range(LOOKBACK, df_len - 1):
                s = self.serialize(X.iloc[i])
                price = prices.iloc[i, 0]
                next_price = prices.iloc[i + 1, 0]

                if rand.uniform(0.0, 1.0) <= randomrate:  # going rogue
                    a = rand.randint(0, 2)  # choose the random direction

                # Calculate reward
                r = 0
                if a == 2:  # LONG
                    if holding == 0:
                        holding = 1000
                        df_trades.iloc[i, 0] = 1000
                        r = -self.impact * (price + next_price) * 1000
                    elif holding == -1000:
                        holding = 1000
                        df_trades.iloc[i, 0] = 2000
                        r = -self.impact * (price + next_price) * 2000
                    else:
                        pass

                elif a == 1:  # do nothing
                    pass

                elif a == 0:  # SHORT
                    if holding == 0:
                        holding = -1000
                        df_trades.iloc[i, 0] = -1000
                        r = -self.impact * (price + next_price) * 1000

                    elif holding == 1000:
                        holding = -1000
                        df_trades.iloc[i, 0] = -2000
                        r = -self.impact * (price + next_price) * 2000
                    else:
                        pass

                else:
                    raise Exception("ERROR: INVALID ACTION")

                r += (next_price - price) * holding
                a = self.learner.query(s, r)

            por_vals = ms.compute_portvals(df_trades,
                                           start_val=sv,
                                           commission=0.0,
                                           impact=self.impact)
            cum_ret = por_vals[-1] / por_vals[0] - 1
            run_results.append(cum_ret)
Esempio n. 22
0
    def testPolicy(
            self,
            symbol="IBM",
            sd=dt.datetime(2008, 1, 1),
            ed=dt.datetime(2009, 1, 31),
            sv=10000,
    ):
        """  		  	   		     		  		  		    	 		 		   		 		  
        Tests your learner using data outside of the training data  		  	   		     		  		  		    	 		 		   		 		  
  		  	   		     		  		  		    	 		 		   		 		  
        :param symbol: The stock symbol that you trained on on  		  	   		     		  		  		    	 		 		   		 		  
        :type symbol: str  		  	   		     		  		  		    	 		 		   		 		  
        :param sd: A datetime object that represents the start date, defaults to 1/1/2008  		  	   		     		  		  		    	 		 		   		 		  
        :type sd: datetime  		  	   		     		  		  		    	 		 		   		 		  
        :param ed: A datetime object that represents the end date, defaults to 1/1/2009  		  	   		     		  		  		    	 		 		   		 		  
        :type ed: datetime  		  	   		     		  		  		    	 		 		   		 		  
        :param sv: The starting value of the portfolio  		  	   		     		  		  		    	 		 		   		 		  
        :type sv: int  		  	   		     		  		  		    	 		 		   		 		  
        :return: A DataFrame with values representing trades for each day. Legal values are +1000.0 indicating  		  	   		     		  		  		    	 		 		   		 		  
            a BUY of 1000 shares, -1000.0 indicating a SELL of 1000 shares, and 0.0 indicating NOTHING.  		  	   		     		  		  		    	 		 		   		 		  
            Values of +2000 and -2000 for trades are also legal when switching from long to short or short to  		  	   		     		  		  		    	 		 		   		 		  
            long so long as net holdings are constrained to -1000, 0, and 1000.  		  	   		     		  		  		    	 		 		   		 		  
        :rtype: pandas.DataFrame  		

        """
        syms = [symbol]
        dates = pd.date_range(sd, ed)
        indicator_dates = pd.date_range(sd - dt.timedelta(days=28), ed)
        prices_all = ut.get_data(syms, dates)  # automatically adds SPY
        prices = prices_all[syms]  # only portfolio symbols
        indicator_prices_all = ut.get_data(
            syms, indicator_dates
        )  #will this be the same size as the number of days traded?
        indicator_prices = indicator_prices_all[syms]
        prices_SPY = prices_all["SPY"]  # only SPY, for comparison later

        rm = ind.get_rolling_mean(indicator_prices[symbol], window=20)
        percent_bb = ind.get_rolling_std(indicator_prices[symbol],
                                         window=20)  #aka rstd
        upper_band, lower_band = ind.get_bollinger_bands(rm, percent_bb)

        percent_bb = percent_bb.iloc[19:]
        rm = rm.iloc[19:]
        upper_band = upper_band.iloc[19:]
        lower_band = lower_band.iloc[19:]
        for x in range(rm.size):  #did i format that right??
            #print(prices.iloc[x])
            #print(type(rm.iloc[x]))
            if (prices.iloc[x][0] == rm.iloc[x]):
                percent_bb.iloc[x] = 0.0
            elif (prices.iloc[x][0] > rm.iloc[x]):
                percent_bb.iloc[x] = (prices.iloc[x][0] - rm.iloc[x]) / (
                    upper_band.iloc[x] - rm.iloc[x])
            elif (prices.iloc[x][0] < rm.iloc[x]):
                percent_bb.iloc[x] = (rm.iloc[x] - prices.iloc[x][0]) / (
                    lower_band.iloc[x] - rm.iloc[x])

        percent_bb = pd.Series(percent_bb)
        #print(percent_bb)
        indicator_prices = indicator_prices.iloc[9:]
        #print(indicator_prices)
        momentum = pd.Series(
            ind.get_momentum(indicator_prices[symbol], window=10))
        momentum = momentum.iloc[10:]
        #print(momentum)
        volatility = pd.Series(
            ind.get_volatility(indicator_prices[symbol], window=10))
        volatility = volatility.iloc[10:]
        # here we build a fake set of trades
        # your code should return the same sort of data
        dates = pd.date_range(sd, ed)
        prices_all = ut.get_data([symbol], dates)  # automatically adds SPY
        trades = prices_all[[
            symbol,
        ]]  # only portfolio symbols
        trades_SPY = prices_all["SPY"]  # only SPY, for comparison later
        trades.values[:, :] = 0  # set them all to nothing
        vol, momnt, bb = self.discretize(symbol)
        #print(volatility.iloc[0])
        #print(vol)
        vol_bin = ""
        mo_bin = ""
        bb_bin = ""

        holdings = 0
        for x in range(trades.size):
            vol_set = False
            mo_set = False
            bb_set = False
            for y in range(vol.size):
                if (volatility.iloc[x] <= vol[y] and vol_set == False):
                    #print(x)
                    vol_bin = str(y)
                    vol_set = True
                elif (y == vol.size - 1 and vol_set == False):
                    vol_bin = str(y + 1)
                    vol_set = True
                if (momentum.iloc[x] <= momnt[y] and mo_set == False):
                    mo_bin = str(y)
                    mo_set = True
                elif (y == momnt.size - 1 and mo_set == False):
                    mo_bin = str(y + 1)
                    mo_set = True
                if (percent_bb.iloc[x] <= bb[y] and bb_set == False):
                    bb_bin = str(y)
                    bb_set = True
                elif (y == bb.size - 1 and bb_set == False):
                    bb_bin = str(y + 1)
                    bb_set = True
            state = int(vol_bin + mo_bin + bb_bin)
            #print(state)
            action = self.learner.querysetstate(state) - 1
            #print(action)
            if (action == 1):
                if (holdings == 0):
                    trades.values[x, :] = 1000
                elif (holdings == -1000):
                    trades.values[x, :] = 2000
                elif (holdings == 1000):
                    trades.values[x, :] = 0
                holdings = 1000
            elif (action == 0):
                if (holdings == 0):
                    trades.values[x, :] = 0
                elif (holdings == -1000):
                    trades.values[x, :] = 1000
                elif (holdings == 1000):
                    trades.values[x, :] = -1000
                holdings = 0
            elif (action == -1):
                if (holdings == 0):
                    trades.values[x, :] = -1000
                elif (holdings == -1000):
                    trades.values[x, :] = 0
                elif (holdings == 1000):
                    trades.values[x, :] = -2000
                holdings = -1000
        #print(trades)
        if self.verbose:
            print(type(trades))  # it better be a DataFrame!
        if self.verbose:
            print(trades)
        if self.verbose:
            print(prices_all)
        #print(trades)
        return trades
Esempio n. 23
0
    def testPolicy(self,
                   symbol="JPM",
                   sd=dt.datetime(2008, 1, 1),
                   ed=dt.datetime(2009, 12, 31),
                   sv=100000):
        '''
        The input parameters are:
            symbol: the stock symbol to act on
            sd: A datetime object that represents the start date
            ed: A datetime object that represents the end date
            sv: Start value of the portfolio

        The output df_trades in form:   Date | Symbol | Order | Shares
        '''
        # window = 10
        dates = pd.date_range(sd, ed)
        symbols = symbol
        prices = ut.get_data([symbol], dates)
        prices.fillna(method='ffill', inplace=True)
        prices.fillna(method='bfill', inplace=True)
        #     print("prices[:20]")
        #     print(prices[:20])
        #     print(len(prices))

        # 1. compute the 3 indicators from indicator.py
        # note: first 10 days might be no tradings since they are within the window time frame and 3 indicators rerturns N/A
        SMA = ind.get_SMA(prices, symbols, self.window)
        price_SMA_ratio = ind.get_SMA_ratio(prices, symbols, self.window)
        momentum = ind.get_momentum(prices, self.window)
        bb_value = ind.get_bollinger_band(prices, symbols, self.window)

        #     print('Price/SMA ratio print here:')
        #     print(price_SMA_ratio[:20])
        #     print(len(price_SMA_ratio))
        #     print('================')
        #     print('momentum print here:')
        #     print(momentum[:20])
        #     print(len(momentum))
        #     print('================')
        #     print('bb_value print here:')
        #     print(bb_value[:20])
        #     print('================')

        #This is for creating the dataframe for df_trades
        symbol_list = []
        date_range = []
        price_of_day = []
        order = []
        share = []

        current_shares = 0
        net_hold = 0  #net_hold = 0 no share, net_hold = 1: long position, net_hold = -1 shorted position
        buy_date = []
        sell_date = []

        #for SMA_ratio: small should buy, large should sell
        #for momemtum: negative should sell, positive should buy
        #for bb_value: small should buy, large should sell
        for i in range(len(prices.index) - 1):  # for i in 0 - 504
            symbol_list.append(symbol)
            date_range.append(prices.index[i])
            price_of_day.append(prices[symbol][i])

            #when you should buy
            if price_SMA_ratio['Price/SMA ratio'][i] < 0.95 or momentum[symbol][
                    i] > 0.3 or bb_value[i] <= 0.6 and current_shares == 0:
                order.append("BUY")
                share.append(1000)
                current_shares += 1000
            elif price_SMA_ratio['Price/SMA ratio'][i] < 0.95 or momentum[
                    symbol][
                        i] > 0.3 or bb_value[i] <= 0.6 and current_shares < 0:
                order.append("BUY")
                share.append(2000)
                current_shares += 2000

            #when you should sell
            elif price_SMA_ratio['Price/SMA ratio'][i] > 1.0 or momentum[
                    symbol][i] < -0.15 or bb_value[
                        i] > 0.9 and current_shares == 0:
                order.append("SELL")
                share.append(-1000)
                current_shares += -1000
            elif price_SMA_ratio['Price/SMA ratio'][i] > 1.0 or momentum[
                    symbol][
                        i] < -0.15 or bb_value[i] > 0.9 and current_shares > 0:
                order.append("SELL")
                share.append(-2000)
                current_shares += -2000

            else:
                order.append("HOLD")
                share.append(0)
                current_shares += 0

        #create the dataframe to store the result
        df_trades = pd.DataFrame(
            index=date_range, columns=['Symbol', 'Prices', 'Order', 'Shares'])
        df_trades['Symbol'] = symbol_list
        df_trades['Prices'] = price_of_day
        df_trades['Order'] = order
        df_trades['Shares'] = share

        # print("df_trades[:20]")
        # print(df_trades[:20])
        # print(len(df_trades))
        return df_trades
Esempio n. 24
0
    def add_evidence(  #this is where you could use the inspiration for the grading function from project 7  		  		  		    	 		 		   		 		  
            self,
            symbol="JPM",
            sd=dt.datetime(2008, 1, 1),
            ed=dt.datetime(2009, 1, 1),
            sv=10000,
    ):
        """  		  	   		     		  		  		    	 		 		   		 		  
        Trains your strategy learner over a given time frame.  		  	   		     		  		  		    	 		 		   		 		  
  		  	   		     		  		  		    	 		 		   		 		  
        :param symbol: The stock symbol to train on  		  	   		     		  		  		    	 		 		   		 		  
        :type symbol: str  		  	   		     		  		  		    	 		 		   		 		  
        :param sd: A datetime object that represents the start date, defaults to 1/1/2008  		  	   		     		  		  		    	 		 		   		 		  
        :type sd: datetime  		  	   		     		  		  		    	 		 		   		 		  
        :param ed: A datetime object that represents the end date, defaults to 1/1/2009  		  	   		     		  		  		    	 		 		   		 		  
        :type ed: datetime  		  	   		     		  		  		    	 		 		   		 		  
        :param sv: The starting value of the portfolio  		  	   		     		  		  		    	 		 		   		 		  
        :type sv: int  		  	   		     		  		  		    	 		 		   		 		  
        """

        # add your code to do learning here
        syms = [symbol]
        dates = pd.date_range(sd, ed)
        indicator_dates = pd.date_range(sd - dt.timedelta(days=28), ed)
        prices_all = ut.get_data(syms, dates)  # automatically adds SPY
        prices = prices_all[syms]  # only portfolio symbols
        indicator_prices_all = ut.get_data(
            syms, indicator_dates
        )  #will this be the same size as the number of days traded?
        indicator_prices = indicator_prices_all[syms]
        prices_SPY = prices_all["SPY"]  # only SPY, for comparison later

        #get 3 indicators using passed in start date minus window required for each
        rm = ind.get_rolling_mean(indicator_prices[symbol], window=20)
        percent_bb = ind.get_rolling_std(indicator_prices[symbol],
                                         window=20)  #aka rstd
        upper_band, lower_band = ind.get_bollinger_bands(rm, percent_bb)

        percent_bb = percent_bb.iloc[19:]
        rm = rm.iloc[19:]
        upper_band = upper_band.iloc[19:]
        lower_band = lower_band.iloc[19:]
        for x in range(rm.size):  #did i format that right??
            #print(prices.iloc[x])
            #print(type(rm.iloc[x]))
            if (prices.iloc[x][0] == rm.iloc[x]):
                percent_bb.iloc[x] = 0.0
            elif (prices.iloc[x][0] > rm.iloc[x]):
                percent_bb.iloc[x] = (prices.iloc[x][0] - rm.iloc[x]) / (
                    upper_band.iloc[x] - rm.iloc[x])
            elif (prices.iloc[x][0] < rm.iloc[x]):
                percent_bb.iloc[x] = (rm.iloc[x] - prices.iloc[x][0]) / (
                    lower_band.iloc[x] - rm.iloc[x])

        percent_bb = pd.Series(percent_bb)
        #print(percent_bb)
        indicator_prices = indicator_prices.iloc[9:]
        #print(indicator_prices)
        momentum = pd.Series(
            ind.get_momentum(indicator_prices[symbol], window=10))
        momentum = momentum.iloc[10:]
        #print(momentum)
        volatility = pd.Series(
            ind.get_volatility(indicator_prices[symbol], window=10))
        volatility = volatility.iloc[10:]
        #print(volatility.values.shape)

        uglystupidnobodylikesyouvol, vol = pd.qcut(volatility.values,
                                                   10,
                                                   retbins=True)
        esrfergs, momnt = pd.qcut(momentum.values, 10, retbins=True)
        rgefsegrf, bb = pd.qcut(percent_bb.values, 10, retbins=True)
        vol = vol[1:-1]
        momnt = momnt[1:-1]
        bb = bb[1:-1]
        #print(volatility.iloc[0])
        #print(vol)
        #print(volatility.iloc[0] in vol[0])

        total_reward = 0
        performance_list = np.zeros(10)
        for z in range(10):
            cash_value = float(sv)
            stock_value = 0.0
            portfolio_value = cash_value + stock_value
            #figure out state
            vol_set = False
            mo_set = False
            bb_set = False
            vol_bin = ""
            mo_bin = ""
            bb_bin = ""

            for x in range(vol.size):
                if (volatility.iloc[0] <= vol[x] and vol_set == False):

                    vol_bin = str(x)
                    vol_set = True

                elif (x == vol.size - 1 and vol_set == False):
                    vol_bin = str(x + 1)
                    vol_set = True
                if (momentum.iloc[0] <= momnt[x] and mo_set == False):
                    mo_bin = str(x)
                    mo_set = True
                elif (x == momnt.size - 1 and mo_set == False):
                    mo_bin = str(x + 1)
                    mo_set = True
                if (percent_bb.iloc[0] <= bb[x] and bb_set == False):
                    bb_bin = str(x)
                    bb_set = True
                elif (x == bb.size - 1 and bb_set == False):
                    bb_bin = str(x + 1)
                    bb_set = True

            #print(volatility.iloc[0])
            #position = 0   actually this could be action variable below
            final_str = vol_bin + mo_bin + bb_bin
            state = int(final_str)
            #print(state)
            action = self.learner.querysetstate(state) - 1
            old_action = action
            same_action = False
            count = 0
            stock_value = action * 1000.0 * prices.iloc[0]
            cash_value -= stock_value

            #print("Daily Value for end of Day 1" + ": " + str(portfolio_value))
            for x in range(
                    1, prices.size
            ):  #while the trading simualtion hasnt reached last day

                #at this point assume day 1 or x is over and now calculate the reward of the prior day's
                #decision to pass in next action call as r. also calculate the
                # holdings of the bot(maybe just check the action variable for this)
                daily_gain = (prices.values[x, 0] - prices.values[x - 1, 0]
                              ) / prices.values[x - 1,
                                                0]  #daily percentage gain

                #print(type(daily_gain))
                portfolio_value = (
                    (1.0 + daily_gain) * stock_value) + cash_value
                #print(portfolio_value)

                if (action == 1):
                    if (daily_gain - self.impact > 0.02):
                        reward = 35.0
                    elif (daily_gain - self.impact > 0.012):
                        reward = 20.0
                    elif (daily_gain - self.impact > 0.004):
                        reward = 7.5
                    elif (daily_gain - self.impact < -0.019):
                        reward = -25.0
                    elif (daily_gain - self.impact < -0.009):
                        reward = -10.0
                    else:
                        reward = daily_gain * 10.0
                elif (action == 0):
                    reward = abs(daily_gain - self.impact) * 3.5
                elif (action == -1):
                    if (daily_gain - self.impact < -0.026):
                        reward = 35.0
                    elif (daily_gain - self.impact < -0.015):
                        reward = 20.0
                    elif (daily_gain - self.impact < -0.004):
                        reward = 7.5
                    elif (daily_gain - self.impact > 0.019):
                        reward = -25.0
                    elif (daily_gain - self.impact > 0.007):
                        reward = -10.0
                    else:
                        reward = daily_gain * -10.0

                if (same_action == True):
                    reward += (7.5 + self.impact)
                #determine state
                vol_set = False
                mo_set = False
                bb_set = False
                vol_bin = ""
                mo_bin = ""
                bb_bin = ""
                for y in range(vol.size):
                    if (volatility.iloc[x] <= vol[y] and vol_set == False):
                        #print(x)
                        vol_bin = str(y)
                        vol_set = True
                    elif (y == vol.size - 1 and vol_set == False):
                        vol_bin = str(y + 1)
                        vol_set = True
                    if (momentum.iloc[x] <= momnt[y] and mo_set == False):
                        mo_bin = str(y)
                        mo_set = True
                    elif (y == momnt.size - 1 and mo_set == False):
                        mo_bin = str(y + 1)
                        mo_set = True
                    if (percent_bb.iloc[x] <= bb[y] and bb_set == False):
                        bb_bin = str(y)
                        bb_set = True
                    elif (y == bb.size - 1 and bb_set == False):
                        bb_bin = str(y + 1)
                        bb_set = True
                state = int(vol_bin + mo_bin + bb_bin)
                old_action = action
                action = self.learner.query(state, reward) - 1
                same_action = False

                if (old_action == action and reward > 0.0):
                    same_action = True
                stock_value = action * 1000.0 * prices.iloc[x]
                cash_value = portfolio_value - stock_value
                total_reward += reward

                #print("Daily Value for end of Day " + str(x+1) + ": " + str(portfolio_value))
            #print("Ending value for test phase " + str(z+1) + ": " + str(portfolio_value))
            performance_list[z] = portfolio_value
        mat.pyplot.plot(performance_list)
    def testPolicy(self, symbol = "IBM", \
        sd=dt.datetime(2009,1,1), \
        ed=dt.datetime(2010,1,1), \
        sv = 10000):

        # here we build a fake set of trades
        # your code should return the same sort of data
        dates = pd.date_range(sd, ed)
        prices_all = ut.get_data([symbol], dates)  # automatically adds SPY
        prices = prices_all[[
            symbol,
        ]]  # only portfolio symbols
        trades_SPY = prices_all['SPY']  # only SPY, for comparison later

        bb_val, upper, lower, rm, rs = get_bb(prices)
        sma = get_sma(prices)
        mom = get_momentum(prices)
        x_test = np.zeros(shape=(len(prices), 7))

        for i in range(20, len(prices) - self.N):
            x_test[i][0] = bb_val[i]
            x_test[i][1] = upper[i]
            x_test[i][2] = lower[i]
            x_test[i][3] = rm[i]
            x_test[i][4] = rs[i]
            x_test[i][5] = sma[i]
            x_test[i][6] = mom[i]

        x_test = pd.DataFrame(x_test)
        x_test = x_test[:-self.N]
        x_test = x_test.values
        y_test = self.learner.query(x_test)

        trades = pd.DataFrame(0, columns=prices.columns, index=prices.index)

        flag = 0
        for i in range(0, len(prices) - self.N):
            if y_test[i] == 1:
                if flag == 0:
                    flag = 1000
                    trades[symbol].iloc[i] = 1000
                elif flag == -1000:
                    flag = 1000
                    trades.iloc[i, 0] = 2000
            if y_test[i] == -1:
                if flag == 0:
                    flag = -1000
                    trades[symbol].iloc[i] = -1000
                elif flag == 1000:
                    flag = -1000
                    trades[symbol].iloc[i] = -2000

        # trades.values[:,:] = 0 # set them all to nothing
        # trades.values[0,:] = 1000 # add a BUY at the start
        # trades.values[40,:] = -1000 # add a SELL
        # trades.values[41,:] = 1000 # add a BUY
        # trades.values[60,:] = -2000 # go short from long
        # trades.values[61,:] = 2000 # go long from short
        # trades.values[-1,:] = -1000 #exit on the last day
        # if self.verbose: print type(trades) # it better be a DataFrame!
        # if self.verbose: print trades
        # if self.verbose: print prices_all
        return trades
Esempio n. 26
0
    def addEvidence(self,
                    symbol="JPM",
                    sd=dt.datetime(2008, 1, 1),
                    ed=dt.datetime(2009, 12, 31),
                    sv=100000):

        df_prices = ut.get_data([symbol], pd.date_range(sd,
                                                        ed)).ffill().bfill()
        df_prices = df_prices[[symbol]]

        indicator_details = df_prices.copy()
        indicator_details.drop([symbol], axis=1, inplace=True)
        indicator_details[self.momentum] = idc.get_momentum(df_prices)
        indicator_details[self.sma_ratio] = idc.get_sma_r(df_prices)
        indicator_details[self.bollinger_percent] = idc.get_bbp(df_prices)

        self.add_indicator_details(indicator_details)

        indicators = indicator_details.iloc[self.window - 1]
        s = self.serialize(indicators)
        a = self.learner.querysetstate(s)
        df_prices_len = df_prices.shape[0]

        ith_run = 0
        run_results = []

        while ith_run < self.max_runs:
            if len(run_results) > 10 and round(run_results[-1], 4) == round(
                    run_results[-2], 4):
                break
            ith_run = ith_run + 1
            holding = 0
            df_trades = df_prices.copy()
            df_trades[symbol] = 0

            for i in range(self.window, df_prices_len - 1):
                reward = 0
                s = self.serialize(indicator_details.iloc[i])
                current_price = df_prices.iloc[i, 0]
                next_price = df_prices.iloc[i + 1, 0]
                if rand.uniform(0.0, 1.0) <= 0:
                    a = rand.randint(0, 2)
                if a == 1:
                    pass
                elif a == 2 and holding == 0:
                    holding = 1000
                    df_trades.iloc[i, 0] = holding
                    reward = -self.impact * (current_price +
                                             next_price) * holding
                elif a == 2 and holding == -1000:
                    holding = 1000
                    df_trades.iloc[i, 0] = 2 * holding
                    reward = -self.impact * (current_price +
                                             next_price) * 2 * holding
                elif a == 0 and holding == 0:
                    holding = -1000
                    df_trades.iloc[i, 0] = holding
                    reward = -self.impact * (current_price + next_price) * 1000

                elif a == 0 and holding == 1000:
                    holding = -1000
                    df_trades.iloc[i, 0] = 2 * holding
                    reward = -self.impact * (current_price + next_price) * 2000

                reward += (next_price - current_price) * holding
                a = self.learner.query(s, reward)

            df_trades.index.names = ['Date']
            df_trades.columns = ['Shares']
            df_trades["Symbol"] = "JPM"
            df_trades["Order"] = [
                "BUY" if x > 0 else "SELL" if x < 0 else "NA"
                for x in df_trades['Shares']
            ]
            df_trades.drop(df_trades[df_trades['Shares'] == 0].index,
                           inplace=True)
            df_trades['Shares'] = df_trades['Shares'].abs()
            df_trades = df_trades.reindex(
                columns=['Symbol', 'Order', 'Shares'])
            df_trades.to_csv('orders.csv')

            port_values = ms.compute_portvals('./orders.csv',
                                              start_val=sv,
                                              commission=0.0,
                                              impact=self.impact)
            cumulative_return = port_values[-1] / port_values[0] - 1
            run_results.append(cumulative_return)
Esempio n. 27
0
    def add_evidence(
            self,
            symbol="IBM",
            sd=dt.datetime(2008, 1, 1),
            ed=dt.datetime(2009, 1, 1),
            sv=10000,
    ):
        """  		  	   		   	 			  		 			 	 	 		 		 	
        Trains your strategy learner over a given time frame.  		  	   		   	 			  		 			 	 	 		 		 	
  		  	   		   	 			  		 			 	 	 		 		 	
        :param symbol: The stock symbol to train on  		  	   		   	 			  		 			 	 	 		 		 	
        :type symbol: str  		  	   		   	 			  		 			 	 	 		 		 	
        :param sd: A datetime object that represents the start date, defaults to 1/1/2008  		  	   		   	 			  		 			 	 	 		 		 	
        :type sd: datetime  		  	   		   	 			  		 			 	 	 		 		 	
        :param ed: A datetime object that represents the end date, defaults to 1/1/2009  		  	   		   	 			  		 			 	 	 		 		 	
        :type ed: datetime  		  	   		   	 			  		 			 	 	 		 		 	
        :param sv: The starting value of the portfolio  		  	   		   	 			  		 			 	 	 		 		 	
        :type sv: int  		  	   		   	 			  		 			 	 	 		 		 	
        """

        # add your code to do learning here

        converged = False
        x = np.zeros((3, 1))
        dates = pd.date_range(sd, ed)
        df_prices = ind.get_price(symbol, dates)

        daily_rets = (df_prices / df_prices.shift(1)) - 1
        daily_rets = daily_rets[1:]

        sd_older = sd - dt.timedelta(days=365)
        dates_older = pd.date_range(sd_older, ed)
        df_prices_older = ind.get_price(symbol, dates_older)
        sd_key = df_prices.index[0]
        sd_index = df_prices_older.index.get_loc(sd_key)

        num_bins = len(self.bins)
        max_state_idx = num_bins + num_bins * 10 + num_bins * 100

        # Call Q-Learner Constructor
        self.learner = QLearner(
            num_states=(max_state_idx + 1),
            num_actions=3,
            alpha=0.01,
            gamma=0.0,
            rar=0.98,
            radr=0.9995,
            dyna=0,
            verbose=False,
        )

        # df_trades = df_prices.copy()
        df_holdings = df_prices.copy()
        df_holdings['Holdings'] = np.nan
        del df_holdings[symbol]  # print(df_holdings)

        # Initlialize Vars
        cum_ret_prev = 0
        iters = 0
        conv_counter = 0
        Q_prev = np.copy(self.learner.Q)

        # Get Indicator Values
        _, _, ind1 = ind.get_BB(df_prices_older, self.lookback)
        ind2 = ind.get_CCI(df_prices_older, self.lookback)
        _, _, ind3 = ind.get_SMA_Cross(self.lookback, 100, df_prices_older)
        ind4 = ind.get_momentum(df_prices_older, self.lookback)
        _, _, ind5 = ind.get_MACD(df_prices_older)
        BB = ind1.iloc[sd_index:].values
        CCI = ind2.iloc[sd_index:].values
        SMA_Cross = ind3.iloc[sd_index:].values
        Momentum = ind4.iloc[sd_index:].values
        MACD = ind5.iloc[sd_index:].values
        _, self.x0bins = pd.qcut(BB[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        _, self.x1bins = pd.qcut(CCI[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        _, self.x2bins = pd.qcut(SMA_Cross[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        _, self.x3bins = pd.qcut(Momentum[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        _, self.x4bins = pd.qcut(MACD[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        x_0 = np.digitize(BB[:, 0], self.x0bins[1:-1])
        x_1 = np.digitize(CCI[:, 0], self.x1bins[1:-1])
        x_2 = np.digitize(SMA_Cross[:, 0], self.x2bins[1:-1])
        x_3 = np.digitize(Momentum[:, 0], self.x3bins[1:-1])
        x_4 = np.digitize(MACD[:, 0], self.x4bins[1:-1])
        state = x_0 + x_3 * 10 + x_4 * 100

        while not converged:

            action = self.learner.querysetstate(state[0])
            daily_return = daily_rets.iloc[0][symbol]
            cur_price = df_prices.iloc[0][symbol]
            next_price = df_prices.iloc[1][symbol]
            df_holdings.iloc[0]['Holdings'], reward = self.take_action(
                0, action, cur_price, next_price)

            for day_idx in range(1, daily_rets.shape[0]):

                daily_return = daily_rets.iloc[day_idx][symbol]
                cur_price = df_prices.iloc[day_idx - 1][symbol]
                next_price = df_prices.iloc[day_idx][symbol]
                df_holdings.iloc[day_idx][
                    'Holdings'], reward = self.take_action(
                        df_holdings.iloc[day_idx - 1]['Holdings'], action,
                        cur_price, next_price)
                action = self.learner.query(state[day_idx], reward)

            df_holdings.iloc[-1]['Holdings'] = 0
            df_trades = df_holdings.diff()
            df_trades['Trades'] = df_trades['Holdings']
            del df_trades['Holdings']
            df_trades.iloc[0]['Trades'] = 0

            portvals = msc.compute_portvals(
                df_trades,
                symbol,
                sv,
                self.commission,
                self.impact,
            )

            cum_ret = (portvals[-1] / portvals[0]) - 1
            Q_diff = np.abs(self.learner.Q - Q_prev)
            Q_max_diff = Q_diff.max()

            if iters > 20:

                # if abs(cum_ret - cum_ret_prev) < 0.0001:
                if Q_max_diff < 0.001:
                    conv_counter += 1
                else:
                    conv_counter = 0

                if conv_counter > 5 or iters > 20000:
                    converged = True
            # if iters > 100:
            #     if iters % 100 == 0:
            #         print("Iteration #", iters)
            print("----------------------------------------------")
            print("--                                          --")
            print("Iteration #", iters)
            print("Error = ", abs(cum_ret - cum_ret_prev))
            print("Q Diff: ", Q_max_diff)
            print("Epsilon: ", self.learner.rar)

            cum_ret_prev = cum_ret
            Q_prev = np.copy(self.learner.Q)
            iters += 1
            self.learner.rar *= self.learner.radr
        # print("Iters = ", iters)
        print("Mode Trained in ", iters, " iterations!")
        np.savetxt('Q_Table.csv', self.learner.Q, delimiter=',')
Esempio n. 28
0
    def testPolicy(
            self,
            symbol="jpm",
            sd=dt.datetime(2008, 1, 1),
            ed=dt.datetime(2009, 12, 31),
            sv=10000,
    ):
        """  		  	   		   	 			  		 			 	 	 		 		 	
        Tests your learner using data outside of the training data  		  	   		   	 			  		 			 	 	 		 		 	
  		  	   		   	 			  		 			 	 	 		 		 	
        :param symbol: The stock symbol that you trained on on  		  	   		   	 			  		 			 	 	 		 		 	
        :type symbol: str  		  	   		   	 			  		 			 	 	 		 		 	
        :param sd: A datetime object that represents the start date, defaults to 1/1/2008  		  	   		   	 			  		 			 	 	 		 		 	
        :type sd: datetime  		  	   		   	 			  		 			 	 	 		 		 	
        :param ed: A datetime object that represents the end date, defaults to 1/1/2009  		  	   		   	 			  		 			 	 	 		 		 	
        :type ed: datetime  		  	   		   	 			  		 			 	 	 		 		 	
        :param sv: The starting value of the portfolio  		  	   		   	 			  		 			 	 	 		 		 	
        :type sv: int  		  	   		   	 			  		 			 	 	 		 		 	
        :return: A DataFrame with values representing trades for each day. Legal values are +1000.0 indicating  		  	   		   	 			  		 			 	 	 		 		 	
            a BUY of 1000 shares, -1000.0 indicating a SELL of 1000 shares, and 0.0 indicating NOTHING.  		  	   		   	 			  		 			 	 	 		 		 	
            Values of +2000 and -2000 for trades are also legal when switching from long to short or short to  		  	   		   	 			  		 			 	 	 		 		 	
            long so long as net holdings are constrained to -1000, 0, and 1000.  		  	   		   	 			  		 			 	 	 		 		 	
        :rtype: pandas.DataFrame  		  	   		   	 			  		 			 	 	 		 		 	
        """

        dates = pd.date_range(sd, ed)
        df_prices = ind.get_price(symbol, dates)

        daily_rets = (df_prices / df_prices.shift(1)) - 1
        daily_rets = daily_rets[1:]

        sd_older = sd - dt.timedelta(days=365)
        dates_older = pd.date_range(sd_older, ed)
        df_prices_older = ind.get_price(symbol, dates_older)
        sd_key = df_prices.index[0]
        sd_index = df_prices_older.index.get_loc(sd_key)

        df_holdings = df_prices.copy()
        df_holdings['Holdings'] = np.nan
        del df_holdings[symbol]
        # print(df_holdings)

        cum_ret_prev = 0
        iters = 0

        num_bins = len(self.bins)

        _, _, ind1 = ind.get_BB(df_prices_older, self.lookback)
        ind2 = ind.get_CCI(df_prices_older, self.lookback)
        _, _, ind3 = ind.get_SMA_Cross(self.lookback, 100, df_prices_older)
        ind4 = ind.get_momentum(df_prices_older, self.lookback)
        _, _, ind5 = ind.get_MACD(df_prices_older)
        BB = ind1.iloc[sd_index:].values
        CCI = ind2.iloc[sd_index:].values
        SMA_Cross = ind3.iloc[sd_index:].values
        Momentum = ind4.iloc[sd_index:].values
        MACD = ind5.iloc[sd_index:].values
        _, self.x0bins = pd.qcut(BB[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        _, self.x1bins = pd.qcut(CCI[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        _, self.x2bins = pd.qcut(SMA_Cross[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        _, self.x3bins = pd.qcut(Momentum[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        _, self.x4bins = pd.qcut(MACD[:, 0],
                                 num_bins,
                                 labels=False,
                                 retbins=True)
        x_0 = np.digitize(BB[:, 0], self.x0bins[1:-1])
        x_1 = np.digitize(CCI[:, 0], self.x1bins[1:-1])
        x_2 = np.digitize(SMA_Cross[:, 0], self.x2bins[1:-1])
        x_3 = np.digitize(Momentum[:, 0], self.x3bins[1:-1])
        x_4 = np.digitize(MACD[:, 0], self.x4bins[1:-1])
        state = x_0 + x_3 * 10 + x_4 * 100

        self.learner.rar = 0

        action = self.learner.querysetstate(state[0])

        daily_return = daily_rets.iloc[0][symbol]
        df_holdings.iloc[0]['Holdings'] = 0

        for day_idx in range(1, daily_rets.shape[0]):

            # implement action
            cur_price = df_prices.iloc[day_idx - 1][symbol]
            next_price = df_prices.iloc[day_idx][symbol]
            action = self.learner.querysetstate(state[day_idx])
            df_holdings.iloc[day_idx]['Holdings'], _ = self.take_action(
                df_holdings.iloc[day_idx - 1]['Holdings'], action, cur_price,
                next_price)

        df_holdings.iloc[-1]['Holdings'] = 0
        df_trades = df_holdings.diff()
        df_trades['Trades'] = df_trades['Holdings']
        del df_trades['Holdings']
        df_trades.iloc[0]['Trades'] = 0
        return df_trades
Esempio n. 29
0
def testPolicyMixed(n_days_bb=20,
                    n_days_mtum=20,
                    n_days_std=20,
                    n_days_rsi=20,
                    tresh_bb=1,
                    tresh_mmtum=0.2,
                    tresh_std_low=1,
                    tresh_std_high=1,
                    symbol="JPM",
                    sd=dt.datetime(2008, 1, 1),
                    ed=dt.datetime(2009, 12, 31),
                    sv=100000):
    df_prices_all = get_data([symbol], pd.date_range(sd, ed))
    df_prices = df_prices_all[symbol]
    df_trades = pd.DataFrame(data=np.zeros(len(df_prices)),
                             index=df_prices.index,
                             columns=['trades'])

    #rstd = idc.get_rolling_stdev(pd.DataFrame(df_prices, index = df_prices.index, columns = [symbol]),  n_days_std)
    rstd = pd.rolling_std(df_prices, window=n_days_std)
    bband = idc.get_bbands(
        pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]),
        n_days_bb)
    momentum = idc.get_momentum(
        pd.DataFrame(df_prices, index=df_prices.index, columns=[symbol]),
        n_days_mtum)
    abs_momentum = momentum.abs()
    rsi = idc.get_rsi(df_prices, n_days_rsi)
    # use rsi to generat sell & buy signal:
    # > 70 : overbought : should sell
    # < 30 : oversold : should buy
    #use volatility as a filter:
    # if std to low, time to buy, std will increase soon, # maybe make a cross over on the rmean of std ?
    # if std to high, means the growth was strong but will back to the mean
    # use momentum to confirm sell & buy signal:
    # confirmed if small enough momentum
    # (changes in prices is slowing - time to take action)
    for t in range(1, len(df_prices) - 1):
        df_net_holdings = df_trades.cumsum(axis=0)
        net_holdings = df_net_holdings.values[t]
        if (net_holdings > 1000) | (net_holdings < -1000):
            print("ERROR")

        # buy signal
        if ((bband[t - 1] <= -tresh_bb) &
            (bband[t] > -tresh_bb)) | (rsi.iloc[t] < 30):
            if (abs_momentum[t] <= tresh_mmtum):
                if rstd[t] <= tresh_std_low:
                    if (net_holdings == 0):
                        df_trades.iloc[t] = 1000
                    elif (net_holdings == -1000):
                        df_trades.iloc[t] = 2000
        # sell signal
        if ((bband[t - 1] >= tresh_bb) &
            (bband[t] < tresh_bb)) | (rsi.iloc[t] > 70):
            if (abs_momentum[t] <= tresh_mmtum):
                if rstd[t] >= tresh_std_high:  # could be remove since thresh = 0
                    if (net_holdings == 0):
                        df_trades.iloc[t] = -1000
                    elif (net_holdings == 1000):
                        df_trades.iloc[t] = -2000
    return df_trades, rstd