基于期限利差策略的债券回测分析——kingstar因子投研平台

本文主要是介绍基于期限利差策略的债券回测分析——kingstar因子投研平台,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在上篇文章期限利差怎么看文章中详细介绍了期限利差策略的内容,本次将介绍代码实现,重要的是理解整个交易的逻辑,为什么要这样去做?对以后写代码会有很大帮助。

首先导入相关库:

from typing import List, Dict
import numpy as np
import datetimefrom base.constant import Direction, Offset, BusinessType
from bond.base.utility import ArrayManager
from base.constant import Direction, Offset, BusinessType
from bond.base.object import TickData, OrderData, TradeData, BarData, QuoteRequest, FactorData
from bond.base.template import StrategyTemplate
from bond.base.inter_base import BaseInterface
from bond.data.data_http import HttpDataHandler
from bond.base.inter_kslib import KSLibInterface, KSQuoteType
from util.common_exception import CommonException

导入typing、numpy、datetime库,导入内部债券相关基本库做准备。

接下来定义好相关变量,所有都有说明:

class PairTradingStrategy(StrategyTemplate):#合约1为长期债券,合约2为短期债券variety_list = ['leg1_symbol', 'leg2_symbol']#用于套利的两个合约的参数名称parameters = ['up_threshold', 'up_threshold_sell','down_threshold','down_threshold_sell', 'spread_length']#可变输入参数variables = []up_threshold = 0.8#利差突破债券上限的分位数,买入债券1,卖出债券2up_threshold_sell=0.6#利差从债券上限回落的分位数,平仓down_threshold = 0.2#利差突破债券下限的分位数,买入债券2,卖出债券1down_threshold_sell=0.45#利差从债券下限回升的分位数,平仓spread_length = 50#至少需要累积的利差数据长度market_1 = []#存放债券1的行情数据————是一个object,key为leg1_symbol,value为price、yield等market_2 = []#存放债券2的行情数据————是一个object,key为leg1_symbol,value为price、yield等close_diff_list = []#存贮利差的listtime_list_filter = []# 过滤重复的时间戳target_pos = {}#记录目标手数,防止因为债券行情导致的成交不到而不停发单order_mess = QuoteRequest()hdh = HttpDataHandler()kslib = KSLibInterface()# -------------------分隔线--------------------leg1_symbol = '200210.BOND'  #下单腿,用于成交的腿,20年国开10年期债券leg2_symbol = '220305.BOND'  #用于计算价差的另一腿,22年进出口5年期债券start_date = '2023-02-25'  # %Y-%m-%dend_date = '2023-08-25'  # %Y-%m-%d

相关的输入界面如图:(注意:输入界面的所有参数都是可变的,输入会覆盖原定义的值)

定义含参数后,进行初始化:

    def __init__(self, strategy_engine, strategy_name: str, vt_symbols: List[str], setting: dict = None,factors: List[str] = None):#注意:因子的初始化因为后面有接触因子回测这里就先初始化#父类初始化,策略引擎、合约初始化super().__init__(strategy_engine, strategy_name, vt_symbols,setting)# Obtain contract infoself.leg1_symbol, self.leg2_symbol = vt_symbolsdef on_init(self):"""时间戳、利差、仓位、行情数据初始化,输出日志"""self.write_log("策略初始化")self.load_bars(0)self.close_diff_list.clear()self.time_list_filter.clear()for s in self.vt_symbols:self.target_pos[s] = 0def on_start(self):"""Callback when strategy is started."""self.write_log("策略启动")self.put_event()def on_stop(self):"""Callback when strategy is stopped."""self.write_log("策略停止")self.put_event()def on_tick(self, tick: TickData):pass"""Callback of new tick data update, 实时数据"""

下面获取行情数据进行数据处理:

    def on_bars(self, bars: Dict[str, BarData]):self.cancel_all()#取消所有订单if self.leg1_symbol not in bars or self.leg2_symbol not in bars:return# bar_trade = bars[self.leg1_symbol]# bar_base = bars[self.leg2_symbol]"""注意:必须要在前面先定义market_1和market_2两个对象 =[],原因:如果这里没有获取到行情,后续对market_1 or market_2处理时报错没找到对象{也就是说:所有后续用到的变量最好是先定义}"""#获取bar线数据for key in bars:if key == self.leg1_symbol and bars[key].close_price > 80:self.market_1.append(bars[key])self.write_log("执行on_bars: %s - %s" % (key, str(bars[key])))elif key == self.leg2_symbol and bars[key].close_price > 80:self.market_2.append(bars[key])self.write_log("执行on_bars: %s - %s" % (key, str(bars[key])))"""注意:bar里面是两个合约,每次获取一条行情,所以说下面的if与for对齐,如果合约1或合约2没获取到行情就返回,并且上面for里面的每个if和else对应,为一组,上面是if和elif,不能是两个if,因为每次只能进一个选项,不是if就是elif下面的if若也在for里面,每次获取两个合约中任意一个后就会判断是否为空,不可置疑,肯定有一个为空(每次对合约1或合约2获取一条行情数据),这样就导致永远无法继续执行下去,到这里就退出来行情函数"""if len(self.market_1) == 0 or len(self.market_2) == 0:return"""注意:两个合约获取的日期必须是在同一天,同一天的行情才能进行比较所以后续的所有交易买卖都在这个前提下进行而且要注意market_1和market_2是对象,里面存储大量的行情,所以是对获取到的最新行情进行处理,也就是market_1[-1],如果是market_1就每次是对其第一条行情进行处理"""if self.market_1[-1].datetime == self.market_2[-1].datetime:bar_close_trade = self.market_1[-1].yield_rateself.write_log("%s ytm:  %s" % (self.leg1_symbol,str(bar_close_trade)))bar_close_base = self.market_2[-1].yield_rateself.write_log("%s ytm:  %s" % (self.leg2_symbol,str(bar_close_base)))close_diff = bar_close_trade - bar_close_baseself.write_log("%s - %s 利差ytm:  %s" % (self.leg1_symbol,self.leg2_symbol,str(close_diff)))if len(self.close_diff_list) < self.spread_length:  # 当利差保存数量小于最小值,则保存利差并跳过self.close_diff_list.append(close_diff)  # 保存利差returnelse:spread_up = np.quantile(np.array(self.close_diff_list), self.up_threshold)  # 上分位数spread_up_sell = np.quantile(np.array(self.close_diff_list), self.up_threshold_sell)  # 平仓的回落下分位数spread_down = np.quantile(np.array(self.close_diff_list), self.down_threshold)  # 下分位数spread_down_sell = np.quantile(np.array(self.close_diff_list),self.down_threshold_sell)  # 平仓的回升上分位数self.write_log("利差动态上下限: %s - %s - %s - %s" % (spread_up,spread_up_sell,spread_down,spread_down_sell))self.close_diff_list.pop(0)  # 利差滚动存放self.close_diff_list.append(close_diff)"""定义了一个计算利差所处分位数的函数,计算分位数时就会调用"""def calculate_percentile(current_value, spread_list):sorted_spread = sorted(spread_list)index = sorted_spread.index(current_value)percentile = (index / len(spread_list)) * 100return percentilepercentile = calculate_percentile(close_diff, self.close_diff_list)self.write_log("当前利差所处分位数:  %s" % (str(percentile)))

进行好上述操作后,下面就要判断买卖操作逻辑了,具体逻辑如下:

                """策略逻辑如下:如果利差(10年-1年) > 以往利差的0.8上分位数,此时利率处在高位,预计未来向均值回归,利差缩小,要买入长期限债,就买入1手10年期债券,做空1手1年期短期债,利差数据序列继续读利差数据,如果利差继续保持0.8分位数以上就继续买入,仓位不做限制,原本有仓位也买入,若未来有一天利差缩小向均值回归,利差 < 0.6分位数,此时只要利差读到的数据满足该条件就一次性卖出全部仓位,加了个条件leg1_pos > 0有仓位才平仓,没仓位的话不会做空,不用担心影响到接下来的利差骤降, < spread_down(0.2),不能做空合约1,从0.8分位数到0.2分位数必然会先被利差<0.6分位数逻辑识别到先对合约1平仓,再运行利差<0.2开空仓,因为4个if是平齐的,假设运行了rate_diff > spread_up0.8分位数,势必会运行到rate_diff > spread_down_sell 0.45分位数,但后者的前提是合约1的仓位 < 0,运行> spread_up0.8分位数后合约1的仓位肯定 >0,所以不用担心它们之间会有影响,做多1次合约1又做多一次合约1的错误逻辑"""

代码如下:

                bar_trade_price =self.market_1[-1].close_pricebar_base_price =self.market_2[-1].close_price#利率上行周期,买长卖短if close_diff > spread_up:  # 当价差大于布林带上界,买价差,买trade,卖baseleg1_pos = self.get_pos(self.leg1_symbol)self.write_log("准备报单,1买2卖时,当前合约1价格:  %s" % (str(bar_trade_price)))self.write_log("准备报单,1买2卖时,当前合约2价格:  %s" % (str(bar_base_price)))if leg1_pos == 0 or leg1_pos > 0 :  # 当前无论有无仓位,对合约1开多仓self.write_log("准备报单了,1买2卖")self.order_mess.clear()#清理报单self.order_mess.vt_symbol = self.leg1_symbol#选择合约对象self.order_mess.bid_price = bar_trade_price #报单价格self.order_mess.bid_volume = 100#报单量self.order_mess.settle_type = '2'#确定结算类型self.order_mess.quote_type = '2'#确定报单类型self.quote(BusinessType.XBOND, self.order_mess)#这里是债券报单,所以是双向报单,对于API接口中buy、sell、short、cover等报单类型不适用,这些都是对期货合约定义的,债券只需要quote即可self.write_log("合约1仓位:  %s" % (str(self.get_pos(self.leg1_symbol))))self.order_mess.clear()self.order_mess.vt_symbol = self.leg2_symbolself.order_mess.ask_price = bar_base_priceself.order_mess.ask_volume = 100self.order_mess.settle_type = '2'self.order_mess.quote_type = '2'self.quote(BusinessType.XBOND, self.order_mess)#买1同时也要卖2,同时操作,调参数时调整成交委托比来实现成交量的改变self.write_log("合约2仓位:  %s" % (str(self.get_pos(self.leg2_symbol))))if close_diff < spread_up_sell:leg1_pos = self.get_pos(self.leg1_symbol)self.write_log("1买2卖,平仓,当前合约1价格:  %s" % (str(bar_trade_price)))self.write_log("1买2卖,平仓,当前合约2价格:  %s" % (str(bar_base_price)))if leg1_pos > 0  :  # 当前有仓位,就先平仓self.write_log("准备报单了,1买2卖,平仓")self.order_mess.clear()self.order_mess.vt_symbol = self.leg1_symbolself.order_mess.ask_price = bar_trade_priceself.order_mess.ask_volume = abs(self.get_pos(self.leg1_symbol))self.order_mess.settle_type = '2'self.order_mess.quote_type = '2'self.quote(BusinessType.XBOND, self.order_mess)self.write_log("合约1仓位:  %s" % (str(self.get_pos(self.leg1_symbol))))self.order_mess.clear()self.order_mess.vt_symbol = self.leg2_symbolself.order_mess.bid_price = bar_base_priceself.order_mess.bid_volume = abs(self.get_pos(self.leg2_symbol))self.order_mess.settle_type = '2'self.order_mess.quote_type = '2'self.quote(BusinessType.XBOND, self.order_mess)self.write_log("合约2仓位:  %s" % (str(self.get_pos(self.leg2_symbol))))#利率下行周期,卖长买短if close_diff < spread_down:  # 当价差小于布林带下界,卖价差,卖trade买baseleg1_pos = self.get_pos(self.leg1_symbol)self.write_log("准备报单,1卖2买,当前合约1价格:  %s" % (str(bar_trade_price)))self.write_log("准备报单,1卖2买,当前合约2价格:  %s" % (str(bar_base_price)))if leg1_pos == 0 or leg1_pos < 0 : self.write_log("准备报单了,1卖2买")self.order_mess.clear()self.order_mess.vt_symbol = self.leg1_symbolself.order_mess.ask_price = bar_trade_priceself.order_mess.ask_volume = 100self.order_mess.settle_type = '2'self.order_mess.quote_type = '2'self.quote(BusinessType.XBOND, self.order_mess)self.write_log("合约1仓位:  %s" % (str(self.get_pos(self.leg1_symbol))))self.order_mess.clear()self.order_mess.vt_symbol = self.leg2_symbolself.order_mess.bid_price = bar_base_priceself.order_mess.bid_volume = 100self.order_mess.settle_type = '2'self.order_mess.quote_type = '2'self.quote(BusinessType.XBOND, self.order_mess)self.write_log("合约2仓位:  %s" % (str(self.get_pos(self.leg2_symbol))))if close_diff > spread_down_sell:leg1_pos = self.get_pos(self.leg1_symbol)self.write_log("1卖2买,平仓,当前合约1价格:  %s" % (str(bar_trade_price)))self.write_log("1卖2买,平仓,当前合约2价格:  %s" % (str(bar_base_price)))if leg1_pos < 0:  # 当前空仓位,就平仓self.write_log("准备报单了,1卖2买,平仓")self.order_mess.clear()self.order_mess.vt_symbol = self.leg1_symbolself.order_mess.bid_price = bar_trade_priceself.order_mess.bid_volume =abs(self.get_pos(self.leg1_symbol))self.order_mess.settle_type = '2'self.order_mess.quote_type = '2'self.quote(BusinessType.XBOND, self.order_mess)self.write_log("合约1仓位:  %s" % (str(self.get_pos(self.leg1_symbol))))self.order_mess.clear()self.order_mess.vt_symbol = self.leg2_symbolself.order_mess.ask_price = bar_base_priceself.order_mess.ask_volume = abs(self.get_pos(self.leg2_symbol))self.order_mess.settle_type = '2'self.order_mess.quote_type = '2'self.quote(BusinessType.XBOND, self.order_mess)self.write_log("合约2仓位:  %s" % (str(self.get_pos(self.leg2_symbol))))#self.sell(BusinessType.XBOND, self.order_mess)self.put_event()

整个策略的交易逻辑就体现在上述代码里面了。

策略回测结果如图:

国开债-进出口到期收益率图示2022.02-2023.08

 

国开债-进出口收益率利差图示2022.02-2023.08

回测参数

品种:220205.BOND(22附息国开债05);220305.BOND(22附息进出口债05)
回测区间:2022年2月10日-2023年8月30日
起始资金:1000000
粒度:每天

策略参数

up_threshold = 0.8up_threshold_sell=0.6down_threshold = 0.2down_threshold_sell=0.45spread_length = 50

回测结果

统计指标

年化收益(%)

5.8582

总收益率(%)

9.5366

最大回撤(%)

-8.6538

期初资金

1000000

期末资金

1095366.35

总盈亏

95366.35

总成交笔数

323

买次数

卖次数

收益回撤比

1.1

夏普比率

0.13

收益概览

收益概览图示2022.02.10-2023.8.30

结果解析

2022-05-10至2022-05-23成交记录

操作记录

这部分是所有获取行情数据里面该有的对象:

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# add by gaolong.liu"""
基础数据对象
"""from dataclasses import dataclass, field
from datetime import datetime
from logging import INFOfrom base.constant import Direction, Exchange, Interval, Offset, Product, OptionType, OrderType, \StopOrderStatus, Side, BusinessType, QuoteStatus, QuotationType# ACTIVE_STATUSES = set([Status.SUBMITTING, Status.NOTTRADED, Status.PARTTRADED])
ACTIVE_STATUSES = set([QuoteStatus.NORMAL, QuoteStatus.NEW, QuoteStatus.TRADED])@dataclass
class BaseData:"""Any data object needs a gateway_name as sourceand should inherit base data."""gateway_name: str@dataclass
class MarketFuture():"""Tick data contains information about:* last trade in market* orderbook snapshot* intraday market statistics."""symbol: strexchange: Exchangedatetime: datetimename: str = ""volume: int = 0turnover: float = 0open_interest: float = 0last_price: float = 0last_volume: int = 0limit_up: float = 0limit_down: float = 0open_price: float = 0high_price: float = 0low_price: float = 0pre_close: float = 0bid_price_1: float = 0bid_price_2: float = 0bid_price_3: float = 0bid_price_4: float = 0bid_price_5: float = 0bid_price_6: float = 0bid_price_7: float = 0bid_price_8: float = 0bid_price_9: float = 0bid_price_10: float = 0ask_price_1: float = 0ask_price_2: float = 0ask_price_3: float = 0ask_price_4: float = 0ask_price_5: float = 0ask_price_6: float = 0ask_price_7: float = 0ask_price_8: float = 0ask_price_9: float = 0ask_price_10: float = 0bid_volume_1: int = 0bid_volume_2: int = 0bid_volume_3: int = 0bid_volume_4: int = 0bid_volume_5: int = 0bid_volume_6: int = 0bid_volume_7: int = 0bid_volume_8: int = 0bid_volume_9: int = 0bid_volume_10: int = 0ask_volume_1: int = 0ask_volume_2: int = 0ask_volume_3: int = 0ask_volume_4: int = 0ask_volume_5: int = 0ask_volume_6: int = 0ask_volume_7: int = 0ask_volume_8: int = 0ask_volume_9: int = 0ask_volume_10: int = 0@dataclass
class MarketLevelBond():swap_trade_volume: int = 0swap_entry_px: float = 0bond_yield_type: str = ""bond_yield: float = 0bond_entry_price: float = 0bond_settle_type: str = ""bond_quote_type: str = ""bond_delivery_type: str = ""bond_clear_method: str = ""bond_quote_id: str = ""bond_maker_six_code: str = ""bond_maker_trader_code: str = ""bond_mdEntryDate: str = ""bond_mdEntryTime: str = ""md_entry_size: int = 0@dataclass
class MarketBond():msg_type: str = ""market_indicator: str = ""book_type: str = ""book_type_sub: str = ""security_type: str = ""security_id: str = ""symbol: str = ""bond_code_val: str = ""market_depth: int = 0message_id: str = ""message_source: str = ""create_time_ms: str = ""create_time: str = ""transact_time: str = ""sender_comp_id: str = ""sender_sub_id: str = ""#行情类型(报价类型)quotation_type: QuotationType = None# 档位行情信息bid_1: MarketLevelBond = Noneask_1: MarketLevelBond = Nonebid_2: MarketLevelBond = Noneask_2: MarketLevelBond = Nonebid_3: MarketLevelBond = Noneask_3: MarketLevelBond = Nonebid_4: MarketLevelBond = Noneask_4: MarketLevelBond = Nonebid_5: MarketLevelBond = Noneask_5: MarketLevelBond = Nonebid_6: MarketLevelBond = Noneask_6: MarketLevelBond = Nonebid_7: MarketLevelBond = Noneask_7: MarketLevelBond = Nonebid_8: MarketLevelBond = Noneask_8: MarketLevelBond = Nonebid_9: MarketLevelBond = Noneask_9: MarketLevelBond = Nonebid_10: MarketLevelBond = Noneask_10: MarketLevelBond = None@dataclass
class TickData(BaseData):"""Tick data contains information about:* 通用字段* 债券部分字段* 期货、贵金属部分字典"""symbol: strexchange: Exchangename: str = ""datetime: datetime = Nonemarket_bond: MarketBond = Nonemarket_future: MarketFuture = Nonelocaltime: datetime = Nonedef __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"@dataclass
class BarData(BaseData):"""Candlestick bar data of a certain trading period."""symbol: strexchange: Exchangedatetime: datetimeinterval: Interval = Nonevolume: int = 0turnover: float = 0open_interest: float = 0# 开盘价open_price: float = 0# 最高价high_price: float = 0# 最低价low_price: float = 0# 收盘价close_price: float = 0# 收益率yield_rate: float = 0# 全价full_price: float = 0def __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"@dataclass
class FactorData(BaseData):"""Candlestick factor data of a certain trading period."""factor_schedule: strfactor_class: strdatetime: datetimefactor_value: str = None@dataclass
class TradeData(BaseData):"""Trade data contains information of a fill of an order. One ordercan have several trade fills."""# 债券代码symbol: str# 交易所exchange: Exchange# 委托单IDorderid: str# 成交单IDtradeid: str# 方向(期货)direction: Direction = None# 方向(债券)side: Side = None# 开平offset: Offset = Offset.NONE# 成交价格price: float = 0# 成交收益率yield_rate: float = 0# 成交量(手)volume: int = 0# 成交日期datetime: datetime = None# 面值(元)face_value: float = 1.0def __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"self.vt_orderid = f"{self.gateway_name}.{self.orderid}"self.vt_tradeid = f"{self.gateway_name}.{self.tradeid}"@dataclass
class StopOrder:vt_symbol: strdirection: Directionoffset: Offsetprice: floatvolume: intstop_orderid: strstrategy_name: strdatetime: datetimelock: bool = Falsenet: bool = Falsevt_orderids: list = field(default_factory=list)status: StopOrderStatus = StopOrderStatus.WAITING@dataclass
class PositionData(BaseData):"""Positon data is used for tracking each individual position holding."""symbol: strexchange: Exchangedirection: Directionvolume: int = 0frozen: float = 0price: float = 0pnl: float = 0yd_volume: int = 0def __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"self.vt_positionid = f"{self.vt_symbol}.{self.direction.value}"@dataclass
class AccountData(BaseData):"""Account data contains information about balance, frozen andavailable."""accountid: strbalance: float = 0frozen: float = 0def __post_init__(self):""""""self.available = self.balance - self.frozenself.vt_accountid = f"{self.gateway_name}.{self.accountid}"@dataclass
class LogData(BaseData):"""Log data is used for recording log messages on GUI or in log files."""msg: strlevel: int = INFOdef __post_init__(self):""""""self.time = datetime.now()@dataclass
class ContractData(BaseData):"""Contract data contains basic information about each contract traded."""symbol: strexchange: Exchangename: strproduct: Productsize: floatpricetick: floatmin_volume: int = 1           # minimum trading volume of the contractstop_supported: bool = False    # whether server supports stop ordernet_position: bool = False      # whether gateway uses net position volumehistory_data: bool = False      # whether gateway provides bar history dataoption_strike: float = 0option_underlying: str = ""     # vt_symbol of underlying contractoption_type: OptionType = Noneoption_listed: datetime = Noneoption_expiry: datetime = Noneoption_portfolio: str = ""option_index: str = ""          # for identifying options with same strike pricedef __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"@dataclass
class OrderData(BaseData):"""Order data contains information for tracking lastest statusof a specific order."""symbol: strexchange: Exchangeorderid: strordertype: BusinessTypedata: BaseDatatradeid: str = ""time: str = ""datetime: datetime = Noneupdatetime: str = ""status: QuoteStatus = QuoteStatus.NEWorderrejectreason: str = ""SysLocalOrderID: str = ""# 触发委托的场景序号(bar\tick\factor)scene_sn: str = ""def __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"self.vt_orderid = f"{self.gateway_name}.{self.orderid}"def is_active(self) -> bool:"""Check if the order is active."""if self.status in ACTIVE_STATUSES:return Trueelse:return Falsedef create_cancel_request(self) -> "CancelRequest":"""Create cancel request object from order."""req = CancelRequest(orderid=self.orderid, symbol=self.symbol, exchange=self.exchange)return reqdef addTradeQty(self,tradeQty:int=0, lastQty:int=0, side:Side=None):self.data.update_last_qty(tradeQty,lastQty,side)def getTradeQty(self, side:Side=None):return self.data.get_last_qty(side)def isTraded_All(self):return self.data.isTraded_All()@dataclass
class QuoteData(BaseData):"""Quote data contains information for tracking lastest statusof a specific quote."""symbol: strexchange: Exchangequoteid: strbid_price: float = 0.0bid_volume: int = 0ask_price: float = 0.0ask_volume: int = 0bid_offset: Offset = Offset.NONEask_offset: Offset = Offset.NONEstatus: QuoteStatus = QuoteStatus.NEWdatetime: datetime = Nonereference: str = ""def __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"self.vt_quoteid = f"{self.gateway_name}.{self.quoteid}"def is_active(self) -> bool:"""Check if the quote is active."""return self.status in ACTIVE_STATUSESdef create_cancel_request(self) -> "CancelRequest":"""Create cancel request object from quote."""req = CancelRequest(orderid=self.quoteid, symbol=self.symbol, exchange=self.exchange)return req@dataclass
class SubscribeRequest:"""Request sending to specific gateway for subscribing tick data update."""symbol: strexchange: Exchangedef __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"@dataclass
class CancelRequest:"""Request sending to specific gateway for canceling an existing order."""orderid: strsymbol: strexchange: Exchangedef __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"@dataclass
class QuoteRequest:"""Request sending to specific gateway for creating a new quote."""vt_symbol: str = ""bid_yield: float = 0bid_price: float = 0bid_volume: int = 0ask_yield: float = 0ask_price: float = 0ask_volume: int = 0settle_type: str = ""valid_unit_time: str = ""clear_method: str = ""delivery_type: str = ""# 报价方式,字典:1-集中匹配,2-连续匹配quote_type: str = ""# 订单类型,字典:2-限价订单,b-FAK(点击成交)order_type: str = ""real_time_flag: str = ""direction: Direction = Noneoffset: Offset = Offset.NONEreference: str = ""# 当前行情ID(现券做市FAK点击时填写)md_quote_id: str = ""# 当前行情的业务发生时间transact_time: str = ""# 面值(元)face_value: float = 0.0# def __post_init__(self):#     """"""#     self.vt_symbol = f"{self.symbol}.{self.exchange.value}"def clear(self):self.vt_symbol: str = ""self.bid_yield: float = 0self.bid_price: float = 0self.bid_volume: int = 0self.ask_yield: float = 0self.ask_price: float = 0self.ask_volume: int = 0self.settle_type: str = ""self.valid_unit_time: str = ""self.clear_method: str = ""self.delivery_type: str = ""self.quote_type: str = ""self.order_type: str = ""self.real_time_flag: str = ""self.direction: Direction = Noneself.offset: Offset = Offset.NONEself.reference: str = ""self.md_quote_id = ""self.transact_time = ""# def create_quote_data(self, quoteid: str, gateway_name: str) -> QuoteData:#     """#     Create quote data from request.#     """#     quote = QuoteData(#         symbol=self.symbol,#         exchange=self.exchange,#         quoteid=quoteid,#         bid_price=self.bid_price,#         bid_volume=self.bid_volume,#         ask_price=self.ask_price,#         ask_volume=self.ask_volume,#         bid_offset=self.bid_offset,#         ask_offset=self.ask_offset,#         reference=self.reference,#         gateway_name=gateway_name,#     )#     return quote@dataclass
class BarOverview:"""Overview of bar data stored in database."""symbol: str = ""exchange: str = ""interval: str = ""count: int = 0start: datetime = Noneend: datetime = None@dataclass
class QuoteBondMaker(BaseData):"""现券做市报价"""orderid: strsymbol: stryield_bid: float = 0yield_offer: float = 0order_qty_bid: int = 0order_qty_offer: int = 0price_bid: float = 0price_offer: float = 0strategy_id: str = ""invest_group_name: str = ""trader_code: str = ""valid_unit_time: str = ""clear_method: str = ""settle_type: str = ""delivery_type: str = ""# 订单类型,字典:2-限价订单,b-FAK(点击成交)order_type: str = ""run_id: str = ""run_unit_id: str = ""exchange: Exchange = Exchange.NONElast_qty_bid: int = 0last_qty_offer: int = 0# 当前行情ID(现券做市FAK点击时填写)md_quote_id: str = ""# 对应行情的业务发生时间transact_time: str = ""# 面值(元)face_value: float = 100.0def __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"self.vt_orderid = f"{self.gateway_name}.{self.orderid}"# 更新已成交量def update_last_qty(self, trade_qty: int = 0, last_qty: int = 0, side: Side = None):# 依据成交量计算总成交量if trade_qty != 0:if side == Side.DOUBLE_BUY or side == Side.SINGLE_BUY:self.last_qty_bid += trade_qtyelif side == Side.DOUBLE_SELL or side == Side.SINGLE_SELL:self.last_qty_offer += trade_qty# 更新总成交量为已成交量if last_qty != 0:if side == Side.DOUBLE_BUY or side == Side.SINGLE_BUY:self.last_qty_bid = last_qtyelif side == Side.DOUBLE_SELL or side == Side.SINGLE_SELL:self.last_qty_offer = last_qty# 获得成交量def get_last_qty(self, side: Side = None):if side == Side.DOUBLE_BUY or side == Side.SINGLE_BUY:return self.last_qty_bidelif side == Side.DOUBLE_SELL or side == Side.SINGLE_SELL:return self.last_qty_offerdef isTraded_All(self):return self.last_qty_offer == self.order_qty_offer and self.last_qty_bid == self.order_qty_biddef toJson(self):data = {"api_id": self.orderid,"symbol": self.symbol,"exchange": self.exchange.value,"vt_symbol": self.vt_symbol,"yield_bid": self.yield_bid,"yield_offer": self.yield_offer,"order_qty_bid": self.order_qty_bid,"order_qty_offer": self.order_qty_offer,"price_bid": self.price_bid,"price_offer": self.price_offer,"strategy_id": self.strategy_id,"invest_group_name": self.invest_group_name,"trader_code": self.trader_code,"valid_unit_time": self.valid_unit_time,"clear_method": self.clear_method,"settle_type": self.settle_type,"order_type": self.order_type,"run_id": self.run_id,"run_unit_id": self.run_unit_id,"delivery_type": self.delivery_type,"md_quote_id": self.md_quote_id,"transact_time": self.transact_time,"face_value": self.face_value}return data@dataclass
class QuoteXBond(BaseData):"""现券匿名报价"""orderid: strsymbol: strside: Side = Noneyield_rate: float = 0order_qty: int = 0price: float = 0strategy_id: str = ""invest_group_name: str = ""trader_code: str = ""settle_type: str = ""# 报价方式,字典:1-集中匹配,2-连续匹配match_type: str = ""# 订单类型,字典:2-限价订单,b-FAK(点击成交)order_type: str = ""run_id: str = ""run_unit_id: str = ""side_id: str = ""exchange: Exchange = Exchange.NONElast_qty: int = 0# 面值(元)face_value: float = 100.0def __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"self.vt_orderid = f"{self.gateway_name}.{self.orderid}"# 更新已成交量def update_last_qty(self, trade_qty: int = 0, last_qty: int = 0, side: Side = None):# 依据成交量计算总成交量if trade_qty != 0:self.last_qty += trade_qty# 更新总成交量为已成交量if last_qty != 0:self.last_qty = last_qty# 获得成交量def get_last_qty(self, side: Side = None):return self.last_qtydef isTraded_All(self):return self.last_qty == self.order_qtydef toJson(self):data = {"api_id": self.orderid,"symbol": self.symbol,"exchange": self.exchange.value,"vt_symbol": self.vt_symbol,"side": self.side.value,"yield_rate": self.yield_rate,"order_qty": self.order_qty,"price": self.price,"strategy_id": self.strategy_id,"invest_group_name": self.invest_group_name,"trader_code": self.trader_code,"side_id": self.side_id,"settle_type": self.settle_type,"run_id": self.run_id,"run_unit_id": self.run_unit_id,"match_type": self.match_type,"order_type": self.order_type,"face_value": self.face_value}return data@dataclass
class QuoteXSwap(BaseData):"""利率互换匿名报价"""orderid: strsymbol: strside: Side = Noneorder_qty: int = 0price: float = 0strategy_id: str = ""invest_group_name: str = ""trader_code: str = ""valid_unit_time: str = ""# 报价方式,字典:1-集中匹配,2-连续匹配match_type: str = ""real_time_flag: str = ""run_id: str = ""run_unit_id: str = ""side_id: str = ""expire_time: str = ""exchange: Exchange = Exchange.NONElast_qty: int = 0def __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"self.vt_orderid = f"{self.gateway_name}.{self.orderid}"# 更新已成交量def update_last_qty(self, trade_qty:int=0, last_qty:int=0, side:Side=None):# 依据成交量计算总成交量if trade_qty != 0:self.last_qty += trade_qty# 更新总成交量为已成交量if last_qty != 0:self.last_qty = last_qty# 获得成交量def get_last_qty(self, side: Side = None):return self.last_qtydef isTraded_All(self):return self.last_qty == self.order_qtydef toJson(self):data = {"api_id": self.orderid,"symbol": self.symbol,"exchange": self.exchange.value,"vt_symbol": self.vt_symbol,"real_time_flag": self.real_time_flag,"side": self.side.value,"order_qty": self.order_qty,"price": self.price,"expire_time": self.expire_time,"strategy_id": self.strategy_id,"invest_group_name": self.invest_group_name,"trader_code": self.trader_code,"side_id": self.side_id,"valid_unit_time": self.valid_unit_time,"run_id": self.run_id,"run_unit_id": self.run_unit_id,"match_type": self.match_type}return data@dataclass
class QuoteFuture(BaseData):"""期货报价"""orderid: strsymbol: strtype: OrderType = OrderType.LIMITdirection: Direction = Noneoffset: Offset = Offset.NONEprice: float = 0volume: int = 0traded: int = 0exchange: Exchange = Exchange.NONEdef __post_init__(self):""""""self.vt_symbol = f"{self.symbol}.{self.exchange.value}"self.vt_orderid = f"{self.gateway_name}.{self.orderid}"# 更新已成交量def update_last_qty(self, trade_qty:int=0, last_qty:int=0, side:Side=None):# 依据成交量计算总成交量if trade_qty != 0:self.traded += trade_qty# 更新总成交量为已成交量if last_qty !=0:self.traded = last_qty# 获得成交量def get_last_qty(self, side: Side = None):return self.tradeddef isTraded_All(self):return self.traded == self.volumedef toJson(self):data = {"type": self.type.value,"direction": self.direction.value,"offset": self.offset.value,"price": self.price,"volume": self.volume,"traded": self.traded}return data@dataclass
class BondInfo:"""债券基本信息"""# 债券代码security_id: str# 债券名称name: str# 债券类型bond_type: str# 面值(元)face_value: float# 债券起息日dated_date: datetime# 到期兑付日maturity_date: datetime# 付息频率(0-半年,1-年,2-到期,3-月,4-季)frequency: str# 息票类型(0-固定,1-浮动,2-零息,3-贴现)coupon_rate_type: str# 票面利率coupon: float# 计息基准(0-实际/实际,1-实际/360,2-30/360,3-实际/365,5-实际/365F)day_count: str# 到期期限term_to_maturity: str = None

这篇关于基于期限利差策略的债券回测分析——kingstar因子投研平台的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/583308

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

如何解决线上平台抽佣高 线下门店客流少的痛点!

目前,许多传统零售店铺正遭遇客源下降的难题。尽管广告推广能带来一定的客流,但其费用昂贵。鉴于此,众多零售商纷纷选择加入像美团、饿了么和抖音这样的大型在线平台,但这些平台的高佣金率导致了利润的大幅缩水。在这样的市场环境下,商家之间的合作网络逐渐成为一种有效的解决方案,通过资源和客户基础的共享,实现共同的利益增长。 以最近在上海兴起的一个跨行业合作平台为例,该平台融合了环保消费积分系统,在短

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57