Exemplo n.º 1
0
    def send_order(
        self,
        strategy: CtaTemplate,
        direction: Direction,
        offset: Offset,
        price: float,
        volume: float,
        stop: bool,
        lock: bool
    ):
        """
        """
        contract = self.main_engine.get_contract(strategy.vt_symbol)
        if not contract:
            self.write_log(f"委托失败,找不到合约:{strategy.vt_symbol}", strategy)
            return ""

        # Round order price and volume to nearest incremental value
        price = round_to(price, contract.pricetick)
        volume = round_to(volume, contract.min_volume)

        if stop:
            if contract.stop_supported:
                return self.send_server_stop_order(strategy, contract, direction, offset, price, volume, lock)
            else:
                return self.send_local_stop_order(strategy, direction, offset, price, volume, lock)
        else:
            return self.send_limit_order(strategy, contract, direction, offset, price, volume, lock)
Exemplo n.º 2
0
    def calculate_price(self):
        """"""
        self.clear_price()

        # Go through all legs to calculate price
        for n, leg in enumerate(self.legs.values()):
            # Filter not all leg price data has been received
            if not leg.bid_volume or not leg.ask_volume:
                self.clear_price()
                return

            # Calculate price
            price_multiplier = self.price_multipliers[leg.vt_symbol]
            if price_multiplier > 0:
                self.bid_price += leg.bid_price * price_multiplier
                self.ask_price += leg.ask_price * price_multiplier
            else:
                self.bid_price += leg.ask_price * price_multiplier
                self.ask_price += leg.bid_price * price_multiplier

            # Round price to pricetick
            if self.pricetick:
                self.bid_price = round_to(self.bid_price, self.pricetick)
                self.ask_price = round_to(self.ask_price, self.pricetick)

            # Calculate volume
            trading_multiplier = self.trading_multipliers[leg.vt_symbol]
            inverse_contract = self.inverse_contracts[leg.vt_symbol]

            if not inverse_contract:
                leg_bid_volume = leg.bid_volume
                leg_ask_volume = leg.ask_volume
            else:
                leg_bid_volume = calculate_inverse_volume(
                    leg.bid_volume, leg.bid_price, leg.size)
                leg_ask_volume = calculate_inverse_volume(
                    leg.ask_volume, leg.ask_price, leg.size)

            if trading_multiplier > 0:
                adjusted_bid_volume = floor_to(
                    leg_bid_volume / trading_multiplier, self.min_volume)
                adjusted_ask_volume = floor_to(
                    leg_ask_volume / trading_multiplier, self.min_volume)
            else:
                adjusted_bid_volume = floor_to(
                    leg_ask_volume / abs(trading_multiplier), self.min_volume)
                adjusted_ask_volume = floor_to(
                    leg_bid_volume / abs(trading_multiplier), self.min_volume)

            # For the first leg, just initialize
            if not n:
                self.bid_volume = adjusted_bid_volume
                self.ask_volume = adjusted_ask_volume
            # For following legs, use min value of each leg quoting volume
            else:
                self.bid_volume = min(self.bid_volume, adjusted_bid_volume)
                self.ask_volume = min(self.ask_volume, adjusted_ask_volume)

            # Update calculate time
            self.datetime = datetime.now()
Exemplo n.º 3
0
    def send_order(
        self,
        strategy: StrategyTemplate,
        vt_symbol: str,
        direction: Direction,
        offset: Offset,
        price: float,
        volume: float,
        lock: bool
    ):
        """
        Send a new order to server.
        """
        contract: ContractData = self.main_engine.get_contract(vt_symbol)
        if not contract:
            self.write_log(f"委托失败,找不到合约:{vt_symbol}", strategy)
            return ""

        # Round order price and volume to nearest incremental value
        price = round_to(price, contract.pricetick)
        volume = round_to(volume, contract.min_volume)

        # Create request and send order.
        original_req = OrderRequest(
            symbol=contract.symbol,
            exchange=contract.exchange,
            direction=direction,
            offset=offset,
            type=OrderType.LIMIT,
            price=price,
            volume=volume,
            reference=f"{APP_NAME}_{strategy.strategy_name}"
        )

        # Convert with offset converter
        req_list = self.offset_converter.convert_order_request(original_req, lock)

        # Send Orders
        vt_orderids = []

        for req in req_list:
            req.reference = strategy.strategy_name      # Add strategy name as order reference

            vt_orderid = self.main_engine.send_order(
                req, contract.gateway_name)

            # Check if sending order successful
            if not vt_orderid:
                continue

            vt_orderids.append(vt_orderid)

            self.offset_converter.update_order_request(req, vt_orderid)

            # Save relationship between orderid and strategy.
            self.orderid_strategy_map[vt_orderid] = strategy

        return vt_orderids
Exemplo n.º 4
0
    def calculate_traded_price(self):
        """"""
        self.traded_price = 0
        spread = self.spread

        # Basic spread
        if not isinstance(spread, AdvancedSpreadData):
            for leg in spread.legs.values():
                # If any leg is not traded yet, set spread trade price to 0
                leg_traded = self.leg_traded[leg.vt_symbol]
                if not leg_traded:
                    self.traded_price = 0
                    break

                leg_cost = self.leg_cost[leg.vt_symbol]
                leg_price = leg_cost / leg_traded

                price_multiplier = spread.price_multipliers[leg.vt_symbol]
                self.traded_price += leg_price * price_multiplier

            self.traded_price = round_to(self.traded_price, spread.pricetick)
        # Advanced spread
        else:
            data = {}

            for variable, vt_symbol in spread.variable_symbols.items():
                leg = spread.legs[vt_symbol]
                trading_multiplier = spread.trading_multipliers[leg.vt_symbol]

                # Use last price for non-trading leg (trading multiplier is 0)
                if not trading_multiplier:
                    data[variable] = leg.tick.last_price
                else:
                    # If any leg is not traded yet, clear data dict to set traded price to 0
                    leg_traded = self.leg_traded[leg.vt_symbol]
                    if not leg_traded:
                        data.clear()
                        break

                    leg_cost = self.leg_cost[leg.vt_symbol]
                    data[variable] = leg_cost / leg_traded

            if data:
                self.traded_price = spread.parse_formula(
                    spread.price_code, data)
                self.traded_price = round_to(self.traded_price,
                                             spread.pricetick)
            else:
                self.traded_price = 0
Exemplo n.º 5
0
    def send_order(
        self,
        vt_symbol: str,
        price: float,
        volume: float,
        direction: Direction,
    ):
        """"""
        # For inverse contract:
        # calculate contract trading volume from coin trading volume
        if self.spread.is_inverse(vt_symbol):
            size = self.spread.get_leg_size(vt_symbol)

            if self.offset == Offset.CLOSE:
                leg = self.spread.legs[vt_symbol]
                volume = volume * leg.net_pos_price / size
            else:
                volume = volume * price / size

        # Round order volume to min_volume of contract
        leg = self.spread.legs[vt_symbol]
        volume = round_to(volume, leg.min_volume)

        # If new order volume is 0, then check if algo finished
        if not volume:
            finished = self.check_algo_finished()

            if finished:
                self.status = Status.ALLTRADED
                self.put_event()

                msg = "各腿剩余数量均不足最小下单量,算法执行结束"
                self.write_log(msg)

            return

        # Round order price to pricetick of contract
        price = round_to(price, leg.pricetick)

        # Otherwise send order
        vt_orderids = self.algo_engine.send_order(self, vt_symbol, price,
                                                  volume, direction, self.lock)

        self.leg_orders[vt_symbol].extend(vt_orderids)

        msg = "发出委托[{}],{},{},{}@{}".format("|".join(vt_orderids), vt_symbol,
                                            direction.value, volume, price)
        self.write_log(msg)
Exemplo n.º 6
0
    def send_order(self, algo: AlgoTemplate, vt_symbol: str,
                   direction: Direction, price: float, volume: float,
                   order_type: OrderType, offset: Offset):
        """"""
        contract = self.main_engine.get_contract(vt_symbol)
        if not contract:
            self.write_log(f'委托下单失败,找不到合约:{vt_symbol}', algo)
            return

        volume = round_to(volume, contract.min_volume)
        if not volume:
            return ""

        req = OrderRequest(symbol=contract.symbol,
                           exchange=contract.exchange,
                           direction=direction,
                           type=order_type,
                           volume=volume,
                           price=price,
                           offset=offset,
                           reference=f"{APP_NAME}_{algo.algo_name}")
        vt_orderid = self.main_engine.send_order(req, contract.gateway_name)

        self.orderid_algo_map[vt_orderid] = algo
        return vt_orderid
Exemplo n.º 7
0
    def send_order(self, strategy: StrategyTemplate, vt_symbol: str,
                   direction: Direction, offset: Offset, price: float,
                   volume: float, lock: bool) -> List[str]:
        """"""
        price = round_to(price, self.priceticks[vt_symbol])
        symbol, exchange = extract_vt_symbol(vt_symbol)

        self.limit_order_count += 1

        order = OrderData(
            symbol=symbol,
            exchange=exchange,
            orderid=str(self.limit_order_count),
            direction=direction,
            offset=offset,
            price=price,
            volume=volume,
            status=Status.SUBMITTING,
            datetime=self.datetime,
            gateway_name=self.gateway_name,
        )

        self.active_limit_orders[order.vt_orderid] = order
        self.limit_orders[order.vt_orderid] = order

        return [order.vt_orderid]
Exemplo n.º 8
0
    def generate_rand_volume(self):
        """"""
        rand_volume = uniform(self.min_volume, self.max_volume)
        rand_volume = round_to(rand_volume, self.volume_change)

        if self.volume_change == 1:
            rand_volume = int(rand_volume)

        return rand_volume
Exemplo n.º 9
0
def load_bar_data(spread: SpreadData,
                  interval: Interval,
                  start: datetime,
                  end: datetime,
                  pricetick: float = 0):
    """"""
    # Load bar data of each spread leg
    leg_bars: Dict[str, Dict] = {}

    for vt_symbol in spread.legs.keys():
        symbol, exchange = extract_vt_symbol(vt_symbol)

        bar_data: List[BarData] = database_manager.load_bar_data(
            symbol, exchange, interval, start, end)

        bars: Dict[datetime, BarData] = {bar.datetime: bar for bar in bar_data}
        leg_bars[vt_symbol] = bars

    # Calculate spread bar data
    spread_bars: List[BarData] = []

    for dt in bars.keys():
        spread_price = 0
        spread_value = 0
        spread_available = True

        for leg in spread.legs.values():
            leg_bar = leg_bars[leg.vt_symbol].get(dt, None)

            if leg_bar:
                price_multiplier = spread.price_multipliers[leg.vt_symbol]
                spread_price += price_multiplier * leg_bar.close_price
                spread_value += abs(price_multiplier) * leg_bar.close_price
            else:
                spread_available = False

        if spread_available:
            if pricetick:
                spread_price = round_to(spread_price, pricetick)

            spread_bar = BarData(
                symbol=spread.name,
                exchange=exchange.LOCAL,
                datetime=dt,
                interval=interval,
                open_price=spread_price,
                high_price=spread_price,
                low_price=spread_price,
                close_price=spread_price,
                gateway_name="SPREAD",
            )
            spread_bar.value = spread_value
            spread_bars.append(spread_bar)

    return spread_bars
Exemplo n.º 10
0
 def send_order(self, strategy: CtaTemplate, direction: Direction,
                offset: Offset, price: float, volume: float, stop: bool,
                lock: bool):
     """"""
     price = round_to(price, self.pricetick)
     if stop:
         vt_orderid = self.send_stop_order(direction, offset, price, volume)
     else:
         vt_orderid = self.send_limit_order(direction, offset, price,
                                            volume)
     return [vt_orderid]
Exemplo n.º 11
0
    def hedge_passive_legs(self):
        """
        Send orders to hedge all passive legs.
        """
        # Calcualte spread volume to hedge
        active_leg = self.spread.active_leg
        active_traded = self.leg_traded[active_leg.vt_symbol]
        active_traded = round_to(active_traded, self.spread.min_volume)

        hedge_volume = self.spread.calculate_spread_volume(
            active_leg.vt_symbol, active_traded)

        # Calculate passive leg target volume and do hedge
        for leg in self.spread.passive_legs:
            passive_traded = self.leg_traded[leg.vt_symbol]
            passive_traded = round_to(passive_traded, self.spread.min_volume)

            passive_target = self.spread.calculate_leg_volume(
                leg.vt_symbol, hedge_volume)

            leg_order_volume = passive_target - passive_traded
            if leg_order_volume:
                self.send_leg_order(leg.vt_symbol, leg_order_volume)
Exemplo n.º 12
0
    def calculate_traded_volume(self):
        """"""
        self.traded = 0
        spread = self.spread

        n = 0
        for leg in spread.legs.values():
            leg_traded = self.leg_traded[leg.vt_symbol]
            trading_multiplier = spread.trading_multipliers[leg.vt_symbol]
            if not trading_multiplier:
                continue

            adjusted_leg_traded = leg_traded / trading_multiplier
            adjusted_leg_traded = round_to(adjusted_leg_traded,
                                           spread.min_volume)

            if adjusted_leg_traded > 0:
                adjusted_leg_traded = floor_to(adjusted_leg_traded,
                                               spread.min_volume)
            else:
                adjusted_leg_traded = ceil_to(adjusted_leg_traded,
                                              spread.min_volume)

            if not n:
                self.traded = adjusted_leg_traded
            else:
                if adjusted_leg_traded > 0:
                    self.traded = min(self.traded, adjusted_leg_traded)
                elif adjusted_leg_traded < 0:
                    self.traded = max(self.traded, adjusted_leg_traded)
                else:
                    self.traded = 0

            n += 1

        self.traded_volume = abs(self.traded)

        if self.target > 0 and self.traded >= self.target:
            self.status = Status.ALLTRADED
        elif self.target < 0 and self.traded <= self.target:
            self.status = Status.ALLTRADED
        elif not self.traded:
            self.status = Status.NOTTRADED
        else:
            self.status = Status.PARTTRADED
Exemplo n.º 13
0
    def update_trade(self, trade: TradeData):
        """"""
        # For inverse contract:
        # record coin trading volume as leg trading volume,
        # not contract volume!
        if self.spread.is_inverse(trade.vt_symbol):
            size = self.spread.get_leg_size(trade.vt_symbol)

            trade_volume = calculate_inverse_volume(trade.volume, trade.price,
                                                    size)
        else:
            trade_volume = trade.volume

        if trade.direction == Direction.LONG:
            self.leg_traded[trade.vt_symbol] += trade_volume
            self.leg_cost[trade.vt_symbol] += trade_volume * trade.price
        else:
            self.leg_traded[trade.vt_symbol] -= trade_volume
            self.leg_cost[trade.vt_symbol] -= trade_volume * trade.price

        self.calculate_traded_volume()
        self.calculate_traded_price()

        # Sum up total traded volume of each order,
        self.order_trade_volume[trade.vt_orderid] += trade.volume

        # Remove order from active list if all volume traded
        order = self.orders[trade.vt_orderid]
        contract = self.get_contract(trade.vt_symbol)

        trade_volume = round_to(self.order_trade_volume[order.vt_orderid],
                                contract.min_volume)

        if trade_volume == order.volume:
            vt_orderids = self.leg_orders[order.vt_symbol]
            if order.vt_orderid in vt_orderids:
                vt_orderids.remove(order.vt_orderid)

        msg = "委托成交[{}],{},{},{}@{}".format(trade.vt_orderid, trade.vt_symbol,
                                            trade.direction.value,
                                            trade.volume, trade.price)
        self.write_log(msg)

        self.put_event()
        self.on_trade(trade)
Exemplo n.º 14
0
    def calculate_price(self):
        """"""
        self.clear_price()

        # Go through all legs to calculate price
        bid_data = {}
        ask_data = {}
        volume_inited = False

        for variable, leg in self.variable_legs.items():
            # Filter not all leg price data has been received
            if not leg.bid_volume or not leg.ask_volume:
                self.clear_price()
                return

            # Generate price dict for calculating spread bid/ask
            variable_direction = self.variable_directions[variable]
            if variable_direction > 0:
                bid_data[variable] = leg.bid_price
                ask_data[variable] = leg.ask_price
            else:
                bid_data[variable] = leg.ask_price
                ask_data[variable] = leg.bid_price

            # Calculate volume
            trading_multiplier = self.trading_multipliers[leg.vt_symbol]
            if not trading_multiplier:
                continue

            inverse_contract = self.inverse_contracts[leg.vt_symbol]
            if not inverse_contract:
                leg_bid_volume = leg.bid_volume
                leg_ask_volume = leg.ask_volume
            else:
                leg_bid_volume = calculate_inverse_volume(
                    leg.bid_volume, leg.bid_price, leg.size)
                leg_ask_volume = calculate_inverse_volume(
                    leg.ask_volume, leg.ask_price, leg.size)

            if trading_multiplier > 0:
                adjusted_bid_volume = floor_to(
                    leg_bid_volume / trading_multiplier, self.min_volume)
                adjusted_ask_volume = floor_to(
                    leg_ask_volume / trading_multiplier, self.min_volume)
            else:
                adjusted_bid_volume = floor_to(
                    leg_ask_volume / abs(trading_multiplier), self.min_volume)
                adjusted_ask_volume = floor_to(
                    leg_bid_volume / abs(trading_multiplier), self.min_volume)

            # For the first leg, just initialize
            if not volume_inited:
                self.bid_volume = adjusted_bid_volume
                self.ask_volume = adjusted_ask_volume
                volume_inited = True
            # For following legs, use min value of each leg quoting volume
            else:
                self.bid_volume = min(self.bid_volume, adjusted_bid_volume)
                self.ask_volume = min(self.ask_volume, adjusted_ask_volume)

        # Calculate spread price
        self.bid_price = self.parse_formula(self.price_code, bid_data)
        self.ask_price = self.parse_formula(self.price_code, ask_data)

        # Round price to pricetick
        if self.pricetick:
            self.bid_price = round_to(self.bid_price, self.pricetick)
            self.ask_price = round_to(self.ask_price, self.pricetick)

        # Update calculate time
        self.datetime = datetime.now()