Example #1
0
    def _calc_indicator(self, OHLCV_input):
        """
        Calculates the Moving Average Convergence/Divergence using a wrapper for the TA-lib

        Args:
            :param OHLCV_input:  the dataframe with the Open, High, Low, Close and Volume values
            :type OHLCV_input: pandas DataFrame

        Returns:
            DataFrame with scaled features with size (n_observations, n_features).
        """
        try:
            close = OHLCV_input['close'].values[:, 0]
        except IndexError:
            close = OHLCV_input['close'].values

        macd, macdsignal, macdhist = MACD(close, self.__fastperiod, self.__slowperiod, self.__signalperiod)

        macd = DataFrame(macd)
        macdsignal = DataFrame(macdsignal)
        macdhist = DataFrame(macdhist)

        macd.colmuns = ['macd%d' % self.__signalperiod]
        macdsignal.colmuns = ['macdsignal%d' % self.__signalperiod]
        macdhist.colmuns = ['macdhist%d' % self.__signalperiod]

        return concat([macd, macdsignal, macdhist], axis=1, ignore_index=True)
Example #2
0
def WADDAH_ATTAR_EXPLOSION(close, high, low, sensitive = 150, fast_period=20, slow_period = 40, channel_period = 20, channel_mult = 2, dead_zone=30):
    
    from talib import MACD 
    from talib import BBANDS 
    from talib import ATR 
    from talib import WMA 
    macd, macdsignal, macdhist = MACD(close, fastperiod=fast_period, slowperiod=slow_period, signalperiod=9)
    upperband, middleband, lowerband = BBANDS(close, timeperiod=channel_period, nbdevup=channel_mult, nbdevdn=channel_mult, matype=0)

    ind_trend1 = np.full(len(close), np.nan)
    ind_itrend1 = np.full(len(close), np.nan)
    ind_explo1 = np.full(len(close), np.nan)
    tr = WMA(ATR(high, low, close, 20),3)
    ind_dead = tr*dead_zone / 10
    for i in range(0,len(close)):
        if(i<2):
            continue
        trend1 = (macd[i] - macd[i-1]) * sensitive;
        trend2 = (macd[i-1] - macd[i-2]) * sensitive;
        explo1 = (upperband[i] - lowerband[i])
        #explo2 = (upperband[i-1] - lowerband[i-1])
        
        if(trend1>=0):
            ind_trend1[i]=trend1
            ind_itrend1[i]=0
        if(trend1<0):
            ind_trend1[i]=0
            ind_itrend1[i]=(trend1*-1)
        ind_explo1[i] = explo1
        #print(str(i)+"\t "+str(close[i])+"\t "+str(close[i])+"\t "+str(ind_trend1[i])+"\t"+str(ind_itrend1[i]))
    return ind_trend1, ind_itrend1, ind_explo1, ind_dead
Example #3
0
    async def handle_buy_side(
        self,
        symbols_position: Dict[str, float],
        data_loader: DataLoader,
        now: datetime,
        trade_fee_precentage: float,
    ) -> Dict[str, Dict]:
        actions = {}

        for symbol, position in symbols_position.items():
            if position != 0:
                continue

            current_price = data_loader[symbol].close[now]

            sma_50 = (
                data_loader[symbol]
                .close[now - timedelta(days=60) : now]  # type: ignore
                .resample("1D")
                .last()
                .rolling(50)
                .mean()
                .dropna()
                .iloc[-1]
            )

            if current_price >= sma_50:

                macds = MACD(
                    data_loader[symbol].close[now - timedelta(days=100) : now],  # type: ignore
                    12,
                    26,
                    9,
                )
                macd = macds[0]
                macd_signal = macds[1]

                if macd[-1] > macd_signal[-1] and macd[-1] > 0:
                    buy_indicators[symbol] = {
                        "sma_50": sma_50,
                        "macd": macd[-5:].tolist(),
                        "mac_signal": macd_signal[-5:].tolist(),
                        "current_price": current_price,
                    }
                    shares_to_buy = await self.calc_qty(
                        current_price,
                        trade_fee_precentage,
                    )
                    tlog(
                        f"[{self.name}][{now}] Submitting buy for {shares_to_buy} shares of {symbol} at {current_price}"
                    )
                    tlog(f"indicators:{buy_indicators[symbol]}")
                    actions[symbol] = {
                        "side": "buy",
                        "qty": str(shares_to_buy),
                        "type": "limit",
                        "limit_price": str(current_price),
                    }

        return actions
Example #4
0
def calculate_indicators(df):

    logging.info('Calculating indicators...')

    # Build dictionary:
    indicator_dict = dict()

    # MACD
    fast = 12
    slow = 26
    signal = 9
    macd, macdsignal, macdhist = MACD(df['price_close'], fast, slow, signal)
    indicator_dict['macd_current'] = macd[-1]
    indicator_dict['macd_signal_current'] = macdsignal[-1]

    # ADX
    time_period = 14
    adx = ADX(df['price_high'], df['price_low'], df['price_close'],
              time_period)
    indicator_dict['adx_current'] = adx[-1]

    # DI+/DI-
    time_period = 14
    di_plus = PLUS_DI(df['price_high'], df['price_low'], df['price_close'],
                      time_period)
    di_minus = MINUS_DI(df['price_high'], df['price_low'], df['price_close'],
                        time_period)
    indicator_dict['di_plus_current'] = di_plus[-1]
    indicator_dict['di_minus_current'] = di_minus[-1]

    return indicator_dict
Example #5
0
    def refresh(self, df):
        df = df[-(MAX_ROWS + 1):-1]
        open = df.open.astype("f8").values
        high = df.high.astype("f8").values
        low = df.low.astype("f8").values
        close = df.close.astype("f8").values
        volume = df.volume.astype("f8").values

        df["price"] = WCLPRICE(high, low, close)  #Weighted Close Price
        df["obv"] = OBV(close, volume)
        df["ad"] = AD(high, low, close, volume)
        df["macd"], df["signal"], df["histogram"] = MACD(close)
        df["rsi"] = RSI(close)  #relative strong index
        #df["willr"] = WILLR(high, low, close) + 100 #will index
        df["roc"] = ROC(close)

        #統計
        df["beta"] = BETA(high, low)
        df["linearR"] = LINEARREG(close)  #線形回帰
        df["linearA"] = LINEARREG_ANGLE(close)  ##線形回帰 角度
        df["linearI"] = LINEARREG_INTERCEPT(close)  #線形回帰 JIEJU
        df["linearS"] = LINEARREG_SLOPE(close)  #線形回帰 坂
        df["stddev"] = STDDEV(close)  #標準偏差
        df["tsf"] = TSF(close)  #Time Series Forecast
        df["var"] = VAR(close)  #方差

        df["wramount"] = 0
        df["amount"] = 0
        df["memo"] = 0
Example #6
0
def getMACD(price):
    date = 1
    MACD_ = []
    macd, macdsignal, macdhist = MACD(price)
    for ele,ele1,ele2 in zip(macd, macdsignal, macdhist):
        MACD_.append([date, ele,ele1,ele2])
        date = date + 1
    return MACD_
Example #7
0
 def calcMACD(self, dates, price):
     MACD_ = []
     macd, macdsignal, macdhist = MACD(price)
     for ele, ele1, ele2 in zip(macd, macdsignal, macdhist):
         MACD_.append([ele, ele1, ele2])
     MACD_, isExist = self.createDateFrame(
         dates, MACD_, ['timestamp', 'macd', 'macdsignal', 'macdhist'])
     return MACD_, isExist
    def execute(self, env, df):
        '''
        Execute a single iteration of algorithmic trading
        '''
        last_row_idx = len(df) - 1

        for product_id in env.product_id_list:

            product_df = df[product_id]

            rsi = RSI(product_df.close)

            macd, macd_signal, macd_hist = MACD(
                product_df.close,
                fastperiod=self.fast_period,
                slowperiod=self.slow_period,
                signalperiod=self.signal_period)

            if self.states.get(product_id) is None:
                self.states[product_id] = NO_POSITION

            next_state = self.next_state(product_id, rsi[last_row_idx],
                                         macd[last_row_idx])

            if self.states[product_id] != next_state:
                if next_state == BUY:
                    # buy
                    if len(env.positions) == 0:
                        quantity = env.balance / product_df.close[last_row_idx]
                        ts = product_df.timestamp[last_row_idx]
                        price = product_df.close[last_row_idx]
                        buy_order = BuyMarketOrder(product_id,
                                                   ts,
                                                   funds=env.balance)
                        env.process_buy_order(buy_order)
                    else:
                        print("already holding trade")
                    self.states[product_id] = POSITION_HELD
                elif next_state == SELL:
                    # sell
                    if len(env.positions):
                        for position in env.find_positions(
                                lambda x: x.product_id == product_id):
                            ts = product_df.timestamp[last_row_idx]
                            sell_order = SellMarketOrder(
                                product_id,
                                ts,
                                quantity=position.quantity,
                            )
                            env.process_sell_order(sell_order)
                    else:
                        print("did not have active trade")
                    self.states[product_id] = NO_POSITION
                else:
                    self.states[product_id] = next_state
Example #9
0
    def binaryClassificationInThirtyMinutes(self, df):
        '''
        Predict the price of bitcoin in the next 30 minutes by a given df (dataframe)

        Example: 
            binaryClassificationInThirtyMinutes(df) = 0

        Parameters:
            df: a dataframe with df.columns = ['open', 'high', 'low', 'close', 'volume']
        Returns:
            prediction: int = a prediction by the model, 0 for down, 1 for same or up
        '''

        # if len(df) != 34:
        #    # due to wma
        #    raise Exception("Dataframe must have 34 rows")

        data = df.copy()

        rsi = RSI(data['close'])
        k, d = STOCH(data['high'], data['low'], data['close'])
        macd, macdsignal, macdhist = MACD(data['close'],
                                          fastperiod=12,
                                          slowperiod=26,
                                          signalperiod=9)
        williams_r = WILLR(data['high'], data['low'], data['close'])
        rate_of_change = ROC(data['close'])
        on_balance_volume = OBV(data['close'], data['volume'])
        weighted_moving_average = WMA(data['close'])
        normalized_average_true_range = NATR(data['high'], data['low'],
                                             data['close'])

        data['rsi'] = rsi
        data['k'] = k
        data['d'] = d
        data['macd'] = macd
        data['williams_r'] = williams_r
        data['rate_of_change'] = rate_of_change
        data['on_balance_volume'] = on_balance_volume
        data['weighted_moving_average'] = weighted_moving_average
        data['normalized_average_true_range'] = normalized_average_true_range

        data = data.dropna(axis=0)

        data = self.normalizeDataframe(data)

        with open(
                pathlib.Path(__file__).resolve().parent /
                "random_forest_params", "rb") as file:
            model = pickle.load(file)

        features = data.values
        prediction = model.predict(features)
        return prediction[0]
Example #10
0
 def compute_macd(df,
                  field=None,
                  fast_period=None,
                  slow_period=None,
                  signal_period=None):
     df['macd'], df['macd_signal'], df['macd_hist'] = MACD(
         df[field].values.astype(float),
         fastperiod=fast_period,
         slowperiod=slow_period,
         signalperiod=signal_period)
     return df
Example #11
0
def CalculateIndices(df):
    MACD_FAST = 10
    MACD_SLOW = 21
    MACD_SIGNAL = 7

    macd, macdSignal, macdHist = MACD(df['c'], MACD_FAST, MACD_SLOW,
                                      MACD_SIGNAL)
    rsi10 = RSI(df['c'], 10)
    rsi14 = RSI(df['c'], 14)

    return macd, macdSignal, macdHist, rsi10, rsi14
def create_lots_of_macds(prices):
    macd, macdsignal, macdhist = MACD(prices,
                                      fastperiod=12,
                                      slowperiod=26,
                                      signalperiod=9)

    all_macds = np.reshape(macdsignal, (len(prices), 1))

    for fast_period in range(9, 16):
        for slow_period in range(20, 31):
            for signal_period in range(5, 12):
                macd, macdsignal2, macdhist = MACD(prices,
                                                   fastperiod=fast_period,
                                                   slowperiod=slow_period,
                                                   signalperiod=signal_period)

                current_macd = np.reshape(macdsignal2, (len(prices), 1))
                all_macds = np.hstack((all_macds, current_macd))

    return all_macds
Example #13
0
def CalculateIndices(df):
    MACD_FAST = 10
    MACD_SLOW = 21
    MACD_SIGNAL = 7

    macd, macdSignal, macdHist = MACD(df['c'], MACD_FAST, MACD_SLOW,
                                      MACD_SIGNAL)

    df[ind_columns[0]] = macd
    df[ind_columns[1]] = macdSignal
    df[ind_columns[2]] = macdHist
    return df
Example #14
0
    def update(self, data):
        Candle.update(self, data)
        candles = self.dataline.get_nd_candles(
            data['token'], self.timeperiod, self.prev, count=200)
        r = None
        try:
            r = MACD(np.array(candles['close']), self.fastperiod,
                    self.slowperiod, self.signalperiod)
        except:
            r = {self.k : [0]}
            print("Exception")

        self.setd(0 if np.isnan(r[self.k][-1]) else r[self.k][-1])
        return self
Example #15
0
def get_indicators(df, indicators=[]):
    if "bbands" in indicators:
        df["upperband"], df["middleband"], df["lowerband"] = BBANDS(
            df["close"], timeperiod=20, nbdevup=2, nbdevdn=2, matype=0)
    if "macd" in indicators:
        df["macd"], df["macdsignal"], df["macdhist"] = MACD(df["close"],
                                                            fastperiod=12,
                                                            slowperiod=26,
                                                            signalperiod=9)
    if "price_logreturn" in indicators:
        df["price_logreturn"] = log_return(df["close"].to_numpy())
    if "volume_logreturn" in indicators:
        df["volume_logreturn"] = log_return(df["volume"].to_numpy())

    return df
Example #16
0
def handle_data(context, data):

    # Request history for the stock
    history = data.history(context.universe, "close",
                           context.index_average_window, "1d")

    for i in range(len(history.columns)):
        stock = np.array(history.iloc[:, i])
        macd, macdsignal, macdhist = MACD(stock,
                                          fastperiod=12,
                                          slowperiod=26,
                                          signalperiod=9)
        if macd[-2] <= macdsignal[-2] and macd[-1] > macdsignal[-1]:
            order_target_percent(history.columns[i], 0.2)
        if macd[-2] >= macdsignal[-2] and macd[-1] < macdsignal[-1]:
            order_target_percent(history.columns[i], 0.0)
    def execute(self, df):

        last_row_idx = len(df) - 1

        macd, macd_signal, macd_hist = MACD(df.close,
                                            fastperiod=self.fast_period,
                                            slowperiod=self.slow_period,
                                            signalperiod=self.signal_period)

        macd_state = MACD_HIGH if macd_hist[last_row_idx] > 0 else MACD_LOW

        if self.signal is None:
            self.signal = macd_state
        elif self.signal != macd_state:
            if macd_state == MACD_HIGH:
                # buy
                if self.trade is None:
                    quantity = self.cash / df.close[last_row_idx]
                    product_id = df.product_id[last_row_idx]
                    ts = df.timestamp[last_row_idx]
                    price = df.close[last_row_idx]
                    trade = Trade(product_id, ts, price, quantity, self.cash)
                    print(
                        f"Bought {quantity} shares of {product_id} at "
                        f"{ts} for {price} a share (for a total of {self.cash})"
                    )
                    self.trade = trade
                    self.cash = 0
                else:
                    print("already holding trade")
            elif macd_state == MACD_LOW:
                # sell
                if self.trade is not None:
                    sell_price = df.close[last_row_idx]
                    sell_value = self.trade.quantity * sell_price
                    sell_ts = df.timestamp[last_row_idx]
                    print(
                        f"Sold {self.trade.quantity} shares of {self.trade.product_id} "
                        f"at {sell_ts} for {sell_price} a share (for a total "
                        f"of {sell_value}, profit of "
                        f"{sell_value-self.trade.value}")
                    self.cash = sell_value
                    self.trade = None
                else:
                    print("did not have active trade")
            self.signal = macd_state
Example #18
0
def calculateIndex(filePath):
    File = open(filePath, "r")
    text = File.read()
    text = text.rstrip()
    File.close()

    OHLCV = json.loads(text)
    timePeriod = np.array(OHLCV['t'])
    nClose = np.array(OHLCV['c'])

    rsi = RSI(nClose, timeperiod=RSI_T)
    macd, macdSignal, macdHist = MACD(nClose, MACD_FAST, MACD_SLOW,
                                      MACD_SIGNAL)
    emaSlow = EMA(nClose, EMA_SLOW)
    emaMedium = EMA(nClose, EMA_MEDIUM)
    emaFast = EMA(nClose, EMA_FAST)

    #print("RSI (first 10 elements)\n", rsi[10:20])
    return timePeriod, rsi, macd, macdSignal, macdHist, emaSlow, emaMedium, emaFast
Example #19
0
def calculateIndex(filePath):
    File = open(filePath, "r")
    text = File.read()
    text = text.rstrip()
    File.close()

    OHLCV = json.loads(text)

    timePeriod = OHLCV['t']

    if timePeriod:
        nClose = np.array(OHLCV['c'])
        rsi = RSI(nClose, timeperiod=RSI_T)
        macd, macdSignal, macdHist = MACD(nClose, MACD_FAST, MACD_SLOW,
                                          MACD_SIGNAL)
        #print("RSI (first 10 elements)\n", rsi[-1])
        return rsi, macd, macdSignal, macdHist
    else:
        return 100, 0, 0, 0
Example #20
0
def create_lots_of_macds(historical_data):
    prices = historical_data['Adj Close'].as_matrix()

    all_macds = dict()

    for fast_period in range(9, 16):
        for slow_period in range(20, 31):
            for signal_period in range(5, 12):
                macd, macdsignal2, macdhist = MACD(prices,
                                                   fastperiod=fast_period,
                                                   slowperiod=slow_period,
                                                   signalperiod=signal_period)

                all_macds['macd_{}_{}_{}'.format(fast_period, slow_period,
                                                 signal_period)] = macdsignal2

    macds_dataframe = pd.DataFrame(all_macds)

    return historical_data.join(macds_dataframe)
Example #21
0
    def execute(self, env, df):

        last_row_idx = len(df)-1

        for product_id in env.product_id_list:

            product_df = df[product_id]

            macd, macd_signal, macd_hist = MACD(product_df.close,
                                                fastperiod=self.fast_period,
                                                slowperiod=self.slow_period,
                                                signalperiod=self.signal_period)

            macd_state = MACD_HIGH if macd_hist[last_row_idx] > 0 else MACD_LOW

            if self.signals.get(product_id) is None:
                self.signals[product_id] = macd_state
            elif self.signals[product_id] != macd_state:
                if macd_state == MACD_HIGH:
                    # buy
                    if len(env.positions) == 0:
                        quantity = env.balance/product_df.close[last_row_idx]
                        ts = product_df.timestamp[last_row_idx]
                        price = product_df.close[last_row_idx]
                        buy_order = BuyMarketOrder(product_id, ts, funds=env.balance)
                        env.process_buy_order(buy_order)
                    else:
                        print("already holding trade")
                elif macd_state == MACD_LOW:
                    # sell
                    if len(env.positions):
                        for position in env.find_positions(lambda x: x.product_id == product_id):
                            ts = product_df.timestamp[last_row_idx]
                            sell_order = SellMarketOrder(
                                product_id,
                                ts,
                                quantity=position.quantity,
                            )
                            env.process_sell_order(sell_order)
                    else:
                        print("did not have active trade")
                self.signals[product_id] = macd_state
Example #22
0
def execute(dates, price):
    macd, macdsignal, macdhist = MACD(price,
                                      fastperiod=12,
                                      slowperiod=26,
                                      signalperiod=9)

    indicator = {
        'series': macdsignal,
        'go_up': macdsignal > 0,
        'go_down': macdsignal < 0
    }

    all_orders = stragegy_helper_single_indicator.get_orders(
        dates, price, indicator)
    statistics = trade_helper.compute_statistics_from_orders(all_orders)

    new_stats = copy.deepcopy(statistics)
    new_stats['name'] = 'macd'

    return new_stats
def calculate_macd(pair, agg=60, fast=12, slow=26, signal=9):

    now = str(pd.Timestamp.today())[0:16]
    logging.info('Calculating MACD for {now}...'.format(now=now))

    # Calculate metrics
    try:
        df = k.get_ohlc_data(pair, interval=agg, ascending=True)[0]
        df.index = df.index.tz_localize(tz='UTC').tz_convert('US/Central')
        macd, macdsignal, macdhist = MACD(df['close'],
                                          fastperiod=fast,
                                          slowperiod=slow,
                                          signalperiod=signal)
        macd_current = macd[-1]
        signal_current = macdsignal[-1]
        current_price = df['close'][-1]
        logging.info('MACD is: {macd} and Signal is: {signal}'.format(
            macd=macd_current, signal=signal_current))
        return current_price, macd_current, signal_current
    except:
        logging.info('Data Request Error.')
        pass
def main():
    file_content = file_io_service.load_historical_data('PETR4.SA')
    file_content = file_content.dropna()

    close = file_content['Adj Close'].values
    date = np.array(
        list(
            map(lambda x: date_helper.parse_date_to_datetime(x),
                file_content['Date'])))

    rsi = RSI(close, timeperiod=14)
    macd, macdsignal, macdhist = MACD(close,
                                      fastperiod=12,
                                      slowperiod=26,
                                      signalperiod=9)
    up, mid, low = BBANDS(close, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0)

    fig, (ax0, ax1, ax2) = plt.subplots(3, 1, sharex=True, figsize=(12, 8))
    ax0.plot(date, close, label='Close')
    ax0.set_xlabel('Date')
    ax0.set_ylabel('Close')
    ax0.grid()

    ax1.plot(date, rsi, label='Close', linewidth=.5)
    ax1.set_xlabel('Date')
    ax1.set_ylabel('Close')
    ax1.grid()

    ax2.plot(date, up, label='BB_up', color='BLUE', linewidth=.5)
    ax2.plot(date, close, label='AdjClose', color='BLACK', linewidth=.5)
    ax2.plot(date, low, label='BB_low', color='RED', linewidth=.5)
    ax2.fill_between(date, y1=low, y2=up, color='#adccff', alpha='0.3')
    ax2.set_xlabel('Date')
    ax2.set_ylabel('Bollinger Bands')
    ax2.grid()

    fig.tight_layout()
    plt.show()
def execute(dates, price):
    rsi = RSI(price, timeperiod=14)
    macd, macdsignal, macdhist = MACD(price, fastperiod=12, slowperiod=26, signalperiod=9)

    rsi_buy = (rsi < 30) + 0
    rsi_sell = (rsi > 70) + 0

    macd_buy = (macdsignal > 0) + 0
    macd_sell = (macdsignal < 0) + 0

    indicator = {
        'series': macdsignal,
        'go_up': (rsi_buy + macd_buy) == 2,
        'go_down': (rsi_sell + macd_sell) == 2
    }

    all_orders = stragegy_helper_single_indicator.get_orders(dates, price, indicator)
    statistics = trade_helper.compute_statistics_from_orders(all_orders)

    new_stats = copy.deepcopy(statistics)
    new_stats['name'] = 'rsi+macd'

    return new_stats
Example #26
0
def cut_losses(context,data):
    """ 
    Sells/Invert positions according to returns. 

    """
    
    for stock in context.portfolio.positions:
        
        #current_position = context.portfolio.positions[stock].amount
        prices = data.history(stock,fields='close',
                              bar_count=context.bar_count,
                              frequency='1m')
        
        hist = data.history(stock,
                            fields=['price', 'open', 'high', 'low', 'close', 'volume'],
                            bar_count=context.bar_count,
                            frequency='1d')

        try:
            macd = MACD(prices,
                        fastperiod=context.fastperiod,
                        slowperiod=context.slowperiod, 
                        signalperiod=context.signalperiod)
            
            price = context.portfolio.positions[stock].last_sale_price            
            predicted = predict_prices(hist['close'], prices, context.returns_lookback)
            
            # print('Current price: Predicted price', price, predicted)
            if stock in context.long_secs.index:
                if macd < 0 and predicted < 1.2*price: 
                    order_target_percent(stock, 0)
            else:
                if macd > 0 and 1.1*predicted > price: 
                    order_target_percent(stock, 0)
        except Exception as e:
            print(e)
Example #27
0
    def get_new_data(self, now):
        # If the current dataset has gaps in it, we refresh it from Kraken
        if self.data_has_gaps(now):
            self.init_data()

        new_row = {'timestamp': now.strftime("%Y-%m-%d %H:%M")}

        # Calculate moving averages and RSI values
        for a_kraken_ticker, a_robinhood_ticker in config['ticker_list'].items(
        ):
            if not config['simulate_api_calls']:
                try:
                    result = get_json(
                        'https://api.kraken.com/0/public/Ticker?pair=' +
                        str(a_kraken_ticker)).json()

                    if len(result['error']) == 0:
                        new_row[a_robinhood_ticker] = round(
                            float(result['result'][a_kraken_ticker]['a'][0]),
                            3)
                except:
                    print('An exception occurred retrieving prices.')
                    return False
            else:
                new_row[a_robinhood_ticker] = round(
                    float(randint(400000, 500000)), 3)

            # If the new price is more than 40% lower/higher than the previous reading, assume it's an error somewhere
            percent_diff = (abs(new_row[a_robinhood_ticker] -
                                self.data.iloc[-1][a_robinhood_ticker]) /
                            self.data.iloc[-1][a_robinhood_ticker]) * 100
            if percent_diff > 30:
                print('Error: new price ($' +
                      str(new_row[a_robinhood_ticker]) + ') differs ' +
                      str(round(percent_diff, 2)) +
                      '% from previous value, ignoring.')
                return False

            self.data = self.data.append(new_row, ignore_index=True)

            # If the Kraken API is overloaded, they freeze the values it returns
            if (self.data.tail(4)[a_robinhood_ticker].to_numpy()[-1] ==
                    self.data.tail(4)[a_robinhood_ticker].to_numpy()).all():
                print('Repeating values detected for ' +
                      str(a_robinhood_ticker) + '. Ignoring data point.')
                self.data = self.data[:-1]

            elif self.data.shape[0] > 0:
                self.data[a_robinhood_ticker +
                          '_SMA_F'] = self.data[a_robinhood_ticker].rolling(
                              window=config['moving_average_periods']
                              ['sma_fast']).mean()
                self.data[a_robinhood_ticker +
                          '_SMA_S'] = self.data[a_robinhood_ticker].rolling(
                              window=config['moving_average_periods']
                              ['sma_slow']).mean()
                self.data[a_robinhood_ticker +
                          '_SMA_S'] = self.data[a_robinhood_ticker].rolling(
                              window=config['moving_average_periods']
                              ['sma_slow']).mean()
                self.data[
                    a_robinhood_ticker +
                    '_EMA_F'] = self.data[a_robinhood_ticker].ewm(
                        span=config['moving_average_periods']['ema_fast'],
                        adjust=False,
                        min_periods=config['moving_average_periods']
                        ['ema_fast']).mean()
                self.data[
                    a_robinhood_ticker +
                    '_EMA_S'] = self.data[a_robinhood_ticker].ewm(
                        span=config['moving_average_periods']['ema_slow'],
                        adjust=False,
                        min_periods=config['moving_average_periods']
                        ['ema_slow']).mean()
                self.data[a_robinhood_ticker + '_RSI'] = RSI(
                    self.data[a_robinhood_ticker].values,
                    timeperiod=config['rsi_period'])
                self.data[a_robinhood_ticker + '_MACD'], self.data[
                    a_robinhood_ticker + '_MACD_S'], macd_hist = MACD(
                        self.data[a_robinhood_ticker].values,
                        fastperiod=config['moving_average_periods']
                        ['macd_fast'],
                        slowperiod=config['moving_average_periods']
                        ['macd_slow'],
                        signalperiod=config['moving_average_periods']
                        ['macd_signal'])

            if config['save_charts'] == True:
                self.save_chart([
                    a_robinhood_ticker,
                    str(a_robinhood_ticker) + '_SMA_F',
                    str(a_robinhood_ticker) + '_SMA_S'
                ],
                                str(a_robinhood_ticker) + '_sma')
                self.save_chart([
                    a_robinhood_ticker,
                    str(a_robinhood_ticker) + '_EMA_F',
                    str(a_robinhood_ticker) + '_EMA_S'
                ],
                                str(a_robinhood_ticker) + '_ema')
                self.save_chart_rescale(
                    [a_robinhood_ticker,
                     str(a_robinhood_ticker) + '_RSI'],
                    str(a_robinhood_ticker) + '_rsi')
                self.save_chart_rescale([
                    a_robinhood_ticker,
                    str(a_robinhood_ticker) + '_MACD',
                    str(a_robinhood_ticker) + '_MACD_S'
                ],
                                        str(a_robinhood_ticker) + '_macd')

        return True
Example #28
0
    def init_data(self):
        print('Starting with a fresh dataset.')

        # Download historical data from Kraken
        column_names = ['timestamp']

        for a_robinhood_ticker in config['ticker_list'].values():
            column_names.append(a_robinhood_ticker)

        self.data = pd.DataFrame(columns=column_names)

        for a_kraken_ticker, a_robinhood_ticker in config['ticker_list'].items(
        ):
            try:
                result = get_json(
                    'https://api.kraken.com/0/public/OHLC?interval=' +
                    str(config['minutes_between_updates']) + '&pair=' +
                    a_kraken_ticker).json()
                historical_data = pd.DataFrame(
                    result['result'][a_kraken_ticker])
                historical_data = historical_data[[0, 1]]

                # Be nice to the Kraken API
                sleep(3)
            except:
                print(
                    'An exception occurred retrieving historical data from Kraken.'
                )

            # Convert timestamps
            self.data['timestamp'] = [
                datetime.fromtimestamp(x).strftime("%Y-%m-%d %H:%M")
                for x in historical_data[0]
            ]

            # Copy the data
            self.data[a_robinhood_ticker] = [
                round(float(x), 3) for x in historical_data[1]
            ]

            # Calculate the indicators
            self.data[a_robinhood_ticker +
                      '_SMA_F'] = self.data[a_robinhood_ticker].shift(
                          1).rolling(window=config['moving_average_periods']
                                     ['sma_fast']).mean()
            self.data[a_robinhood_ticker +
                      '_SMA_S'] = self.data[a_robinhood_ticker].shift(
                          1).rolling(window=config['moving_average_periods']
                                     ['sma_slow']).mean()
            self.data[a_robinhood_ticker +
                      '_EMA_F'] = self.data[a_robinhood_ticker].ewm(
                          span=config['moving_average_periods']['ema_fast'],
                          adjust=False,
                          min_periods=config['moving_average_periods']
                          ['ema_fast']).mean()
            self.data[a_robinhood_ticker +
                      '_EMA_S'] = self.data[a_robinhood_ticker].ewm(
                          span=config['moving_average_periods']['ema_slow'],
                          adjust=False,
                          min_periods=config['moving_average_periods']
                          ['ema_slow']).mean()
            self.data[a_robinhood_ticker + '_RSI'] = RSI(
                self.data[a_robinhood_ticker].values,
                timeperiod=config['rsi_period'])
            self.data[a_robinhood_ticker + '_MACD'], self.data[
                a_robinhood_ticker + '_MACD_S'], macd_hist = MACD(
                    self.data[a_robinhood_ticker].values,
                    fastperiod=config['moving_average_periods']['macd_fast'],
                    slowperiod=config['moving_average_periods']['macd_slow'],
                    signalperiod=config['moving_average_periods']
                    ['macd_signal'])
Example #29
0
def compute_macd(close):
    macd = MACD(close)[0]
    return (macd - np.mean(macd)) / np.std(macd)
    async def run(
        self,
        symbol: str,
        shortable: bool,
        position: int,
        minute_history: df,
        now: datetime,
        portfolio_value: float = None,
        trading_api: tradeapi = None,
        debug: bool = False,
        backtesting: bool = False,
    ) -> Tuple[bool, Dict]:
        data = minute_history.iloc[-1]
        prev_min = minute_history.iloc[-2]

        morning_rush = (
            True if (now - config.market_open).seconds // 60 < 30 else False
        )

        if (
            await super().is_buy_time(now)
            and not position
            and not open_orders.get(symbol, None)
            and not await self.should_cool_down(symbol, now)
        ):
            # Check for buy signals
            lbound = config.market_open.replace(second=0, microsecond=0)
            ubound = lbound + timedelta(minutes=15)
            try:
                high_15m = minute_history[lbound:ubound]["high"].max()  # type: ignore
            except Exception as e:
                tlog(f"{symbol}[{now}] failed to aggregate {ubound}:{lbound}")
                return False, {}

            if data.close > high_15m or (
                hasattr(config, "bypass_market_schedule")
                and config.bypass_market_schedule
            ):
                close = (
                    minute_history["close"]
                    .dropna()
                    .between_time("9:30", "16:00")
                )
                close_5m = (
                    minute_history["close"]
                    .dropna()
                    .between_time("9:30", "16:00")
                    .resample("5min")
                    .last()
                ).dropna()

                macds = MACD(close)
                # sell_macds = MACD(close, 13, 21)

                macd = macds[0]
                macd_signal = macds[1]
                macd_hist = macds[2]
                macd_trending = macd[-3] < macd[-2] < macd[-1]
                macd_above_signal = macd[-1] > macd_signal[-1] * 1.1
                macd_hist_trending = (
                    macd_hist[-3] < macd_hist[-2] < macd_hist[-1]
                )

                if (
                    macd[-1] > 0
                    and macd_trending
                    and macd_above_signal
                    and macd_hist_trending
                    and (
                        data.vwap > data.open > prev_min.close
                        and data.vwap != 0.0
                        or data.vwap == 0.0
                        and data.close > data.open > prev_min.close
                    )
                ):
                    macd2 = MACD(close, 40, 60)[0]
                    if macd2[-1] >= 0 and np.diff(macd2)[-1] >= 0:
                        if debug:
                            tlog(
                                f"[{self.name}][{now}] slow macd confirmed trend"
                            )

                        # check RSI does not indicate overbought
                        rsi = RSI(close, 14)

                        if debug:
                            tlog(
                                f"[{self.name}][{now}] {symbol} RSI={round(rsi[-1], 2)}"
                            )

                        rsi_limit = 75
                        if rsi[-1] < rsi_limit:
                            if debug:
                                tlog(
                                    f"[{self.name}][{now}] {symbol} RSI {round(rsi[-1], 2)} <= {rsi_limit}"
                                )
                        else:
                            tlog(
                                f"[{self.name}][{now}] {symbol} RSI over-bought, cool down for 5 min"
                            )
                            cool_down[symbol] = now.replace(
                                second=0, microsecond=0
                            ) + timedelta(minutes=5)

                            return False, {}

                        stop_price = find_stop(
                            data.close if not data.vwap else data.vwap,
                            minute_history,
                            now,
                        )
                        target_price = (
                            3 * (data.close - stop_price) + data.close
                        )
                        target_prices[symbol] = target_price
                        stop_prices[symbol] = stop_price

                        if portfolio_value is None:
                            if trading_api:

                                retry = 3
                                while retry > 0:
                                    try:
                                        portfolio_value = float(
                                            trading_api.get_account().portfolio_value
                                        )
                                        break
                                    except ConnectionError as e:
                                        tlog(
                                            f"[{symbol}][{now}[Error] get_account() failed w/ {e}, retrying {retry} more times"
                                        )
                                        await asyncio.sleep(0)
                                        retry -= 1

                                if not portfolio_value:
                                    tlog(
                                        "f[{symbol}][{now}[Error] failed to get portfolio_value"
                                    )
                                    return False, {}
                            else:
                                raise Exception(
                                    f"{self.name}: both portfolio_value and trading_api can't be None"
                                )

                        shares_to_buy = (
                            portfolio_value
                            * config.risk
                            // (data.close - stop_prices[symbol])
                        )
                        if not shares_to_buy:
                            shares_to_buy = 1
                        shares_to_buy -= position
                        if shares_to_buy > 0:
                            buy_price = max(data.close, data.vwap)
                            tlog(
                                f"[{self.name}][{now}] Submitting buy for {shares_to_buy} shares of {symbol} at {buy_price} target {target_prices[symbol]} stop {stop_prices[symbol]}"
                            )

                            buy_indicators[symbol] = {
                                "macd": macd[-5:].tolist(),
                                "macd_signal": macd_signal[-5:].tolist(),
                                "vwap": data.vwap,
                                "avg": data.average,
                            }

                            return (
                                True,
                                {
                                    "side": "buy",
                                    "qty": str(shares_to_buy),
                                    "type": "limit",
                                    "limit_price": str(buy_price),
                                }
                                if not morning_rush
                                else {
                                    "side": "buy",
                                    "qty": str(shares_to_buy),
                                    "type": "market",
                                },
                            )
            else:
                if debug:
                    tlog(f"[{self.name}][{now}] {data.close} < 15min high ")
        if (
            await super().is_sell_time(now)
            and position > 0
            and symbol in latest_cost_basis
            and last_used_strategy[symbol].name == self.name
            and not open_orders.get(symbol)
        ):
            if (
                not self.whipsawed.get(symbol, None)
                and data.close < latest_cost_basis[symbol] * 0.98
            ):
                self.whipsawed[symbol] = True

            serie = (
                minute_history["close"].dropna().between_time("9:30", "16:00")
            )

            if data.vwap:
                serie[-1] = data.vwap

            macds = MACD(serie, 13, 21,)

            macd = macds[0]
            macd_signal = macds[1]
            rsi = RSI(
                minute_history["close"].dropna().between_time("9:30", "16:00"),
                14,
            )

            movement = (
                data.close - latest_scalp_basis[symbol]
            ) / latest_scalp_basis[symbol]
            macd_val = macd[-1]
            macd_signal_val = macd_signal[-1]

            round_factor = (
                2 if macd_val >= 0.1 or macd_signal_val >= 0.1 else 3
            )
            scalp_threshold = (
                target_prices[symbol] + latest_scalp_basis[symbol]
            ) / 2.0

            macd_below_signal = round(macd_val, round_factor) < round(
                macd_signal_val, round_factor
            )
            bail_out = (
                (
                    latest_scalp_basis[symbol] > latest_cost_basis[symbol]
                    or movement > 0.02
                )
                and macd_below_signal
                and round(macd[-1], round_factor)
                < round(macd[-2], round_factor)
            )
            bail_on_whiplash = (
                data.close > latest_cost_basis[symbol]
                and macd_below_signal
                and round(macd[-1], round_factor)
                < round(macd[-2], round_factor)
            )
            scalp = movement > 0.04 or data.vwap > scalp_threshold
            below_cost_base = data.vwap < latest_cost_basis[symbol]

            rsi_limit = 79 if not morning_rush else 85
            to_sell = False
            partial_sell = False
            limit_sell = False
            sell_reasons = []
            if data.close <= stop_prices[symbol]:
                to_sell = True
                sell_reasons.append("stopped")
            elif (
                below_cost_base
                and round(macd_val, 2) < 0
                and rsi[-1] < rsi[-2]
                and round(macd[-1], round_factor)
                < round(macd[-2], round_factor)
                and data.vwap < 0.95 * data.average
            ):
                to_sell = True
                sell_reasons.append(
                    "below cost & macd negative & RSI trending down and too far from VWAP"
                )
            elif data.close >= target_prices[symbol] and macd[-1] <= 0:
                to_sell = True
                sell_reasons.append("above target & macd negative")
            elif rsi[-1] >= rsi_limit:
                to_sell = True
                sell_reasons.append("rsi max, cool-down for 5 minutes")
                cool_down[symbol] = now.replace(
                    second=0, microsecond=0
                ) + timedelta(minutes=5)
            elif bail_out:
                to_sell = True
                sell_reasons.append("bail")
            elif scalp:
                partial_sell = True
                to_sell = True
                sell_reasons.append("scale-out")
            elif bail_on_whiplash:
                to_sell = True
                sell_reasons.append("bail post whiplash")

            if to_sell:
                sell_indicators[symbol] = {
                    "rsi": rsi[-3:].tolist(),
                    "movement": movement,
                    "sell_macd": macd[-5:].tolist(),
                    "sell_macd_signal": macd_signal[-5:].tolist(),
                    "vwap": data.vwap,
                    "avg": data.average,
                    "reasons": " AND ".join(
                        [str(elem) for elem in sell_reasons]
                    ),
                }

                if not partial_sell:
                    if not limit_sell:
                        tlog(
                            f"[{self.name}][{now}] Submitting sell for {position} shares of {symbol} at market with reason:{sell_reasons}"
                        )
                        return (
                            True,
                            {
                                "side": "sell",
                                "qty": str(position),
                                "type": "market",
                            },
                        )
                    else:
                        tlog(
                            f"[{self.name}][{now}] Submitting sell for {position} shares of {symbol} at {data.close} with reason:{sell_reasons}"
                        )
                        return (
                            True,
                            {
                                "side": "sell",
                                "qty": str(position),
                                "type": "limit",
                                "limit_price": str(data.close),
                            },
                        )
                else:
                    qty = int(position / 2) if position > 1 else 1
                    tlog(
                        f"[{self.name}][{now}] Submitting sell for {str(qty)} shares of {symbol} at limit of {data.close }with reason:{sell_reasons}"
                    )
                    return (
                        True,
                        {
                            "side": "sell",
                            "qty": str(qty),
                            "type": "limit",
                            "limit_price": str(data.close),
                        },
                    )

        return False, {}