Beispiel #1
0
def rebalance(context, data):
    context.i += 1

    # skip first LONG_WINDOW bars to fill windows
    if context.i < LONG_WINDOW:
        return

    # get pipeline data for asset of interest
    pipeline_data = context.pipeline_data
    pipeline_data = pipeline_data[pipeline_data.index == context.asset].iloc[0]

    # retrieve long and short moving averages from pipeline
    short_mavg = pipeline_data.short_mavg
    long_mavg = pipeline_data.long_mavg
    price = pipeline_data.price

    # check that order has not already been placed
    open_orders = get_open_orders()
    if context.asset not in open_orders:
        # check that the asset of interest can currently be traded
        if data.can_trade(context.asset):
            # adjust portfolio based on comparison of long and short vwap
            if short_mavg > long_mavg:
                order_target_percent(context.asset, TARGET_INVESTMENT_RATIO)
            elif short_mavg < long_mavg:
                order_target_percent(context.asset, 0.0)

    record(
        price=price,
        cash=context.portfolio.cash,
        leverage=context.account.leverage,
        short_mavg=short_mavg,
        long_mavg=long_mavg,
    )
Beispiel #2
0
def handle_data(context, data):
    cash = context.portfolio.cash
    target_hodl_value = TARGET_HODL_RATIO * context.portfolio.starting_cash
    reserve_value = RESERVE_RATIO * context.portfolio.starting_cash

    # Cancel any outstanding orders
    orders = get_open_orders(context.asset) or []
    for order in orders:
        cancel_order(order)

    # Stop buying after passing the reserve threshold
    if cash <= reserve_value:
        context.is_buying = False

    # Retrieve current asset price from pricing data
    price = data[context.asset].price

    # Check if still buying and could (approximately) afford another purchase
    if context.is_buying and cash > price:
        # Place order to make position in asset equal to target_hodl_value
        order_target_value(
            context.asset,
            target_hodl_value,
            limit_price=price * 1.1,
            stop_price=price * 0.9,
        )

    record(
        price=price,
        cash=cash,
        starting_cash=context.portfolio.starting_cash,
        leverage=context.account.leverage,
    )
def handle_data(context, data):
    # define the windows for the moving averages
    short_window = 50
    long_window = 200

    # Skip as many bars as long_window to properly compute the average
    context.i += 1
    if context.i < long_window:
        return

    # Compute moving averages calling data.history() for each
    # moving average with the appropriate parameters. We choose to use
    # minute bars for this simulation -> freq="1m"
    # Returns a pandas dataframe.
    short_mavg = data.history(context.asset,
                              'price',
                              bar_count=short_window,
                              frequency="1m").mean()
    long_mavg = data.history(context.asset,
                             'price',
                             bar_count=long_window,
                             frequency="1m").mean()

    # Let's keep the price of our asset in a more handy variable
    price = data.current(context.asset, 'price')

    # If base_price is not set, we use the current value. This is the
    # price at the first bar which we reference to calculate price_change.
    if context.base_price is None:
        context.base_price = price
    price_change = (price - context.base_price) / context.base_price

    # Save values for later inspection
    record(price=price,
           cash=context.portfolio.cash,
           price_change=price_change,
           short_mavg=short_mavg,
           long_mavg=long_mavg)

    # Since we are using limit orders, some orders may not execute immediately
    # we wait until all orders are executed before considering more trades.
    orders = get_open_orders(context.asset)
    if len(orders) > 0:
        return

    # Exit if we cannot trade
    if not data.can_trade(context.asset):
        return

    # We check what's our position on our portfolio and trade accordingly
    pos_amount = context.portfolio.positions[context.asset].amount

    # Trading logic
    if short_mavg > long_mavg and pos_amount == 0:
        # we buy 100% of our portfolio for this asset
        order_target_percent(context.asset, 1)
    elif short_mavg < long_mavg and pos_amount > 0:
        # we sell all our positions for this asset
        order_target_percent(context.asset, 0)
def _handle_buy_sell_decision(context, data, signal, price):
    orders = get_open_orders(context.asset)
    if len(orders) > 0:
        log.info('skipping bar until all open orders execute')
        return

    positions = context.portfolio.positions
    if context.position is None and context.asset in positions:
        position = positions[context.asset]
        context.position = dict(
            cost_basis=position['cost_basis'],
            amount=position['amount'],
            stop=None
        )

    # action = None
    if context.position is not None:
        cost_basis = context.position['cost_basis']
        amount = context.position['amount']
        log.info(
            'found {amount} positions with cost basis {cost_basis}'.format(
                amount=amount,
                cost_basis=cost_basis
            )
        )
        stop = context.position['stop']

        target = cost_basis * (1 + context.TARGET)
        if price >= target:
            context.position['cost_basis'] = price
            context.position['stop'] = context.STOP

        stop_target = context.STOP_LOSS if stop is None else context.STOP
        if price < cost_basis * (1 - stop_target):
            log.info('executing stop loss')
            order(
                asset=context.asset,
                amount=-amount,
                limit_price=price * (1 - context.SLIPPAGE_ALLOWED),
            )
            # action = 0
            context.position = None

    else:
        if signal == 'long':
            log.info('opening position')
            buy_amount = context.MAX_HOLDINGS / price
            order(
                asset=context.asset,
                amount=buy_amount,
                limit_price=price * (1 + context.SLIPPAGE_ALLOWED),
            )
            context.position = dict(
                cost_basis=price,
                amount=buy_amount,
                stop=None
            )
def rebalance(context, data):
    context.i += 1

    # Skip first LONG_WINDOW bars to fill windows
    if context.i < context.WIN	DOW:
        return

    # Get pipeline data for asset of interest
    pipeline_data = context.pipeline_data
    pipeline_data = pipeline_data[pipeline_data.index == context.asset].iloc[0]

    # Compute the necessary statistics
    sma = pipeline_data.sma
    std = pipeline_data.std()
    price = pipeline_data.price
    
    # Compute buy and sell thresholds
    # Buy threshold is the simple moving average value plus one standard dev.
    # Sell threshold is the simple moving average value minus one standard dev.
    buy_threshold = sma-0.3*std/math.sqrt(context.WINDOW)
    sell_threshold = sma+0.3*std/math.sqrt(context.WINDOW)
    
    # Check that the order has not already been placed
    open_orders = get_open_orders()
    if context.asset not in open_orders:
        # check that the asset of interest can currently be traded
        if data.can_trade(context.asset):
            # Trading logic: if price is less than the buy threshold, mean 
            # reversion should drive price up. Algorithm invests 100% in the 
            # asset. In the opposite case, mean reversion should drive price 
            # down. Algorithm invests 50% in cash and 50% in the asset. If
            # price is between buy and sell thresholds, algorithm invests 25%
            # in cash and 75% in the asset.
            if price < buy_threshold:
                order_target_percent(
                    context.asset,
                    1.0,
                )
            elif price > sell_threshold:
                order_target_percent(
                    context.asset,
                    0.5,
                )
            else:
                order_target_percent(
                    context.asset,
                    0.75,
                )

    record(
        price=price,
        leverage=context.account.leverage,
        sma=sma,
        std=std,
        buy_threshold=buy_threshold,
        sell_threshold=sell_threshold,
    )
Beispiel #6
0
 def _initialize(self):
     if self.initialized:
         return
     
     if self.is_live:
         exchange_orders = get_open_orders(self.asset)
         if exchange_orders is None:
             self.ignored_orderid = []
         else:
             for o in exchange_orders:
                 self.ignored_orderid.append(o.id)
     self.initialized = True
Beispiel #7
0
def _handle_buy_sell_decision(context, data, signal, price):
    orders = get_open_orders(context.asset)
    if len(orders) > 0:
        log.info('skipping bar until all open orders execute')
        return

    positions = context.portfolio.positions
    if context.position is None and context.asset in positions:
        position = positions[context.asset]
        context.position = dict(cost_basis=position['cost_basis'],
                                amount=position['amount'],
                                stop=None)

    action = None
    if context.position is not None:
        cost_basis = context.position['cost_basis']
        amount = context.position['amount']
        log.info(
            'found {amount} positions with cost basis {cost_basis}'.format(
                amount=amount, cost_basis=cost_basis))
        stop = context.position['stop']

        target = cost_basis * (1 + context.TARGET)
        if price >= target:
            context.position['cost_basis'] = price
            context.position['stop'] = context.STOP

        stop_target = context.STOP_LOSS if stop is None else context.STOP
        if price < cost_basis * (1 - stop_target):
            log.info('executing stop loss')
            order(
                asset=context.asset,
                amount=-amount,
                limit_price=price * (1 - context.SLIPPAGE_ALLOWED),
            )
            action = 0
            context.position = None

    else:
        if signal == 'long':
            log.info('opening position')
            buy_amount = context.MAX_HOLDINGS / price
            order(
                asset=context.asset,
                amount=buy_amount,
                limit_price=price * (1 + context.SLIPPAGE_ALLOWED),
            )
            context.position = dict(cost_basis=price,
                                    amount=buy_amount,
                                    stop=None)
            action = 0
Beispiel #8
0
    def initialize(self):
        if self.initialized:
            return
        try:
            self.is_live = self.context.mode_name == 'live'
        except:
            self.is_live = False

        if self.is_live:
            exchange_orders = get_open_orders(self.context.asset)
            if exchange_orders is None:
                self.ignored_orderid = []
            else:
                for o in exchange_orders:
                    self.ignored_orderid.append(o.id)
        self.initialized = True
Beispiel #9
0
def handle_data(context, data):
    sym = symbol("XRP_BTC")
    #res = data.can_trade(sym)

    #history = data.history(symbol("bch_btc"), ['close'],
    #                       bar_count=11,
    #                       frequency='5T')

    #print('\nnow: %s\n%s' % (data.current_dt, history))
    #if not hasattr(context, 'i'):
    #    context.i = 0
    #context.i += 1
    #print(history)

    #get_order(5, return_price=True)
    print(get_open_orders(sym))
Beispiel #10
0
def rebalance(context, data):
    # To make market decisions, we're calculating the token's
    # moving average for the last 5 days.

    # We get the price history for the last 5 days.
    price_history = data.history(context.asset,
                                 fields='price',
                                 bar_count=5,
                                 frequency='1d')

    # Then we take an average of those 5 days.
    average_price = price_history.mean()

    # We also get the coin's current price.
    price = data.current(context.asset, 'price')

    # Cancel any outstanding orders
    orders = get_open_orders(context.asset) or []
    for order in orders:
        cancel_order(order)

    # If our coin is currently listed on a major exchange
    if data.can_trade(context.asset):
        # If the current price is 1% above the 5-day average price,
        # we open a long position. If the current price is below the
        # average price, then we want to close our position to 0 shares.
        if price > (1.01 * average_price):
            # Place the buy order (positive means buy, negative means sell)
            order_target_percent(context.asset, .99)
            log.info("Buying %s" % (context.asset.symbol))
        elif price < average_price:
            # Sell all of our shares by setting the target position to zero
            order_target_percent(context.asset, 0)
            log.info("Selling %s" % (context.asset.symbol))

    # Use the record() method to track up to five custom signals.
    # Record Apple's current price and the average price over the last
    # five days.
    cash = context.portfolio.cash
    leverage = context.account.leverage

    record(price=price,
           average_price=average_price,
           cash=cash,
           leverage=leverage)
Beispiel #11
0
def handle_data(context, data):
    context.asset = symbol("btc_usd")
    current = data.history(context.asset, ['price', 'volume'],
                           bar_count=1,
                           frequency='1T')

    price = data.current(context.asset, 'price')
    volume = data.current(context.asset, 'volume')

    #pd.set_option("display.precision", 8)
    #print(history)

    context.pricing_data = context.pricing_data.append(current)
    context.csvwriter.writerow([
        current.index[0], current.iloc[0]['price'], current.iloc[0]['volume']
    ])
    if context.index == 0 or context.index == 2 or context.index == 4:
        order(context.asset, 1)
        for item, orders in get_open_orders().items():
            o = orders[0]
            get_order(o.sid)

    elif context.index == 6:
        order(context.asset, -1)

    elif context.index == 8:
        order(context.asset, -1)

    if context.portfolio.positions:
        position = context.portfolio.positions[context.asset]
        print("index={}".format(context.index))
        print("amount={}, cost-basis={}".format(position.amount,
                                                position.cost_basis))

    #
    # context.csvwriter.writerow([data.current_dt,
    #                             current.iloc[0]['price'],
    #                             current.iloc[0]['volume']])

    #print(context.blotter.current_dt)
    #print(data.current_dt)

    context.index += 1
Beispiel #12
0
def handle_data(context, data):

    if context.index == 0:
        order(symbol("bat_btc"), -9.9, limit_price=0.00002630)

    print("blotter={}".format(context.blotter.orders))

    #res = data.can_trade(sym)

    #history = data.history(symbol("bch_btc"), ['close'],
    #                       bar_count=11,
    #                       frequency='5T')

    #print('\nnow: %s\n%s' % (data.current_dt, history))
    #if not hasattr(context, 'i'):
    #    context.i = 0
    #context.i += 1
    #print(history)

    #get_order(5, return_price=True)
    print("open orders={}".format(get_open_orders(context.asset)))

    context.index += 1
Beispiel #13
0
def trade_logic(context, data):

    # Cancel any outstanding orders
    orders = get_open_orders(context.asset) or []
    for order in orders:
        cancel_order(order)

    # Define base price and make initial trades to achieve target investment ratio of 0.5
    order_target_percent(context.asset, 0.5)

    # Retrieve current asset price from pricing data
    price = data.current(context.asset, "price")

    # Compute portfolio cumulative return
    Portfolio_cumulative_return = (context.portfolio.portfolio_value /
                                   context.portfolio.starting_cash - 1) * 100
    # Save values for later inspection
    record(
        price=price,
        cash=context.portfolio.cash,
        leverage=context.account.leverage,
        Portfolio_cumulative_return=Portfolio_cumulative_return,
    )
Beispiel #14
0
def handle_data(context, data):
    context.i += 1

    starting_cash = context.portfolio.starting_cash
    target_hodl_value = context.TARGET_HODL_RATIO * starting_cash
    reserve_value = context.RESERVE_RATIO * starting_cash

    # Cancel any outstanding orders
    orders = get_open_orders(context.asset) or []
    for order in orders:
        cancel_order(order)

    # Stop buying after passing the reserve threshold
    cash = context.portfolio.cash
    if cash <= reserve_value:
        context.is_buying = False

    # Retrieve current asset price from pricing data
    price = data.current(context.asset, 'price')

    # Check if still buying and could (approximately) afford another purchase
    if context.is_buying and cash > price:
        print('buying')
        # Place order to make position in asset equal to target_hodl_value
        order_target_value(
            context.asset,
            target_hodl_value,
            limit_price=price * 1.1,
        )

    record(
        price=price,
        volume=data.current(context.asset, 'volume'),
        cash=cash,
        starting_cash=context.portfolio.starting_cash,
        leverage=context.account.leverage,
    )
Beispiel #15
0
def handle_data(context, data):
    today = data.current_dt.floor('1D')
    if today != context.current_day:
        context.current_day = today
        context.cmx_invent.cancel_all()
        if context.global_mode == 'live':
            context.cmx_account.update(data)
            context.cmx_risk.adjust_position_limits(data)

    context.cmx_risk.run(data)

    bid_price = 999
    ask_price = 0
    quantity = 100

    print('{} @ {}'.format(
        context.portfolio.positions[context.asset].cost_basis,
        context.portfolio.positions[context.asset].amount))
    if context.can_buy and context.cmx_risk.position < 1000:
        context.cmx_exec.send_orders({bid_price: quantity}, side.buy)
        #context.cmx_exec.send_orders({ask_price: -1 * quantity}, side.sell)
    else:
        context.can_sell = True
        context.can_buy = False
    if context.can_sell and context.cmx_risk.position > 0:
        context.cmx_exec.send_orders({ask_price: -1 * quantity}, side.sell)

    if context.cmx_risk.position != 0:
        logging.info('tester: risk.position = {} @ {}'.format(
            context.cmx_risk.position, context.cmx_risk.ts))

    else:
        corders = context.blotter.open_orders[context.asset]
        eorders = get_open_orders(context.asset)
        logging.info('context orders: {}'.format(corders))
        logging.info('exchange orders: {}'.format(eorders))
Beispiel #16
0
def _handle_data(context, data):
    price = data.current(context.asset, 'close')
    log.info('got price {price}'.format(price=price))

    if price is None:
        log.warn('no pricing data')
        return

    prices = data.history(context.asset,
                          fields='price',
                          bar_count=1,
                          frequency='1m')
    rsi = talib.RSI(prices.values, timeperiod=14)[-1]
    log.info('got rsi: {}'.format(rsi))

    # Buying more when RSI is low, this should lower our cost basis
    if rsi <= 30:
        buy_increment = 1
    elif rsi <= 40:
        buy_increment = 0.5
    elif rsi <= 70:
        buy_increment = 0.1
    else:
        buy_increment = None

    cash = context.portfolio.cash
    log.info('base currency available: {cash}'.format(cash=cash))

    record(price=price)

    orders = get_open_orders(context.asset)
    if len(orders) > 0:
        log.info('skipping bar until all open orders execute')
        return

    is_buy = False
    cost_basis = None
    if context.asset in context.portfolio.positions:
        position = context.portfolio.positions[context.asset]

        cost_basis = position.cost_basis
        log.info(
            'found {amount} positions with cost basis {cost_basis}'.format(
                amount=position.amount, cost_basis=cost_basis))

        if position.amount >= context.TARGET_POSITIONS:
            log.info('reached positions target: {}'.format(position.amount))
            return

        if price < cost_basis:
            is_buy = True
        elif position.amount > 0 and \
                        price > cost_basis * (1 + context.PROFIT_TARGET):
            profit = (price * position.amount) - (cost_basis * position.amount)

            log.info('closing position, taking profit: {}'.format(profit))
            order_target_percent(
                asset=context.asset,
                target=0,
                limit_price=price * (1 - context.SLIPPAGE_ALLOWED),
            )
        else:
            log.info('no buy or sell opportunity found')
    else:
        is_buy = True

    if is_buy:
        if buy_increment is None:
            return

        if price * buy_increment > cash:
            log.info('not enough base currency to consider buying')
            return

        log.info('buying position cheaper than cost basis {} < {}'.format(
            price, cost_basis))
        limit_price = price * (1 + context.SLIPPAGE_ALLOWED)
        order(asset=context.asset,
              amount=buy_increment,
              limit_price=limit_price)
        pass
Beispiel #17
0
def handle_data(context, data):
    current_time = get_datetime().time()
    if current_time.hour == 0 and current_time.minute == 0:
        print('Current date is ' + str(get_datetime().date()))

    context.i += 1
    if context.i < context.atr_time:
        return

    if not data.can_trade(context.asset):
        return

    starting_cash = context.portfolio.starting_cash
    current = data.current(context.asset, 'close')
    price = data.current(context.asset, 'price')
    last_price = data.history(context.asset,
                              'price',
                              bar_count=context.atr_time - 1,
                              frequency=context.tf)

    if order_vol == 0.1 and stop == 0.9975:
        if context.i % 60 == 0:

            ohlcv_data = data.history(
                context.asset,
                fields=['open', 'high', 'low', 'close', 'volume'],
                bar_count=1,
                frequency='H')

            get_ohlcv(database=db,
                      exchange=exchange_name,
                      pair='BTCUSDT',
                      open=ohlcv_data.open,
                      high=ohlcv_data.high,
                      low=ohlcv_data.low,
                      close=ohlcv_data.close,
                      volume=ohlcv_data.volume,
                      timestamp=datetime.timestamp(get_datetime()))

    bb_data = data.history(context.asset,
                           'close',
                           bar_count=context.bb,
                           frequency=context.tf)

    hlc_data = data.history(context.asset,
                            fields=['high', 'low', 'close'],
                            bar_count=context.atr_time,
                            frequency=context.tf)

    upperband, middleband, lowerband = talib.BBANDS(bb_data,
                                                    timeperiod=context.bb - 1,
                                                    nbdevup=2,
                                                    nbdevdn=2,
                                                    matype=0)
    upperband, middleband, lowerband = upperband[-1], middleband[
        -1], lowerband[-1]
    bb_range = upperband - lowerband

    record(price=price,
           starting_cash=starting_cash,
           cash=context.portfolio.cash,
           upperband=upperband,
           middleband=middleband,
           lowerband=lowerband,
           num_trades=context.num_trades,
           order_result=context.order_result)

    context.model = pyrenko.renko()
    optimal_brick = context.model.set_brick_size(HLC_history=hlc_data)
    context.model.build_history(prices=last_price)

    prev_dir = context.model.get_renko_directions()
    last_dir = prev_dir[-4:-1]

    if not context.is_open:
        if last_dir == context.open_trigger and bb_range > 500:
            order_target_percent(context.asset,
                                 order_vol,
                                 limit_price=current * 1.001)
            context.is_open = True
            context.started = get_open_orders(context.asset)[-1].dt
            context.order_price = get_open_orders(context.asset)[-1].limit
            context.amount = get_open_orders(context.asset)[-1].amount

            positions(db,
                      type=algo_type,
                      side='Buy',
                      start=context.started,
                      open_price=context.order_price,
                      finish=None,
                      close=None,
                      amount=context.amount,
                      status='Open',
                      closed_by=None,
                      exchange=exchange_name,
                      timestamp=datetime.timestamp(get_datetime()))

    else:
        if current <= context.order_price * stop and stop != 0:
            close_id = order_target_percent(context.asset,
                                            0,
                                            limit_price=current)
            context.is_open = False
            context.num_trades += 1
            price_diff = current - context.order_price
            context.order_result.append(price_diff)

            context.finished = get_order(close_id).dt
            context.close_price = get_order(close_id).limit
            context.closed_by = 'Stop Loss'
            record(num_trades=context.num_trades,
                   order_result=context.order_result)

            query = Position.select(fn.MAX(Position.id))

            p = (Position.update({
                'finished': context.finished,
                'closed_price': context.close_price,
                'closed_by': context.closed_by,
                'status': 'Closed'
            }).where(Position.id == query.scalar()))
            p.execute()

        else:
            if last_dir == context.close_trigger:
                close_id = order_target_percent(context.asset,
                                                0,
                                                limit_price=current)
                context.model = pyrenko.renko()
                context.is_open = False

                price_diff = current - context.order_price
                context.order_result.append(price_diff)
                context.num_trades += 1
                context.finished = get_order(close_id).dt
                context.close_price = get_order(close_id).limit
                context.closed_by = 'Algo'

                record(num_trades=context.num_trades,
                       order_result=context.order_result)
                query = Position.select(fn.MAX(Position.id))

                p = (Position.update({
                    'finished': context.finished,
                    'closed_price': context.close_price,
                    'closed_by': context.closed_by,
                    'status': 'Closed'
                }).where(Position.id == query.scalar()))
                p.execute(db)
def handle_data(context, data):
    # define the windows for the moving averages
    short_window = 50
    long_window = 200

    # Skip as many bars as long_window to properly compute the average
    context.i += 1
    if context.i < long_window:
        return

    # Compute moving averages calling data.history() for each
    # moving average with the appropriate parameters. We choose to use
    # minute bars for this simulation -> freq="1m"
    # Returns a pandas dataframe.
    short_data = data.history(context.asset,
                              'price',
                              bar_count=short_window,
                              frequency="1T",
                              )
    short_mavg = short_data.mean()
    long_data = data.history(context.asset,
                             'price',
                             bar_count=long_window,
                             frequency="1T",
                             )
    long_mavg = long_data.mean()

    # Let's keep the price of our asset in a more handy variable
    price = data.current(context.asset, 'price')

    # If base_price is not set, we use the current value. This is the
    # price at the first bar which we reference to calculate price_change.
    if context.base_price is None:
        context.base_price = price
    price_change = (price - context.base_price) / context.base_price

    # Save values for later inspection
    record(price=price,
           cash=context.portfolio.cash,
           price_change=price_change,
           short_mavg=short_mavg,
           long_mavg=long_mavg)

    # Since we are using limit orders, some orders may not execute immediately
    # we wait until all orders are executed before considering more trades.
    orders = get_open_orders(context.asset)
    if len(orders) > 0:
        return

    # Exit if we cannot trade
    if not data.can_trade(context.asset):
        return

    # We check what's our position on our portfolio and trade accordingly
    pos_amount = context.portfolio.positions[context.asset].amount

    # Trading logic
    if short_mavg > long_mavg and pos_amount == 0:
        # we buy 100% of our portfolio for this asset
        order_target_percent(context.asset, 1)
    elif short_mavg < long_mavg and pos_amount > 0:
        # we sell all our positions for this asset
        order_target_percent(context.asset, 0)
Beispiel #19
0
def handle_data(context, data):
    log.info('handling bar {}'.format(data.current_dt))

    buying_price = data.current(
        context.trading_pairs[context.buying_exchange], 'price')

    log.info('price on buying exchange {exchange}: {price}'.format(
        exchange=context.buying_exchange.name.upper(),
        price=buying_price,
    ))

    selling_price = data.current(
        context.trading_pairs[context.selling_exchange], 'price')

    log.info('price on selling exchange {exchange}: {price}'.format(
        exchange=context.selling_exchange.name.upper(),
        price=selling_price,
    ))

    # If for example,
    #   selling price = 50
    #   buying price = 25
    #   expected gap = 1

    # If follows that,
    #   selling price - buying price / buying price
    #   50 - 25 / 25 = 1
    gap = (selling_price - buying_price) / buying_price
    log.info(
        'the price gap: {gap} ({gap_percent}%)'.format(
            gap=gap,
            gap_percent=gap * 100
        )
    )
    record(buying_price=buying_price, selling_price=selling_price, gap=gap)

    # Waiting for orders to close before initiating new ones
    for exchange in context.trading_pairs:
        asset = context.trading_pairs[exchange]

        orders = get_open_orders(asset)
        if orders:
            log.info(
                'found {order_count} open orders on {exchange_name} '
                'skipping bar until all open orders execute'.format(
                    order_count=len(orders),
                    exchange_name=exchange.name
                )
            )
            return

    # Consider the least ambitious entry point first
    # Override of wider gap is found
    entry_points = sorted(
        context.entry_points,
        key=lambda point: point['gap'],
    )

    buy_amount = None
    for entry_point in entry_points:
        if gap > entry_point['gap']:
            buy_amount = entry_point['amount']

    if buy_amount:
        log.info('found buy trigger for amount: {}'.format(buy_amount))
        place_orders(
            context=context,
            amount=buy_amount,
            buying_price=buying_price,
            selling_price=selling_price,
            action='enter'
        )

    else:
        # Consider the narrowest exit gap first
        # Override of wider gap is found
        exit_points = sorted(
            context.exit_points,
            key=lambda point: point['gap'],
            reverse=True
        )

        sell_amount = None
        for exit_point in exit_points:
            if gap < exit_point['gap']:
                sell_amount = exit_point['amount']

        if sell_amount:
            log.info('found sell trigger for amount: {}'.format(sell_amount))
            place_orders(
                context=context,
                amount=sell_amount,
                buying_price=buying_price,
                selling_price=selling_price,
                action='exit'
            )
def handle_data(context, data):
    # This handle_data function is where the real work is done.  Our data is
    # minute-level tick data, and each minute is called a frame.  This function
    # runs on each frame of the data.

    # We flag the first period of each day.
    # Since cryptocurrencies trade 24/7 the `before_trading_starts` handle
    # would only execute once. This method works with minute and daily
    # frequencies.
    today = data.current_dt.floor('1D')
    if today != context.current_day:
        context.traded_today = False
        context.current_day = today

    # We're computing the volume-weighted-average-price of the security
    # defined above, in the context.market variable.  For this example, we're
    # using three bars on the 15 min bars.

    # The frequency attribute determine the bar size. We use this convention
    # for the frequency alias:
    # http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
    prices = data.history(context.market,
                          fields='close',
                          bar_count=50,
                          frequency=context.CANDLE_SIZE)

    # Ta-lib calculates various technical indicator based on price and
    # volume arrays.

    # In this example, we are comp
    rsi = talib.RSI(prices.values, timeperiod=14)

    # We need a variable for the current price of the security to compare to
    # the average. Since we are requesting two fields, data.current()
    # returns a DataFrame with
    current = data.current(context.market, fields=['close', 'volume'])
    price = current['close']

    # If base_price is not set, we use the current value. This is the
    # price at the first bar which we reference to calculate price_change.
    if context.base_price is None:
        context.base_price = price

    price_change = (price - context.base_price) / context.base_price
    cash = context.portfolio.cash

    # Now that we've collected all current data for this frame, we use
    # the record() method to save it. This data will be available as
    # a parameter of the analyze() function for further analysis.

    record(volume=current['volume'],
           price=price,
           price_change=price_change,
           rsi=rsi[-1],
           cash=cash)
    # We are trying to avoid over-trading by limiting our trades to
    # one per day.
    if context.traded_today:
        return

    # TODO: retest with open orders
    # Since we are using limit orders, some orders may not execute immediately
    # we wait until all orders are executed before considering more trades.
    orders = get_open_orders(context.market)
    if len(orders) > 0:
        log.info('exiting because orders are open: {}'.format(orders))
        return

    # Exit if we cannot trade
    if not data.can_trade(context.market):
        return

    # Another powerful built-in feature of the Catalyst backtester is the
    # portfolio object.  The portfolio object tracks your positions, cash,
    # cost basis of specific holdings, and more.  In this line, we calculate
    # how long or short our position is at this minute.
    pos_amount = context.portfolio.positions[context.market].amount

    if rsi[-1] <= context.RSI_OVERSOLD and pos_amount == 0:
        log.info('{}: buying - price: {}, rsi: {}'.format(
            data.current_dt, price, rsi[-1]))
        # Set a style for limit orders,
        limit_price = price * 1.005
        order_target_percent(context.market, 1, limit_price=limit_price)
        context.traded_today = True

    elif rsi[-1] >= context.RSI_OVERBOUGHT and pos_amount > 0:
        log.info('{}: selling - price: {}, rsi: {}'.format(
            data.current_dt, price, rsi[-1]))
        limit_price = price * 0.995
        order_target_percent(context.market, 0, limit_price=limit_price)
        context.traded_today = True
def handle_data(context, data):
    # This handle_data function is where the real work is done.  Our data is
    # minute-level tick data, and each minute is called a frame.  This function
    # runs on each frame of the data.

    # We flag the first period of each day.
    # Since cryptocurrencies trade 24/7 the `before_trading_starts` handle
    # would only execute once. This method works with minute and daily
    # frequencies.
    today = data.current_dt.floor('1D')
    if today != context.current_day:
        context.traded_today = False
        context.current_day = today

    # We're computing the volume-weighted-average-price of the security
    # defined above, in the context.market variable.  For this example, we're
    # using three bars on the 15 min bars.

    # The frequency attribute determine the bar size. We use this convention
    # for the frequency alias:
    # http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
    prices = data.history(
        context.market,
        fields='close',
        bar_count=50,
        frequency=context.CANDLE_SIZE
    )

    # Ta-lib calculates various technical indicator based on price and
    # volume arrays.

    # In this example, we are comp
    rsi = talib.RSI(prices.values, timeperiod=14)

    # We need a variable for the current price of the security to compare to
    # the average. Since we are requesting two fields, data.current()
    # returns a DataFrame with
    current = data.current(context.market, fields=['close', 'volume'])
    price = current['close']

    # If base_price is not set, we use the current value. This is the
    # price at the first bar which we reference to calculate price_change.
    if context.base_price is None:
        context.base_price = price

    price_change = (price - context.base_price) / context.base_price
    cash = context.portfolio.cash

    # Now that we've collected all current data for this frame, we use
    # the record() method to save it. This data will be available as
    # a parameter of the analyze() function for further analysis.

    record(
        volume=current['volume'],
        price=price,
        price_change=price_change,
        rsi=rsi[-1],
        cash=cash
    )
    # We are trying to avoid over-trading by limiting our trades to
    # one per day.
    if context.traded_today:
        return

    # TODO: retest with open orders
    # Since we are using limit orders, some orders may not execute immediately
    # we wait until all orders are executed before considering more trades.
    orders = get_open_orders(context.market)
    if len(orders) > 0:
        log.info('exiting because orders are open: {}'.format(orders))
        return

    # Exit if we cannot trade
    if not data.can_trade(context.market):
        return

    # Another powerful built-in feature of the Catalyst backtester is the
    # portfolio object.  The portfolio object tracks your positions, cash,
    # cost basis of specific holdings, and more.  In this line, we calculate
    # how long or short our position is at this minute.
    pos_amount = context.portfolio.positions[context.market].amount

    if rsi[-1] <= context.RSI_OVERSOLD and pos_amount == 0:
        log.info(
            '{}: buying - price: {}, rsi: {}'.format(
                data.current_dt, price, rsi[-1]
            )
        )
        # Set a style for limit orders,
        limit_price = price * 1.005
        order_target_percent(
            context.market, 1, limit_price=limit_price
        )
        context.traded_today = True

    elif rsi[-1] >= context.RSI_OVERBOUGHT and pos_amount > 0:
        log.info(
            '{}: selling - price: {}, rsi: {}'.format(
                data.current_dt, price, rsi[-1]
            )
        )
        limit_price = price * 0.995
        order_target_percent(
            context.market, 0, limit_price=limit_price
        )
        context.traded_today = True
Beispiel #22
0
def handle_data(context, data):
    # This handle_data function is where the real work is done.  Our data is
    # minute-level tick data, and each minute is called a frame.  This function
    # runs on each frame of the data.

    # We flag the first period of each day.
    # Since cryptocurrencies trade 24/7 the `before_trading_starts` handle
    # would only execute once. This method works with minute and daily
    # frequencies.
    today = data.current_dt.floor('1D')
    if today != context.current_day:
        context.traded_today = False
        context.current_day = today

    # We're computing the volume-weighted-average-price of the security
    # defined above, in the context.eth_btc variable.  For this example, we're
    # using three bars on the 15 min bars.

    # The frequency attribute determine the bar size. We use this convention
    # for the frequency alias:
    # http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
    prices = data.history(context.eth_btc,
                          fields='close',
                          bar_count=50,
                          frequency='15T')

    # Ta-lib calculates various technical indicator based on price and
    # volume arrays.

    # In this example, we are comp
    rsi = talib.RSI(prices.values, timeperiod=14)
    upper, middle, lower = talib.BBANDS(prices.values,
                                        timeperiod=20,
                                        nbdevup=2,
                                        nbdevdn=2,
                                        matype=MA_Type.EMA)

    # We need a variable for the current price of the security to compare to
    # the average. Since we are requesting two fields, data.current()
    # returns a DataFrame with
    current = data.current(context.eth_btc, fields=['close', 'volume'])
    price = current['close']

    # If base_price is not set, we use the current value. This is the
    # price at the first bar which we reference to calculate price_change.
    if context.base_price is None:
        context.base_price = price

    price_change = (price - context.base_price) / context.base_price
    cash = context.portfolio.cash

    # Now that we've collected all current data for this frame, we use
    # the record() method to save it. This data will be available as
    # a parameter of the analyze() function for further analysis.
    record(price=price,
           volume=current['volume'],
           upper_band=upper[-1],
           lower_band=lower[-1],
           price_change=price_change,
           rsi=rsi[-1],
           cash=cash)

    # We are trying to avoid over-trading by limiting our trades to
    # one per day.
    if context.traded_today:
        return

    # Since we are using limit orders, some orders may not execute immediately
    # we wait until all orders are executed before considering more trades.
    orders = get_open_orders(context.eth_btc)
    if len(orders) > 0:
        return

    # Exit if we cannot trade
    if not data.can_trade(context.eth_btc):
        return

    # Another powerful built-in feature of the Catalyst backtester is the
    # portfolio object.  The portfolio object tracks your positions, cash,
    # cost basis of specific holdings, and more.  In this line, we calculate
    # how long or short our position is at this minute.
    pos_amount = context.portfolio.positions[context.eth_btc].amount

    # In this example, we're using a trigger instead of buying directly after
    # a signal. Since this is mean reversion, our signals go against the
    # momentum. Using a trigger allow us to spot the opportunity but trade
    # only when a trade reversal begins.
    if context.trigger is not None:
        # The tread_direction() method determines the trend based on the last
        # two bars of the series.
        direction = trend_direction(rsi)
        if context.trigger[1] == 'buy' and direction == 'up':
            log.info('{}: buying - price: {}, rsi: {}, bband: {}'.format(
                data.current_dt, price, rsi[-1], lower[-1]))
            order_target_percent(context.eth_btc, 1)
            context.traded_today = True
            context.trigger = None

        elif context.trigger[1] == 'sell' and direction == 'down':
            log.info('{}: selling - price: {}, rsi: {}, bband: {}'.format(
                data.current_dt, price, rsi[-1], upper[-1]))
            order_target_percent(context.eth_btc, 0)
            context.traded_today = True
            context.trigger = None

        # If we found a signal but no trade reversal within two hours, we
        # reset the trigger.
        elif context.trigger[0] + timedelta(hours=2) < data.current_dt:
            context.trigger = None

    else:
        # Determining the entry and exit signals based on RSI and SMA
        if rsi[-1] <= 30 and pos_amount == 0:
            context.trigger = (data.current_dt, 'buy')

        elif rsi[-1] >= 80 and pos_amount > 0:
            context.trigger = (data.current_dt, 'sell')
def handle_data(context, data):
    log.info('handling bar {}'.format(data.current_dt))

    buying_price = data.current(
        context.trading_pairs[context.buying_exchange], 'price')

    log.info('price on buying exchange {exchange}: {price}'.format(
        exchange=context.buying_exchange.name.upper(),
        price=buying_price,
    ))

    selling_price = data.current(
        context.trading_pairs[context.selling_exchange], 'price')

    log.info('price on selling exchange {exchange}: {price}'.format(
        exchange=context.selling_exchange.name.upper(),
        price=selling_price,
    ))

    # If for example,
    #   selling price = 50
    #   buying price = 25
    #   expected gap = 1

    # If follows that,
    #   selling price - buying price / buying price
    #   50 - 25 / 25 = 1
    gap = (selling_price - buying_price) / buying_price
    log.info(
        'the price gap: {gap} ({gap_percent}%)'.format(
            gap=gap,
            gap_percent=gap * 100
        )
    )
    record(buying_price=buying_price, selling_price=selling_price, gap=gap)

    # Waiting for orders to close before initiating new ones
    for exchange in context.trading_pairs:
        asset = context.trading_pairs[exchange]

        orders = get_open_orders(asset)
        if orders:
            log.info(
                'found {order_count} open orders on {exchange_name} '
                'skipping bar until all open orders execute'.format(
                    order_count=len(orders),
                    exchange_name=exchange.name
                )
            )
            return

    # Consider the least ambitious entry point first
    # Override of wider gap is found
    entry_points = sorted(
        context.entry_points,
        key=lambda point: point['gap'],
    )

    buy_amount = None
    for entry_point in entry_points:
        if gap > entry_point['gap']:
            buy_amount = entry_point['amount']

    if buy_amount:
        log.info('found buy trigger for amount: {}'.format(buy_amount))
        place_orders(
            context=context,
            amount=buy_amount,
            buying_price=buying_price,
            selling_price=selling_price,
            action='enter'
        )

    else:
        # Consider the narrowest exit gap first
        # Override of wider gap is found
        exit_points = sorted(
            context.exit_points,
            key=lambda point: point['gap'],
            reverse=True
        )

        sell_amount = None
        for exit_point in exit_points:
            if gap < exit_point['gap']:
                sell_amount = exit_point['amount']

        if sell_amount:
            log.info('found sell trigger for amount: {}'.format(sell_amount))
            place_orders(
                context=context,
                amount=sell_amount,
                buying_price=buying_price,
                selling_price=selling_price,
                action='exit'
            )