Example #1
0
def MACD(df_quotes, fast=12, slow=26, signal=9, symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_MACD_{}_{}_{}.pkl'.format(
            symbol, quotes_range(df_quotes), fast, slow, signal)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    df = pd.DataFrame(index=df_quotes.index)
    fast_ema = EMA(df_quotes, fast, symbol=symbol)
    slow_ema = EMA(df_quotes, slow, symbol=symbol)
    df['MACD'] = fast_ema.EMA - slow_ema.EMA
    signal_ema = EMA(df, signal, field='MACD', symbol=symbol)
    df['Signal'] = signal_ema.EMA
    df['MACDCrossoverSignal'] = np.where(
        np.logical_and(df.MACD > df.Signal,
                       df.MACD.shift(1) <= df.Signal.shift(1)), 1, 0)
    df['SignalCrossoverMACD'] = np.where(
        np.logical_and(df.MACD < df.Signal,
                       df.Signal.shift(1) <= df.MACD.shift(1)), 1, 0)
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #2
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df = pd.DataFrame(index=df_quotes.index)
        ema = self.factory.create(EMA, period=self.period,
                                  field='Volume').run(symbol, df_quotes)
        df[self.Columns.VOLUME.value] = df_quotes.Volume
        df[self.Columns.EMA.value] = ema.EMA
        df[self.Columns.UP.value] = np.where(df_quotes.Open < df_quotes.Close,
                                             df_quotes.Volume, 0)
        df[self.Columns.DOWN.value] = np.where(
            df_quotes.Open >= df_quotes.Close, df_quotes.Volume, 0)

        self.add_direction(
            df,
            np.logical_and(
                df[self.Columns.VOLUME.value] > df[self.Columns.EMA.value],
                df[self.Columns.VOLUME.value].shift(1) <
                df[self.Columns.EMA.value].shift(1)),
            np.logical_and(
                df[self.Columns.VOLUME.value] < df[self.Columns.EMA.value],
                df[self.Columns.VOLUME.value].shift(1) >
                df[self.Columns.EMA.value].shift(1)))
        df = utils.round_df(df)
        return df
Example #3
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df = pd.DataFrame(index=df_quotes.index)
        for col in self.columns:
            df['{}{}'.format(self.SMA_COLUMN,
                             col)] = self.factory.create(SMA, period=col).run(
                                 symbol, df_quotes)[self.SMA_COLUMN]
        col_size = len(self.columns)
        df_comparison = df.lt(df_quotes.Close, axis=0)
        df_comparison['CountSMABelowPrice'] = round(
            100 * (df_comparison.filter(like=self.SMA_COLUMN)
                   == True).astype(int).sum(axis=1) / col_size)
        df_comparison['CountSMAAbovePrice'] = round(
            100 * -(df_comparison.filter(like=self.SMA_COLUMN)
                    == False).astype(int).sum(axis=1) / col_size)
        df[self.Columns.TREND_STRENGTH.
           value] = df_comparison.CountSMABelowPrice + df_comparison.CountSMAAbovePrice

        self.add_direction(
            df,
            np.logical_and(
                df[self.Columns.TREND_STRENGTH.value] >= 100,
                df[self.Columns.TREND_STRENGTH.value].shift(1) < 100),
            np.logical_and(
                df[self.Columns.TREND_STRENGTH.value] <= -100,
                df_quotes.High < df.filter(like=self.SMA_COLUMN).min(axis=1)))
        df = utils.round_df(df)
        return df
Example #4
0
def EMA(df_quotes, period, field='Close', symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_{}_EMA_{}.pkl'.format(
            symbol, quotes_range(df_quotes), field, period)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    c = 2. / (period + 1.)
    df = pd.DataFrame(columns=['EMA'], index=df_quotes.index)
    sma = SMA(df_quotes, period, field)
    _sma = sma.dropna()
    if len(_sma.index.values) == 0:
        print('ts')
    df.loc[_sma.index.values[0], 'EMA'] = _sma.SMA.values[0]
    for i in range(1, len(df_quotes)):
        prev_ema = df.iloc[i - 1]
        if pd.isnull(prev_ema.EMA): continue
        price = df_quotes.iloc[i]
        ema_value = c * price[field] + (1. - c) * prev_ema.EMA
        df.loc[df_quotes.index.values[i], 'EMA'] = ema_value
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #5
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df = pd.DataFrame(index=df_quotes.index)
        fast_sma = self.factory.create(SMA, period=self.fast).run(
            symbol, df_quotes)
        slow_sma = self.factory.create(SMA, period=self.slow).run(
            symbol, df_quotes)
        df[self.Columns.FAST.value] = fast_sma.SMA
        df[self.Columns.SLOW.value] = slow_sma.SMA
        df[self.Columns.SLOW_ON_TOP.value] = np.where(
            np.logical_and(
                df[self.Columns.FAST.value] <= df[self.Columns.SLOW.value],
                df[self.Columns.FAST.value].shift(1) >
                df[self.Columns.SLOW.value].shift(1)), 1, 0)
        df[self.Columns.FAST_ON_TOP.value] = np.where(
            np.logical_and(
                df[self.Columns.FAST.value] >= df[self.Columns.SLOW.value],
                df[self.Columns.SLOW.value].shift(1) >
                df[self.Columns.FAST.value].shift(1)), 1, 0)
        self.add_direction(
            df, df[self.Columns.FAST.value] > df[self.Columns.SLOW.value],
            df[self.Columns.SLOW.value] > df[self.Columns.FAST.value])
        df = utils.round_df(df)
        return df
Example #6
0
def SMA_cross(df_quotes, fast=40, slow=60, symbol=None, field='Close'):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_{}_SMA_cross_{}_{}.pkl'.format(
            symbol, quotes_range(df_quotes), field, fast, slow)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    df = pd.DataFrame(index=df_quotes.index)
    fast_sma = SMA(df_quotes, fast, field=field, symbol=symbol)
    slow_sma = SMA(df_quotes, slow, field=field, symbol=symbol)
    df['FastSMA'] = fast_sma.SMA
    df['SlowSMA'] = slow_sma.SMA
    df['SlowCrossoverFast'] = np.where(
        np.logical_and(df.FastSMA <= df.SlowSMA,
                       df.FastSMA.shift(1) > df.SlowSMA.shift(1)), 1, 0)
    df['FastCrossoverSlow'] = np.where(
        np.logical_and(df.FastSMA >= df.SlowSMA,
                       df.SlowSMA.shift(1) > df.FastSMA.shift(1)), 1, 0)
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #7
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df = pd.DataFrame(columns=[_.value for _ in self.Columns],
                          index=df_quotes.index)
        df[self.Columns.HIGH.value] = df_quotes.High.rolling(
            window=self.high).max()
        df[self.Columns.LOW.value] = df_quotes.Low.rolling(
            window=self.low).min()
        df[self.Columns.MID.value] = (df[self.Columns.HIGH.value] +
                                      df[self.Columns.LOW.value]) / 2

        self.add_direction(
            df,
            np.logical_and(
                df[self.Columns.HIGH.value].shift(1) <
                df[self.Columns.HIGH.value],
                df[self.Columns.LOW.value].shift(1) <=
                df[self.Columns.LOW.value]),
            np.logical_or(
                df[self.Columns.LOW.value].shift(1) >
                df[self.Columns.LOW.value],
                df[self.Columns.HIGH.value].shift(1) >
                df[self.Columns.HIGH.value]))
        df = utils.round_df(df)
        return df
Example #8
0
def SLSMA(df_quotes,
          s_fast=40,
          s_slow=60,
          l_fast=100,
          l_slow=150,
          field='Close',
          symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_{}_SLSMA_cross_{}_{}.pkl'.format(
            symbol, quotes_range(df_quotes), field, s_fast, s_slow, l_fast,
            l_slow)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    # For charting...
    df = pd.DataFrame(index=df_quotes.index)
    s_fast_sma = SMA(df_quotes, s_fast, field=field, symbol=symbol)
    s_slow_sma = SMA(df_quotes, s_slow, field=field, symbol=symbol)
    l_fast_sma = SMA(df_quotes, l_fast, field=field, symbol=symbol)
    l_slow_sma = SMA(df_quotes, l_slow, field=field, symbol=symbol)
    df['S_FastSMA'] = s_fast_sma.SMA
    df['S_SlowSMA'] = s_slow_sma.SMA
    df['L_FastSMA'] = l_fast_sma.SMA
    df['L_SlowSMA'] = l_slow_sma.SMA
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #9
0
def volume(df_quotes, period=20):
    df = pd.DataFrame(index=df_quotes.index)
    ema = EMA(df_quotes, period=period, field='Volume')
    df['Volume'] = df_quotes.Volume
    df['EMA'] = ema.EMA
    df = utils.round_df(df)
    return df
Example #10
0
def ATR(df_quotes, period=10, symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_ATR_{}.pkl'.format(
            symbol, quotes_range(df_quotes), period)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    df = pd.DataFrame(columns=['ATR'], index=df_quotes.index)
    df_true_range = true_range(df_quotes)
    for i in range(1 + len(df_quotes) - period):
        if pd.isnull(df_true_range.iloc[i].true_range): continue
        start = i
        end = i + period
        last_index = end - 1
        trs = df_true_range[start:end]
        prev_atr = df.iloc[last_index - 1].ATR
        if pd.isnull(prev_atr):
            atr = np.mean([tr for tr in trs.true_range.values])
        else:
            atr = (prev_atr * (period - 1) +
                   df_true_range.iloc[last_index].true_range) / period
        df.loc[df_quotes.index.values[last_index], 'ATR'] = atr

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return utils.round_df(df)
Example #11
0
def trend_strength_indicator(df_quotes,
                             start=40,
                             end=150,
                             step=5,
                             symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_trend_strength_indicator_{}_{}_{}.pkl'.format(
            symbol, quotes_range(df_quotes), start, end, step)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    df = pd.DataFrame(index=df_quotes.index)
    columns = [x for x in range(start, end, step)]
    columns += [end]
    for col in columns:
        df['SMA{}'.format(col)] = SMA(df_quotes, col, symbol=symbol)
    col_size = len(columns)
    df_comparison = df.lt(df_quotes.Close, axis=0)
    df_comparison['CountSMABelowPrice'] = round(
        100 *
        (df_comparison.filter(like='SMA') == True).astype(int).sum(axis=1) /
        col_size)
    df_comparison['CountSMAAbovePrice'] = round(
        100 *
        -(df_comparison.filter(like='SMA') == False).astype(int).sum(axis=1) /
        col_size)
    df['TrendStrength'] = df_comparison.CountSMABelowPrice + df_comparison.CountSMAAbovePrice
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #12
0
 def true_range(self, df_quotes):
     df = pd.DataFrame(index=df_quotes.index)
     df['H_minus_L'] = df_quotes.High - df_quotes.Low
     df['H_minus_PrevC'] = abs(df_quotes.High - df_quotes.shift(1).Close)
     df['L_minus_PrevC'] = abs(df_quotes.Low - df_quotes.shift(1).Close)
     df = utils.round_df(df, 4)
     df['true_range'] = df.max(axis=1)
     return df.filter(like='true_range')
Example #13
0
 def run(self, symbol, df_quotes, df_indicator=None):
     if self.is_updated(df_quotes, df_indicator):
         return df_indicator
     df = pd.DataFrame(index=df_quotes.index)
     df['STDEV'] = df_quotes[self.field].rolling(self.period).std()
     self.add_direction(df, df_quotes[self.field] > df['STDEV'],
                        df_quotes[self.field] < df['STDEV'])
     df = utils.round_df(df)
     return df
Example #14
0
def trailing_stops(df_quotes, multiplier=4, period=10, symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_trailing_stops_{}_{}.pkl'.format(
            symbol, quotes_range(df_quotes), period, multiplier)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    df = pd.DataFrame(columns=['BuyStops', 'SellStops'], index=df_quotes.index)
    df_atr = ATR(df_quotes, period=period, symbol=symbol)
    sign = -1  # SellStops: -1, BuyStops: 1
    for i in range(len(df_quotes) - 1):
        if pd.isnull(df_atr.iloc[i].ATR): continue
        start = i - period
        end = i
        quotes = df_quotes.iloc[start + 1:end + 1]
        cur_quote = df_quotes.iloc[i]
        next_quote = df_quotes.iloc[i + 1]
        _atr = df_atr.iloc[i].ATR

        # close_price = next_quote.Close
        # trend_dir_sign = -1 if close_price > _atr else 1

        max_price = quotes.Close.max()
        min_price = quotes.Close.min()

        sell = max_price + sign * (multiplier * _atr)
        buy = min_price + sign * (multiplier * _atr)

        sell = [sell, df.iloc[i].SellStops]
        buy = [buy, df.iloc[i].BuyStops]

        try:
            sell = np.max([x for x in sell if not pd.isnull(x)])
            buy = np.min([x for x in buy if not pd.isnull(x)])
        except:
            print(sell)

        if sign < 0:
            df.set_value(index=df_quotes.index.values[i + 1],
                         col='SellStops',
                         value=sell)
            if next_quote.Close <= sell:
                sign = 1
        else:
            df.set_value(index=df_quotes.index.values[i + 1],
                         col='BuyStops',
                         value=buy)
            if next_quote.Close >= buy:
                sign = -1
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #15
0
def generate_equity_curve(df_trades, starting_balance, historical_data, selling_fees_method=None, start_date=None, end_date=None):
    df_trades['StartDate'] = pd.to_datetime(df_trades['StartDate'])
    df_trades['EndDate'] = pd.to_datetime(df_trades['EndDate'])
    df_trades['LastRecordDate'] = pd.to_datetime(df_trades['LastRecordDate'])

    if start_date is None:
        start_date = df_trades.StartDate.min()
    if end_date is None:
        end_date = df_trades.LastRecordDate.max()

    start_date = pd.to_datetime(start_date)
    df_quotes = historical_data.copy()
    if start_date:
        df_quotes = df_quotes.loc[start_date:]
    if end_date:
        df_quotes = df_quotes.loc[:end_date]

    df = pd.DataFrame()
    for index in df_quotes.index.values.astype('datetime64[D]'):
        date = pd.to_datetime(index)
        cash = starting_balance - df_trades.loc[df_trades['StartDate'] <= date].BuyValue.sum()
        cash_value = cash + df_trades.loc[df_trades['EndDate'] <= date].SellValue.dropna().sum()

        current_value = 0
        open_trades = df_trades.loc[df_trades['StartDate'] <= date]
        open_trades = open_trades[(open_trades['EndDate'] > date) | (pd.isnull(open_trades['EndDate']))]
        for open_trade_index in open_trades.index:
            open_trade = open_trades.loc[open_trade_index]
            prices = df_quotes.loc[:date]['{}_Close'.format(open_trade.Symbol)].dropna().values
            price = prices[-1] if len(prices) > 0 else open_trade['LastPrice']
            shares = open_trade.Shares
            value = price * shares
            if selling_fees_method is not None:
                value = price * shares - selling_fees_method(price, shares)
            current_value += value

        equity_value = cash_value + current_value
        index = pd.to_datetime(index)
        df.loc[index, 'Cash'] = cash_value
        df.loc[index, 'Equity'] = equity_value
        exposure_pct = 100 * current_value / equity_value
        df.loc[index, 'Exposure %'] = exposure_pct

    if not df.empty:
        before_start_date = pd.to_datetime(df.index.values[0]) - datetime.timedelta(days=1)
        df.loc[before_start_date, 'Cash'] = starting_balance
        df.loc[before_start_date, 'Equity'] = starting_balance
        df.loc[before_start_date, 'Exposure %'] = 0.0
        df = df.sort_index()

        df['Drawdown'] = df['Equity'].expanding().apply(drawdown)
        df['DrawdownPercent'] = df['Equity'].expanding().apply(drawdown_pct)

        df = utils.round_df(df)
    return df
Example #16
0
 def run(self, symbol, df_quotes, df_indicator=None):
     if self.is_updated(df_quotes, df_indicator):
         return df_indicator
     else:
         df = pd.DataFrame(index=df_quotes.index)
         df[self.Columns.SMA.value] = df_quotes[self.field].rolling(
             self.period).mean()
         self.add_direction(
             df, df_quotes[self.field] > df[self.Columns.SMA.value],
             df_quotes[self.field] < df[self.Columns.SMA.value])
         df = utils.round_df(df)
         return df
Example #17
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df = pd.DataFrame(columns=['ATR'], index=df_quotes.index)
        df_true_range = self.true_range(df_quotes)
        df['ATR'] = df_true_range.true_range.rolling(self.period).mean()
        for i in df.index.values:
            if pd.isnull(df['ATR'].shift(1).loc[i]): continue
            df.loc[i, 'ATR'] = (df['ATR'].shift(1).loc[i] * (self.period - 1) +
                                df_true_range.loc[i].true_range) / self.period

        self.add_direction(df, False, False)
        return utils.round_df(df)
Example #18
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df = pd.DataFrame(columns=['BuyStops', 'SellStops'],
                          index=df_quotes.index)
        df_atr = self.factory.create(ATR, period=self.period).run(
            symbol, df_quotes)
        sign = -1  # SellStops: -1, BuyStops: 1
        for i in range(len(df_quotes) - 1):
            if pd.isnull(df_atr.iloc[i].ATR): continue
            start = i - self.period
            end = i
            quotes = df_quotes.iloc[start + 1:end + 1]
            cur_quote = df_quotes.iloc[i]
            next_quote = df_quotes.iloc[i + 1]
            _atr = df_atr.iloc[i].ATR

            # close_price = next_quote.Close
            # trend_dir_sign = -1 if close_price > _atr else 1

            max_price = quotes.Close.max()
            min_price = quotes.Close.min()

            sell = max_price + sign * (self.multiplier * _atr)
            buy = min_price + sign * (self.multiplier * _atr)

            sell = [sell, df.iloc[i].SellStops]
            buy = [buy, df.iloc[i].BuyStops]

            try:
                sell = np.max([x for x in sell if not pd.isnull(x)])
                buy = np.min([x for x in buy if not pd.isnull(x)])
            except:
                print(sell)

            if sign < 0:
                df.loc[df_quotes.index.values[i + 1]]['SellStops'] = sell
                if next_quote.Close <= sell:
                    sign = 1
            else:
                df.loc[df_quotes.index.values[i + 1]]['BuyStops'] = buy
                if next_quote.Close >= buy:
                    sign = -1

        self.add_direction(df, df_quotes.Close >= df.BuyStops,
                           df_quotes.Close <= df.SellStops)
        df = utils.round_df(df)
        return df
Example #19
0
def STDEV(df_quotes, period, field='Close', symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_{}_STDEV_{}.pkl'.format(
            symbol, quotes_range(df_quotes), field, period)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    df = pd.DataFrame(index=df_quotes.index)
    df['STDEV'] = df_quotes[field].rolling(period).std()
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #20
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df = pd.DataFrame(index=df_quotes.index)
        df_sma = self.factory.create(SMA, period=self.period).run(
            symbol, df_quotes)
        df_stdev = self.factory.create(STDEV, period=self.period).run(
            symbol, df_quotes)
        df['Top'] = df_sma.SMA + (df_stdev.STDEV * self.stdev)
        df['Mid'] = df_sma.SMA
        df['Bottom'] = df_sma.SMA - (df_stdev.STDEV * self.stdev)

        self.add_direction(df, df_quotes.Close >= df.Top,
                           df_quotes.High < df.Bottom)
        df = utils.round_df(df)
        return df
Example #21
0
def donchian_channel(df_quotes, high=50, low=50, symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_donchian_channel_{}_{}.pkl'.format(
            symbol, quotes_range(df_quotes), high, low)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    df = pd.DataFrame(columns=['high', 'mid', 'low'], index=df_quotes.index)
    df['high'] = df_quotes.High.rolling(window=high).max()
    df['low'] = df_quotes.Low.rolling(window=low).min()
    df['mid'] = (df.high + df.low) / 2
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #22
0
    def update(self, date, account: Account):
        if len(self.df.index.values) == 0:
            earlier = pd.to_datetime(date) - datetime.timedelta(days=1)
            self.df.loc[earlier] = pd.Series()
            self.df.loc[earlier,
                        EquityCurveKey.EQUITY.value] = account.starting_balance
            self.df.loc[earlier,
                        EquityCurveKey.CASH.value] = account.starting_balance

        self.df.loc[date] = pd.Series()
        self.df.loc[date, EquityCurveKey.EQUITY.value] = account.equity
        self.df.loc[date, EquityCurveKey.CASH.value] = account.cash

        self.df[EquityCurveKey.DRAWDOWN.value] = self.df[
            EquityCurveKey.EQUITY.value].expanding(1).apply(
                lambda d: -(d.max() - d[-1]))
        self.df[EquityCurveKey.DRAWDOWN_PERCENT.value] = self.df[
            EquityCurveKey.EQUITY.value].expanding(1).apply(
                lambda d: -(100 * (d.max() - d[-1]) / d.max()))
        self.df = utils.round_df(self.df)
Example #23
0
def bollinger_band(df_quotes, period=60, stdev=1.2, symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_bollinger_band_{}_{}.pkl'.format(
            symbol, quotes_range(df_quotes), period, stdev)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)

    df = pd.DataFrame(index=df_quotes.index)
    df_sma = SMA(df_quotes, period, symbol=symbol)
    df_stdev = STDEV(df_quotes, period, symbol=symbol)
    df['UP'] = df_sma.SMA + (df_stdev.STDEV * stdev)
    df['MID'] = df_sma.SMA
    df['LOW'] = df_sma.SMA - (df_stdev.STDEV * stdev)
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #24
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df_top_atr = self.factory.create(ATR, period=self.top).run(
            symbol, df_quotes)
        df_bottom_atr = self.factory.create(ATR, period=self.bottom).run(
            symbol, df_quotes)
        df_sma = self.factory.create(SMA,
                                     period=self.sma).run(symbol, df_quotes)
        df = pd.DataFrame(columns=[_.value for _ in self.Columns],
                          index=df_quotes.index)
        df[self.Columns.MID.value] = df_sma.SMA
        df[self.Columns.TOP.
           value] = df[self.Columns.MID.value] + df_top_atr.ATR
        df[self.Columns.BOTTOM.
           value] = df[self.Columns.MID.value] - df_bottom_atr.ATR
        self.add_direction(df, df_quotes.Close > df[self.Columns.TOP.value],
                           df_quotes.Close < df[self.Columns.BOTTOM.value])
        df = utils.round_df(df)
        return df
Example #25
0
def atr_channel(df_quotes, top=7, bottom=3, sma=150, symbol=None):
    if symbol:
        outpath = INDICATORS_OUTPUT_PATH / '{}/{}_atr_channel_{}_{}_{}.pkl'.format(
            symbol, quotes_range(df_quotes), top, bottom, sma)
        if os.path.exists(outpath):
            return pd.read_pickle(outpath)
    df_top_atr = ATR(df_quotes, period=top, symbol=symbol)
    df_bottom_atr = ATR(df_quotes, period=bottom, symbol=symbol)
    df_sma = SMA(df_quotes, period=sma, symbol=symbol)

    df = pd.DataFrame(columns=['top', 'mid', 'bottom'], index=df_quotes.index)
    df['mid'] = df_sma.SMA
    df['top'] = df.mid + df_top_atr.ATR
    df['bottom'] = df.mid - df_bottom_atr.ATR
    df = utils.round_df(df)

    if symbol:
        if not os.path.exists(outpath.parent):
            os.makedirs(outpath.parent)
        df.to_pickle(outpath)
    return df
Example #26
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator
        c = 2. / (self.period + 1.)
        df = pd.DataFrame(columns=['EMA'], index=df_quotes.index)
        _sma = self.factory.create(SMA, period=self.period,
                                   field=self.field).run(symbol,
                                                         df_quotes).dropna()
        if not _sma.empty:
            df.loc[_sma.index.values[0], 'EMA'] = _sma.SMA.values[0]
            for i in range(1, len(df_quotes)):
                prev_ema = df.iloc[i - 1]
                if pd.isnull(prev_ema.EMA): continue
                price = df_quotes.iloc[i]
                ema_value = c * price[self.field] + (1. - c) * prev_ema.EMA
                df.loc[df_quotes.index.values[i], 'EMA'] = ema_value

        self.add_direction(df, df_quotes[self.field] > df['EMA'],
                           df_quotes[self.field] < df['EMA'])
        df = utils.round_df(df)
        return df
Example #27
0
    def run(self, symbol, df_quotes, df_indicator=None):
        if self.is_updated(df_quotes, df_indicator):
            return df_indicator

        df = pd.DataFrame(index=df_quotes.index)
        fast_ema = self.factory.create(EMA, period=self.fast).run(
            symbol, df_quotes)
        slow_ema = self.factory.create(EMA, period=self.slow).run(
            symbol, df_quotes)
        df['MACD'] = fast_ema.EMA - slow_ema.EMA
        signal_ema = self.factory.create(EMA, period=self.signal,
                                         field='MACD').run(symbol, df)
        df['Signal'] = signal_ema.EMA
        df['MACDCrossoverSignal'] = np.where(
            np.logical_and(df.MACD > df.Signal,
                           df.MACD.shift(1) <= df.Signal.shift(1)), 1, 0)
        df['SignalCrossoverMACD'] = np.where(
            np.logical_and(df.MACD < df.Signal,
                           df.Signal.shift(1) <= df.MACD.shift(1)), 1, 0)
        self.add_direction(df, df['MACDCrossoverSignal'] == 1,
                           df['SignalCrossoverMACD'] == 1)
        df = utils.round_df(df)
        return df
Example #28
0
    def translate_transactions_to_trades(self):
        df = self.trades.copy()
        close_transactions = self.transactions.loc[self.transactions['Action']
                                                   == Action.CLOSE]
        df['EndDate'] = close_transactions['Date']
        df['Symbol'] = close_transactions['Symbol']
        df['SellPrice'] = close_transactions['Price']
        df['Shares'] = close_transactions['Shares']
        df['SellValue'] = close_transactions['Value']
        df['CloseIndicator'] = close_transactions['Indicator']
        df['LastRecordDate'] = close_transactions['Date']
        df['LastPrice'] = close_transactions['Price']
        df['LastValue'] = close_transactions['Value']

        for index in close_transactions.index.values:
            _df = self.transactions.copy()
            close_transaction = close_transactions.loc[index]
            open_transaction = _df.loc[
                _df['Shares'] == close_transaction.Shares].loc[
                    _df['Date'] <= close_transaction.Date].loc[
                        _df['Symbol'] == close_transaction.Symbol].loc[
                            _df['Action'] != Action.CLOSE].iloc[-1]
            df_index = df.loc[df['EndDate'] == close_transaction.Date].loc[
                df['Symbol'] == close_transaction.Symbol].index.values[-1]
            df.loc[df_index, 'StartDate'] = pd.to_datetime(
                open_transaction.Date).strftime('%Y-%m-%d')
            df.loc[df_index, 'BuyPrice'] = open_transaction.Price
            df.loc[df_index, 'BuyValue'] = open_transaction.Value
            df.loc[df_index, 'OpenIndicator'] = open_transaction.Indicator
            df.loc[df_index,
                   'TotalRisk'] = self.position_sizing.calculate_total_risk(
                       open_transaction.Price, close_transaction.Shares)

        for index in self.positions.loc[
                self.positions.Quantity > 0].index.values:
            _df = self.transactions.copy()
            position = self.positions.loc[index]
            open_transaction = _df.loc[_df['Shares'] == position.Quantity].loc[
                _df['Symbol'] == position.Symbol].loc[
                    _df['Action'] != Action.CLOSE].iloc[-1]
            df = df.append(pd.DataFrame(
                {
                    'StartDate':
                    pd.to_datetime(open_transaction.Date).strftime('%Y-%m-%d'),
                    'BuyPrice':
                    open_transaction.Price,
                    'BuyValue':
                    open_transaction.Value,
                    'OpenIndicator':
                    open_transaction.Indicator,
                    'TotalRisk':
                    self.position_sizing.calculate_total_risk(
                        open_transaction.Price, open_transaction.Shares),
                    'Symbol':
                    position.Symbol,
                    'Shares':
                    open_transaction.Shares,
                    'LastRecordDate':
                    position.LastRecordDate,
                    'LastPrice':
                    position.LastPrice,
                    'LastValue':
                    position.LastValue
                },
                index=[0]),
                           ignore_index=True)

        df = df.sort_values(['StartDate'])
        df = df.reset_index()
        df = df.drop(['index'], axis=1)
        try:
            df['BarsHeld'] = df.apply(
                lambda trade: len(self.df_group_quotes.loc[pd.to_datetime(
                    trade['StartDate']):pd.to_datetime(trade[
                        'LastRecordDate'])].filter(regex='^{}_Close'.format(
                            trade.Symbol)).dropna().values),
                axis=1)
        except:
            pass
        df['PnL'] = np.subtract(df['SellValue'].values,
                                np.absolute(df['BuyValue'].values))
        df['RMultiple'] = np.divide(df['PnL'].values, df['TotalRisk'])
        df['LastPnL'] = np.subtract(df['LastValue'].values,
                                    np.absolute(df['BuyValue'].values))
        df['LastRMultiple'] = np.divide(df['LastPnL'].values, df['TotalRisk'])
        df = utils.round_df(df)

        df['RMultiple'] = utils._round(df['RMultiple'], places=2)
        df['LastRMultiple'] = utils._round(df['LastRMultiple'], places=2)

        columns = self.trades.columns
        self.trades = df.copy()[columns]
Example #29
0
def performance_data(starting_capital,
                     df_backtest,
                     df_trades,
                     index='Performance'):
    df = pd.DataFrame()

    equities = df_backtest['Equity'].values
    years = len(equities) / TRADE_DAYS_PER_YEAR

    ending_capital = df_backtest['Equity'].values[-1]
    net_profit = ending_capital - starting_capital
    net_profit_pct = 100 * net_profit / starting_capital
    annualized_gain = ((ending_capital / starting_capital)**(1 / years) - 1)
    max_system_dd = max_drawdown(df_backtest)
    max_system_pct_dd = max_pct_drawdown(df_backtest)
    max_peak = df_backtest.Equity.max()
    df_winning_trades = df_trades[df_trades['LastPnL'] > 0]
    df_losing_trades = df_trades[df_trades['LastPnL'] <= 0]
    ui = ulcer_index(df_backtest)
    avg_bars_held_value = avg_bars_held(df_backtest, df_trades)
    avg_expectancy_pct_value = avg_expectancy_pct(df_trades)
    risk_free_rate = 0.01

    df.loc[index, 'Number of Trading Days'] = df_backtest.Equity.count()
    df.loc[index, 'Starting Capital'] = starting_capital
    df.loc[index, 'Ending Capital'] = ending_capital
    df.loc[index, 'Net Profit'] = net_profit
    df.loc[index, 'Net Profit %'] = net_profit_pct

    df.loc[index, 'SQN'] = SQN(df_trades)
    df.loc[index, 'Annualized Gain'] = annualized_gain

    df.loc[index, 'Max Profit'] = df_trades.LastPnL.max()
    df.loc[index, 'Max Loss'] = df_trades.LastPnL.min()

    df.loc[index, 'Number of Trades'] = len(df_trades.index.values)
    df.loc[index, 'Winning Trades'] = len(df_winning_trades.index.values)
    df.loc[index, 'Losing Trades'] = len(df_losing_trades.index.values)
    try:
        df.loc[index, 'Winning Trades %'] = np.round(
            100 * (len(df_winning_trades.index.values) /
                   len(df_trades.index.values)), 2)
    except:
        df.loc[index, 'Winning Trades %'] = 0

    df.loc[index, 'Avg Profit/Loss'] = avg_expectancy(df_trades)
    df.loc[index, 'Avg Profit'] = avg_expectancy(df_winning_trades)
    df.loc[index, 'Avg Loss'] = avg_expectancy(df_losing_trades)

    df.loc[index, 'Avg Profit/Loss %'] = avg_expectancy_pct_value
    df.loc[index, 'Avg Profit %'] = avg_expectancy_pct(df_winning_trades)
    df.loc[index, 'Avg Loss %'] = avg_expectancy_pct(df_losing_trades)

    df.loc[index, 'Avg Bars Held'] = avg_bars_held_value
    df.loc[index,
           'Avg Winning Bars Held'] = avg_bars_held(df_backtest,
                                                    df_winning_trades)
    df.loc[index,
           'Avg Losing Bars Held'] = avg_bars_held(df_backtest,
                                                   df_losing_trades)

    df.loc[index, 'Max System Drawdown'] = max_system_dd
    df.loc[index, 'Max System % Drawdown'] = max_system_pct_dd
    df.loc[index, 'Max Peak'] = max_peak

    df.loc[index, 'Recovery Factor'] = net_profit / abs(max_system_pct_dd)
    try:
        df.loc[index,
               'Profit Factor'] = df_winning_trades['LastPnL'].sum() / abs(
                   df_losing_trades['LastPnL'].sum())
    except:
        df.loc[index, 'Profit Factor'] = 0.0
    df.loc[index, 'Payoff Ratio'] = df_winning_trades['LastPnL'].mean() / abs(
        df_losing_trades['LastPnL'].mean())

    return utils.round_df(df, places=2)