예제 #1
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
예제 #2
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
예제 #3
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
예제 #4
0
파일: trader.py 프로젝트: cal97g/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

        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.price = limit_price

            postdict['ordType'] = "Limit"
            postdict['price'] = 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 and 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
예제 #5
0
파일: trader.py 프로젝트: venkiiee/siis
    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

        trader_market = self._markets.get(market_or_instrument.market_id)
        if not trader_market:
            error_logger.error(
                "Trader %s refuse to close position because the market %s is not found"
                % (self.name, market_or_instrument.market_id))
            return False

        result = False

        with self._mutex:
            # retrieve the position
            position = self._positions.get(position_id)

            if position and position.is_opened():
                # market stop order
                order = Order(self, position.symbol)
                order.set_position_id(position_id)

                order.direction = position.close_direction()

                if limit_price:
                    order.order_type = Order.ORDER_LIMIT
                    order.price = limit_price
                else:
                    order.order_type = Order.ORDER_MARKET

                order.quantity = position.quantity  # fully close
                order.leverage = position.leverage  # same as open

                order.close_only = True
                order.reduce_only = True

                #
                # price according to order type
                #

                bid_price = 0
                ofr_price = 0

                if order.order_type == Order.ORDER_LIMIT:
                    bid_price = order.price
                    ofr_price = order.price

                elif order.order_type == Order.ORDER_MARKET:
                    bid_price = trader_market.bid
                    ofr_price = trader_market.ofr

                # open long are executed on bid and short on ofr, close the inverse
                if order.direction == Position.LONG:
                    open_exec_price = ofr_price  # bid_price
                    close_exec_price = bid_price  # ofr_price
                elif order.direction == Position.SHORT:
                    open_exec_price = bid_price  # ofr_price
                    close_exec_price = ofr_price  # bid_price
                else:
                    logger.error("Unsupported direction")
                    return False

                if not open_exec_price or not close_exec_price:
                    logger.error("No order execution price")
                    return False

                if self._slippage > 0.0:
                    # @todo deferred to update
                    return False
                else:
                    # immediate execution of the order
                    if trader_market.has_position:
                        # close isolated position
                        result = close_position(self, trader_market, position,
                                                close_exec_price,
                                                Order.ORDER_MARKET)
                    else:
                        # close position (could be using FIFO method)
                        result = exec_margin_order(self, order, trader_market,
                                                   open_exec_price,
                                                   close_exec_price)
            else:
                result = False

        return result
예제 #6
0
파일: trader.py 프로젝트: rptrk/siis
    def close_position(self, position_id, market=True, limit_price=None):
        if not self._activity:
            return False

        result = False

        self.lock()
        position = self._positions.get(position_id)

        if position and position.is_opened():
            # market stop order
            order = Order(self, position.symbol)
            order.set_position_id(position_id)

            order.direction = position.close_direction()

            if market and limit_price:
                order.order_type = Order.ORDER_LIMIT
                order.price = limit_price
            else:
                order.order_type = Order.ORDER_MARKET

            order.quantity = position.quantity  # fully close
            order.leverage = position.leverage  # same as open

            order.close_only = True
            order.reduce_only = True

            self.unlock()

            #
            # price according to order type
            #

            market = self.market(order.symbol)

            bid_price = 0
            ofr_price = 0

            if order.order_type == Order.ORDER_LIMIT:
                bid_price = order.price
                ofr_price = order.price

            elif order.order_type == Order.ORDER_MARKET:
                bid_price = market.bid
                ofr_price = market.ofr

            # open long are executed on bid and short on ofr, close the inverse
            if order.direction == Position.LONG:
                open_exec_price = ofr_price  # bid_price
                close_exec_price = bid_price  # ofr_price
            elif order.direction == Position.SHORT:
                open_exec_price = bid_price  # ofr_price
                close_exec_price = ofr_price  # bid_price
            else:
                logger.error("Unsupported direction")
                return False

            if not open_exec_price or not close_exec_price:
                logger.error("No order execution price")
                return False

            if self._slippage > 0.0:
                # @todo
                return False
            else:
                # immediate execution of the order
                result = exec_margin_order(self, order, market, open_exec_price, close_exec_price)
        else:
            self.unlock()
            result = False         

        return result