VeighNa量化社区
你的开源社区量化交易平台
Member
avatar
加入于:
帖子: 141
声望: 57

首选修改vnpy\trader,object.py里面的ContractData

@dataclass
class ContractData(BaseData):
    """
    Contract data contains basic information about each contract traded.
    """
    price_tick: float = 0                               #最小价格变动

    margin_ratio : float = 0                            #保证金率
    max_order_volume : float = 0                        #限价单最大单次委托量
    open_commission_ratio : float = 0                   #开仓手续费率
    open_commission : float = 0                         #开仓手续费
    close_commission_ratio : float = 0                  #平仓手续费率
    close_commission : float = 0                        #平仓手续费  
    close_commission_today_ratio : float = 0            #平今手续费率
    close_commission_today : float = 0                  #平今手续费

CtpGateway里面加上

import shelve
#------------------------------------------------------------------------------------
def remain_alpha(convert_contract:str) -> str:
    """
    返回vt_symbol或者symbol的字母字符串
    """
    if "." in convert_contract:
        convert_contract = extract_vt_symbol(convert_contract)[0]
    symbol_mark = "".join(list(filter(str.isalpha,convert_contract)))
    return symbol_mark
#-------------------------------------------------------------------------------------------------
class CtpGateway(BaseGateway):
    #-------------------------------------------------------------------------------------------------
    def query_commission(self):
        """查询手续费数据"""
        self.td_api.query_commission()
    #-------------------------------------------------------------------------------------------------
    def save_commission(self):
        """保存手续费数据"""
        self.td_api.save_commission()
    #-------------------------------------------------------------------------------------------------
    def query_margin_ratio(self):
        """查询保证金率数据"""
        self.td_api.query_margin_ratio()
    #-------------------------------------------------------------------------------------------------
    def save_margin_ratio(self):
        """保存保证金率数据"""
        self.td_api.save_margin_ratio()
    #-------------------------------------------------------------------------------------------------
    def close(self):
        """"""
        #关闭ctp api前保存手续费,保证金率数据到硬盘
        self.save_commission()
        self.save_margin_ratio()
        self.td_api.close()
        self.md_api.close()
        self.query_functions = [self.query_account, self.query_position,self.query_commission,self.query_margin_ratio]

tdapi里面加上

class CtpTdApi(TdApi):
    """"""

    def __init__(self, gateway):
        self.commission_file_name = 'commission_data'
        self.commission_file_path = get_folder_path(self.commission_file_name)        
        self.commission_req = {}        #手续费查询字典   
        self.commission_data = {}       #手续费字典
        self.margin_ratio_file_name = 'margin_ratio_data'
        self.margin_ratio_file_path = get_folder_path(self.margin_ratio_file_name)        
        self.margin_ratio_req = {}        #保证金率查询字典   
        self.margin_ratio_data = {}       #保证金率字典 
        #读取硬盘存储手续费数据,保证金率数据
        self.load_commission() 
        self.load_margin_ratio()
    def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool): 
        """合约查询回报"""        
        contract = ContractData(
            symbol=data["InstrumentID"],
            exchange=EXCHANGE_CTP2VT[data["ExchangeID"]],
            name=data["InstrumentName"],
            product=PRODUCT_CTP2VT.get(data["ProductClass"], None),
            size=data["VolumeMultiple"],
            price_tick=data["PriceTick"],                    #合约最小价格变动
            max_order_volume=data["MaxLimitOrderVolume"],  #限价单次最大委托量
            gateway_name=self.gateway_name)
        symbol = contract.symbol
        symbol_alpha = remain_alpha(symbol)
        #手续费数据合并到contract
        if symbol in list(self.commission_data):
            contract.open_commission_ratio=self.commission_data[symbol]["OpenRatioByMoney"]                  #开仓手续费率
            contract.open_commission=self.commission_data[symbol]["OpenRatioByVolume"]                       #开仓手续费
            contract.close_commission_ratio=self.commission_data[symbol]["CloseRatioByMoney"]                #平仓手续费率
            contract.close_commission=self.commission_data[symbol]["CloseRatioByVolume"]                     #平仓手续费
            contract.close_commission_today_ratio=self.commission_data[symbol]["CloseTodayRatioByMoney"]     #平今手续费率
            contract.close_commission_today=self.commission_data[symbol]["CloseTodayRatioByVolume"]          #平今手续费                
        elif symbol_alpha in list(self.commission_data):
            contract.open_commission_ratio=self.commission_data[symbol_alpha]["OpenRatioByMoney"]      #开仓手续费率
            contract.open_commission=self.commission_data[symbol_alpha]["OpenRatioByVolume"]        #开仓手续费
            contract.close_commission_ratio=self.commission_data[symbol_alpha]["CloseRatioByMoney"]    #平仓手续费率
            contract.close_commission=self.commission_data[symbol_alpha]["CloseRatioByVolume"]          #平仓手续费
            contract.close_commission_today_ratio=self.commission_data[symbol_alpha]["CloseTodayRatioByMoney"]#平今手续费率
            contract.close_commission_today=self.commission_data[symbol_alpha]["CloseTodayRatioByVolume"]   #平今手续费
        if symbol in  list(self.margin_ratio_data):                
            contract.margin_ratio = self.margin_ratio_data[symbol]["LongMarginRatioByMoney"]       #合约保证金比率
    #-------------------------------------------------------------------------------------------------
    def onRspQryInstrumentCommissionRate(self, data: dict, error: dict, reqid: int, last: bool):
        """查询合约手续费率"""
        symbol = data.get('InstrumentID',None)
        if symbol:
            self.commission_data[symbol] = data
    #-------------------------------------------------------------------------------------------------
    def onRspQryInstrumentMarginRate(self, data: dict, error: dict, reqid: int, last: bool):
        """查询保证金率"""
        symbol = data.get('InstrumentID',None)
        if symbol:
            self.margin_ratio_data[symbol] = data
    #-------------------------------------------------------------------------------------------------
    def load_commission(self):
        """从硬盘读取手续费数据"""
        f = shelve.open(f"{self.commission_file_path}\\commission_data.vt")
        if 'data' in f:
            d = f['data']
            for key, value in list(d.items()):
                self.commission_data[key] = value
        f.close()
    #-------------------------------------------------------------------------------------------------
    def save_commission(self):
        """保存手续费数据到硬盘"""
        f = shelve.open(f"{self.commission_file_path}\\commission_data.vt")
        f['data'] = self.commission_data
        f.close()         
    #-------------------------------------------------------------------------------------------------
    def load_margin_ratio(self):
        """从硬盘读取保证金率数据"""
        f = shelve.open(f"{self.margin_ratio_file_path}\\margin_ratio_data.vt")
        if 'data' in f:
            d = f['data']
            for key, value in list(d.items()):
                self.margin_ratio_data[key] = value
        f.close()
    #-------------------------------------------------------------------------------------------------
    def save_margin_ratio(self):
        """保存保证金率数据到硬盘"""
        f = shelve.open(f"{self.margin_ratio_file_path}\\margin_ratio_data.vt")
        f['data'] = self.margin_ratio_data
        f.close() 
    #-------------------------------------------------------------------------------------------------
    #commission_vt_symbol,margin_ratio_vt_symbol都是全市场合约列表,需要自己维护
    #我用的合约连接交易所符号是'_',用'.'自己替换
    #-------------------------------------------------------------------------------------------------
    def query_commission(self):
        #查询手续费率
        if len(commission_vt_symbol) > 0:
            symbol = commission_vt_symbol[0].split('_')[0]
            #手续费率查询字典
            self.commission_req['BrokerID'] = self.brokerid
            self.commission_req['InvestorID'] = self.userid
            self.commission_req['InstrumentID'] = symbol
            self.reqid += 1 
            #请求查询手续费率
            self.reqQryInstrumentCommissionRate(self.commission_req,self.reqid)  
            commission_vt_symbol.pop(0)
    def query_margin_ratio(self):
        if len(margin_ratio_vt_symbol) > 0:
            symbol = margin_ratio_vt_symbol[0].split('_')[0]
            #保证金率查询字典
            self.margin_ratio_req['BrokerID'] = self.brokerid
            self.margin_ratio_req['InvestorID'] = self.userid
            self.margin_ratio_req['InstrumentID'] = symbol
            self.margin_ratio_req['HedgeFlag'] = THOST_FTDC_HF_Speculation
            self.reqid += 1 
            #请求查询保证金率
            self.reqQryInstrumentMarginRate(self.margin_ratio_req,self.reqid)  
            margin_ratio_vt_symbol.pop(0)

trader\ui,widget.py里面修改

class ContractManager(QtWidgets.QWidget):
    """
    Query contract data available to trade in system.
    """

    headers = {
        "vt_symbol": "本地代码",
        "symbol": "代码",
        "exchange": "交易所",
        "name": "名称",
        "product": "合约分类",
        "size": "合约乘数",
        "price_tick": "价格跳动",
        "min_volume": "最小委托量",
        "margin_ratio": "保证金率",
        "open_commission_ratio": "开仓手续费率",
        "open_commission": "开仓手续费",
        "close_commission_ratio": "平仓手续费率",
        "close_commission": "平仓手续费",
        "close_commission_today_ratio": "平今手续费率",
        "close_commission_today": "平今手续费",
        "gateway_name": "交易接口",
    }
Member
avatar
加入于:
帖子: 141
声望: 57

这样就可以在软件界面帮助/查询合约里面查看手续费率等参数了,想在策略里面调用可以用main_engine.get_contract(vt_symbol)函数

Member
avatar
加入于:
帖子: 141
声望: 57

无界面交易可以在vnpy\trader,engine.py里面加上

class MainEngine:
    """
    Acts as the core of VN Trader.
    """
    #--------------------------------------------------------------------------------------------------
    def save_costs(self):
        """保存接口合约手续费,保证金率参数"""
        for gateway in self.gateways.values():
            gateway.save_commission()
            gateway.save_margin_ratio()

然后在无界面程序里面加上

run_child_process():
    while True:
        #在策略启动代码的后面加上,不然连不上交易接口
        #每5分钟保存一次手续费数据,保证金率数据
        main_engine.save_costs() 
        sleep(300)
Member
avatar
加入于:
帖子: 1
声望: 0

楼主请问下,我通过接口reqQryInstrumentCommissionRate查询手续费返回的成交量都是0呢,我的代码如下:

def onRspQryInstrumentCommissionRate(self, data: dict, error: dict, reqid: int, last: bool):
    """查询合约手续费率"""
    symbol = data.get('InstrumentID', None)
    if symbol:
        self.commission_data[symbol] = data
        self.gateway.write_log("%s手续费:%s"% (symbol, data))


def query_commission(self, symbol):
    self.commission_req['BrokerID'] = self.brokerid
    self.commission_req['InvestorID'] = self.userid
    self.commission_req['InstrumentID'] = symbol
    self.reqid += 1
    # 请求查询手续费率
    self.reqQryInstrumentCommissionRate(self.commission_req, self.reqid)

结果如下:

{
'InstrumentID': 'hc',
'InvestorRange': '1',
'BrokerID': '9999',
'InvestorID': '00000000',
'OpenRatioByMoney': 0.0001,
'OpenRatioByVolume': 0.0,
'CloseRatioByMoney': 0.0001,
'CloseRatioByVolume': 0.0,
'CloseTodayRatioByMoney': 0.0001,
'CloseTodayRatioByVolume': 0.0,
'ExchangeID': '',
'BizType': '\x00',
'InvestUnitID': ''
}

InstrumentID 我填写的是hc1910,怎么返回的是hc?大佬们帮忙看下哈

Member
avatar
加入于:
帖子: 141
声望: 57

@ShineWell 手续费都相同返回标的的代码标识比如hc,这里我也处理了。手续费跟hc的不同就会返回具体合约代码比如hc2009

Member
avatar
加入于:
帖子: 1
声望: 0

上弦之月 wrote:

首选修改vnpy\trader,object.py里面的ContractData

@dataclass
class ContractData(BaseData):
    """
    Contract data contains basic information about each contract traded.
    """
    price_tick: float = 0                               #最小价格变动

    margin_ratio : float = 0                            #保证金率
    max_order_volume : float = 0                        #限价单最大单次委托量
    open_commission_ratio : float = 0                   #开仓手续费率
    open_commission : float = 0                         #开仓手续费
    close_commission_ratio : float = 0                  #平仓手续费率
    close_commission : float = 0                        #平仓手续费  
    close_commission_today_ratio : float = 0            #平今手续费率
    close_commission_today : float = 0                  #平今手续费

CtpGateway里面加上

import shelve
#-------------------------------------------------------------------------------------------------
class CtpGateway(BaseGateway):
    #-------------------------------------------------------------------------------------------------
    def query_commission(self):
        """查询手续费数据"""
        self.td_api.query_commission()
    #-------------------------------------------------------------------------------------------------
    def save_commission(self):
        """保存手续费数据"""
        self.td_api.save_commission()
    #-------------------------------------------------------------------------------------------------
    def query_margin_ratio(self):
        """查询保证金率数据"""
        self.td_api.query_margin_ratio()
    #-------------------------------------------------------------------------------------------------
    def save_margin_ratio(self):
        """保存保证金率数据"""
        self.td_api.save_margin_ratio()
    #-------------------------------------------------------------------------------------------------
    def close(self):
        """"""
        #关闭ctp api前保存手续费,保证金率数据到硬盘
        self.save_commission()
        self.save_margin_ratio()
        self.td_api.close()
        self.md_api.close()
        self.query_functions = [self.query_account, self.query_position,self.query_commission,self.query_margin_ratio]

tdapi里面加上

class CtpTdApi(TdApi):
    """"""

    def __init__(self, gateway):
        self.commission_file_name = 'commission_data'
        self.commission_file_path = get_folder_path(self.commission_file_name)        
        self.commission_req = {}        #手续费查询字典   
        self.commission_data = {}       #手续费字典
        self.margin_ratio_file_name = 'margin_ratio_data'
        self.margin_ratio_file_path = get_folder_path(self.margin_ratio_file_name)        
        self.margin_ratio_req = {}        #保证金率查询字典   
        self.margin_ratio_data = {}       #保证金率字典 
    def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool): 
        #读取硬盘存储手续费数据,保证金率数据
        self.load_commission() 
        self.load_margin_ratio()
        """合约查询回报"""        
        contract = ContractData(
            symbol=data["InstrumentID"],
            exchange=EXCHANGE_CTP2VT[data["ExchangeID"]],
            name=data["InstrumentName"],
            product=PRODUCT_CTP2VT.get(data["ProductClass"], None),
            size=data["VolumeMultiple"],
            price_tick=data["PriceTick"],                    #合约最小价格变动
            max_order_volume=data["MaxLimitOrderVolume"],  #限价单次最大委托量
            gateway_name=self.gateway_name)
        #手续费数据合并到contract
        for X in self.commission_data.keys():
            if X == contract.symbol:
                contract.open_commission_ratio=self.commission_data[X]['OpenRatioByMoney']                  #开仓手续费率
                contract.open_commission=self.commission_data[X]['OpenRatioByVolume']                       #开仓手续费
                contract.close_commission_ratio=self.commission_data[X]['CloseRatioByMoney']                #平仓手续费率
                contract.close_commission=self.commission_data[X]['CloseRatioByVolume']                     #平仓手续费
                contract.close_commission_today_ratio=self.commission_data[X]['CloseTodayRatioByMoney']     #平今手续费率
                contract.close_commission_today=self.commission_data[X]['CloseTodayRatioByVolume']          #平今手续费
            elif contract.symbol[:2] in X:
                contract.open_commission_ratio=self.commission_data[X]['OpenRatioByMoney']                  #开仓手续费率
                contract.open_commission=self.commission_data[X]['OpenRatioByVolume']                       #开仓手续费
                contract.close_commission_ratio=self.commission_data[X]['CloseRatioByMoney']                #平仓手续费率
                contract.close_commission=self.commission_data[X]['CloseRatioByVolume']                     #平仓手续费
                contract.close_commission_today_ratio=self.commission_data[X]['CloseTodayRatioByMoney']     #平今手续费率
                contract.close_commission_today=self.commission_data[X]['CloseTodayRatioByVolume']          #平今手续费  
            elif contract.symbol[:1] in X:
                contract.open_commission_ratio=self.commission_data[X]['OpenRatioByMoney']                  
                contract.open_commission=self.commission_data[X]['OpenRatioByVolume']                       
                contract.close_commission_ratio=self.commission_data[X]['CloseRatioByMoney']                
                contract.close_commission=self.commission_data[X]['CloseRatioByVolume']                     
                contract.close_commission_today_ratio=self.commission_data[X]['CloseTodayRatioByMoney']     
                contract.close_commission_today=self.commission_data[X]['CloseTodayRatioByVolume']  
        for Y in self.margin_ratio_data.keys():
            if Y == contract.symbol:
                contract.margin_ratio = self.margin_ratio_data[Y]['LongMarginRatioByMoney']                 #合约保证金比率
    #-------------------------------------------------------------------------------------------------
    def onRspQryInstrumentCommissionRate(self, data: dict, error: dict, reqid: int, last: bool):
        """查询合约手续费率"""
        symbol = data.get('InstrumentID',None)
        if symbol:
            self.commission_data[symbol] = data
    #-------------------------------------------------------------------------------------------------
    def onRspQryInstrumentMarginRate(self, data: dict, error: dict, reqid: int, last: bool):
        """查询保证金率"""
        symbol = data.get('InstrumentID',None)
        if symbol:
            self.margin_ratio_data[symbol] = data
    #-------------------------------------------------------------------------------------------------
    def load_commission(self):
        """从硬盘读取手续费数据"""
        f = shelve.open(f"{self.commission_file_path}\\commission_data.vt")
        if 'data' in f:
            d = f['data']
            for key, value in list(d.items()):
                self.commission_data[key] = value
        f.close()
    #-------------------------------------------------------------------------------------------------
    def save_commission(self):
        """保存手续费数据到硬盘"""
        f = shelve.open(f"{self.commission_file_path}\\commission_data.vt")
        f['data'] = self.commission_data
        f.close()         
    #-------------------------------------------------------------------------------------------------
    def load_margin_ratio(self):
        """从硬盘读取保证金率数据"""
        f = shelve.open(f"{self.margin_ratio_file_path}\\margin_ratio_data.vt")
        if 'data' in f:
            d = f['data']
            for key, value in list(d.items()):
                self.margin_ratio_data[key] = value
        f.close()
    #-------------------------------------------------------------------------------------------------
    def save_margin_ratio(self):
        """保存保证金率数据到硬盘"""
        f = shelve.open(f"{self.margin_ratio_file_path}\\margin_ratio_data.vt")
        f['data'] = self.margin_ratio_data
        f.close() 
    #-------------------------------------------------------------------------------------------------
    #commission_vt_symbol,margin_ratio_vt_symbol都是全市场合约列表,需要自己维护
    #我用的合约连接交易所符号是'_',用'.'自己替换
    #-------------------------------------------------------------------------------------------------
    def query_commission(self):
        #查询手续费率
        if len(commission_vt_symbol) > 0:
            symbol = commission_vt_symbol[0].split('_')[0]
            #手续费率查询字典
            self.commission_req['BrokerID'] = self.brokerid
            self.commission_req['InvestorID'] = self.userid
            self.commission_req['InstrumentID'] = symbol
            self.reqid += 1 
            #请求查询手续费率
            self.reqQryInstrumentCommissionRate(self.commission_req,self.reqid)  
            commission_vt_symbol.pop(0)
    def query_margin_ratio(self):
        if len(margin_ratio_vt_symbol) > 0:
            symbol = margin_ratio_vt_symbol[0].split('_')[0]
            #保证金率查询字典
            self.margin_ratio_req['BrokerID'] = self.brokerid
            self.margin_ratio_req['InvestorID'] = self.userid
            self.margin_ratio_req['InstrumentID'] = symbol
            self.margin_ratio_req['HedgeFlag'] = THOST_FTDC_HF_Speculation
            self.reqid += 1 
            #请求查询保证金率
            self.reqQryInstrumentMarginRate(self.margin_ratio_req,self.reqid)  
            margin_ratio_vt_symbol.pop(0)

trader\ui,widget.py里面修改

class ContractManager(QtWidgets.QWidget):
    """
    Query contract data available to trade in system.
    """

    headers = {
        "vt_symbol": "本地代码",
        "symbol": "代码",
        "exchange": "交易所",
        "name": "名称",
        "product": "合约分类",
        "size": "合约乘数",
        "price_tick": "价格跳动",
        "min_volume": "最小委托量",
        "margin_ratio": "保证金率",
        "open_commission_ratio": "开仓手续费率",
        "open_commission": "开仓手续费",
        "close_commission_ratio": "平仓手续费率",
        "close_commission": "平仓手续费",
        "close_commission_today_ratio": "平今手续费率",
        "close_commission_today": "平今手续费",
        "gateway_name": "交易接口",
    }

大神,请教下,这个窗口的数据怎么保存到csv呢,好像没有右键保存到 CSV 功能

Member
avatar
加入于:
帖子: 141
声望: 57

@liaura 数据都保存在本地,直接引用就行

Member
avatar
加入于:
帖子: 9
声望: 0

大神你好,按照你的步骤操作之后,vn station打不开了,请问适用吗?
我的系统是win10,只有vnstudio一个python安装环境,版本是最新的2.06

Member
avatar
加入于:
帖子: 419
声望: 170

上弦之月,你好,按照你的步骤操作之后,vn station也打不开了,无奈又把修改后的文件又改回去,请问问题可能出在哪?
我的系统是win10,版本是最新的2.1.3.1

Member
avatar
加入于:
帖子: 141
声望: 57

@pilotao @hxxjava
commission_vt_symbol,margin_ratio_vt_symbol都是全市场合约列表,需要自己维护
不建议新手折腾这个

Member
avatar
加入于:
帖子: 16
声望: 0

description
请问直接在合约查询里查不到吗

Member
加入于:
帖子: 132
声望: 0

self.query_functions = [self.query_account, self.query_position,self.query_commission,self.query_margin_ratio]
ctp接口都关闭了,还需要更改定时器函数列表(self.query_functions)吗? 关闭ctp接口了,也不可能通过self.query_margin_ratio查询到保证金了吧!

Member
加入于:
帖子: 132
声望: 0
def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool): 
    #读取硬盘存储手续费数据,保证金率数据
    self.load_commission() 
    self.load_margin_ratio()

因为请求查询合约响应(onRspQryInstrument)函数会被调用很多次,导致load_commission() 和load_margin_ratio()被多次调用,把这两个函数调用放在
class CtpTdApi的init()方法中效果要好一点

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】