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)
def calculate_traded(self): """""" # Calculate traded volume self.traded = 0 for n, leg in enumerate(self.spread.legs.values()): leg_traded = self.leg_traded[leg.vt_symbol] trading_multiplier = self.spread.trading_multipliers[ leg.vt_symbol] adjusted_leg_traded = leg_traded / trading_multiplier adjusted_leg_traded = round_to( adjusted_leg_traded, self.spread.min_volume) if adjusted_leg_traded > 0: adjusted_leg_traded = floor_to( adjusted_leg_traded, self.spread.min_volume) else: adjusted_leg_traded = ceil_to( adjusted_leg_traded, self.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 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 # Calculate traded price self.traded_price = 0 for n, leg in enumerate(self.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 = self.spread.price_multipliers[leg.vt_symbol] self.traded_price += leg_price * price_multiplier self.traded_price = round_to(self.traded_price, self.spread.pricetick)
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 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()
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( vt_symbol, direction, volume, price ) self.write_log(msg)
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
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
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]
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
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
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]
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() # 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_symbol, trade.direction, trade.volume, trade.price ) self.write_log(msg) self.put_event() self.on_trade(trade)
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)