예제 #1
0
파일: hma.py 프로젝트: Deanzou/jesse
def hma(candles: np.ndarray, period=5, source_type="close", sequential=False) -> Union[float, np.ndarray]:
    """
    Hull Moving Average

    :param candles: np.ndarray
    :param period: int - default: 5
    :param source_type: str - default: "close"
    :param sequential: bool - default=False

    :return: float | np.ndarray
    """
    if not sequential and len(candles) > 240:
        candles = candles[-240:]

    source = get_candle_source(candles, source_type=source_type)
    res = ti.hma(np.ascontiguousarray(source), period=period)

    return np.concatenate((np.full((candles.shape[0] - res.shape[0]), np.nan), res), axis=0) if sequential else res[-1]
예제 #2
0
파일: hma.py 프로젝트: noenfugler/jesse-1
def hma(candles: np.ndarray,
        period: int = 5,
        source_type: str = "close",
        sequential: bool = False) -> Union[float, np.ndarray]:
    """
    Hull Moving Average

    :param candles: np.ndarray
    :param period: int - default: 5
    :param source_type: str - default: "close"
    :param sequential: bool - default=False

    :return: float | np.ndarray
    """
    candles = slice_candles(candles, sequential)

    source = get_candle_source(candles, source_type=source_type)
    res = ti.hma(np.ascontiguousarray(source), period=period)

    return same_length(candles, res) if sequential else res[-1]
예제 #3
0
def bot():

    # globalize variables that are changed by the bot
    global amount_crypto
    global current_position
    global current_entry_price
    global old_position
    global old_entry_price_adjusted
    global next_position
    global n_trades
    global cumulated_profit

    # initiate start time to track how long one full bot iteration takes
    start = time.time()

    # fetch the required data from the exchange to compute the indicator from
    df = use_function[exchange.lower()][0](symbol=symbol,
                                           timeframe=timeframe,
                                           length=length,
                                           include_current_candle=True,
                                           file_format='',
                                           api_cooldown_seconds=0)

    ###   INDICATOR   ##########################################################################################
    if moving_average_type == 'simple_ma':
        short_ma = pd.rolling_mean(df['Close'], window=short_period)
        long_ma = pd.rolling_mean(df['Close'], window=long_period)
    if moving_average_type == 'double_exponential_ma':
        short_ma = pd.Series(ti.dema(df['Close'].as_matrix(), short_period))
        long_ma = pd.Series(ti.dema(df['Close'].as_matrix(), long_period))
    if moving_average_type == 'triple_exponential_ma':
        short_ma = pd.Series(ti.tema(df['Close'].as_matrix(), short_period))
        long_ma = pd.Series(ti.tema(df['Close'].as_matrix(), long_period))
    if moving_average_type == 'exponential_ma':
        short_ma = pd.Series(ti.ema(df['Close'].as_matrix(), short_period))
        long_ma = pd.Series(ti.ema(df['Close'].as_matrix(), long_period))
    if moving_average_type == 'hull_ma':
        short_ma = pd.Series(ti.hma(df['Close'].as_matrix(), short_period))
        long_ma = pd.Series(ti.hma(df['Close'].as_matrix(), long_period))
    if moving_average_type == 'kaufman_adaptive_ma':
        short_ma = pd.Series(ti.kama(df['Close'].as_matrix(), short_period))
        long_ma = pd.Series(ti.kama(df['Close'].as_matrix(), long_period))
    if moving_average_type == 'triangular_ma':
        short_ma = pd.Series(ti.trima(df['Close'].as_matrix(), short_period))
        long_ma = pd.Series(ti.trima(df['Close'].as_matrix(), long_period))
    if moving_average_type == 'volume_weighted_ma':
        short_ma = pd.Series(ti.vwma(df['Close'].as_matrix(), short_period))
        long_ma = pd.Series(ti.vwma(df['Close'].as_matrix(), long_period))
    if moving_average_type == 'zero_lag_exponential_ma':
        short_ma = pd.Series(ti.zlema(df['Close'].as_matrix(), short_period))
        long_ma = pd.Series(ti.zlema(df['Close'].as_matrix(), long_period))
    if moving_average_type == 'arnaud_legoux_ma':
        # prepare the data to be used for the actual indicator computation
        # (when this step is not done the ALMA function returns the ALMA value
        # from the last full candle, effectively omitting the most current value)
        alma_data = df['Close'].shift(-1)
        alma_data.iloc[-1] = 0

        def ALMA(data, period=100, offset=0.85, sigma=6):
            '''
            ALMA - Arnaud Legoux Moving Average,
            http://www.financial-hacker.com/trend-delusion-or-reality/
            https://github.com/darwinsys/Trading_Strategies/blob/master/ML/Features.py
            '''
            m = np.floor(float(offset) * (period - 1))
            s = period / float(sigma)
            alma = np.zeros(data.shape)
            w_sum = np.zeros(data.shape)

            for i in range(len(data)):
                if i < period - 1:
                    continue
                else:
                    for j in range(period):
                        w = np.exp(-(j - m) * (j - m) / (2 * s * s))
                        alma[i] += data[i - period + j] * w
                        w_sum[i] += w
                    alma[i] = alma[i] / w_sum[i]

            return alma

        # get the indicator values using the ALMA function above
        short_ma = pd.Series(
            ALMA(data=alma_data.as_matrix(),
                 period=short_period,
                 offset=0.85,
                 sigma=6))
        long_ma = pd.Series(
            ALMA(data=alma_data.as_matrix(),
                 period=long_period,
                 offset=0.85,
                 sigma=6))

    ###   STRATEGY   ###########################################################################################
    # if the current short moving average value is ABOVE (or equal) the current long moving average value go LONG
    if short_ma.iloc[-1] >= long_ma.iloc[-1]:
        next_position = 1  # LONG
    # if the current short moving average value is BELOW the current long moving average value go SHORT
    if short_ma.iloc[-1] < long_ma.iloc[-2]:
        next_position = -1  # SHORT

    ###   TRADING ENGINE   #####################################################################################
    # print this message when trading is disabled
    if disable_trading == True:
        print('>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<')
        print('>>>        !  CAUTION  !         <<<')
        print('>>>       TRADING DISABLED       <<<')
        print('>>>     TRADES ARE SIMULATED     <<<')
        print('>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<')

    # create a list of open orders of the respective symbol
    # used to check if trailing-stop has been hitted, cancelling old trailing-stop
    if disable_trading == False:
        symbol_orders = [
            order
            for order in use_function[exchange.lower()][1].fetch_open_orders(
                symbol=symbol)
        ]
        # check if there is an open position already (maybe the trailing stop has been hitted so there is no open position anymore)
        if len(symbol_orders) == 0:
            current_position = 0

    print(
        '>>>  TRADE LOG  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'
    )
    # if there is an open position
    if current_position != 0:

        if next_position == -1:
            if current_position == -1:
                print('==>  HOLD SHORT  <==')

            if current_position == 1:
                # delete old TRAILING-STOP order
                if set_trailing_stop == True:
                    if disable_trading == False:
                        use_function[exchange.lower()][1].cancel_order(
                            id=symbol_orders[-1]['id'])
                        time.sleep(api_cooldown)
                    print('Old Trailing-Stop Cancelled')

                # if trading is disabled get the first bid price from the order book as current_entry_price
                if disable_trading == True:
                    current_entry_price = round(
                        float(
                            use_function[exchange.lower()][2].fetch_order_book(
                                symbol=symbol, limit=1)['bids'][0][0]),
                        decimals)
                # create SELL order
                if disable_trading == False:
                    use_function[exchange.lower()][1].create_market_sell_order(
                        symbol, amount_crypto * 2, {'type': 'market'})
                    time.sleep(api_cooldown)
                current_position = -1
                print('==>  ENTERED SHORT  <==')

                # create TRAILING-STOP order, BUY
                if set_trailing_stop == True:
                    if disable_trading == False:
                        symbol_trades = [
                            trade for trade in use_function[exchange.lower()]
                            [1].fetch_my_trades(symbol=symbol)
                        ]
                        use_function[exchange.lower()][1].create_order(
                            symbol=symbol,
                            type='trailing-stop',
                            side='buy',
                            amount=amount_crypto,
                            price=round(
                                float(symbol_trades[-1]['price']) *
                                (trailing_stop_pct / 100), 4))
                    print('Trailing-Stop Placed (BUY)')

        if next_position == 1:
            if current_position == 1:
                print('==>  HOLD LONG  <==')

            if current_position == -1:
                # delete old TRAILING-STOP order
                if set_trailing_stop == True:
                    if disable_trading == False:
                        use_function[exchange.lower()][1].cancel_order(
                            id=symbol_orders[-1]['id'])
                        time.sleep(api_cooldown)
                    print('Old Trailing-Stop Cancelled')

                # if trading is disabled get the first ask price from the order book as current_entry_price
                if disable_trading == True:
                    current_entry_price = round(
                        float(
                            use_function[exchange.lower()][2].fetch_order_book(
                                symbol=symbol, limit=1)['asks'][0][0]),
                        decimals)
                # create BUY order
                if disable_trading == False:
                    use_function[exchange.lower()][1].create_market_buy_order(
                        symbol, amount_crypto * 2, {'type': 'market'})
                    time.sleep(api_cooldown)
                current_position = 1
                print('==>  ENTERED LONG  <==')

                # create TRAILING-STOP order, SELL
                if set_trailing_stop == True:
                    if disable_trading == False:
                        symbol_trades = [
                            trade for trade in use_function[exchange.lower()]
                            [1].fetch_my_trades(symbol=symbol)
                        ]
                        use_function[exchange.lower()][1].create_order(
                            symbol=symbol,
                            type='trailing-stop',
                            side='sell',
                            amount=amount_crypto,
                            price=round(
                                float(symbol_trades[-1]['price']) *
                                (trailing_stop_pct / 100), 4))
                    print('Trailing-Stop Placed (SELL)')

    # if there is no position yet or the position was closed within the timeframe (trailing-stop hitted)
    if current_position == 0:

        # set the amount to be traded in respective cryptocurrency as (amount_usd_to_trade) / (current average price of the cryptocurrency)
        amount_crypto = round(
            float(amount_usd_to_trade /
                  use_function[exchange.lower()][2].fetch_ticker(
                      symbol=symbol)['last']), 8)

        if next_position == 1:
            # if trading is disabled get the first ask price from the order book as current_entry_price
            if disable_trading == True:
                current_entry_price = round(
                    float(use_function[exchange.lower()][2].fetch_order_book(
                        symbol=symbol, limit=1)['asks'][0][0]), decimals)
            # create BUY order
            if disable_trading == False:
                use_function[exchange.lower()][1].create_market_buy_order(
                    symbol, amount_crypto, {'type': 'market'})
                time.sleep(api_cooldown)
            current_position = 1
            print('Initial LONG (Market Order)')

            # create TRAILING-STOP order, SELL
            if set_trailing_stop == True:
                if disable_trading == False:
                    symbol_trades = [
                        trade for trade in use_function[exchange.lower()]
                        [1].fetch_my_trades(symbol=symbol)
                    ]
                    use_function[exchange.lower()][1].create_order(
                        symbol=symbol,
                        type='trailing-stop',
                        side='sell',
                        amount=amount_crypto,
                        price=round(
                            float(symbol_trades[-1]['price']) *
                            (trailing_stop_pct / 100), 4))
                print('Initial Trailing-Stop (SELL)')

        if next_position == -1:
            # if trading is disabled get the first bid price from the order book as current_entry_price
            if disable_trading == True:
                current_entry_price = round(
                    float(use_function[exchange.lower()][2].fetch_order_book(
                        symbol=symbol, limit=1)['bids'][0][0]), decimals)
            # create SELL order
            if disable_trading == False:
                use_function[exchange.lower()][1].create_market_sell_order(
                    symbol, amount_crypto, {'type': 'market'})
                time.sleep(api_cooldown)
            current_position = -1
            print('Initial SHORT (Market Order)')

            # create TRAILING-STOP order, BUY
            if set_trailing_stop == True:
                if disable_trading == False:
                    symbol_trades = [
                        trade for trade in use_function[exchange.lower()]
                        [1].fetch_my_trades(symbol=symbol)
                    ]
                    use_function[exchange.lower()][1].create_order(
                        symbol=symbol,
                        type='trailing-stop',
                        side='buy',
                        amount=amount_crypto,
                        price=round(
                            float(symbol_trades[-1]['price']) *
                            (trailing_stop_pct / 100), 4))
                print('Initial Trailing-Stop (BUY)')

    time.sleep(api_cooldown)
    if disable_trading == False:
        current_entry_price = float(
            bitfinex.fetch_my_trades(symbol=symbol,
                                     limit=1)[0]['info']['price'])
    ###   END OF TRADER   ######################################################################################

    ###   LOG OUTPUT   #########################################################################################
    print(
        '>>>  BOT LOG  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'
    )
    # only show the full output when the position changes
    if next_position != old_position:
        n_trades += 1
        print('  < ' + symbol + ' | ' + timeframe + ' | ' + exchange +
              ' | Iterations: ' + str(loops_per_timeframe) + ' | Inception: ' +
              inception_time + ' >')
        print('| Strategy: \t\t\t\t' + str(moving_average_type))
        print('| Short Moving Average Period: \t\t' + str(short_period))
        print('| Long Moving Average Period: \t\t' + str(long_period))
        print('| Amount to Trade: \t\t\tUSD ' + str(amount_usd_to_trade))
        if disable_trading == False:
            print('| Trailing Stop: \t\t\t' + str(set_trailing_stop))
            if set_trailing_stop == True:
                print('| Trailing Stop Distance: \t\t' +
                      str(trailing_stop_pct) + '%')
        print('| Date and Time: \t\t\t' + str(
            datetime.datetime.fromtimestamp(int(time.time())).strftime(
                '%d-%m-%Y %H:%M:%S')))
        print()
        if old_position != 0:
            print(' --  Old Position: \t\t\t' +
                  ('LONG' if int(old_position) == 1 else 'SHORT'))
        print(' --  Current Position: \t\t\t' +
              ('LONG' if int(current_position) == 1 else 'SHORT'))
        print(' --  Amount Crypto: \t\t\t' + str(symbol.split('/')[0]) + ' ' +
              str(round(amount_crypto, 5)))
        print(' --  Entry Price (Fee Adj.): \t\t' + str(symbol.split('/')[1]) +
              ' ' + str(
                  round(
                      float(current_entry_price *
                            (1 +
                             (bitfinex_taker_fee / 100))) if next_position ==
                      1 else float(current_entry_price *
                                   (1 -
                                    (bitfinex_taker_fee / 100))), decimals)))
        print(' --  Entry Price: \t\t\t' + str(symbol.split('/')[1]) + ' ' +
              str(current_entry_price))
        print()
        print(' --  Current Price: \t\t\t' + str(symbol.split('/')[1]) + ' ' +
              str(round(df['Close'].iloc[-1], decimals)))
        print(' --  Short Moving Average Value: \t' +
              str(symbol.split('/')[1]) + ' ' +
              str(round(short_ma.iloc[-1], decimals)))
        print(' --  Long Moving Average Value: \t' +
              str(symbol.split('/')[1]) + ' ' +
              str(round(long_ma.iloc[-1], decimals)))
        print()
        # the below is printed only after the first position is exited
        if old_entry_price_adjusted != 0:
            print(' --  Old Entry Price (Fee Adj.): \t' +
                  str(symbol.split('/')[1]) + ' ' +
                  str(round(old_entry_price_adjusted, decimals)))
            adjusted_profit = ((
                ((float(current_entry_price *
                        (1 + (bitfinex_taker_fee / 100))) if next_position == 1
                  else float(current_entry_price *
                             (1 - (bitfinex_taker_fee / 100)))) -
                 old_entry_price_adjusted) / old_entry_price_adjusted) * 100 *
                               int(old_position))
            print(' --  Approximate P/L (Fee Adj.): \t' +
                  str(round(adjusted_profit, decimals)) + '%')
            cumulated_profit += adjusted_profit
            print(' --  Cumulated P/L (Fee Adj.): \t\t' +
                  str(round(cumulated_profit, decimals)) + '%')
        print(' --  Trades since Inception: \t\t' + str(n_trades))
        # if the position changed update the old entry price
        old_entry_price_adjusted = float(
            current_entry_price *
            (1 + (bitfinex_taker_fee / 100))) if next_position == 1 else float(
                current_entry_price * (1 - (bitfinex_taker_fee / 100)))
        # calculate fee expenses per trade (to have it available)
        position_trading_fees = current_entry_price * (1 + (
            (bitfinex_taker_fee * amount_crypto) / 100))
        print()  # leave some space for nicely formatted output

    if next_position == old_position:
        print(' --  Entry Price (Fee Adj.): \t\t' + str(symbol.split('/')[1]) +
              ' ' + str(
                  round(
                      float(current_entry_price *
                            (1 +
                             (bitfinex_taker_fee / 100))) if next_position ==
                      1 else float(current_entry_price *
                                   (1 -
                                    (bitfinex_taker_fee / 100))), decimals)))
        print(' --  Current Price: \t\t\t' + str(symbol.split('/')[1]) + ' ' +
              str(round(df['Close'].iloc[-1], decimals)))
        print(' --  Short Moving Average Value: \t' +
              str(symbol.split('/')[1]) + ' ' +
              str(round(short_ma.iloc[-1], decimals)))
        print(' --  Long Moving Average Value: \t' +
              str(symbol.split('/')[1]) + ' ' +
              str(round(long_ma.iloc[-1], decimals)))
        # print current date and time for reference
        print('| Date and Time: \t\t\t' + str(
            datetime.datetime.fromtimestamp(int(time.time())).strftime(
                '%d-%m-%Y %H:%M:%S')))

    # update value for old_position
    old_position = current_position

    # sleep for ((one timeframe) / (how often to reevaluate the position within the timeframe))
    # - time it took to run one full bot iteration
    time.sleep(((timeframes[timeframe] / loops_per_timeframe) / 1000) -
               (time.time() - start))