예제 #1
0
    def open(self,
             trader,
             instrument,
             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, instrument.market_id)
        order.direction = direction
        order.order_type = order_type
        order.quantity = quantity
        order.leverage = leverage
        order.margin_trade = True
        order.post_only = False

        if order_type == Order.ORDER_LIMIT:
            order.price = order_price

        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.price  # retains the order price
        self.oq = order.quantity  # ordered quantity

        self.tp = take_profit
        self.sl = stop_loss

        self.leverage = leverage

        self._stats['entry-order-type'] = order.order_type

        if trader.create_order(order, instrument):
            # keep the related create position identifier if available
            self.create_oid = order.order_id
            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._entry_state = StrategyTrade.STATE_REJECTED
            return False
예제 #2
0
    def modify_take_profit(self, trader, instrument, limit_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=limit_price):
                self.tp = limit_price
                return True

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

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

            self._stats['limit-order-type'] = order.order_type

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

                self.last_tp_ot[0] = order.created_time
                self.last_tp_ot[1] += 1

                self.tp = limit_price

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

        return False
예제 #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.

        @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
예제 #4
0
    def modify_take_profit(self, trader, instrument, limit_price):
        if self.limit_oid:
            # cancel the limit order and create a new one
            if trader.cancel_order(self.limit_oid, instrument):
                self.limit_ref_oid = None
                self.limit_oid = None
                self.limit_order_qty = 0.0
            else:
                return self.ERROR

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

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

        if self.e > 0 and limit_price > 0.0:
            # only if filled entry partially or totally
            order = Order(self, instrument.market_id)
            order.direction = -self.direction
            order.order_type = Order.ORDER_LIMIT
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining
            order.price = limit_price
            order.leverage = self.leverage
            order.margin_trade = True

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

            self._stats['take-profit-order-type'] = order.order_type

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

                self.last_tp_ot[0] = order.created_time
                self.last_tp_ot[1] += 1

                self.tp = limit_price

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

                return self.REJECTED

        return self.NOTHING_TO_DO
예제 #5
0
    def close(self, trader, instrument):
        """
        Close the position and cancel the related orders.
        """
        if self._closing:
            # already closing order
            return False

        if self.create_oid:
            # cancel the remaining buy order
            if trader.cancel_order(self.create_oid):
                self.create_ref_oid = None
                self.create_oid = None

                self._entry_state = StrategyTrade.STATE_CANCELED

        if self.stop_oid:
            # cancel the stop order
            if trader.cancel_order(self.stop_oid):
                self.stop_ref_oid = None
                self.stop_oid = None

        if self.limit_oid:
            # cancel the limit order
            if trader.cancel_order(self.limit_oid):
                self.limit_ref_oid = None

        if self.e - self.x > 0.0:
            # bitmex case no have position id
            order = Order(trader, instrument.market_id)
            order.direction = -self.dir  # neg dir
            order.order_type = Order.ORDER_MARKET
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining qty
            order.leverage = self.leverage
            order.margin_trade = True

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

            self._stats['stop-order-type'] = order.order_type

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

                # closing order defined
                self._closing = True

                return True
            else:
                self.stop_ref_oid = None
                return False

        return True
예제 #6
0
    def open(self,
             trader,
             instrument,
             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, instrument.market_id)
        order.direction = direction
        order.price = order_price
        order.order_type = order_type
        order.quantity = quantity
        order.post_only = False
        order.margin_trade = True
        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.price  # retains the order price
        self.oq = order.quantity  # ordered quantity

        self.tp = take_profit
        self.sl = stop_loss

        self.leverage = leverage

        self._stats['entry-order-type'] = order.order_type

        if trader.create_order(order, instrument):
            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._entry_state = StrategyTrade.STATE_REJECTED
            return False
예제 #7
0
    def modify_stop_loss(self, trader, market_id, stop_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.position_id:
            # if not accepted as modification do it as stop order
            if trader.modify_position(self.position_id,
                                      stop_loss_price=stop_price):
                self.sl = stop_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_STOP
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining
            order.stop_price = stop_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.last_sl_ot[0] = order.created_time
                self.last_sl_ot[1] += 1

                self.sl = stop_price

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

        return False
예제 #8
0
    def modify_stop_loss(self, trader, instrument, stop_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 and stop_price > 0.0:
            # only if filled entry partially or totally
            order = Order(self, instrument.market_id)
            order.direction = -self.direction
            order.order_type = Order.ORDER_STOP
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining
            order.stop_price = stop_price
            order.leverage = self.leverage
            order.margin_trade = True

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

            self._stats['stop-order-type'] = order.order_type

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

                self.last_sl_ot[0] = order.created_time
                self.last_sl_ot[1] += 1

                self.sl = stop_price

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

        return False
예제 #9
0
    def open(self,
             trader,
             market_id,
             direction,
             order_type,
             order_price,
             quantity,
             take_profit,
             stop_loss,
             leverage=1.0,
             hedging=None):
        """
        Buy an asset.
        """
        if self._entry_state != StrategyTrade.STATE_NEW:
            return False

        order = Order(trader, market_id)
        order.direction = direction
        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.entry_ref_oid = order.ref_order_id

        self.dir = order.direction

        self.op = 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
예제 #10
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
예제 #11
0
파일: trader.py 프로젝트: simhaonline/siis
    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

        # @todo

        return True
예제 #12
0
    def close(self, trader, market_id):
        """
        Close the position and cancel the related orders.
        """
        if self._closing:
            # already closing order
            return False

        if self.create_oid:
            # cancel the remaining buy order
            if trader.cancel_order(self.create_oid):
                self.create_ref_oid = None
                self.create_oid = None

                self._entry_state = StrategyTrade.STATE_CANCELED

        if self.stop_oid:
            # cancel the stop order
            if trader.cancel_order(self.stop_oid):
                self.stop_ref_oid = None
                self.stop_oid = None

        if self.limit_oid:
            # cancel the limit order
            if trader.cancel_order(self.limit_oid):
                self.limit_ref_oid = None
                self.limit_oid = None

        if self.e - self.x > 0.0:
            order = Order(trader, market_id)
            order.direction = -self.dir  # neg dir
            order.order_type = Order.ORDER_MARKET
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining qty

            # generated a reference order id
            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

                # closing order defined
                self._closing = True

                return True
            else:
                self.stop_ref_oid = None
                return False

        return True
예제 #13
0
    def close(self, trader, market_id):
        """
        Close the position and cancel the related orders.
        """
        if self.create_oid:
            # cancel the remaining buy order
            if trader.cancel_order(self.create_oid):
                self.create_ref_oid = None
                self.create_oid = None

                self._entry_state = StrategyTrade.STATE_CANCELED

        if self.stop_oid:
            # cancel the stop order
            if trader.cancel_order(self.stop_oid):
                self.stop_ref_oid = None
                self.stop_oid = None

        if self.limit_oid:
            # cancel the limit order
            if trader.cancel_order(self.limit_oid):
                self.limit_ref_oid = None

        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:
            # most of the margin broker case we have a position id
            if self._exit_state != StrategyTrade.STATE_PARTIALLY_FILLED:
                if trader.close_position(self.position_id):
                    return True
                else:
                    return False
        else:
            # bitmex case no have position id
            order = Order(trader, market_id)
            order.direction = -self.dir  # neg dir
            order.order_type = Order.ORDER_MARKET
            order.quantity = self.e - self.x  # remaining qty

            # generated a reference order id
            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):
                return True
            else:
                self.stop_ref_oid = None
                return False

        return True
예제 #14
0
    def modify_stop_loss(self, trader, instrument, stop_price):
        if self.stop_oid:
            # cancel the stop order and create a new one
            if trader.cancel_order(self.stop_oid, instrument):
                self.stop_ref_oid = None
                self.stop_oid = None
            else:
                return self.ERROR

        if self.e - self.x > 0.0:
            # only if filled entry partially or totally
            order = Order(self, instrument.market_id)
            order.direction = -self.direction
            order.order_type = Order.ORDER_STOP
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining
            order.stop_price = stop_price
            order.margin_trade = True
            order.leverage = self.leverage

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

            self._stats['stop-order-type'] = order.order_type

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

                self.last_stop_ot[0] = order.created_time
                self.last_stop_ot[1] += 1

                self.sl = stop_price

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

                return self.REJECTED

        return self.NOTHING_TO_DO
예제 #15
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
예제 #16
0
    def modify_take_profit(self, trader, instrument, limit_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 > 0.0:
            # only if filled entry partially or totally
            order = Order(self, instrument.market_id)
            order.direction = -self.direction
            order.order_type = Order.ORDER_LIMIT
            order.reduce_only = True
            order.quantity = self.e - self.x  # remaining
            order.price = limit_price
            order.margin_trade = True
            order.leverage = self.leverage

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

            self._stats['limit-order-type'] = order.order_type

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

                self.last_tp_ot[0] = order.created_time
                self.last_tp_ot[1] += 1

                self.tp = limit_price

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

        return False
예제 #17
0
    def close(self, trader, market_id):
        if self.sell_ref_oid:
            logger.error("Trade %s has already ordered an exit !" % self.id)
            return False

        if self.buy_oid:
            # cancel the remaining buy order
            if trader.cancel_order(self.sell_oid):
                self.buy_ref_oid = None
                self.buy_oid = None

                self._entry_state = StrategyTrade.STATE_CANCELED

        if self.sell_oid:
            # cancel the sell order and create a new one
            if trader.cancel_order(self.sell_oid):
                self.sell_ref_oid = None
                self.sell_oid = None
                self.sell_order_type = Order.ORDER_MARKET
                self.sell_order_qty = 0.0

                self._exit_state = StrategyTrade.STATE_CANCELED

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

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

        order = Order(trader, market_id)
        order.direction = -self.dir  # neg dir
        order.order_type = Order.ORDER_MARKET
        order.quantity = self.e - self.x  # remaining qty

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

        # generated a reference order id and keep it before ordering to retrieve its signals
        trader.set_ref_order_id(order)
        self.sell_ref_oid = order.ref_order_id

        if trader.create_order(order):
            self.sell_order_type = order.order_type
            self.sell_order_qty = order.quantity

            return True
        else:
            # rejected
            self.sell_ref_oid = None

            return False
예제 #18
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
예제 #19
0
    def modify_take_profit(self, trader, market_id, limit_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 > 0.0:
            # only if filled entry partially or totally
            order = Order(self, market_id)
            order.direction = -self.direction
            order.order_type = Order.ORDER_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.price = limit_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.last_tp_ot[0] = order.created_time
                self.last_tp_ot[1] += 1

                self.tp = limit_price

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

        return False
예제 #20
0
    def open(self,
             trader,
             instrument,
             direction,
             order_type,
             order_price,
             quantity,
             take_profit,
             stop_loss,
             leverage=1.0,
             hedging=None,
             use_oco=False):
        """
        Buy an asset.
        """
        if self._entry_state != StrategyTrade.STATE_NEW:
            return False

        order = Order(trader, instrument.market_id)
        order.direction = direction
        order.price = order_price
        order.order_type = order_type
        order.quantity = quantity

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

        self.dir = order.direction

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

        self.tp = take_profit
        self.sl = stop_loss

        self._use_oco = use_oco

        self._stats['entry-order-type'] = order.order_type

        if trader.create_order(order, instrument):
            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
예제 #21
0
    def modify_stop_loss(self, trader, market_id, stop_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 > 0.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.stop_price = stop_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.last_sl_ot[0] = order.created_time
                self.last_sl_ot[1] += 1

                self.sl = stop_price

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

        return False
예제 #22
0
    def close_position(self, position_id, market_or_instrument, direction, quantity, market=True, limit_price=None):
        if not position_id or not market_or_instrument:
            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, market_or_instrument.market_id)
        order.set_position_id(position_id)
        order.quantity = quantity
        order.direction = -direction  # neg direction

        # @todo

        return True
예제 #23
0
    def modify_stop_loss(self, trader, market_id, price):
        self.sl = price

        if self.sell_oid:
            # cancel the sell order and create a new one
            if trader.cancel_order(self.sell_oid):
                # returns true, no need to wait signal confirmation
                self.sell_ref_oid = None
                self.sell_oid = None
                self.sell_order_type = Order.ORDER_MARKET
                self.sell_order_qty = 0.0

                self._exit_state = StrategyTrade.STATE_DELETED

        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 price:
            order = Order(trader, market_id)
            order.direction = -self.dir  # neg dir
            order.order_type = Order.ORDER_STOP
            order.quantity = self.e - self.x  # remaining

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

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

            if trader.create_order(order):
                self.sell_order_type = order.order_type
                self.sell_order_qty = order.quantity

                return True
            else:
                return False

        return True
예제 #24
0
    def close_position(self, position_or_id, market=True, limit_price=None):
        """
        Close an existing position.
        Market is default, take care of the fee.
        Limit price can be defined but then it will create a limit order in the opposite direction in some broker
        and modify the position in some other (depends of the mode hedging...).
        """
        if type(position_or_id) is str:
            position = self._positions.get(position_or_id)
        else:
            position = position_or_id

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

        # market stop order
        order = Order(self, position.symbol)
        order.direction = position.close_direction()
        order.order_type = Order.ORDER_MARKET
        order.quantity = position.quantity  # fully close
        order.leverage = position.leverage  # same as open

        # simply create an order in the opposite direction
        return self.create_order(order)
예제 #25
0
    def close(self, trader, instrument):
        if self._closing:
            # already closing order
            return self.NOTHING_TO_DO

        if self.oco_oid:
            # @todo cancel OCO order and create an order market
            return self.ERROR
        else:
            if self.stop_ref_oid:
                logger.error("Trade %s has already ordered an exit !" %
                             self.id)
                return self.NOTHING_TO_DO

            if self.entry_oid:
                # cancel the remaining buy order
                if trader.cancel_order(self.entry_oid, instrument):
                    self.entry_ref_oid = None
                    self.entry_oid = None
                else:
                    return self.ERROR

            if self.limit_oid:
                # cancel the sell limit order
                if trader.cancel_order(self.limit_oid, instrument):
                    self.limit_ref_oid = None
                    self.limit_oid = None
                    self.limit_order_qty = 0.0
                else:
                    return self.ERROR

            if self.stop_oid:
                # cancel the sell stop order and create a new one
                if trader.cancel_order(self.stop_oid, instrument):
                    self.stop_ref_oid = None
                    self.stop_oid = None
                    self.stop_order_qty = 0.0
                else:
                    return self.ERROR

            if self.x >= self.e:
                # all qty is filled
                return self.NOTHING_TO_DO

            order = Order(trader, instrument.market_id)
            order.direction = -self.dir  # neg dir
            order.order_type = Order.ORDER_MARKET
            order.quantity = self.e - self.x  # remaining qty

            self._stats['stop-order-type'] = order.order_type

            # generated a reference order id and keep it before ordering to retrieve its signals
            trader.set_ref_order_id(order)
            self.stop_ref_oid = order.ref_order_id

            if trader.create_order(order, instrument):
                # REST sync
                self.stop_oid = order.order_id
                self.stop_order_qty = order.quantity

                # closing order defined
                self._closing = True

                return self.ACCEPTED
            else:
                # rejected
                self.stop_ref_oid = None
                return self.REJECTED

        return self.NOTHING_TO_DO
예제 #26
0
    def modify_stop_loss(self, trader, instrument, stop_price):
        if self._closing:
            # already closing order
            return self.NOTHING_TO_DO

        if self._exit_state == StrategyTrade.STATE_FILLED:
            # exit already fully filled
            return self.NOTHING_TO_DO

        if self.oco_oid:
            # @todo need recreate stop and limit OCO order
            return self.ERROR
        else:
            if self.stop_oid:
                # cancel the sell stop order and create a new one
                if trader.cancel_order(self.stop_oid, instrument):
                    # REST sync
                    # returns true, no need to wait signal confirmation
                    self.stop_ref_oid = None
                    self.stop_oid = None
                    self.stop_order_qty = 0.0
                else:
                    return self.ERROR

            if self.limit_oid:
                # cancel the sell limit order (only one or the other)
                if trader.cancel_order(self.limit_oid, instrument):
                    # REST sync
                    # returns true, no need to wait signal confirmation
                    self.limit_ref_oid = None
                    self.limit_oid = None
                    self.limit_order_qty = 0.0
                else:
                    return self.ERROR

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

            if stop_price:
                order = Order(trader, instrument.market_id)
                order.direction = -self.dir  # neg dir
                order.order_type = Order.ORDER_STOP
                order.stop_price = stop_price
                order.quantity = self.e - self.x  # remaining

                self._stats['stop-order-type'] = order.order_type

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

                if trader.create_order(order, instrument):
                    # REST sync
                    self.stop_oid = order.order_id
                    self.stop_order_qty = order.quantity

                    self.last_stop_ot[0] = order.created_time
                    self.last_stop_ot[1] += 1

                    self.sl = stop_price

                    return self.ACCEPTED
                else:
                    # rejected
                    self.stop_ref_oid = None
                    self.stop_order_qty = 0.0

                    return self.REJECTED

            return self.NOTHING_TO_DO
예제 #27
0
    def close(self, trader, market_id):
        if self._closing:
            # already closing order
            return False

        if self.oco_oid:
            # @todo cancel OCO order and create an order market
            return False
        else:
            # if self.stop_ref_oid:
            #     logger.error("Trade %s has already ordered an exit !" % self.id)
            #     return False

            if self.entry_oid:
                # cancel the remaining buy order
                if trader.cancel_order(self.entry_oid):
                    self.entry_ref_oid = None
                    self.entry_oid = None

            if self.limit_oid:
                # cancel the sell limit order
                if trader.cancel_order(self.limit_oid):
                    self.limit_ref_oid = None
                    self.limit_oid = None
                    self.limit_order_type = Order.ORDER_MARKET
                    self.limit_order_qty = 0.0

            if self.stop_oid:
                # cancel the sell stop order and create a new one
                if trader.cancel_order(self.stop_oid):
                    self.stop_ref_oid = None
                    self.stop_oid = None
                    self.stop_order_type = Order.ORDER_MARKET
                    self.stop_order_qty = 0.0

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

            order = Order(trader, market_id)
            order.direction = -self.dir  # neg dir
            order.order_type = Order.ORDER_MARKET
            order.quantity = self.e - self.x  # remaining qty

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

            # generated a reference order id and keep it before ordering to retrieve its signals
            trader.set_ref_order_id(order)
            self.stop_ref_oid = order.ref_order_id

            if trader.create_order(order):
                self.stop_order_type = order.order_type
                self.stop_order_qty = order.quantity

                # closing order defined
                self._closing = True

                return True
            else:
                # rejected
                self.stop_ref_oid = None
                return False
예제 #28
0
    def modify_stop_loss(self, trader, market_id, stop_price):
        if self._closing:
            # already closing order
            return False

        if self._exit_state == StrategyTrade.STATE_FILLED:
            # exit already fully filled
            return False

        if self.oco_oid:
            # @todo need recreate stop and limit OCO order
            return False
        else:
            if self.stop_oid:
                # cancel the sell stop order and create a new one
                if trader.cancel_order(self.stop_oid):
                    # REST sync
                    # returns true, no need to wait signal confirmation
                    self.stop_ref_oid = None
                    self.stop_oid = None
                    self.stop_order_type = Order.ORDER_MARKET
                    self.stop_order_qty = 0.0

            if self.limit_oid:
                # cancel the sell limit order (only one or the other)
                if trader.cancel_order(self.limit_oid):
                    # REST sync
                    # returns true, no need to wait signal confirmation
                    self.limit_ref_oid = None
                    self.limit_oid = None
                    self.limit_order_type = Order.ORDER_MARKET
                    self.limit_order_qty = 0.0

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

            if stop_price:
                order = Order(trader, market_id)
                order.direction = -self.dir  # neg dir
                order.order_type = Order.ORDER_STOP
                order.stop_price = stop_price
                order.quantity = self.e - self.x  # remaining

                # @todo not correct, depend of what is executed
                self._stats['exit-maker'] = not order.is_market()

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

                if trader.create_order(order):
                    # REST sync
                    self.stop_order_type = order.order_type
                    self.stop_order_qty = order.quantity

                    self.last_sl_ot[0] = order.created_time
                    self.last_sl_ot[1] += 1

                    self.sl = stop_price

                    return True
                else:
                    # rejected
                    self.stop_ref_oid = None
                    return False

            return True
예제 #29
0
def close_position(trader,
                   market,
                   position,
                   close_exec_price,
                   order_type=Order.ORDER_LIMIT):
    """
    Close a position.
    """
    if not position:
        return False

    trader.lock()

    if not position.is_opened():
        trader.unlock()
        return False

    # create an order for the close
    order = Order(trader, position.symbol)
    order.set_position_id(position.position_id)

    order.direction = position.close_direction()
    order.order_type = order_type

    if order_type == Order.ORDER_LIMIT:
        order.price = close_exec_price

    order.quantity = position.quantity
    order.leverage = position.leverage

    order.close_only = True
    order.reduce_only = True

    # increase or reduce the current position
    org_quantity = position.quantity
    exec_price = 0.0

    # price difference depending of the direction
    delta_price = 0
    if position.direction == Position.LONG:
        delta_price = close_exec_price - position.entry_price
    elif position.direction == Position.SHORT:
        delta_price = position.entry_price - close_exec_price

    # keep for percent calculation
    prev_entry_price = position.entry_price or close_exec_price
    leverage = order.leverage

    # most of thoose data rarely change except the base_exchange_rate
    value_per_pip = market.value_per_pip
    contract_size = market.contract_size
    lot_size = market.lot_size
    one_pip_means = market.one_pip_means
    base_exchange_rate = market.base_exchange_rate
    margin_factor = market.margin_factor

    realized_position_cost = 0.0  # realized cost of the position in base currency

    # effective meaning of delta price in base currency
    effective_price = (delta_price / one_pip_means) * value_per_pip

    # in base currency
    position_gain_loss = 0.0

    # the position is closed, exact quantity in the opposite direction
    position_gain_loss = effective_price * position.quantity
    position.quantity = 0.0
    position.exit_price = close_exec_price

    # directly executed quantity
    order.executed = order.quantity
    exec_price = close_exec_price

    realized_position_cost = market.effective_cost(order.quantity,
                                                   close_exec_price)
    margin_cost = market.margin_cost(order.quantity, close_exec_price)

    # and decrease used margin
    trader.account.free_margin(margin_cost)

    # transaction time is current timestamp
    order.transact_time = trader.timestamp

    if position_gain_loss != 0.0 and realized_position_cost > 0.0:
        # ratio
        gain_loss_rate = position_gain_loss / realized_position_cost
        relative_gain_loss_rate = delta_price / prev_entry_price

        # if maker close (limit+post-order) (for now same as market)
        position.profit_loss = position_gain_loss
        position.profit_loss_rate = gain_loss_rate

        # if taker close (market)
        position.profit_loss_market = position_gain_loss
        position.profit_loss_market_rate = gain_loss_rate

        trader.account.add_realized_profit_loss(position_gain_loss /
                                                base_exchange_rate)

        # display only for debug
        if position_gain_loss > 0.0:
            Terminal.inst().high(
                "Close profitable position with %.2f on %s (%.2fpips) (%.2f%%) at %s"
                % (position_gain_loss, order.symbol,
                   delta_price / one_pip_means, gain_loss_rate * 100.0,
                   market.format_price(close_exec_price)),
                view='debug')
        elif position_gain_loss < 0.0:
            Terminal.inst().low(
                "Close loosing position with %.2f on %s (%.2fpips) (%.2f%%) at %s"
                % (position_gain_loss, order.symbol,
                   delta_price / one_pip_means, gain_loss_rate * 100.0,
                   market.format_price(close_exec_price)),
                view='debug')
    else:
        gain_loss_rate = 0.0

    # unlock before notify signals
    trader.unlock()

    #
    # order signal (SIGNAL_ORDER_OPENED+DELETED because we assume fully completed)
    #

    order_data = {
        'id': order.order_id,
        'symbol': order.symbol,
        'type': order.order_type,
        'direction': order.direction,
        'timestamp': order.created_time,
        'quantity': order.quantity,
        'price': order.price,
        'stop-price': order.stop_price,
        'stop-loss': order.stop_loss,
        'take-profit': order.take_profit,
        'time-in-force': order.time_in_force
    }

    # signal as watcher service (opened + fully traded qty)
    trader.service.watcher_service.notify(
        Signal.SIGNAL_ORDER_OPENED, trader.name,
        (order.symbol, order_data, order.ref_order_id))

    order_data = {
        'id': order.order_id,
        'symbol': order.symbol,
        'type': order.order_type,
        'trade-id': 0,
        'direction': order.direction,
        'timestamp': order.transact_time,
        'quantity': order.quantity,
        'price': order.price,
        'stop-price': order.stop_price,
        'exec-price': exec_price,
        'avg-price': position.entry_price,
        'filled': order.executed,
        'cumulative-filled': order.executed,
        'quote-transacted': realized_position_cost,  # its margin
        'stop-loss': order.stop_loss,
        'take-profit': order.take_profit,
        'time-in-force': order.time_in_force,
        'commission-amount': 0,
        'commission-asset': trader.account.currency
    }

    trader.service.watcher_service.notify(
        Signal.SIGNAL_ORDER_TRADED, trader.name,
        (order.symbol, order_data, order.ref_order_id))

    #
    # position signal
    #

    # closed position
    position_data = {
        'id': position.position_id,
        'symbol': position.symbol,
        'direction': position.direction,
        'timestamp': order.transact_time,
        'quantity': 0,
        'avg-entry-price': position.entry_price,
        'avg-exit-price': position.exit_price,
        'exec-price': exec_price,
        'stop-loss': None,
        'take-profit': None,
        'profit-loss': position.profit_loss,
        'profit-loss-currency': market.quote
    }

    trader.service.watcher_service.notify(
        Signal.SIGNAL_POSITION_DELETED, trader.name,
        (order.symbol, position_data, order.ref_order_id))

    # and then deleted order
    trader.service.watcher_service.notify(Signal.SIGNAL_ORDER_DELETED,
                                          trader.name,
                                          (order.symbol, order.order_id, ""))

    position.exit(exec_price)

    return True
예제 #30
0
파일: trader.py 프로젝트: cal97g/siis
    def __update_orders(self):
        if not self.connected:
            return

        # 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.price = src_order.get('price')

            elif src_order['ordType'] == "Stop":
                order.order_type = Order.ORDER_STOP
                order.stop_price = src_order.get('stopPx')

            elif src_order['ordType'] == "StopLimit":
                order.order_type = Order.ORDER_STOP_LIMIT
                order.price = src_order.get('price')
                order.stop_price = src_order.get('stopPx')

            elif src_order['ordType'] == "MarketIfTouched":
                order.order_type = Order.ORDER_TAKE_PROFIT
                order.stop_price = src_order.get('stopPx')

            elif src_order['ordType'] == "LimitIfTouched":
                order.order_type = Order.ORDER_TAKE_PROFIT_LIMIT
                order.price = src_order.get('price')
                order.stop_price = src_order.get('stopPx')

            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