# joinquant_trader_miniqmt **Repository Path**: sevenx4/joinquant_trader_miniqmt ## Basic Information - **Project Name**: joinquant_trader_miniqmt - **Description**: 聚宽策略交易miniqmt - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 7 - **Created**: 2025-10-15 - **Last Updated**: 2025-10-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # joinquant_trader_miniqmt #### 介绍 joinquant_trader_miniqmt是一个聚宽交易信号发送到服务器在读取服务器交易信号的交易系统 QuantTrader MiniQMT 是一个专为聚宽(JoinQuant)用户设计的高效交易信号传递系统。 它的主要功能是将本地开发和生成的交易信号发送到远程服务器,并在接收到服务器返回的交易信号后进行相应处理。 这种系统设计旨在帮助量化交易者更好地管理和执行他们的交易策略,提高交易效率和准确性。 主要功能 信号传输:将本地生成的交易信号实时发送到服务器,确保交易指令的及时性和准确性。 信号接收与处理:从服务器接收交易信号,并对其进行解析和处理,以便执行相应的交易操作。 日志记录:详细记录每次信号发送和接收的时间、内容及状态,方便后续分析与调试。 异常处理:具备完善的异常处理机制,确保在网络波动或服务器故障时能够及时报警并采取相应措施。 配置灵活:支持多种配置选项,用户可以根据实际需求自定义信号传输的频率、格式及其他参数。 安全性:采用加密技术保护信号传输过程中的数据安全,防止信息泄露和篡改。 使用场景 量化交易策略测试:在本地开发和测试交易策略后,通过MiniQMT将信号发送到实盘环境进行验证。 自动化交易:实现全自动化的量化交易系统,从信号生成到执行全程无需人工干预。 跨平台交易:支持在不同交易平台之间传递交易信号,实现多平台协同工作。 风险管理:结合风控系统,对交易信号进行实时监控和管理,降低交易风险。 技术架构 客户端:运行在本地计算机上,负责生成和发送交易信号,以及接收和处理来自服务器的信号。 服务器端:部署在云端或数据中心,负责接收客户端发送的信号,并根据预设规则进行处理和反馈。 通信协议:采用高效的网络通信协议(如WebSocket、gRPC等),确保数据传输的低延迟和高可靠性。 数据库:用于存储历史交易数据和日志信息,便于后续分析和查询。 总结 QuantTrader MiniQMT 是一个功能强大且灵活的交易信号传递系统,适用于各种量化交易场景。通过该系统,用户可以更加便捷地管理和执行他们的交易策略,提高交易效率和成功率。无论是初学者还是经验丰富的量化交易者,都可以通过MiniQMT获得更好的交易体验。 #### 软件架构 作者微信 ![输入图片说明](wximage.png) 更多内容在知识星球 ![输入图片说明](zsxqimage.png) 软件架构说明操作的服务器网页http://124.220.32.224:8025/ ![输入图片说明](1image.png) 组合的授权码找作者要就可以 #### 一聚宽设置教程 ### 1. 登录聚宽选择一个我们要运行的策略比如默认的网页策略 ![输入图片说明](2image.png) ``` # 导入函数库 from jqdata import * # 初始化函数,设定基准等等 def initialize(context): # 设定沪深300作为基准 set_benchmark('000300.XSHG') # 开启动态复权模式(真实价格) set_option('use_real_price', True) # 输出内容到日志 log.info() log.info('初始函数开始运行且全局只运行一次') # 过滤掉order系列API产生的比error级别低的log # log.set_level('order', 'error') ### 股票相关设定 ### # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱 set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock') ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的) # 开盘前运行 run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') # 开盘时运行 run_daily(market_open, time='open', reference_security='000300.XSHG') # 收盘后运行 run_daily(after_market_close, time='after_close', reference_security='000300.XSHG') ## 开盘前运行函数 def before_market_open(context): # 输出运行时间 log.info('函数运行时间(before_market_open):'+str(context.current_dt.time())) # 给微信发送消息(添加模拟交易,并绑定微信生效) # send_message('美好的一天~') # 要操作的股票:平安银行(g.为全局变量) g.security ='513100.XSHG' ## 开盘时运行函数 def market_open(context): log.info('函数运行时间(market_open):'+str(context.current_dt.time())) security = g.security # 获取股票的收盘价 close_data = get_bars(security, count=5, unit='1d', fields=['close']) # 取得过去五天的平均价格 MA5 = close_data['close'].mean() # 取得上一时间点价格 current_price = close_data['close'][-1] # 取得当前的现金 cash = context.portfolio.available_cash # 如果上一时间点价格高出五天平均价1%, 则全仓买入 if (current_price > 1.01*MA5) and (cash > 0): # 记录这次买入 log.info("价格高于均价 1%%, 买入 %s" % (security)) # 用所有 cash 买入股票 order_value(security, cash) # 如果上一时间点价格低于五天平均价, 则空仓卖出 elif current_price < MA5 and context.portfolio.positions[security].closeable_amount > 0: # 记录这次卖出 log.info("价格低于均价, 卖出 %s" % (security)) # 卖出所有股票,使这只股票的最终持有量为0 order_target(security, 0) ## 收盘后运行函数 def after_market_close(context): log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time()))) #得到当天所有成交记录 trades = get_trades() for _trade in trades.values(): log.info('成交记录:'+str(_trade)) log.info('一天结束') log.info('##############################################################') ``` ### 2. 把下面的代码放在策略开头继承交易函数的类就可以 ``` ''' 小果聚宽跟单系统 原理替代,继承聚宽的交易函数类 读取下单类的函数参数把交易数据发送到服务器 把下面的全部源代码复制到聚宽策略的开头就可以 实盘前先模拟盘测试一下数据 把下面的内容全部复制到策略的开头就可以 作者微信15117320079 ''' import requests import json import pandas as pd from jqdata import * url='http://124.220.32.224' port=8025 #自定义服务器编码 url_code='63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad' #记得把这个改成自己的一个策略一个,策略的名称找作者建立 password='123456' class joinquant_trader: def __init__(self,url='http://124.220.32.224', port=8025, url_code='63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad', password='123456'): ''' 获取服务器数据 ''' self.url=url self.port=port self.url_code=url_code self.password=password def get_user_data(self,data_type='用户信息'): ''' 获取使用的数据 data_type='用户信息','实时数据',历史数据','清空实时数据','清空历史数据' ''' url='{}:{}/_dash-update-component'.format(self.url,self.port) headers={'Content-Type':'application/json'} data={"output":"joinquant_trader_table.data@{}".format(self.url_code), "outputs":{"id":"joinquant_trader_table","property":"data@{}".format(self.url_code)}, "inputs":[{"id":"joinquant_trader_password","property":"value","value":self.password}, {"id":"joinquant_trader_data_type","property":"value","value":data_type}, {"id":"joinquant_trader_text","property":"value","value":"\n {'状态': 'held', '订单添加时间': 'datetime.datetime(2024, 4, 23, 9, 30)', '买卖': 'False', '下单数量': '9400', '已经成交': '9400', '股票代码': '001.XSHE', '订单ID': '1732208241', '平均成交价格': '10.5', '持仓成本': '10.59', '多空': 'long', '交易费用': '128.31'}\n "}, {"id":"joinquant_trader_run","property":"value","value":"运行"}, {"id":"joinquant_trader_down_data","property":"value","value":"不下载数据"}], "changedPropIds":["joinquant_trader_run.value"],"parsedChangedPropsIds":["joinquant_trader_run.value"]} res=requests.post(url=url,data=json.dumps(data),headers=headers) text=res.json() df=pd.DataFrame(text['response']['joinquant_trader_table']['data']) return df def send_order(self,result): ''' 发送交易数据 ''' url='{}:{}/_dash-update-component'.format(self.url,self.port) headers={'Content-Type':'application/json'} data={"output":"joinquant_trader_table.data@{}".format(self.url_code), "outputs":{"id":"joinquant_trader_table","property":"data@{}".format(self.url_code)}, "inputs":[{"id":"joinquant_trader_password","property":"value","value":self.password}, {"id":"joinquant_trader_data_type","property":"value","value":'实时数据'}, {"id":"joinquant_trader_text","property":"value","value":result}, {"id":"joinquant_trader_run","property":"value","value":"运行"}, {"id":"joinquant_trader_down_data","property":"value","value":"不下载数据"}], "changedPropIds":["joinquant_trader_run.value"],"parsedChangedPropsIds":["joinquant_trader_run.value"]} res=requests.post(url=url,data=json.dumps(data),headers=headers) text=res.json() df=pd.DataFrame(text['response']['joinquant_trader_table']['data']) return df #继承类 xg_data=joinquant_trader(url=url,port=port,password=password,) def send_order(result): ''' 发送函数 status: 状态, 一个OrderStatus值 add_time: 订单添加时间, [datetime.datetime]对象 is_buy: bool值, 买还是卖,对于期货: 开多/平空 -> 买 开空/平多 -> 卖 amount: 下单数量, 不管是买还是卖, 都是正数 filled: 已经成交的股票数量, 正数 security: 股票代码 order_id: 订单ID price: 平均成交价格, 已经成交的股票的平均成交价格(一个订单可能分多次成交) avg_cost: 卖出时表示下卖单前的此股票的持仓成本, 用来计算此次卖出的收益. 买入时表示此次买入的均价(等同于price). side: 多/空,'long'/'short' action: 开/平, 'open'/'close' commission交易费用(佣金、税费等) ''' data={} data['状态']=str(result.status) data['订单添加时间']=str(result.add_time) data['买卖']=str(result.is_buy) data['下单数量']=str(result.amount) data['已经成交']=str(result.filled) data['股票代码']=str(result.security) data['订单ID']=str(result.order_id) data['平均成交价格']=str(result.price) data['持仓成本']=str(result.avg_cost) data['多空']=str(result.side) data['交易费用']=str(result.commission) result=str(data) xg_data.send_order(result) return data def xg_order(func): ''' 继承order对象 数据交易函数 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_target(func): ''' 继承order_target对象 百分比 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_value(func): ''' 继承order_value对象 数量 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_target_value(func): ''' 继承order_target_value对象 数量 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper order = xg_order(order) order_target = xg_order_target(order_target) order_value = xg_order_value(order_value) order_target_value = xg_order_target_value(order_target_value) ``` 这个参数的策略的名称 password='123456',找作者要就可以 ### 3. 完整的例子,只需要把咋个代码放在策略的开头就可以不需要变动什么 ![输入图片说明](3image.png) 完整的内容只需要添加前面的继续函数就可以 ``` # 导入函数库 from jqdata import * ''' 小果聚宽跟单系统 原理替代,继承聚宽的交易函数类 读取下单类的函数参数把交易数据发送到服务器 把下面的全部源代码复制到聚宽策略的开头就可以 实盘前先模拟盘测试一下数据 把下面的内容全部复制到策略的开头就可以 作者微信15117320079 ''' import requests import json import pandas as pd url='http://124.220.32.224' port=8025 #记得把这个改成自己的一个策略一个,策略的名称找作者建立 password='123456' class joinquant_trader: def __init__(self,url='http://124.220.32.224',port=8025,password='123456'): ''' 获取服务器数据 ''' self.url=url self.port=port self.password=password def get_user_data(self,data_type='用户信息'): ''' 获取使用的数据 data_type='用户信息','实时数据',历史数据','清空实时数据','清空历史数据' ''' url='{}:{}/_dash-update-component'.format(self.url,self.port) headers={'Content-Type':'application/json'} data={"output":"joinquant_trader_table.data@63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad", "outputs":{"id":"joinquant_trader_table","property":"data@63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad"}, "inputs":[{"id":"joinquant_trader_password","property":"value","value":self.password}, {"id":"joinquant_trader_data_type","property":"value","value":data_type}, {"id":"joinquant_trader_text","property":"value","value":"\n {'状态': 'held', '订单添加时间': 'datetime.datetime(2024, 4, 23, 9, 30)', '买卖': 'False', '下单数量': '9400', '已经成交': '9400', '股票代码': '001.XSHE', '订单ID': '1732208241', '平均成交价格': '10.5', '持仓成本': '10.59', '多空': 'long', '交易费用': '128.31'}\n "}, {"id":"joinquant_trader_run","property":"value","value":"运行"}, {"id":"joinquant_trader_down_data","property":"value","value":"不下载数据"}], "changedPropIds":["joinquant_trader_run.value"],"parsedChangedPropsIds":["joinquant_trader_run.value"]} res=requests.post(url=url,data=json.dumps(data),headers=headers) text=res.json() df=pd.DataFrame(text['response']['joinquant_trader_table']['data']) return df def send_order(self,result): ''' 发送交易数据 ''' url='{}:{}/_dash-update-component'.format(self.url,self.port) headers={'Content-Type':'application/json'} data={"output":"joinquant_trader_table.data@63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad", "outputs":{"id":"joinquant_trader_table","property":"data@63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad"}, "inputs":[{"id":"joinquant_trader_password","property":"value","value":self.password}, {"id":"joinquant_trader_data_type","property":"value","value":'实时数据'}, {"id":"joinquant_trader_text","property":"value","value":result}, {"id":"joinquant_trader_run","property":"value","value":"运行"}, {"id":"joinquant_trader_down_data","property":"value","value":"不下载数据"}], "changedPropIds":["joinquant_trader_run.value"],"parsedChangedPropsIds":["joinquant_trader_run.value"]} res=requests.post(url=url,data=json.dumps(data),headers=headers) text=res.json() df=pd.DataFrame(text['response']['joinquant_trader_table']['data']) return df #继承类 xg_data=joinquant_trader(url=url,port=port,password=password) def send_order(result): ''' 发送函数 status: 状态, 一个OrderStatus值 add_time: 订单添加时间, [datetime.datetime]对象 is_buy: bool值, 买还是卖,对于期货: 开多/平空 -> 买 开空/平多 -> 卖 amount: 下单数量, 不管是买还是卖, 都是正数 filled: 已经成交的股票数量, 正数 security: 股票代码 order_id: 订单ID price: 平均成交价格, 已经成交的股票的平均成交价格(一个订单可能分多次成交) avg_cost: 卖出时表示下卖单前的此股票的持仓成本, 用来计算此次卖出的收益. 买入时表示此次买入的均价(等同于price). side: 多/空,'long'/'short' action: 开/平, 'open'/'close' commission交易费用(佣金、税费等) ''' data={} data['状态']=str(result.status) data['订单添加时间']=str(result.add_time) data['买卖']=str(result.is_buy) data['下单数量']=str(result.amount) data['已经成交']=str(result.filled) data['股票代码']=str(result.security) data['订单ID']=str(result.order_id) data['平均成交价格']=str(result.price) data['持仓成本']=str(result.avg_cost) data['多空']=str(result.side) data['交易费用']=str(result.commission) result=str(data) xg_data.send_order(result) return data def xg_order(func): ''' 继承order对象 数据交易函数 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_target(func): ''' 继承order_target对象 百分比 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_value(func): ''' 继承order_value对象 数量 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_target_value(func): ''' 继承order_target_value对象 数量 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper #from jqdata import * order = xg_order(order) order_target = xg_order_target(order_target) order_value = xg_order_value(order_value) order_target_value = xg_order_target_value(order_target_value) # 初始化函数,设定基准等等 def initialize(context): # 设定沪深300作为基准 set_benchmark('000300.XSHG') # 开启动态复权模式(真实价格) set_option('use_real_price', True) # 输出内容到日志 log.info() log.info('初始函数开始运行且全局只运行一次') # 过滤掉order系列API产生的比error级别低的log # log.set_level('order', 'error') ### 股票相关设定 ### # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱 set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock') ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的) # 开盘前运行 run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') # 开盘时运行 run_daily(market_open, time='open', reference_security='000300.XSHG') # 收盘后运行 run_daily(after_market_close, time='after_close', reference_security='000300.XSHG') ## 开盘前运行函数 def before_market_open(context): # 输出运行时间 log.info('函数运行时间(before_market_open):'+str(context.current_dt.time())) # 给微信发送消息(添加模拟交易,并绑定微信生效) # send_message('美好的一天~') # 要操作的股票:平安银行(g.为全局变量) g.security = '513100.XSHG' ## 开盘时运行函数 def market_open(context): log.info('函数运行时间(market_open):'+str(context.current_dt.time())) security = g.security # 获取股票的收盘价 close_data = get_bars(security, count=5, unit='1d', fields=['close']) # 取得过去五天的平均价格 MA5 = close_data['close'].mean() # 取得上一时间点价格 current_price = close_data['close'][-1] # 取得当前的现金 cash = context.portfolio.available_cash # 如果上一时间点价格高出五天平均价1%, 则全仓买入 if (current_price > 1.01*MA5) and (cash > 0): # 记录这次买入 log.info("价格高于均价 1%%, 买入 %s" % (security)) # 用所有 cash 买入股票 order_value(security, cash) # 如果上一时间点价格低于五天平均价, 则空仓卖出 elif current_price < MA5 and context.portfolio.positions[security].closeable_amount > 0: # 记录这次卖出 log.info("价格低于均价, 卖出 %s" % (security)) # 卖出所有股票,使这只股票的最终持有量为0 order_target(security, 0) ## 收盘后运行函数 def after_market_close(context): log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time()))) #得到当天所有成交记录 trades = get_trades() for _trade in trades.values(): log.info('成交记录:'+str(_trade)) log.info('一天结束') log.info('##############################################################') ``` ### 4.把改好的内容挂聚宽模拟盘交易就可以 ![输入图片说明](4image.png) ### **二服务器测试** ### 1为了高频测试我改了一下参数测试的代码 ``` # 导入函数库 from jqdata import * ''' 小果聚宽跟单系统 原理替代,继承聚宽的交易函数类 读取下单类的函数参数把交易数据发送到服务器 把下面的全部源代码复制到聚宽策略的开头就可以 实盘前先模拟盘测试一下数据 把下面的内容全部复制到策略的开头就可以 作者微信15117320079 ''' import requests import json import pandas as pd url='http://124.220.32.224' port=8025 #记得把这个改成自己的一个策略一个,策略的名称找作者建立 password='123456' class joinquant_trader: def __init__(self,url='http://124.220.32.224',port=8025,password='123456'): ''' 获取服务器数据 ''' self.url=url self.port=port self.password=password def get_user_data(self,data_type='用户信息'): ''' 获取使用的数据 data_type='用户信息','实时数据',历史数据','清空实时数据','清空历史数据' ''' url='{}:{}/_dash-update-component'.format(self.url,self.port) headers={'Content-Type':'application/json'} data={"output":"joinquant_trader_table.data@63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad", "outputs":{"id":"joinquant_trader_table","property":"data@63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad"}, "inputs":[{"id":"joinquant_trader_password","property":"value","value":self.password}, {"id":"joinquant_trader_data_type","property":"value","value":data_type}, {"id":"joinquant_trader_text","property":"value","value":"\n {'状态': 'held', '订单添加时间': 'datetime.datetime(2024, 4, 23, 9, 30)', '买卖': 'False', '下单数量': '9400', '已经成交': '9400', '股票代码': '001.XSHE', '订单ID': '1732208241', '平均成交价格': '10.5', '持仓成本': '10.59', '多空': 'long', '交易费用': '128.31'}\n "}, {"id":"joinquant_trader_run","property":"value","value":"运行"}, {"id":"joinquant_trader_down_data","property":"value","value":"不下载数据"}], "changedPropIds":["joinquant_trader_run.value"],"parsedChangedPropsIds":["joinquant_trader_run.value"]} res=requests.post(url=url,data=json.dumps(data),headers=headers) text=res.json() df=pd.DataFrame(text['response']['joinquant_trader_table']['data']) return df def send_order(self,result): ''' 发送交易数据 ''' url='{}:{}/_dash-update-component'.format(self.url,self.port) headers={'Content-Type':'application/json'} data={"output":"joinquant_trader_table.data@63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad", "outputs":{"id":"joinquant_trader_table","property":"data@63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad"}, "inputs":[{"id":"joinquant_trader_password","property":"value","value":self.password}, {"id":"joinquant_trader_data_type","property":"value","value":'实时数据'}, {"id":"joinquant_trader_text","property":"value","value":result}, {"id":"joinquant_trader_run","property":"value","value":"运行"}, {"id":"joinquant_trader_down_data","property":"value","value":"不下载数据"}], "changedPropIds":["joinquant_trader_run.value"],"parsedChangedPropsIds":["joinquant_trader_run.value"]} res=requests.post(url=url,data=json.dumps(data),headers=headers) text=res.json() df=pd.DataFrame(text['response']['joinquant_trader_table']['data']) return df #继承类 xg_data=joinquant_trader(url=url,port=port,password=password) def send_order(result): ''' 发送函数 status: 状态, 一个OrderStatus值 add_time: 订单添加时间, [datetime.datetime]对象 is_buy: bool值, 买还是卖,对于期货: 开多/平空 -> 买 开空/平多 -> 卖 amount: 下单数量, 不管是买还是卖, 都是正数 filled: 已经成交的股票数量, 正数 security: 股票代码 order_id: 订单ID price: 平均成交价格, 已经成交的股票的平均成交价格(一个订单可能分多次成交) avg_cost: 卖出时表示下卖单前的此股票的持仓成本, 用来计算此次卖出的收益. 买入时表示此次买入的均价(等同于price). side: 多/空,'long'/'short' action: 开/平, 'open'/'close' commission交易费用(佣金、税费等) ''' data={} data['状态']=str(result.status) data['订单添加时间']=str(result.add_time) data['买卖']=str(result.is_buy) data['下单数量']=str(result.amount) data['已经成交']=str(result.filled) data['股票代码']=str(result.security) data['订单ID']=str(result.order_id) data['平均成交价格']=str(result.price) data['持仓成本']=str(result.avg_cost) data['多空']=str(result.side) data['交易费用']=str(result.commission) result=str(data) xg_data.send_order(result) return data def xg_order(func): ''' 继承order对象 数据交易函数 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_target(func): ''' 继承order_target对象 百分比 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_value(func): ''' 继承order_value对象 数量 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper def xg_order_target_value(func): ''' 继承order_target_value对象 数量 ''' def wrapper(*args, **kwargs): result = func(*args, **kwargs) if result == None: return send_order(result) return result return wrapper #from jqdata import * order = xg_order(order) order_target = xg_order_target(order_target) order_value = xg_order_value(order_value) order_target_value = xg_order_target_value(order_target_value) # 初始化函数,设定基准等等 def initialize(context): # 设定沪深300作为基准 set_benchmark('000300.XSHG') # 开启动态复权模式(真实价格) set_option('use_real_price', True) # 输出内容到日志 log.info() log.info('初始函数开始运行且全局只运行一次') # 过滤掉order系列API产生的比error级别低的log # log.set_level('order', 'error') ### 股票相关设定 ### # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱 set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock') ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的) # 开盘前运行 run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') # 开盘时运行 run_daily(market_open, time='open', reference_security='000300.XSHG') # 收盘后运行 run_daily(after_market_close, time='after_close', reference_security='000300.XSHG') ## 开盘前运行函数 def before_market_open(context): # 输出运行时间 log.info('函数运行时间(before_market_open):'+str(context.current_dt.time())) # 给微信发送消息(添加模拟交易,并绑定微信生效) # send_message('美好的一天~') # 要操作的股票:平安银行(g.为全局变量) g.security = '513100.XSHG' ## 开盘时运行函数 def market_open(context): log.info('函数运行时间(market_open):'+str(context.current_dt.time())) security = g.security # 获取股票的收盘价 close_data = get_bars(security, count=5, unit='1d', fields=['close']) # 取得过去五天的平均价格 MA5 = close_data['close'].mean() # 取得上一时间点价格 current_price = close_data['close'][-1] # 取得当前的现金 cash = context.portfolio.available_cash pre_close=close_data['close'][-2] # 如果上一时间点价格高出五天平均价1%, 则全仓买入 if (current_price > pre_close) and (cash > 0): # 记录这次买入 log.info("价格高于均价 1%%, 买入 %s" % (security)) # 用所有 cash 买入股票 order_value(security, cash) # 如果上一时间点价格低于五天平均价, 则空仓卖出 elif current_price 0: # 记录这次卖出 log.info("价格低于均价, 卖出 %s" % (security)) # 卖出所有股票,使这只股票的最终持有量为0 order_target(security, 0) ## 收盘后运行函数 def after_market_close(context): log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time()))) #得到当天所有成交记录 trades = get_trades() for _trade in trades.values(): log.info('成交记录:'+str(_trade)) log.info('一天结束') log.info('##############################################################') ``` ### 2点击对应的参数测试一下数据 ![输入图片说明](5image.png) 测试的交易情况 ![输入图片说明](6image.png) 交易历史数据 ![输入图片说明](7image.png) ### **三服务器操作** ### 1访问服务器 点击服务器http://124.220.32.224:8025/ 输入策略是授权码这个参数,需要的找作者获取 ![输入图片说明](7image.png) ### 2查询个人信息 输入用户名称点击个人信息运行获取自己的数据 ![输入图片说明](8image.png) ### 3查询实时跟单数据 点击实时数据 ![输入图片说明](9image.png) ### 4查询历史数据 点击历史数据 ![输入图片说明](10image.png) ### 清空实时数据 点击清空就可以 ![输入图片说明](11image.png) ### 5点击清空实时数据 点击就可以 ![输入图片说明](12image.png) ### **四交易系统设置** ### 1点击安装第三方库bat安装第三方库 ![输入图片说明](13image.png) ###2打开qmt登录选择极简单模式 ![输入图片说明](14image.png) ### 3设置qmt参数 修改qmt路径账户 ``` { "软件授权码":"0xc369da8e2ecf9855c95753ae45545744965b3c28bec30e2b2f17d790df09112653285972d7c6481a13f4f48a301db283c8bbbb59dfdc851ea002a855ffac45adb88e8b314b2db6f25ae5bc690ae4c30a8d96277daec437d92c2096a469b7fcb028ac7a4ee04f3b463a8785ea96e7586dbabd9b75c0fc02ba0a6ba80c655e111f8733", "交易系统设置":"*********************************************", "交易系统选择":"ths/qmt", "交易系统":"qmt", "交易品种":"全部", "交易品种说明":["stock","fund","bond","全部"], "同花顺下单路径":"C:/同花顺软件/同花顺/xiadan.exe", "识别软件安装位置":"C:/Program Files/Tesseract-OCR/tesseract", "qmt路径":"D:/国金QMT交易端模拟/userdata_mini", "qmt账户":"55001947", "qmt账户类型":"STOCK", "证券公司交易设置":"兼容老牌证券公司可转债1手为单位", "是否开启特殊证券公司交易设置":"否", "发送方式选择":"钉钉/qq", "发送方式":"qq", "发送qq":"1752515969@qq.com", "qq掩码":"jgyhavzupyglecaf", "接收qq":"71080306@qq.com", "钉钉账户token":["ab5d0a609429a786b9a849cefd5db60c0ef2f17f2ec877a60bea5f8480d86b1b"], "交易时间段":4, "交易开始时间":9, "交易结束时间":24, "是否参加集合竞价":"否", "开始交易分钟":0, "黑名单":[] } ``` ### 4修改聚宽函数,选择测试参数,实盘改成否 ![输入图片说明](15image.png) 设置跟单参数,支持多策略同时运行,比例跟单,默认模式是聚宽原始的数据,测试的时候先小资金测试 ``` { "聚宽跟单":"跟单原理", "服务器设置":"服务器跟单设置", "服务器":"http://124.220.32.224", "端口":"8025", "测试说明":"开启测试就是选择历史交易不开启就是选择今天的数据", "是否开启测试":"是", "跟单设置":"跟单设置***********", "账户跟单比例":0.5, "多策略用逗号隔开":"多策略用逗号隔开********", "组合名称":["测试1"], "组合授权码":["123456"], "组合跟单比例":[0.5], "不同策略间隔更新时间":0, "下单默认说明":"默认/金额/数量", "下单模式":"金额", "下单值":1000 } ``` ### 5模拟盘测试 点击聚宽跟单就可以 ![输入图片说明](16image.png) 测试的结果 ``` 启测试模式,实盘记得关闭 组合 测试1 策略授权码 123456 2024-11-30今天跟单数据********************* 状态 订单添加时间 买卖 下单数量 已经成交 股票代码 订单ID 平均成交价格 持仓成本 多空 交易费用 交易日 数据状态 证券代码 数据长度 交易类型 组合名称 组合授权码 0 held 2024-11-05 True 69600 69600 513100.XSHG 1732951579 1.437 1.437 long 30.00456 2024-11-30 True 513100 11 buy 测试1 123456 1 held 2024-11-06 False 69600 69600 513100.XSHG 1732951580 1.461 1.437 long 30.50568 2024-11-30 True 513100 11 sell 测试1 123456 2 held 2024-11-07 True 67000 67000 513100.XSHG 1732951581 1.517 1.517 long 30.49170 2024-11-30 True 513100 11 buy 测试1 123456 3 held 2024-11-14 False 67000 67000 513100.XSHG 1732951582 1.526 1.517 long 30.67260 2024-11-30 True 513100 11 sell 测试1 123456 4 held 2024-11-15 True 67400 67400 513100.XSHG 1732951583 1.516 1.516 long 30.65352 2024-11-30 True 513100 11 buy 测试1 123456 5 held 2024-11-18 False 67400 67400 513100.XSHG 1732951584 1.489 1.516 long 30.10758 2024-11-30 True 513100 11 sell 测试1 123456 6 held 2024-11-20 True 66000 66000 513100.XSHG 1732951585 1.519 1.519 long 30.07620 2024-11-30 True 513100 11 buy 测试1 123456 7 held 2024-11-22 False 66000 66000 513100.XSHG 1732951586 1.517 1.519 long 30.03660 2024-11-30 True 513100 11 sell 测试1 123456 8 held 2024-11-25 True 65200 65200 513100.XSHG 1732951587 1.535 1.535 long 30.02460 2024-11-30 True 513100 11 buy 测试1 123456 9 held 2024-11-29 False 65200 65200 513100.XSHG 1732951588 1.528 1.535 long 29.88768 2024-11-30 True 513100 11 sell 测试1 123456 剔除黑名单______________*************************_______________________ 持仓数量: 18 按金额下单513100 交易类型buy 可用资金17970106.04大于 下单金额306.4 下单数量100 buy 100 1.532 持仓数量: 18 组合测试1 组合授权码123456 513100卖出有问题可能没有持股 持仓数量: 18 按金额下单513100 交易类型buy 可用资金17970106.04大于 下单金额306.4 下单数量100 buy 100 1.532 持仓数量: 18 组合测试1 组合授权码123456 513100卖出有问题可能没有持股 持仓数量: 18 按金额下单513100 交易类型buy 可用资金17970106.04大于 下单金额306.4 下单数量100 buy 100 1.532 持仓数量: 18 组合测试1 组合授权码123456 513100卖出有问题可能没有持股 持仓数量: 18 按金额下单513100 交易类型buy 可用资金17970106.04大于 下单金额306.4 下单数量100 buy 100 1.532 持仓数量: 18 组合测试1 组合授权码123456 513100卖出有问题可能没有持股 持仓数量: 18 按金额下单513100 交易类型buy 可用资金17970106.04大于 下单金额306.4 下单数量100 buy 100 1.532 持仓数量: 18 组合测试1 组合授权码123456 513100卖出有问题可能没有持股 下单股票池)))))))))))))))))))))))) 状态 订单添加时间 买卖 下单数量 已经成交 股票代码 订单ID 平均成交价格 持仓成本 多空 ... 数据长度 交易类型 组合名 称 组合授权码 黑名单 品种 账户跟单比例 组合跟单比例 交易检查 数量 0 held 2024-11-05 True 69600 69600 513100.XSHG 1732951579 1.437 1.437 long ... 11 buy 测试1 123456 否 fund 0.5 1 没有交易 100 2 held 2024-11-07 True 67000 67000 513100.XSHG 1732951581 1.517 1.517 long ... 11 buy 测试1 123456 否 fund 0.5 1 没有交易 100 4 held 2024-11-15 True 67400 67400 513100.XSHG 1732951583 1.516 1.516 long ... 11 buy 测试1 123456 否 fund 0.5 1 没有交易 100 6 held 2024-11-20 True 66000 66000 513100.XSHG 1732951585 1.519 1.519 long ... 11 buy 测试1 123456 否 fund 0.5 1 没有交易 100 8 held 2024-11-25 True 65200 65200 513100.XSHG 1732951587 1.535 1.535 long ... 11 buy 测试1 123456 否 fund 0.5 1 没有交易 100 [5 rows x 24 columns] 下单数量为0的标的可能没有持股,可能账户没有资金等待下次成交######################################################## 状态 订单添加时间 买卖 下单数量 已经成交 股票代码 订单ID 平均成交价格 持仓成本 多空 ... 数据长度 交易类型 组合 名称 组合授权码 黑名单 品种 账户跟单比例 组合跟单比例 交易检查 数量 1 held 2024-11-06 False 69600 69600 513100.XSHG 1732951580 1.461 1.437 long ... 11 sell 测试1 123456 否 fund 0.5 1 没有交 易 0 3 held 2024-11-14 False 67000 67000 513100.XSHG 1732951582 1.526 1.517 long ... 11 sell 测试1 123456 否 fund 0.5 1 没有交 易 0 5 held 2024-11-18 False 67400 67400 513100.XSHG 1732951584 1.489 1.516 long ... 11 sell 测试1 123456 否 fund 0.5 1 没有交 易 0 7 held 2024-11-22 False 66000 66000 513100.XSHG 1732951586 1.517 1.519 long ... 11 sell 测试1 123456 否 fund 0.5 1 没有交 易 0 9 held 2024-11-29 False 65200 65200 513100.XSHG 1732951588 1.528 1.535 long ... 11 sell 测试1 123456 否 fund 0.5 1 没有交 易 0 [5 rows x 24 columns] 测试1组合没有符合调参的卖出数据 None 交易类型23 代码513100.SH 价格1.533 数量100 订单编号34 on_order_stock_async_response 55001947 1090522680 34 on order callback: 513100.SH 50 241 None 交易类型23 代码513100.SH 价格1.533 数量100 订单编号37 on_order_stock_async_response 55001947 1090522681 37 on order callback: 513100.SH 50 242 None 交易类型23 代码513100.SH 价格1.533 数量100 订单编号40 on_order_stock_async_response 55001947 1090522682 40 on order callback: 513100.SH 50 243 None 交易类型23 代码513100.SH 价格1.533 数量100 订单编号43 on_order_stock_async_response 55001947 1090522683 43 on order callback: 513100.SH 50 244 None 交易类型23 代码513100.SH 价格1.533 数量100 订单编号46 on_order_stock_async_response 55001947 1090522684 46 on order callback: 513100.SH 50 245 ``` 下单的结果 ![输入图片说明](17image.png) 程序运行的结果 ![输入图片说明](18image.png) ### **五实盘交易** ### 1交易参数是否测试改成否 ![输入图片说明](20image.png) ### 2时间改成和交易所一样 ``` "交易时间段":4, "交易开始时间":9, "交易结束时间":14, "是否参加集合竞价":"否", ``` ### 点击实盘程序 运行的结果 ![输入图片说明](21image.png) ``` 0 持仓数量: 18 账号类型 资金账号 证券代码 股票余额 可用余额 成本价 参考成本价 市值 0 2 55001947 113598 10 10 126.040 126.040 1273.13 1 2 55001947 113667 10 10 124.391 124.391 1249.86 2 2 55001947 113674 10 10 124.293 124.293 1272.99 3 2 55001947 113688 10 10 129.353 129.353 1282.36 4 2 55001947 118048 10 10 125.296 125.296 1248.59 5 2 55001947 511090 100 100 117.202 117.202 11734.70 6 2 55001947 511130 100 100 106.281 106.281 10634.50 7 2 55001947 513290 8100 8100 1.229 1.229 9954.90 8 2 55001947 513400 8300 8300 1.200 1.200 9943.40 9 2 55001947 513500 4500 4500 2.182 2.182 9819.00 10 2 55001947 600036 51500 51500 36.864 36.864 1871510.00 11 2 55001947 123035 10 10 129.732 129.732 1288.67 12 2 55001947 123100 10 10 120.049 120.049 1233.32 13 2 55001947 159502 9200 9200 1.086 1.086 10028.00 14 2 55001947 159655 5400 5400 1.690 1.690 9093.60 15 2 55001947 159830 1700 1700 5.727 5.727 9800.50 16 2 55001947 159934 1700 1700 5.830 5.830 9968.80 17 2 55001947 159937 1700 1700 5.883 5.883 10060.60 剔除黑名单********** 账号类型 资金账号 证券代码 股票余额 可用余额 成本价 参考成本价 市值 黑名单 0 2 55001947 113598 10 10 126.040 126.040 1273.13 否 1 2 55001947 113667 10 10 124.391 124.391 1249.86 否 2 2 55001947 113674 10 10 124.293 124.293 1272.99 否 3 2 55001947 113688 10 10 129.353 129.353 1282.36 否 4 2 55001947 118048 10 10 125.296 125.296 1248.59 否 5 2 55001947 511090 100 100 117.202 117.202 11734.70 否 6 2 55001947 511130 100 100 106.281 106.281 10634.50 否 7 2 55001947 513290 8100 8100 1.229 1.229 9954.90 否 8 2 55001947 513400 8300 8300 1.200 1.200 9943.40 否 9 2 55001947 513500 4500 4500 2.182 2.182 9819.00 否 10 2 55001947 600036 51500 51500 36.864 36.864 1871510.00 否 11 2 55001947 123035 10 10 129.732 129.732 1288.67 否 12 2 55001947 123100 10 10 120.049 120.049 1233.32 否 13 2 55001947 159502 9200 9200 1.086 1.086 10028.00 否 14 2 55001947 159655 5400 5400 1.690 1.690 9093.60 否 15 2 55001947 159830 1700 1700 5.727 5.727 9800.50 否 16 2 55001947 159934 1700 1700 5.830 5.830 9968.80 否 17 2 55001947 159937 1700 1700 5.883 5.883 10060.60 否 账号类型 资金账户 可用金额 冻结金额 持仓市值 总资产 0 2 55001947 17969314.54 766.5 1981396.92 19951501.33 用户信息 用户名称 用户密码 授权码 到期时间 到期天数 信息推送 数据状态 0 123456 123456 123458 2024-12-30 30 授权码正常 True 组合 测试1 策略授权码 123456 2024-11-30今天没有跟单数据********************* 剔除黑名单______________*************************_______________________ 测试1组合没有符合调参数据 持仓数量: 18 账号类型 资金账号 证券代码 股票余额 可用余额 成本价 参考成本价 市值 0 2 55001947 113598 10 10 126.040 126.040 1273.13 1 2 55001947 113667 10 10 124.391 124.391 1249.86 2 2 55001947 113674 10 10 124.293 124.293 1272.99 3 2 55001947 113688 10 10 129.353 129.353 1282.36 4 2 55001947 118048 10 10 125.296 125.296 1248.59 5 2 55001947 511090 100 100 117.202 117.202 11734.70 6 2 55001947 511130 100 100 106.281 106.281 10634.50 7 2 55001947 513290 8100 8100 1.229 1.229 9954.90 8 2 55001947 513400 8300 8300 1.200 1.200 9943.40 9 2 55001947 513500 4500 4500 2.182 2.182 9819.00 10 2 55001947 600036 51500 51500 36.864 36.864 1871510.00 11 2 55001947 123035 10 10 129.732 129.732 1288.67 12 2 55001947 123100 10 10 120.049 120.049 1233.32 13 2 55001947 159502 9200 9200 1.086 1.086 10028.00 14 2 55001947 159655 5400 5400 1.690 1.690 9093.60 15 2 55001947 159830 1700 1700 5.727 5.727 9800.50 16 2 55001947 159934 1700 1700 5.830 5.830 9968.80 17 2 55001947 159937 1700 1700 5.883 5.883 10060.60 剔除黑名单********** 账号类型 资金账号 证券代码 股票余额 可用余额 成本价 参考成本价 市值 黑名单 0 2 55001947 113598 10 10 126.040 126.040 1273.13 否 1 2 55001947 113667 10 10 124.391 124.391 1249.86 否 2 2 55001947 113674 10 10 124.293 124.293 1272.99 否 3 2 55001947 113688 10 10 129.353 129.353 1282.36 否 4 2 55001947 118048 10 10 125.296 125.296 1248.59 否 5 2 55001947 511090 100 100 117.202 117.202 11734.70 否 6 2 55001947 511130 100 100 106.281 106.281 10634.50 否 7 2 55001947 513290 8100 8100 1.229 1.229 9954.90 否 8 2 55001947 513400 8300 8300 1.200 1.200 9943.40 否 9 2 55001947 513500 4500 4500 2.182 2.182 9819.00 否 10 2 55001947 600036 51500 51500 36.864 36.864 1871510.00 否 11 2 55001947 123035 10 10 129.732 129.732 1288.67 否 12 2 55001947 123100 10 10 120.049 120.049 1233.32 否 13 2 55001947 159502 9200 9200 1.086 1.086 10028.00 否 14 2 55001947 159655 5400 5400 1.690 1.690 9093.60 否 15 2 55001947 159830 1700 1700 5.727 5.727 9800.50 否 16 2 55001947 159934 1700 1700 5.830 5.830 9968.80 否 17 2 55001947 159937 1700 1700 5.883 5.883 10060.60 否 账号类型 资金账户 可用金额 冻结金额 持仓市值 总资产 0 2 55001947 17969314.54 766.5 1981396.92 19951501.33 用户信息 用户名称 用户密码 授权码 到期时间 到期天数 信息推送 数据状态 0 123456 123456 123458 2024-12-30 30 授权码正常 True 组合 测试1 策略授权码 123456 2024-11-30今天没有跟单数据********************* 剔除黑名单______________*************************_______________________ 测试1组合没有符合调参数据 ``` ### **6参数** ### 1分析配置 ``` { "软件授权码":"0xc369da8e2ecf9855c95753ae45545744965b3c28bec30e2b2f17d790df09112653285972d7c6481a13f4f48a301db283c8bbbb59dfdc851ea002a855ffac45adb88e8b314b2db6f25ae5bc690ae4c30a8d96277daec437d92c2096a469b7fcb028ac7a4ee04f3b463a8785ea96e7586dbabd9b75c0fc02ba0a6ba80c655e111f8733", "交易系统设置":"*********************************************", "交易系统选择":"ths/qmt", "交易系统":"qmt", "交易品种":"全部", "交易品种说明":["stock","fund","bond","全部"], "同花顺下单路径":"C:/同花顺软件/同花顺/xiadan.exe", "识别软件安装位置":"C:/Program Files/Tesseract-OCR/tesseract", "qmt路径":"D:/国金QMT交易端模拟/userdata_mini", "qmt账户":"55001947", "qmt账户类型":"STOCK", "证券公司交易设置":"兼容老牌证券公司可转债1手为单位", "是否开启特殊证券公司交易设置":"否", "发送方式选择":"钉钉/qq", "发送方式":"qq", "发送qq":"1752515969@qq.com", "qq掩码":"jgyhavzupyglecaf", "接收qq":"71080306@qq.com", "钉钉账户token":["ab5d0a609429a786b9a849cefd5db60c0ef2f17f2ec877a60bea5f8480d86b1b"], "交易时间段":8, "交易开始时间":9, "交易结束时间":24, "是否参加集合竞价":"否", "开始交易分钟":0, "黑名单":[] } ``` ### 2跟单设置 ``` { "聚宽跟单":"跟单原理", "服务器设置":"服务器跟单设置", "服务器":"http://124.220.32.224", "端口":"8025", "测试说明":"开启测试就是选择历史交易不开启就是选择今天的数据", "是否开启测试":"否", "测试数量":200, "跟单设置":"跟单设置***********", "账户跟单比例":0.5, "多策略用逗号隔开":"多策略用逗号隔开********", "组合名称":["测试1"], "组合授权码":["123456"], "组合跟单比例":[1], "不同策略间隔更新时间":0, "下单默认说明":"默认/金额/数量", "下单模式":"金额", "下单值":1000 } ``` ### 3全部源代码 ``` from trader_tool.stock_data import stock_data from trader_tool.bond_cov_data import bond_cov_data from trader_tool.shape_analysis import shape_analysis from trader_tool.analysis_models import analysis_models import pandas as pd from trader_tool.ths_rq import ths_rq from tqdm import tqdm import numpy as np import json from trader_tool import jsl_data from qmt_trader.qmt_trader_ths import qmt_trader_ths from xgtrader.xgtrader import xgtrader from trader_tool.ths_rq import ths_rq from trader_tool.ths_board_concept_data import ths_board_concept_data from trader_tool.unification_data import unification_data import os import pandas as pd from trader_tool.dfcf_etf_data import dfcf_etf_data from trader_tool.xueqie_data import xueqie_data from datetime import datetime from trader_tool.base_func import base_func from qmt_trader.qmt_data import qmt_data import shutil import schedule from trader_tool.xg_jq_data import xg_jq_data import time class joinquant_trader: def __init__(self,trader_tool='qmt',exe='C:/同花顺软件/同花顺/xiadan.exe',tesseract_cmd='C:/Program Files/Tesseract-OCR/tesseract', qq='1029762153@qq.com',open_set='否',qmt_path='D:/国金证券QMT交易端/userdata_mini', qmt_account='8882514071',qmt_account_type='STOCK',name='customize_trading_strategies'): ''' 聚宽跟单模型 ''' self.exe=exe self.tesseract_cmd=tesseract_cmd self.qq=qq self.trader_tool=trader_tool self.open_set=open_set self.qmt_path=qmt_path self.qmt_account=qmt_account self.qmt_account_type=qmt_account_type if trader_tool=='ths': self.trader=xgtrader(exe=self.exe,tesseract_cmd=self.tesseract_cmd,open_set=open_set) else: self.trader=qmt_trader_ths(path=qmt_path,account=qmt_account,account_type=qmt_account_type) self.stock_data=stock_data() self.bond_cov_data=bond_cov_data() self.ths_rq=ths_rq() self.path=os.path.dirname(os.path.abspath(__file__)) self.ths_board_concept_data=ths_board_concept_data() self.name=name self.data=unification_data(trader_tool='ths') self.data=self.data.get_unification_data() self.dfcf_etf_data=dfcf_etf_data() #滑点 self.trader.slippage=0.01 self.base_func=base_func() self.trader.connect() def save_position(self): ''' 保存持股数据 ''' with open(r'分析配置.json',encoding='utf-8') as f: com=f.read() text=json.loads(com) del_df=pd.read_excel(r'{}\黑名单\黑名单.xlsx'.format(self.path),dtype='object') del_trader_stock=text['黑名单'] if del_df.shape[0]>0: del_df['证券代码']=del_df['证券代码'].apply(lambda x : str(x).split('.')[0]) del_df['证券代码']=del_df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) del_stock_list=del_df['证券代码'].tolist() else: del_stock_list=[] for del_stock in del_trader_stock: del_stock_list.append(del_stock) trader_type=text['交易品种'] def select_del_stock_list(x): if str(x)[:6] in del_stock_list: return '是' else: return '否' df=self.trader.position() try: if df==False: print('获取持股失败') except: if df.shape[0]>0: if trader_type=='全部': df=df else: df['选择']=df['证券代码'].apply(self.trader.select_data_type) df=df[df['选择']==trader_type] print(df) df=df[df['可用余额']>=10] df['黑名单']=df['证券代码'].apply(select_del_stock_list) df=df[df['黑名单']=='否'] print('剔除黑名单**********') df.to_excel(r'持股数据\持股数据.xlsx') return df else: df=pd.DataFrame() df['账号类型']=None df['资金账号']=None df['证券代码']=None df['股票余额']=None df['可用余额']=None df['成本价']=None df['市值']=None df['选择']=None df['持股天数']=None df['交易状态']=None df['明细']=None df['证券名称']=None df['冻结数量']=None df['市价']=None df['盈亏']=None df['盈亏比(%)']=None df['当日买入']=None df['当日卖出']=None df.to_excel(r'持股数据\持股数据.xlsx') return df def save_balance(self): ''' 保持账户数据 ''' df=self.trader.balance() df.to_excel(r'账户数据\账户数据.xlsx') return df def get_disk_port_data(self,stock='600031.SH',data_type='卖一'): price=self.data.get_spot_data(stock=stock)['最新价'] return price def get_del_buy_sell_data(self,name='测试1',password='123456'): ''' 处理交易数据 ''' with open(r'{}\聚宽跟单设置.json'.format(self.path),encoding='utf-8') as f: com=f.read() text=json.loads(com) test=text['是否开启测试'] url=text['服务器'] port=text['端口'] now_date=str(datetime.now())[:10] xg_data=xg_jq_data(url=url,port=port,password=password) info=xg_data.get_user_data(data_type='用户信息') df=xg_data.get_user_data(data_type='实时数据') print('用户信息') print(info) if df.shape[0]>0: stats=df['数据状态'].tolist()[-1] if stats==True: df['证券代码']=df['股票代码'].apply(lambda x: str(x).split('.XSHE')[0]) df['数据长度']=df['证券代码'].apply(lambda x: len(str(x))) df['订单添加时间']=df['订单添加时间'].apply(lambda x :str(x)[:10]) df=df[df['数据长度']>=6] df['交易类型']=df['买卖'].apply(lambda x: 'buy' if x==True else 'sell') df=df.drop_duplicates(subset=['股票代码','下单数量','买卖','多空'],keep='last') df['组合名称']=name df['组合授权码']=password df['证券代码']=df['证券代码'].apply(lambda x: str(x)[:6]) if test=='是': print('开启测试模式,实盘记得关闭') df=df else: df=df[df['订单添加时间']==now_date] else: df=pd.DataFrame() else: df=pd.DataFrame() if df.shape[0]>0: print('组合 {} 策略授权码 {} {}今天跟单数据*********************'.format(name,password,now_date)) print(df) else: print('组合 {} 策略授权码 {} {}今天没有跟单数据*********************'.format(name,password,now_date)) df.to_excel(r'{}\原始数据\原始数据.xlsx'.format(self.path)) return df def get_del_not_trader_stock(self,name='测试1',password='123456'): ''' 剔除黑名单 ''' print('剔除黑名单______________*************************_______________________') with open(r'分析配置.json',encoding='utf-8') as f: com=f.read() text=json.loads(com) del_df=pd.read_excel(r'{}\黑名单\黑名单.xlsx'.format(self.path),dtype='object') del_trader_stock=text['黑名单'] if del_df.shape[0]>0: del_df['证券代码']=del_df['证券代码'].apply(lambda x : str(x).split('.')[0]) del_df['证券代码']=del_df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) del_stock_list=del_df['证券代码'].tolist() else: del_stock_list=[] for del_stock in del_trader_stock: del_stock_list.append(del_stock) def select_del_stock_list(x): if str(x)[:6] in del_stock_list: return '是' else: return '否' df=pd.read_excel(r'{}\原始数据\原始数据.xlsx'.format(self.path),dtype='object') if df.shape[0]>0: df['证券代码']=df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) try: del df['Unnamed: 0'] except: pass df['黑名单']=df['证券代码'].apply(select_del_stock_list) df=df[df['黑名单']=='否'] #隔离策略 df['证券代码']=df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) df['品种']=df['证券代码'].apply(lambda x: self.trader.select_data_type(x)) df.to_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path)) else: df=pd.DataFrame() df.to_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path)) def get_trader_data(self,name='测试1',password='123456',zh_ratio=0.1): ''' 获取交易数据 组合的跟单比例 ''' with open(r'{}\聚宽跟单设置.json'.format(self.path),encoding='utf-8') as f: com=f.read() text=json.loads(com) test=text['是否开启测试'] adjust_ratio=text['账户跟单比例'] df=pd.read_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path)) try: df['证券代码']=df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) except: pass try: del df['Unnamed: 0'] except: pass trader_log=pd.read_excel(r'{}\跟单记录\跟单记录.xlsx'.format(self.path)) try: del trader_log['Unnamed: 0'] except: pass now_date=str(datetime.now())[:10] if trader_log.shape[0]>0: trader_log['证券代码']=trader_log['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) trader_log['交易日']=trader_log['交易日'].astype(str) #trader_log['订单ID']=trader_log['订单ID'].str(str) if test=='是': trader_log=trader_log else: trader_log=trader_log[trader_log['交易日']==now_date] trader_log['组合授权码']=trader_log['组合授权码'].astype(str) trader_log_1=trader_log[trader_log['组合授权码']==password] if trader_log_1.shape[0]>0: trader_id_list=trader_log_1['订单ID'].tolist() else: trader_id_list=[] else: trader_id_list=[] if df.shape[0]>0: df['组合授权码']=df['组合授权码'].astype(str) #df['订单ID ']=df['订单ID'].astype(str) df=df[df['组合授权码']==password] if df.shape[0]>0: df['账户跟单比例']=adjust_ratio df['组合跟单比例']=zh_ratio df['交易检查']=df['订单ID'].apply(lambda x: '已经交易' if x in trader_id_list else '没有交易') df=df[df['交易检查']=='没有交易'] amount_list=[] if df.shape[0]>0: for stock,amount,trader_type in zip(df['证券代码'].tolist(),df['下单数量'].tolist(),df['交易类型'].tolist()): price=self.data.get_spot_data(stock=stock)['最新价'] test=text['是否开启测试'] test_amount=text['测试数量'] down_type=text['下单模式'] down_value=text['下单值'] if test=='是': value=test_amount*price else: if down_type=='默认': value=price*amount*adjust_ratio*zh_ratio elif down_type=='数量': value=price*down_value*adjust_ratio*zh_ratio elif down_type=='金额': value=down_value else: value=price*amount*adjust_ratio*zh_ratio if trader_type=='buy': try: trader_type,amount,price=self.trader.order_value(stock=stock,value=value,price=price,trader_type='buy') print(trader_type,amount,price) if trader_type=='buy' and amount>=10: amount=self.trader.adjust_amount(stock=stock,amount=amount) amount_list.append(amount) else: amount_list.append(0) except Exception as e: print('组合{} 组合授权码{} {}买入有问题可能没有资金'.format(name,password,stock)) amount_list.append(0) elif trader_type=='sell': try: trader_type,amount,price=self.trader.order_value(stock=stock,value=value,price=price,trader_type='sell') if trader_type=='sell' and amount>=10: amount=self.trader.adjust_amount(stock=stock,amount=amount) amount_list.append(amount) else: amount_list.append(0) except Exception as e: print('组合{} 组合授权码{} {}卖出有问题可能没有持股'.format(name,password,stock)) amount_list.append(0) else: print('组合{} 组合授权码{} {}未知的交易类型'.format(name,password,stock)) df['数量']=amount_list not_trader=df[df['数量']<=0] #数量为0的不进入下单记录 df=df[df['数量']>=10] print('下单股票池))))))))))))))))))))))))') print(df) print('下单数量为0的标的可能没有持股,可能账户没有资金等待下次成交########################################################') print(not_trader) df.to_excel(r'{}\下单股票池\下单股票池.xlsx'.format(self.path)) df.to_excel(r'数据.xlsx') trader_log=pd.concat([trader_log,df],ignore_index=True) trader_log=trader_log.drop_duplicates(subset=['订单添加时间','订单ID','组合授权码','组合名称'],keep='last') trader_log.to_excel(r'{}\跟单记录\跟单记录.xlsx'.format(self.path)) else: print('{}组合没有需要下单标度******************'.format(name)) df=pd.DataFrame() df.to_excel(r'{}\下单股票池\下单股票池.xlsx'.format(self.path)) else: print('{}没有这个组合*************'.format(name)) df=pd.DataFrame() df.to_excel(r'{}\下单股票池\下单股票池.xlsx'.format(self.path)) def start_trader_on(self,name='测试1',password='123456'): ''' 开始下单 ''' with open(r'{}\聚宽跟单设置.json'.format(self.path),encoding='utf-8') as f: com=f.read() text=json.loads(com) df=pd.read_excel(r'{}\下单股票池\下单股票池.xlsx'.format(self.path)) try: df['证券代码']=df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) except: pass try: del df['Unnamed: 0 '] except: pass if df.shape[0]>0: df['证券代码']=df['证券代码'].astype(str) #print(df['证券代码']) df['证券代码']=df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) #先卖在买 sell_df=df[df['交易类型']=='sell'] if sell_df.shape[0]>0: for stock,amount, in zip(sell_df['证券代码'].tolist(),sell_df['数量'].tolist()): price=self.data.get_spot_data(stock=stock)['最新价'] self.trader.sell(security=stock,amount=amount,price=price) else: print('{}组合没有符合调参的卖出数据'.format(name)) buy_df=df[df['交易类型']=='buy'] if buy_df.shape[0]>0: for stock,amount, in zip(buy_df['证券代码'].tolist(),buy_df['数量'].tolist()): price=self.data.get_spot_data(stock=stock)['最新价'] self.trader.buy(security=stock,amount=amount,price=price) else: print('{}组合没有符合调参的买入数据'.format(name)) else: print('{}组合没有符合调参数据'.format(name)) def update_all_data(self): ''' 更新策略数据 ''' if self.base_func.check_is_trader_date_1(): import time with open(r'{}\聚宽跟单设置.json'.format(self.path),encoding='utf-8') as f: com=f.read() text=json.loads(com) name_list=text['组合名称'] password_list=text['组合授权码'] ratio_list=text['组合跟单比例'] update_time=text['不同策略间隔更新时间'] for name,password,ratio in zip(name_list,password_list,ratio_list): try: print(self.save_position()) except Exception as e: print(e) try: print(self.save_balance()) except Exception as e: print(e) self.get_del_buy_sell_data(name=name,password=password) self.get_del_not_trader_stock(name=name,password=password) self.get_trader_data(name=name,password=password,zh_ratio=ratio) self.start_trader_on(name=name,password=password) time.sleep(update_time*60) else: print('跟单{} 目前不是交易时间***************'.format(datetime.now())) if __name__=='__main__': ''' 跟单 ''' with open('分析配置.json','r+',encoding='utf-8') as f: com=f.read() text=json.loads(com) trader_tool=text['交易系统'] exe=text['同花顺下单路径'] tesseract_cmd=text['识别软件安装位置'] qq=text['发送qq'] open_set=text['是否开启特殊证券公司交易设置'] qmt_path=text['qmt路径'] qmt_account=text['qmt账户'] qmt_account_type=text['qmt账户类型'] trader=joinquant_trader(trader_tool=trader_tool,exe=exe,tesseract_cmd=tesseract_cmd,qq=qq, open_set=open_set,qmt_path=qmt_path,qmt_account=qmt_account, qmt_account_type=qmt_account_type) schedule.every(0.08).minutes.do(trader.update_all_data) while True: schedule.run_pending() time.sleep(1) ``` #### 使用说明 1. x 2. xxxx 3. xxxx #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)