def send_order(self, strategy: MultiFactorTemplate, direction: Direction, offset: Offset, price: float, volume: float, stop: bool, lock: bool): """ cta的下单 """ 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_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(LOCAL_TZ)
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)
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 strategy.exchangematerial in EXCHANGE_MATERIAL: # 如果在列表里,下单量就不做任何四舍五入处理(原样) pass else: 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 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 on_trade(self, trade: TradeData): # 同步数据到数据库 if self.entrust == 0: if trade.offset == Offset.OPEN: msg = f'{trade.offset.value}{trade.direction.value},{trade.volume}张,成交价:{trade.price}' self.entrust = 1 self.write_log(f'交易完成,{trade.orderid[-3:]},{msg}') if trade.direction == Direction.LONG: price = self.ask_price price = round_to(price, self.min_diff) ref = self.sell(price, self.input_ss, False) self.write_log(u'平多单{},价:{}'.format(ref[-5:-3], price)) elif trade.direction == Direction.SHORT: price = self.bid_price price = round_to(price, self.min_diff) ref = self.cover(price, self.input_ss, False) self.write_log(u'平空单{},价:{}'.format(ref[-5:-3], price)) else: if trade.direction == Direction.LONG: direc = '空' else: direc = '多' msg = f'{trade.offset.value}{direc},{trade.volume}张,成交价:{trade.price}' self.write_log(f'交易完成,{trade.orderid[-3:]},{msg}') self.put_event()
def send_order( self, strategy: StrategyTemplate, vt_symbol: str, direction: Direction, offset: Offset, price: float, volume: float, lock: bool, net: 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, net) # 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 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 send_order(self, strategy: CtaTemplate, direction: Direction, offset: Offset, price: float, volume: float, stop: bool, lock: bool): """""" if callable(self.pricetick): price = round_to(price, self.pricetick(price)) else: 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 on_order(self, order: OrderData): """ Callback of new order data update. """ msg = f'\t报单更新,{order.orderid},{order.symbol},{order.offset.value},价:{order.price},委托:{order.volume},{order.status.value}' self.write_log(msg) if order.volume == order.traded or order.status == Status.ALLTRADED: # 开仓,平仓委托单全部成交 # 计算收益 if order.direction == Direction.LONG: self.buy_times = self.buy_times + 1 self.roi = self.roi - order.price * order.traded * self.rate else: self.sell_times = self.sell_times + 1 self.roi = self.roi + (order.price - self.base_line - order.price * self.rate) * order.traded self.base_line = order.price self.new_up = self.base_line * (1 + self.grid_height / 100) self.new_down = self.base_line / (1 + self.grid_height / 100) self.new_down = round_to(self.new_down, self.min_diff) self.entrust = 0 if self.get_engine_type() == EngineType.LIVE: base_pos = self.cta_engine.main_engine.get_account('.'.join( [order.exchange.value, self.base])) volumn = round_to(base_pos.balance, self.min_volumn) else: volumn = 10 sub = order.symbol + ' ' + order.offset.value + u',{}'.format( order.price) self.roi = round(self.roi, 4) msg2 = u'{},\n低吸次数:{},高抛次数:{},套利:{}{}, 持仓{}'.format( msg, self.buy_times, self.sell_times, self.roi, self.quote, volumn) if self.get_engine_type() == EngineType.LIVE: self.send_email(msg2) sendWxMsg(sub, msg2) elif order.status in [Status.CANCELLED, Status.REJECTED]: self.write_log("取消多余的单") self.cancel_all() sleep(10) # 10s self.entrust = 0 self.put_event()
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
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)
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: CtaTemplate, direction: Direction, offset: Offset, price: float, volume: float, stop: bool, lock: bool): """""" price = round_to(price, self.pricetick) vt_orderid = self.send_limit_order(direction, offset, price, volume) 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 on_order(self, packet: dict) -> None: """委托更新推送""" data = packet["data"] for d in data: order: OrderData = parse_order_data(d, self.gateway_name) self.gateway.on_order(order) # 检查是否有成交 if d["fillSz"] == "0": return # 将成交数量四舍五入到正确精度 trade_volume: float = float(d["fillSz"]) contract: ContractData = symbol_contract_map.get( order.symbol, None) if contract: trade_volume = round_to(trade_volume, contract.min_volume) trade: TradeData = TradeData( symbol=order.symbol, exchange=order.exchange, orderid=order.orderid, tradeid=d["tradeId"], direction=order.direction, offset=order.offset, price=float(d["fillPx"]), volume=trade_volume, datetime=parse_timestamp(d["uTime"]), gateway_name=self.gateway_name, ) self.gateway.on_trade(trade)
def on_order(self, data: dict) -> None: """""" orderid = data["clientOrderId"] order = self.gateway.get_order(orderid) if not order: return traded_volume = float(data.get("tradeVolume", 0)) contract = symbol_contract_map.get(order.symbol, None) if contract: traded_volume = round_to(traded_volume, contract.min_volume) # Push order event order.traded += traded_volume order.status = STATUS_HUOBI2VT.get(data["orderStatus"], None) self.gateway.on_order(order) # Push trade event if not traded_volume: return trade = TradeData( symbol=order.symbol, exchange=Exchange.HUOBI, orderid=order.orderid, tradeid=str(data["tradeId"]), direction=order.direction, price=float(data["tradePrice"]), volume=traded_volume, datetime=datetime.now(CHINA_TZ), gateway_name=self.gateway_name, ) self.gateway.on_trade(trade)
def __init__(self, algo_engine: BaseEngine, algo_name: str, setting: dict): """""" super().__init__(algo_engine, algo_name, setting) # Parameters self.vt_symbol = setting["vt_symbol"] self.direction = Direction(setting["direction"]) self.price = setting["price"] self.volume = setting["volume"] self.time = setting["time"] self.interval = setting["interval"] self.offset = Offset(setting["offset"]) # Variables self.order_volume = self.volume / (self.time / self.interval) contract = self.get_contract(self.vt_symbol) if contract: self.order_volume = round_to(self.order_volume, contract.min_volume) self.timer_count = 0 self.total_count = 0 self.traded = 0 self.last_tick = None self.subscribe(self.vt_symbol) self.put_parameters_event() self.put_variables_event()
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 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 on_start(self): """ Callback when strategy is started. """ self.new_up = self.base_line * (1 + self.grid_height / 100) self.new_down = self.base_line / (1 + self.grid_height / 100) self.new_down = round_to(self.new_down, self.min_diff) self.write_log("策略启动")
def onMarketData(self, mk_type: int, symbol: str, data: dict) -> None: """""" timestamp = f"{self.date}{str(data['nTime'])}" dt = datetime.strptime(timestamp, "%Y%m%d%H%M%S%f") dt = CHINA_TZ.localize(dt) tick = TickData(symbol=symbol, exchange=MK_GTJA2VT[mk_type], datetime=dt, volume=data["iVolume"], last_price=data["uMatch"] / 10000, limit_up=data["uHighLimited"] / 10000, limit_down=data["uLowLimited"] / 10000, open_price=data["uOpen"] / 10000, high_price=data["uHigh"] / 10000, low_price=data["uLow"] / 10000, pre_close=data["uPreClose"] / 10000, gateway_name=self.gateway_name) tick.bid_price_1, tick.bid_price_2, tick.bid_price_3, tick.bid_price_4, tick.bid_price_5 = data[ "bid"][0:5] tick.ask_price_1, tick.ask_price_2, tick.ask_price_3, tick.ask_price_4, tick.ask_price_5 = data[ "ask"][0:5] tick.bid_volume_1, tick.bid_volume_2, tick.bid_volume_3, tick.bid_volume_4, tick.bid_volume_5 = data[ "bid_qty"][0:5] tick.ask_volume_1, tick.ask_volume_2, tick.ask_volume_3, tick.ask_volume_4, tick.ask_volume_5 = data[ "ask_qty"][0:5] pricetick = symbol_pricetick_map.get(tick.vt_symbol, 0) if pricetick: tick.bid_price_1 = round_to(tick.bid_price_1 / 10000, pricetick) tick.bid_price_2 = round_to(tick.bid_price_2 / 10000, pricetick) tick.bid_price_3 = round_to(tick.bid_price_3 / 10000, pricetick) tick.bid_price_4 = round_to(tick.bid_price_4 / 10000, pricetick) tick.bid_price_5 = round_to(tick.bid_price_5 / 10000, pricetick) tick.ask_price_1 = round_to(tick.ask_price_1 / 10000, pricetick) tick.ask_price_2 = round_to(tick.ask_price_2 / 10000, pricetick) tick.ask_price_3 = round_to(tick.ask_price_3 / 10000, pricetick) tick.ask_price_4 = round_to(tick.ask_price_4 / 10000, pricetick) tick.ask_price_5 = round_to(tick.ask_price_5 / 10000, pricetick) tick.name = symbol_name_map.get(tick.vt_symbol, tick.symbol) self.gateway.on_tick(tick)
def cal_annual_returns(trades: {}, end_date, end_cash): """计算年化收益,需要交易日、金额, 截止日:金额""" # cash1 * (1 + x / 100)^[(end_date - self.start_date)/365] + cash2 * (1 + x / 100)^[(end_date - self.start_date)/365] = end_val # trades, key: date, value: cash expression = '' for date, cash in trades.items(): td = round_to((end_date - date).days / 365, 0.001) expression = expression + str(cash) + '*(1 + x) **' + str(td) + '+' expression = expression[:-1] + '-' + str(end_cash) return expression
def onDepthMarketData(self, data: dict) -> None: """""" timestamp = str(data["data_time"]) dt = datetime.strptime(timestamp, "%Y%m%d%H%M%S%f") dt = dt.replace(tzinfo=CHINA_TZ) tick = TickData(symbol=data["ticker"], exchange=EXCHANGE_XTP2VT[data["exchange_id"]], datetime=dt, volume=data["qty"], last_price=data["last_price"], limit_up=data["upper_limit_price"], limit_down=data["lower_limit_price"], open_price=data["open_price"], high_price=data["high_price"], low_price=data["low_price"], pre_close=data["pre_close_price"], gateway_name=self.gateway_name) tick.bid_price_1, tick.bid_price_2, tick.bid_price_3, tick.bid_price_4, tick.bid_price_5 = data[ "bid"][0:5] tick.ask_price_1, tick.ask_price_2, tick.ask_price_3, tick.ask_price_4, tick.ask_price_5 = data[ "ask"][0:5] tick.bid_volume_1, tick.bid_volume_2, tick.bid_volume_3, tick.bid_volume_4, tick.bid_volume_5 = data[ "bid_qty"][0:5] tick.ask_volume_1, tick.ask_volume_2, tick.ask_volume_3, tick.ask_volume_4, tick.ask_volume_5 = data[ "ask_qty"][0:5] pricetick = symbol_pricetick_map.get(tick.vt_symbol, 0) if pricetick: tick.bid_price_1 = round_to(tick.bid_price_1, pricetick) tick.bid_price_2 = round_to(tick.bid_price_2, pricetick) tick.bid_price_3 = round_to(tick.bid_price_3, pricetick) tick.bid_price_4 = round_to(tick.bid_price_4, pricetick) tick.bid_price_5 = round_to(tick.bid_price_5, pricetick) tick.ask_price_1 = round_to(tick.ask_price_1, pricetick) tick.ask_price_2 = round_to(tick.ask_price_2, pricetick) tick.ask_price_3 = round_to(tick.ask_price_3, pricetick) tick.ask_price_4 = round_to(tick.ask_price_4, pricetick) tick.ask_price_5 = round_to(tick.ask_price_5, pricetick) tick.name = symbol_name_map.get(tick.vt_symbol, tick.symbol) self.gateway.on_tick(tick)
def calculate_price(self) -> None: """""" option = self.option # Get ref price self.pricing_impv = option.pricing_impv ref_price = option.calculate_ref_price() self.ref_price = round_to(ref_price, self.pricetick) # Calculate spread algo_spread = max(self.price_spread, self.volatility_spread * option.cash_vega) half_spread = algo_spread / 2 # Calculate bid/ask self.algo_bid_price = round_to(ref_price - half_spread, self.pricetick) self.algo_ask_price = round_to(ref_price + half_spread, self.pricetick) self.algo_spread = round_to(algo_spread, self.pricetick) self.put_pricing_event()
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)
def onRtnOptionData(self, head: dict, data: dict) -> None: """""" timestamp = f"{head['tradeDate']} {head['updateTime']}" tick = TickData(symbol=data["SecurityID"], exchange=EXCHANGE_OES2VT[head["exchId"]], datetime=datetime.strptime(timestamp, "%Y%m%d %H%M%S%f"), volume=data["TotalVolumeTraded"], pre_close=data["PrevClosePx"], last_price=data["TradePx"] / 10000, open_price=data["OpenPx"] / 10000, high_price=data["HighPx"] / 10000, low_price=data["LowPx"] / 10000, gateway_name=self.gateway_name) tick.bid_price_1, tick.bid_price_2, tick.bid_price_3, tick.bid_price_4, tick.bid_price_5 = data[ "bid"][0:5] tick.ask_price_1, tick.ask_price_2, tick.ask_price_3, tick.ask_price_4, tick.ask_price_5 = data[ "ask"][0:5] tick.bid_volume_1, tick.bid_volume_2, tick.bid_volume_3, tick.bid_volume_4, tick.bid_volume_5 = data[ "bid_qty"][0:5] tick.ask_volume_1, tick.ask_volume_2, tick.ask_volume_3, tick.ask_volume_4, tick.ask_volume_5 = data[ "ask_qty"][0:5] pricetick = SYMBOL_PRICETICK_MAP.get(tick.vt_symbol, 0) if pricetick: tick.bid_price_1 = round_to(tick.bid_price_1 / 10000, pricetick) tick.bid_price_2 = round_to(tick.bid_price_2 / 10000, pricetick) tick.bid_price_3 = round_to(tick.bid_price_3 / 10000, pricetick) tick.bid_price_4 = round_to(tick.bid_price_4 / 10000, pricetick) tick.bid_price_5 = round_to(tick.bid_price_5 / 10000, pricetick) tick.ask_price_1 = round_to(tick.ask_price_1 / 10000, pricetick) tick.ask_price_2 = round_to(tick.ask_price_2 / 10000, pricetick) tick.ask_price_3 = round_to(tick.ask_price_3 / 10000, pricetick) tick.ask_price_4 = round_to(tick.ask_price_4 / 10000, pricetick) tick.ask_price_5 = round_to(tick.ask_price_5 / 10000, pricetick) tick.name = SYMBOL_NAME_MAP.get(tick.vt_symbol, "") self.gateway.on_tick(tick)
def process_trade_event(self, event: Event): """""" trade = event.data # Filter duplicate trade push if trade.vt_tradeid in self.vt_tradeids: return self.vt_tradeids.add(trade.vt_tradeid) self.offset_converter.update_trade(trade) strategy = self.orderid_strategy_map.get(trade.vt_orderid, None) if not strategy: return contract = self.main_engine.get_contract(strategy.vt_symbol) if not contract: volume = trade.volume else: # Round order price and volume to nearest incremental value volume = round_to(trade.volume, contract.min_volume) # Update strategy pos before calling on_trade method if trade.direction == Direction.LONG: strategy.pos += volume else: strategy.pos -= volume if contract: strategy.pos = round_to(strategy.pos, contract.min_volume) self.call_strategy_func(strategy, strategy.on_trade, trade) # Sync strategy variables to data file self.sync_strategy_data(strategy) # Update GUI self.put_strategy_event(strategy)
def send_order(self, strategy: CtaTemplate, direction: Direction, offset: Offset, price: float, volume: float, lock: bool, order_type: OrderType, extra: dict): """""" price = round_to(price, self.pricetick) if order_type == order_type.STOP: vt_orderid = self.send_stop_order(direction, offset, price, volume) elif order_type == order_type.MARKET: vt_orderid = self.send_market_order(direction, offset, price, volume, extra) else: vt_orderid = self.send_limit_order(direction, offset, price, volume, extra) return [vt_orderid]
def on_trade(self, trade: TradeData): # 同步数据到数据库 self.posPrice = trade.price self.sync_data() if self.entrust == 0: msg = u'{}{},{}张,成交价:{}'.format(trade.offset.value, trade.direction.value, trade.volume, trade.price) self.write_log(u'交易完成,{},{},pos:{}'.format(trade.orderid, msg, self.poss)) if trade.offset == Offset.OPEN: if trade.direction == Direction.LONG: price = trade.price - self.step price = round_to(price, self.min_diff) ref = self.sell(price, self.input_ss, True) self.write_log(u'开多停止单{},价:{}'.format(ref, price)) elif trade.direction == Direction.SHORT: price = trade.price + self.step price = round_to(price, self.min_diff) ref = self.cover(price, self.input_ss, True) self.write_log(u'开空停止单{},价:{}'.format(ref, price)) self.put_event()