Example #1
0
    def open(self,
             trader,
             market_id,
             direction,
             order_type,
             order_price,
             quantity,
             take_profit,
             stop_loss,
             leverage=1.0,
             hedging=None):
        """
        Open a position or buy an asset.

        @param hedging If defined use the defined value else use the default from the market.
        """
        order = Order(trader, market_id)
        order.direction = direction
        order.order_price = order_price
        order.order_type = order_type
        order.quantity = quantity
        order.leverage = leverage

        if hedging:
            order.hedging = hedging

        # generated a reference order id
        trader.set_ref_order_id(order)
        self.create_ref_oid = order.ref_order_id

        self.dir = order.direction

        self.op = order.order_price  # retains the order price
        self.oq = order.quantity  # ordered quantity

        self.tp = take_profit
        self.sl = stop_loss

        self._stats['entry-maker'] = not order.is_market()

        if trader.create_order(order):
            # keep the related create position identifier if available
            self.position_id = order.position_id

            if not self.eot and order.created_time:
                # only at the first open
                self.eot = order.created_time

            return True
        else:
            self.create_ref_oid = None

        return False
Example #2
0
    def modify_take_profit(self, trader, market_id, price):
        if self.limit_oid:
            # cancel the limit order and create a new one
            if trader.cancel_order(self.limit_oid):
                self.limit_ref_oid = None
                self.limit_oid = None
                self.limit_order_qty = 0.0
            else:
                return False

        if self.e == self.x:
            # all entry qty is filled
            return True

        if self.e < self.x:
            # something wrong but its ok
            return False

        if self.position_id:
            # if not accepted as modification do it as limit order
            if trader.modify_position(self.position_id,
                                      take_profit_price=price):
                self.tp = price
                return True

        elif self.e > 0:
            # only if filled entry partially or totally
            order = Order(self, market_id)
            order.direction = self.direction
            order.order_type = Order.ORDER_TAKE_PROFIT_LIMIT
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining
            order.order_price = price

            trader.set_ref_order_id(order)
            self.limit_ref_oid = order.ref_order_id

            self._stats['exit-maker'] = not order.is_market()

            if trader.create_order(order):
                self.limit_oid = order.order_id
                self.limit_order_qty = order.quantity

                self.tp = price

                return True
            else:
                self.limit_ref_oid = None
                self.limit_order_qty = 0.0

        return False
Example #3
0
    def open(self,
             trader,
             market_id,
             direction,
             order_type,
             order_price,
             quantity,
             take_profit,
             stop_loss,
             leverage=1.0,
             hedging=None):
        """
        Open a position or buy an asset.
        """
        order = Order(trader, market_id)
        order.direction = direction
        order.order_price = order_price
        order.order_type = order_type
        order.quantity = quantity
        order.leverage = leverage

        # if need to retry @todo or cancel
        # self._market_id = market_id
        # self._order_type = order_type
        # self._leverage = leverage

        # generated a reference order id
        trader.set_ref_order_id(order)
        self.buy_ref_oid = order.ref_order_id

        self.dir = order.direction

        self.op = order.order_price  # retains the order price
        self.oq = order.quantity  # ordered quantity

        self.tp = take_profit
        self.sl = stop_loss

        self._stats['entry-maker'] = not order.is_market()

        if trader.create_order(order):
            if not self.eot and order.created_time:
                # only at the first open
                self.eot = order.created_time

            return True
        else:
            self._entry_state = StrategyTrade.STATE_REJECTED
            return False
Example #4
0
    def open(self,
             trader,
             market_id,
             direction,
             order_type,
             order_price,
             quantity,
             take_profit,
             stop_loss,
             leverage=1.0,
             hedging=None):
        """
        Open a position or buy an asset.
        """
        order = Order(trader, market_id)
        order.direction = direction
        order.order_price = order_price
        order.order_type = order_type
        order.quantity = quantity
        order.leverage = leverage

        # generated a reference order id
        trader.set_ref_order_id(order)
        self.create_ref_oid = order.ref_order_id

        self.dir = order.direction

        self.op = order.order_price  # retains the order price
        self.oq = order.quantity  # ordered quantity

        self.tp = take_profit
        self.sl = stop_loss

        self._stats['entry-maker'] = not order.is_market()

        if trader.create_order(order):
            self.position_id = order.position_id  # might be market-id

            if not self.eot and order.created_time:
                self.eot = order.created_time

            return True
        else:
            self.create_ref_oid = None

        return False
Example #5
0
    def modify_take_profit(self, trader, market_id, price):
        if self.limit_oid:
            # cancel the limit order and create a new one
            if trader.cancel_order(self.limit_oid):
                self.limit_ref_oid = None
                self.limit_oid = None
                self.limit_order_qty = 0.0
            else:
                return False

        if self.e == self.x:
            # all entry qty is filled
            return True

        if self.e < self.x:
            # something wrong but its ok
            return False

        if self.e > 0:
            # only if filled entry partially or totally
            order = Order(self, market_id)
            order.direction = self.direction
            order.order_type = Order.ORDER_TAKE_PROFIT_LIMIT
            # order.reduce_only = True (not for now because it implies to have the filled qty, and so need to update each time trade qty is updated)
            order.quantity = self.e - self.x  # remaining
            order.order_price = price

            trader.set_ref_order_id(order)
            self.limit_ref_oid = order.ref_order_id

            self._stats['exit-maker'] = not order.is_market()

            if trader.create_order(order):
                self.limit_oid = order.order_id
                self.limit_order_qty = order.quantity

                self.tp = price

                return True
            else:
                self.limit_ref_oid = None
                self.limit_order_qty = 0.0

        return False
Example #6
0
    def modify_stop_loss(self, trader, market_id, price):
        if self.stop_oid:
            # cancel the stop order and create a new one
            if trader.cancel_order(self.stop_oid):
                self.stop_ref_oid = None
                self.stop_oid = None
            else:
                return False

        if self.e == self.x:
            # all entry qty is filled
            return True

        if self.e < self.x:
            # something wrong but its ok
            return False

        if self.e > 0:
            # only if filled entry partially or totally
            order = Order(self, market_id)
            order.direction = self.direction
            order.order_type = Order.ORDER_STOP
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining
            order.order_price = price

            trader.set_ref_order_id(order)
            self.stop_ref_oid = order.ref_order_id

            self._stats['exit-maker'] = not order.is_market()

            if trader.create_order(order):
                self.stop_oid = order.order_id
                self.stop_order_qty = order.quantity

                self.sl = price

                return True
            else:
                self.stop_ref_oid = None
                self.stop_order_qty = 0.0

        return False
Example #7
0
    def __fetch_orders(self, signals=False):
        """
        This is the synchronous REST fetching, but prefer the WS asynchronous and live one.
        Mainly used for initial fetching.
        """
        try:
            open_orders = self._watcher.connector.open_orders()
        except Exception as e:
            logger.error("__fetch_orders: %s" % repr(e))
            raise

        orders = {}

        for data in open_orders:
            market = self.market(data['symbol'])

            if data['status'] == 'NEW':  # might be...
                order = Order(self, data['symbol'])

                order.set_order_id(data['orderId'])
                order.quantity = data['origQty']
                order.executed = data['executedQty']

                order.direction = Order.LONG if data[
                    'side'] == 'BUY' else Order.SHORT

                if data['type'] == 'LIMIT':
                    order.order_type = Order.ORDER_LIMIT
                elif data['type'] == 'MARKET':
                    order.order_type = Order.ORDER_MARKET
                elif data['type'] == 'STOP_LOSS_LIMIT':
                    order.order_type = Order.ORDER_STOP_LIMIT
                    order.close_only = True
                elif data['type'] == 'TAKE_PROFIT_LIMIT':
                    order.order_type = Order.ORDER_LIMIT
                    order.close_only = True

                order.order_price = data['price']
                order.stop_loss = data['stopPrice']

                order.created_time = data['time']
                order.transact_time = data['updateTime']

                if data['timeInForce'] == 'GTC':
                    order.time_in_force = Order.TIME_IN_FORCE_GTC
                elif data['timeInForce'] == 'IOC':
                    order.time_in_force = Order.TIME_IN_FORCE_IOC
                elif data['timeInForce'] == 'FOK':
                    order.time_in_force = Order.TIME_IN_FORCE_FOK
                else:
                    order.time_in_force = Order.TIME_IN_FORCE_GTC

                # "icebergQty": "0.0"  # @todo a day when I'll be rich
                orders[order.order_id] = order

        if signals:
            # deleted (for signals if no WS)
            deleted_list = self._orders.keys() - orders.keys()
            # @todo

            # created (for signals if no WS)
            created_list = orders.keys() - self._orders.keys()
            # @todo

        self._orders = orders
Example #8
0
    def on_order_traded(self, market_id, data, ref_order_id):
        """
        Order update, trade order in that case, is always successed by an asset update signal.
        Binance order modification is not possible, need cancel and recreate.

        @note Consume 1 API credit to get the asset quote price at the time of the trade.
        """
        market = self._markets.get(data['symbol'])
        if market is None:
            # not interested by this market
            return

        base_asset = self.__get_or_add_asset(market.base)
        quote_asset = self.__get_or_add_asset(market.quote)

        quote_market = None

        order = self._orders.get(data['id'])
        if order is None:
            # not found (might not occurs)
            order = Order(self, data['symbol'])
            order.set_order_id(data['id'])

            # its might be the creation timestamp but it will be the trade execution
            order.created_time = data['timestamp']

            order.direction = data['direction']
            order.order_type = data['type']
            order.time_in_force = data['time-in-force']

            order.quantity = data['quantity']
            order.order_price = data['order-price']
            order.stop_loss = data['stop-loss']

            self._orders[data['id']] = order

        order.executed += data['filled']

        if data['trade-id']:
            # same asset used for commission
            buy_or_sell = data['direction'] == Order.LONG

            # base details in the trade order
            base_trade_qty = data['filled']
            base_exec_price = data['exec-price']

            # price of the quote asset expressed in prefered quote at time of the trade (need a REST call)
            quote_trade_qty = data[
                'quote-transacted']  # or base_trade_qty * base_exec_price
            quote_exec_price = 1.0

            if quote_asset.quote and quote_asset.symbol != quote_asset.quote:
                # quote price to be fetched
                if self._watcher.has_instrument(quote_asset.symbol +
                                                quote_asset.quote):
                    # direct, and get the related market
                    quote_market = self._markets.get(quote_asset.symbol +
                                                     quote_asset.quote)
                    quote_exec_price = self.history_price(
                        quote_asset.symbol + quote_asset.quote,
                        data['timestamp'])

                elif self._watcher.has_instrument(quote_asset.quote +
                                                  quote_asset.symbol):
                    # indirect, but cannot have the market
                    quote_exec_price = 1.0 / self.history_price(
                        quote_asset.quote + quote_asset.symbol,
                        data['timestamp'])

            # base asset
            self.__update_asset(order.order_type, base_asset, market,
                                data['trade-id'], base_exec_price,
                                base_trade_qty, buy_or_sell, data['timestamp'])

            # quote asset
            self.__update_asset(order.order_type, quote_asset, quote_market,
                                None, quote_exec_price, quote_trade_qty,
                                not buy_or_sell, data['timestamp'])

            # commission asset
            if data['commission-asset'] == base_asset.symbol:
                self.__update_asset(Order.ORDER_MARKET, base_asset, market,
                                    None, base_exec_price,
                                    data['commission-amount'], False,
                                    data['timestamp'])
            else:
                commission_asset = self.__get_or_add_asset(
                    data['commission-asset'])
                commission_asset_market = None
                quote_exec_price = 1.0

                if commission_asset.quote and commission_asset.symbol != commission_asset.quote:
                    # commission asset price to be fetched
                    if self._watcher.has_instrument(commission_asset.symbol +
                                                    commission_asset.quote):
                        # direct, and get the related market
                        commission_asset_market = self.market(
                            commission_asset.symbol + commission_asset.quote)
                        quote_exec_price = commission_asset_market.price

                    elif self._watcher.has_instrument(commission_asset.quote +
                                                      commission_asset.symbol):
                        # indirect, but cannot have the market
                        quote_exec_price = 1.0 / self.history_price(
                            commission_asset.quote + commission_asset.symbol,
                            data['timestamp'])

                self.__update_asset(Order.ORDER_MARKET, commission_asset,
                                    commission_asset_market, None,
                                    quote_exec_price,
                                    data['commission-amount'], False,
                                    data['timestamp'])
Example #9
0
    def __update_orders(self):
        # filters only siis managed orders
        src_orders = self._watcher.connector.ws.open_orders("") # "siis_")

        # first delete older orders
        order_rm_list = []
        for k, order in self._orders.items():
            found = False
            
            for src_order in src_orders:
                src_order_id = src_order['clOrdID'] or src_order['orderID']

                if order.order_id == src_order['clOrdID'] or order.order_id == src_order['orderID']:
                    found = True
                    break

            if not found:
                order_rm_list.append(order.order_id)

        for order_id in order_rm_list:
            del self._orders[order_id]

        # insert or update active orders
        for src_order in src_orders:
            found = False
            src_order_id = src_order['clOrdID'] or src_order['orderID']

            order = self._orders.get(src_order_id)

            if order is None:
                # insert
                order = Order(self, src_order['symbol'])
                order.set_order_id(src_order_id)

                self._orders[order.order_id] = order
            else:
                order = self._orders.get(src_order_id)

            # logger.info(src_order)

            # probably modifier or when leavesQty is update the ordStatus must change
            # if src_order['ordStatus'] != "New":
            #   continue

            # update
            order.direction = Position.LONG if src_order['side'] == 'Buy' else Position.SHORT
            # 'orderQty' (ordered qty), 'cumQty' (cumulative done), 'leavesQty' (remaning)
            order.quantity = src_order.get('leavesQty', src_order.get('orderQty', 0))

            if src_order.get('transactTime'):
                order.transact_time = self._parse_datetime(src_order.get('transactTime')).timestamp()

            if src_order['ordType'] == "Market":
                order.order_type = Order.ORDER_MARKET
            elif src_order['ordType'] == "Limit":
                order.order_type = Order.ORDER_LIMIT
                order.order_price = src_order.get('price')
            elif src_order['ordType'] == "Stop":
                order.order_type = Order.ORDER_STOP
                order.order_price = src_order.get('stopPx')
            else:
                # stop limit, trigger marke, tripgger limit
                logger.info("bitmex trader l577 ", src_order['ordType'])

            if src_order['timeInForce'] == 'GoodTillCancel':
                order.time_in_force = Order.TIME_IN_FORCE_GTC
            elif src_order['timeInForce'] == 'ImmediateOrCancel':
                order.time_in_force = Order.TIME_IN_FORCE_IOC
            elif src_order['timeInForce'] == 'FillOrKill':
                order.time_in_force = Order.TIME_IN_FORCE_FOK
            else:
                order.time_in_force = Order.TIME_IN_FORCE_GTC

            # triggered, ordRejReason, currency
            # @todo

            # execution options
            exec_inst = src_order['execInst'].split(',')

            # taker or maker fee
            if 'ParticipateDoNotInitiate' in exec_inst:
                order.post_only = True
            else:
                order.post_only = False

            # close reduce only
            if 'Close' in exec_inst:
                # close only order (must be used with reduce only, only reduce a position, and close opposites orders)
                order.close_only = True
            else:
                order.close_only = False

            # close reduce only
            if 'ReduceOnly' in exec_inst:
                # reduce only order (only reduce a position)
                order.reduce_only = True
            else:
                order.redeuce_only = False

            # execution price
            if 'LastPrice' in exec_inst:
                order.price_type = Order.PRICE_LAST
            elif 'IndexPrice' in exec_inst:
                order.price_type = Order.PRICE_MARK
            elif 'MarkPrice' in exec_inst:
                order.price_type = Order.PRICE_INDEX
Example #10
0
    def close_position(self, position_id, market=True, limit_price=None):
        if not self._activity:
            return False

        position = self._positions.get(position_id)

        if position is None or not position.is_opened():
            return False

        if not self.has_market(position.symbol):
            logger.error("%s does not support market %s on close position %s !" % (
                self.name, position.symbol, position.position_id))
            return False

        ref_order_id = "siis_" + base64.b64encode(uuid.uuid4().bytes).decode('utf8').rstrip('=\n')

        # keep for might be useless in this case
        order.set_ref_order_id(ref_order_id)

        order = Order(self, position.symbol)
        order.set_position_id(position.position_id)
        order.quantity = position.quantity
        order.direction = -position.direction  # neg direction

        postdict = {
            'symbol': order.symbol,
            'clOrdID': ref_order_id,
            'execInst': 'Close',
            # 'execInst': 'ReduceOnly,Close'  # @todo why rejected with ReduceOnly ?
        }

        # short mean negative quantity
        if order.direction == Position.SHORT:
            qty = -qty

        # fully close (using Close and need 'side' when qty is not defined)
        # qty = None

        # order type
        if market:
            order.order_type = Order.ORDER_MARKET
            postdict['ordType'] = "Market"
            postdict['orderQty'] = qty
        else:
            order.order_type = Order.ORDER_LIMIT
            order.order_price = limit_price

            postdict['ordType'] = "Limit"
            postdict['price'] = order.order_price
            postdict['orderQty'] = qty

        if qty is None:
            postdict['side'] = "Buy" if order.direction > 0 else "Sell"

        try:
            result = self._watcher.connector.request(path="order", postdict=postdict, verb='POST', max_retries=15)
        except Exception as e:
            logger.error(str(e))
            return False

        if result.get('ordRejReason'):
            logger.error("%s rejected closing order %s from %s %s - cause : %s !" % (
                self.name, order.direction_to_str(), order.quantity, order.symbol, result['ordRejReason']))
            return False

        # store the order with its order id
        order.set_order_id(result['orderID'])

        # and store the order
        self._orders[order.order_id] = order

        # set position closing until we get confirmation on a next update
        position.closing(limit_price)

        return True
Example #11
0
    def __update_reversal(self, instrument):
        # consts
        MIN_SCORE = 4*60   # min score to reach to validate an order
        BSD_SCORE_FACTOR = 2  # 2,3
        CBO_SCORE_FACTOR = 2  # 2,3
        RSI_SCORE_FACTOR = 0.5  # 0.5,1,2
        RSI_TREND_SCORE_FACTOR = 1  # 0.5,1,2,4
        EMA_VWMA_CROSS_SCORE_FACTOR = 8000  # 5000,8000
        VWMA_PRICE_CROSS_SCORE_FACTOR = 2000  # 2000,4000
        EMA_VWM_BONUS_SCORE = 2  # 1,2,3,5
        TIME_SCORE_REGRESSION_FACTOR = 0.75  # 0.375,0.5,0.75
        RSI_LOW = 30  # 25,30,35
        RSI_HIGH = 70  # 65,70,75

        # @todo a plot of the account balance and % gain/loss of each trade

        # process in 1 minute, retrieve analysis data instrument
        strategy_trader = self._strategy_traders.get(instrument)

        # compute with the max samples
        num_samples = instrument.num_samples(Instrument.TF_MIN)
        depth = min(self.depth, num_samples)
        last_prices = instrument.last_prices(Instrument.TF_MIN, Instrument.PRICE_CLOSE, depth)
        last_volumes = instrument.last_volumes(Instrument.TF_MIN, depth)

        # current timestamp
        timestamp = self.timestamp

        # instrument.last_candles(Instrument.TF_MIN, depth)
        # @todo Typical price is attained by taking adding the high, low and close, and dividing by three: (H+L+C)/3

        if depth < self.min_depth:
            # not enought samples
            return

        rsi = strategy_trader.rsi.compute(last_prices)
        sma = strategy_trader.sma.compute(last_prices)
        ema = strategy_trader.ema.compute(last_prices)
        vwma = strategy_trader.vwma.compute(last_prices, last_volumes)

        #
        # scorify
        #

        bsd_score = 0
        cbo_score = 0
        rsi_score = 0
        ema_vwma_score = 0
        ema_vwma_bonus_score = 0
        price_vwma_score = 0

        if strategy_trader.blueskyday:
            if strategy_trader.blueskyday[-1].direction == Position.LONG:
                bsd_score = BSD_SCORE_FACTOR
            elif strategy_trader.blueskyday[-1].direction == Position.SHORT:
                bsd_score = -BSD_SCORE_FACTOR

        if strategy_trader.channelbreakout:
            if strategy_trader.channelbreakout[-1].direction == Position.LONG:
                cbo_score = CBO_SCORE_FACTOR
            elif strategy_trader.channelbreakout[-1].direction == Position.SHORT:
                cbo_score = -CBO_SCORE_FACTOR

        # rsi 30/70, gives strong signals
        # @todo be we could compute it on two tf (the last 14N and the more global at depth level to have two trends)
        rsi_argmin = np.argmin(rsi)
        rsi_argmax = np.argmax(rsi)

        # trend of the rsi or MM
        if rsi_argmin < rsi_argmax and rsi[rsi_argmin] < rsi[rsi_argmax]:  # ++
            rsi_trend = (rsi[rsi_argmax] + rsi[rsi_argmin]) / (rsi[rsi_argmax] - rsi[rsi_argmin])
        elif rsi_argmax < rsi_argmin and rsi[rsi_argmax] > rsi[rsi_argmin]:  ## --
            rsi_trend = (rsi[rsi_argmin] + rsi[rsi_argmax]) / (rsi[rsi_argmin] - rsi[rsi_argmax])
        else:
            rsi_trend = 0

        if rsi[-1] < RSI_LOW:
            rsi_score = (RSI_LOW-rsi[-1]) * RSI_SCORE_FACTOR  # ++
            if rsi_trend > 0:
                rsi_score += rsi_trend * RSI_TREND_SCORE_FACTOR
        elif rsi[-1] > RSI_HIGH:
            rsi_score = (RSI_HIGH-rsi[-1]) * RSI_SCORE_FACTOR
            if rsi_trend < 0:
                rsi_score += rsi_trend * RSI_TREND_SCORE_FACTOR

        # prev = rsi[0]
        # for (i, v) in enumerate(rsi):
        #   if v < prev and v < RSI_LOW:
        #       longs.append((i, last_prices[i]))
        #       prev = v
        #   elif v > prev and v > RSI_HIGH:
        #       shorts.append((i, last_prices[i]))
        #       prev = v

        # ema/vwma crossing
        ema_vwma_score = (ema[-1]-vwma[-1]) / last_prices[-1] * EMA_VWMA_CROSS_SCORE_FACTOR

        # vwma/price crossing
        price_vwma_score = (last_prices[-1]-vwma[-1]) / last_prices[-1] * VWMA_PRICE_CROSS_SCORE_FACTOR

        # if last_prices[-1] > vwma[-1]:
        #   strategy_trader.scores[-1] += 1
        # elif last_prices[-1] < vwma[-1]:
        #   strategy_trader.scores[-1] -= 1

        # ema/vwma crossing and vwmap/price more score !!
        if ema[-1] > vwma[-1] and last_prices[-1] > vwma[-1]:
            ema_vwma_bonus_score = EMA_VWM_BONUS_SCORE
        elif ema[-1] < vwma[-1] and last_prices[-1] < vwma[-1]:
            ema_vwma_bonus_score = -EMA_VWM_BONUS_SCORE

        # support/resistance signal
        # @todo and then scores +-= 2

        # price delta min including spread, have to determine if the price can vary of a minimal size
        # @todo

        # confirmation on N candles, and don't take care of pyramided orders
        total_score = rsi_score + ema_vwma_score + price_vwma_score + ema_vwma_bonus_score + bsd_score + cbo_score

        #
        # score tuning
        #

        # store the total score
        strategy_trader.scores[-1] = total_score
        final_score = total_score

        # average of the two last score and increase the last, score is exp if signals are in the trend
        if len(strategy_trader.scores) > 2:
            final_score = np.average(strategy_trader.scores[-2:])
            final_score += strategy_trader.scores[-2]

        # and store it
        strategy_trader.scores[-1] = final_score

        # handle a score convergence to avoid multiple signals
        if (strategy_trader.cur_score > 0 and final_score > 0) or (strategy_trader.cur_score < 0 and final_score < 0):
            # cancel all
            # strategy_trader.scores = [0]

            # or ignore
            # strategy_trader.scores[-1] = 0

            # or take 75% of the previous score to minimize its impact progressively
            # strategy_trader.scores[-1] = strategy_trader.scores[-2] * TIME_SCORE_REGRESSION_FACTOR

            # or keep only 37.5% of it
            strategy_trader.scores[-1] *= TIME_SCORE_REGRESSION_FACTOR * 0.5

            # keep as final score or nullify
            final_score = strategy_trader.scores[-1]

        # handle a score divergence
        # if (rsi_score > 0 and ema_vwma_score < 0) or (rsi_score < 0 and ema_vwma_bonus_score > 0):
        #       total_score *= 0.25

        # limit strategy_trader.scores len to max depth
        if len(strategy_trader.scores) > self.depth:
            strategy_trader.scores = strategy_trader.scores[len(strategy_trader.scores)-self.depth:]

        #
        # pass an order if score is accepted
        #

        if abs(final_score) >= MIN_SCORE:
            # keep apart the current score
            strategy_trader.cur_score = final_score

            if final_score > 0:
                strategy_trader.longs.append((timestamp, last_prices[-1]))
            elif final_score < 0:
                strategy_trader.shorts.append((timestamp, last_prices[-1]))

            date_str = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
            direction = Position.LONG if final_score > 0 else Position.SHORT

            # create an order an post it
            if final_score > 0:
                Terminal.inst().notice("> Strategy %s LONG %s%s at price %.4f on %s" % (self.name, instrument.trade_quantity, instrument.market_id, last_prices[-1], date_str))
            else:
                Terminal.inst().notice("> Strategy %s SHORT %s%s at price %.4f on %s" % (self.name, instrument.trade_quantity, instrument.market_id, last_prices[-1], date_str))

            trader = self.trader()
            if trader:
                order = Order(trader, instrument.market_id)
                order.direction = direction
                order.order_price = last_prices[-1]

                # depends of the instrument and the account, and not always necessary, but always in paper trader
                order.leverage = instrument.leverage

                positions = trader.positions(instrument.market_id)

                current_opposite_qty = 0.0
                current_same_qty = 0.0

                for position in positions:
                    # strategy does a reversal (and quantity are always positives)
                    if position.direction != direction:
                        # opposit directions ?
                        current_opposite_qty += position.quantity  # need to close that
                    else:
                        # or same direction ?
                        current_same_qty += position.quantity

                # trading quantity + what we have in opposite direction - what we already have in the same direction
                if self._pyramided >= 1:
                    order.quantity = instrument.trade_quantity + current_opposite_qty - current_same_qty  # @todo
                else:
                    order.quantity = instrument.trade_quantity + current_opposite_qty - current_same_qty

                if order.quantity > 0:
                    # @todo debug only
                    Terminal.inst().info("Do order %s %s with %s" % (instrument.market_id, 'SHORT' if direction==Position.SHORT else 'LONG', order.quantity))
                    trader.create_order(order)

            # consumes buy sell signals
            # @todo could put previous scores into history
            # strategy_trader.scores = [0]
            strategy_trader.blueskyday = []
            strategy_trader.channelbreakout = []
        else:
            # append the next score entry at 0
            strategy_trader.scores.append(0)

        #
        # charting
        #

        if strategy_trader.chart is None and Charting.inst():
            # create the chart if necessary
            strategy_trader.chart = Charting.inst().chart("%s on %s" % (self.name, instrument.symbol))

        rechart = strategy_trader.chart.can_redraw

        if rechart:
            longs = []
            shorts = []

            # take only in depth longs and shorts
            for long in strategy_trader.longs:
                if long[0] + depth*Instrument.TF_MIN >= timestamp:
                    longs.append(((long[0] + depth*Instrument.TF_MIN - timestamp) / Instrument.TF_MIN, long[1]))

            for short in strategy_trader.shorts:
                if short[0] + depth*Instrument.TF_MIN >= timestamp:
                    shorts.append(((short[0] + depth*Instrument.TF_MIN - timestamp) / Instrument.TF_MIN, short[1]))

            # @todo send a stream with the last values or/and updated ranges/objects
            strategy_trader.chart.set_range(0, depth)

            strategy_trader.chart.plot_price_serie(0, last_prices)
            strategy_trader.chart.plot_price_serie(1, sma)
            strategy_trader.chart.plot_price_serie(2, ema)
            strategy_trader.chart.plot_price_serie(3, vwma)
            strategy_trader.chart.annotate_price(0, longs, 'g^')
            strategy_trader.chart.annotate_price(1, shorts, 'r^')

            strategy_trader.chart.plot_serie(1, 0, rsi)
            strategy_trader.chart.plot_serie(1, 1, [30]*len(rsi))
            strategy_trader.chart.plot_serie(1, 2, [70]*len(rsi))
            # strategy_trader.chart.plot_serie(2, 0, mmt)
            strategy_trader.chart.draw()