# 小果大qmt聚宽系统 **Repository Path**: coder_wz/joinquant_trader_bigqmt ## Basic Information - **Project Name**: 小果大qmt聚宽系统 - **Description**: 小果大qmt聚宽系统 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 7 - **Created**: 2025-01-21 - **Last Updated**: 2025-01-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 小果大qmt聚宽系统 miniqmt教程https://gitee.com/li-xingguo11111/joinquant_trader_miniqmt 作者 ![输入图片说明](wximage.png) 全部内容在知识星球 ![输入图片说明](zsxqimage.png) #### 介绍 小果大qmt聚宽系统 小果大 QMT 聚宽跟单系统是一种在金融量化交易领域具有一定创新性和实用性的交易辅助工具,以下是具体介绍: 系统概述 该系统旨在实现聚宽平台的策略与 QMT 平台的对接,使投资者能够在 QMT 平台上跟踪和执行聚宽平台上的优质策略,充分发挥两个平台的优势。 主要功能 策略同步:能够将聚宽平台上的策略实时同步到 QMT 平台,投资者无需手动修改代码或策略,即可在 QMT 上使用聚宽的策略进行交易。 多种跟单模式:支持成交模式、持股模式等多种跟单方式,满足不同投资者的需求。例如,成交模式跟单可按照策略的成交信号进行跟单操作;持股模式跟单则可根据策略的持仓情况来调整自己的持仓。 数据获取与处理:可以从聚宽平台获取相关数据,并在 QMT 平台上进行处理和分析,为交易决策提供数据支持。 风险控制:具备一定的风险控制功能,如设置止损、止盈等参数,帮助投资者控制交易风险。 账户管理:可以对多个交易账户进行管理和监控,方便投资者进行资金管理和风险分散。 优势特点 提高交易效率:通过自动化的跟单系统,减少了人工操作的时间和成本,提高了交易的效率和准确性。 降低技术门槛:对于不熟悉编程和量化交易的投资者来说,使用该系统可以更容易地利用聚宽平台上的优质策略进行交易,降低了参与量化交易的技术门槛。 策略多样性:聚宽平台上拥有丰富的策略资源,投资者可以根据自己的需求和风险偏好选择合适的策略进行跟单,增加了投资的多样性。 灵活性:系统具有一定的灵活性,投资者可以根据自己的需求对跟单参数进行调整和优化,以适应不同的市场环境和交易需求。 应用场景 适合个人投资者:对于那些希望通过量化交易获取收益,但缺乏编程能力和量化交易经验的个人投资者来说,小果大 QMT 聚宽跟单系统提供了一个简单便捷的解决方案。 专业投资机构:一些专业的投资机构也可以利用该系统来拓展投资策略的来源,提高交易的效率和效果,同时降低研发成本。 综上所述,小果大QMT聚宽跟单系统是一款功能强大、易于使用的量化交易辅助工具,它能够帮助投资者更好地利用聚宽平台上的优质策略进行交易,提高交易效率和盈利能力。 #### 软件架构 软件架构说明 #### 安装教程 直接导入大qmt使用 #### 使用说明 ### **一服务器使用** 1打开服务器连接http://124.220.32.224:8025/ ![输入图片说明](1image.png) 2输入用户名称就是策略的授权码比如xg_test ![输入图片说明](2image.png) 3获取实时数据 ![输入图片说明](3image.png) 4历史数据 ![输入图片说明](4image.png) 5清空数据 ![输入图片说明](6image.png) ### **二聚宽设置** 1点击策略列表,随便选择一个策略,建立策略也可以比如我的跟单测试 ![输入图片说明](7image.png) 2把下面的代码放在策略开头就可以,其他的全部不需要改动 ![输入图片说明](8image.png) ``` ''' 小果聚宽跟单系统 原理替代,继承聚宽的交易函数类 读取下单类的函数参数把交易数据发送到服务器 把下面的全部源代码复制到聚宽策略的开头就可以 实盘前先模拟盘测试一下数据 把下面的内容全部复制到策略的开头就可以 作者微信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) ``` 3设置策略授权码和带我去用户名称保持一样,一个策略一个授权码,授权码要唯一,可以找作者要 保持一样xg_test ![输入图片说明](9image.png) 和服务器要一样 ![输入图片说明](10image.png) ### **三聚宽测试测试** 1点击测试测试一下 ![输入图片说明](11image.png) 2交易的情况 ![输入图片说明](12image.png) 3对比服务器 ![输入图片说明](13image.png) 4策略源代码 ``` ''' 小果聚宽跟单系统 原理替代,继承聚宽的交易函数类 读取下单类的函数参数把交易数据发送到服务器 把下面的全部源代码复制到聚宽策略的开头就可以 实盘前先模拟盘测试一下数据 把下面的内容全部复制到策略的开头就可以 作者微信15117320079 ''' import requests import json import pandas as pd url='http://124.220.32.224' port=8025 #记得把这个改成自己的一个策略一个,策略的名称找作者建立 password='xg_test' 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] pre_close=close_data['close'][-2] # 取得当前的现金 cash = context.portfolio.available_cash # 如果上一时间点价格高出五天平均价1%, 则全仓买入 if (current_price >pre_close ) and (cash > 0): # 记录这次买入 log.info("价格高于均价 1%%, 买入 %s" % (security)) # 用所有 cash 买入股票 order_value(security, cash) # 如果上一时间点价格低于五天平均价, 则空仓卖出 elif current_price < pre_close 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('##############################################################') ``` ### **四大qmt实盘设置** 1打开导入策略点击编辑输入账户 ![输入图片说明](14image.png) 2输入账户 ![输入图片说明](15image.png) 3点击运行测试一下具体内容看参数说明 ![输入图片说明](14image.png) 4注意是否测试这个参数实盘改成否,测试的时候选择是 ![输入图片说明](15image.png) 5输入授权码和服务器保存一样,多策略用逗号隔开 ![输入图片说明](16image.png) ### **五挂实盘交易** 点击模型交易 ![输入图片说明](17image.png) 点击实盘运行就可以 ![输入图片说明](18image.png) 策略日志 ![输入图片说明](19image.png) 跟单对接交易 ![输入图片说明](20image.png) ### **六聚宽挂模拟盘** 点击模拟交易挂就可以 ![输入图片说明](21image.png) ### **七全部源代码** ``` #encoding:gbk ''' 声明:源代码只用作学习使用,不做商业用途 小果聚宽跟单交易系统 作者:小果 时间:20240120 教程 https://gitee.com/li-xingguo11111/joinquant_trader_miniqmt 实盘时间设置在下面的text里面改 "交易时间段":4, "交易开始时间":9, "交易结束时间":14, 测试时间设置 "时间设置":"时间设置********", "交易时间段":8, "交易开始时间":0, "交易结束时间":24, "是否参加集合竞价":"否", "开始交易分钟":0, 实盘需要把txet下面的参数是否测试改成否 "是否开启测试":"否", 下面的参数测试的时候改成否,实盘改成是 "是否开启临时id记录":"是" 高频使用循环模式,低频使用定时 ''' import pandas as pd import numpy as np import talib import requests import json from datetime import datetime import math import time text={ "账户":"账户", "账户类型":"STOCK", "聚宽跟单":"跟单原理", "服务器设置":"服务器跟单设置", "服务器":"http://124.220.32.224", "端口":"8025", "测试说明":"开启测试就是选择历史交易不开启就是选择今天的数据", "是否开启测试":"是", "测试数量":200, "跟单设置":"跟单设置***********", "账户跟单比例":0.5, "多策略用逗号隔开":"多策略用逗号隔开********", "组合名称":["小果测试"], "组合授权码":["xg_test"], "组合跟单比例":[1], "不同策略间隔更新时间":0, "下单默认说明":"默认/金额/数量", "下单模式":"默认", "下单值":1000, "时间设置":"时间设置********", "交易时间段":4, "交易开始时间":9, "交易结束时间":14, "是否参加集合竞价":"否", "开始交易分钟":0, "是否开启临时id记录":"是" } #记录临时id,避免循环下没有用的单子 class a: pass a=a() a.log_id=[] def init(c): #账户 c.account=text['账户'] #账户类型 c.account_type=text['账户类型'] c.url=text['服务器'] c.port=text['端口'] print('小果服务器提供数据支持************服务器{} 端口{}'.format(c.url,c.port)) #定时模式 #c.run_time("update_all_data","1nDay","2024-07-25 09:45:00") #c.run_time("update_all_data","1nDay","2024-07-25 14:45:00") #循环模式3秒 c.run_time("update_all_data","3nSecond","2024-07-25 13:20:00") #c.run_time("tarder_test","3nSecond","2024-07-25 13:20:00") print(get_account(c,c.account,c.account_type)) print(get_position(c,c.account,c.account_type)) #print(update_all_data(c)) def handlebar(c): pass def tarder_test(c): print('交易测试***************') stock='513100.SH' amount=100 maker='交易测试' passorder(23, 1101, c.account, stock, 5, 0, amount, maker,1,maker,c) def get_del_buy_sell_data(c,name='测试1',password='123456'): ''' 处理交易数据获取原始数据 ''' 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('.')[0]+'.SH' if str(x).split('.')[-1]=='XSHG' else str(x).split('.')[0]+'.SZ') 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['组合名称']=str(name) df['组合授权码']=str(password) df['策略名称']=str('聚宽跟单') df['订单ID']=df['订单ID'].astype(str) df['证券代码']=df['证券代码'].apply(lambda x: str(x)) df['投资备注']=df['组合授权码']+','+df['订单ID'] 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)) return df def get_trader_data(c,name='测试',password='123456',zh_ratio=0.1): ''' 获取交易数据 组合的跟单比例 ''' test=text['是否开启测试'] adjust_ratio=text['账户跟单比例'] is_open_id_log=text['是否开启临时id记录'] #读取跟单数据 df=get_del_buy_sell_data(c,name=name,password=password) try: df['证券代码']=df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) except: pass trader_log=get_order(c,c.account,c.account_type) now_date=str(datetime.now())[:10] #剔除撤单废单 not_list=[54,57] if trader_log.shape[0]>0: trader_log['撤单']=trader_log['委托状态'].apply(lambda x: '是' if x in not_list else '不是') trader_log=trader_log[trader_log['撤单']=='不是'] else: trader_log=trader_log if trader_log.shape[0]>0: trader_log['证券代码']=trader_log['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) trader_log['组合授权码']=trader_log['投资备注'].apply(lambda x: str(x).split(',')[0]) trader_log['订单ID']=trader_log['投资备注'].apply(lambda x: str(x).split(',')[-1]) trader_log['订单ID']=trader_log['订单ID'].astype(str) if test=='是': trader_log=trader_log else: trader_log=trader_log 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 is_open_id_log=='是': for trader_id in a.log_id: trader_id_list.append(trader_id) else: pass trader_id_list=list(set(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()): try: price=get_price(c,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=order_stock_value(c,c.account,c.account_type,stock,value,'buy') print(trader_type,amount,price) if trader_type=='buy' and amount>=10: amount=adjust_amount(c,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=order_stock_value(c,c.account,c.account_type,stock,value,'sell') if trader_type=='sell' and amount>=10: amount=adjust_amount(c,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)) except Exception as e: print(e,stock,'有问题*************') amount_list.append(0) df['数量']=amount_list not_trader=df[df['数量']<=0] #数量为0的不进入下单记录 df=df[df['数量']>=10] #df=df[df['数量']>=0] print('下单股票池))))))))))))))))))))))))') print(df) print('下单数量为0的标的可能没有持股,可能账户没有资金等待下次成交########################################################') print(not_trader) trader_log=pd.concat([trader_log,df],ignore_index=True) trader_log=trader_log.drop_duplicates(subset=['订单添加时间','订单ID','组合授权码','组合名称'],keep='last') else: print('{}组合没有需要下单标度******************'.format(name)) df=pd.DataFrame() else: print('{}没有这个组合*************'.format(name)) df=pd.DataFrame() else: print('{}交易股票池没有数据*************'.format(name)) df=pd.DataFrame() return df def start_trader_on(c,name='测试1',password='123456',zh_ratio=0.1): ''' 开始下单 ''' is_open_id_log=text['是否开启临时id记录'] df=get_trader_data(c,name,password=password,zh_ratio=zh_ratio) try: df['证券代码']=df['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x)) 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,maker, in zip(sell_df['证券代码'].tolist(),sell_df['数量'].tolist(),sell_df['投资备注'].tolist()): try: price=get_price(c,stock) passorder(24, 1101, c.account, str(stock), 5, 0, int(amount), str(maker),1,str(maker),c) print('组合{} 卖出标的{} 数量{} 价格{}'.format(name,stock,amount,price)) if is_open_id_log=='是': trader_id=str(maker).split(',')[-1] a.log_id.append(trader_id) else: pass except Exception as e: print(e) print('组合{} {}卖出有问题'.format(name,stock)) else: print('{}组合没有符合调参的卖出数据'.format(name)) buy_df=df[df['交易类型']=='buy'] if buy_df.shape[0]>0: for stock,amount,maker, in zip(buy_df['证券代码'].tolist(),buy_df['数量'].tolist(),buy_df['投资备注'].tolist()): try: price=get_price(c,stock) passorder(23, 1101, c.account, str(stock), 5, 0, int(amount), str(maker),1,str(maker),c) #passorder(23, 1101, c.account, stock, 5, 0, int(amount), '',1,'',c) print('组合{} 买入标的{} 数量{} 价格{}'.format(name,stock,amount,price)) if is_open_id_log=='是': trader_id=str(maker).split(',')[-1] a.log_id.append(trader_id) else: pass except Exception as e: print(e) print('组合{} {}买入有问题'.format(name,stock)) else: print('{}组合没有符合调参的买入数据'.format(name)) else: print('{}组合没有符合调参数据'.format(name)) #print(a.log_id) def update_all_data(c): ''' 更新策略数据 ''' if check_is_trader_date_1(): name_list=text['组合名称'] password_list=text['组合授权码'] ratio_list=text['组合跟单比例'] update_time=text['不同策略间隔更新时间'] for name,password,ratio in zip(name_list,password_list,ratio_list): start_trader_on(c,name=name,password=password,zh_ratio=ratio) time.sleep(update_time*60) else: print('跟单{} 目前不是交易时间***************'.format(datetime.now())) def order_stock_value(c,accountid,datatype,stock,value,trader_type): ''' 价值下单函数 ''' price=get_price(c,stock) hold_stock=get_position(c,accountid,datatype) if hold_stock.shape[0]>0: hold_stock=hold_stock[hold_stock['持仓量']>=10] if hold_stock.shape[0]>0: hold_df=hold_stock[hold_stock['证券代码']==stock] if hold_df.shape[0]>0: hold_amount=hold_df['持仓量'].tolist()[-1] av_amount=hold_df['可用数量'].tolist()[-1] else: hold_amount=0 av_amount=0 else: hold_amount=0 av_amount=0 else: hold_amount=0 av_amount=0 account=get_account(c,accountid,datatype) av_cash=account['可用金额'] amount=value/price if str(stock)[:2] in ['11','12']: amount=int(amount/10)*10 else: amount=int(amount/100)*100 if trader_type=='buy': if av_cash>=value and amount>=10: print('金额下单可以资金{}大于买入金额{} 买入{} 价格{} 数量{}'.format(av_cash,value,stock,price,amount)) return 'buy',amount,price else: print('金额下单可以资金{}小于买入金额{} 不买入{} 价格{} 数量{}'.format(av_cash,value,stock,price,amount)) return '','',price elif trader_type=='sell': if av_amount>=amount and amount>=10: print('金额下单 持有数量{} 可用数量{} 大于卖出数量{} 卖出{} 价格{} 数量{}'.format(hold_amount,av_amount,amount,stock,price,amount)) return 'sell',amount,price elif av_amount=10: print('金额下单 持有数量{} 可用数量{} 小于卖出数量{},可以数量大于10 卖出{} 价格{} 数量{}'.format(hold_amount,av_amount,amount,stock,price,amount)) return 'sell',amount,price else: print('金额下单 持有数量{} 可用数量{} 小于卖出数量{},不卖出{} 价格{} 数量{}'.format(hold_amount,av_amount,amount,stock,price,amount)) return 'sell',amount,price else: print('金额下单未知的交易类型{}'.format(stock)) return '',amount,price def buy(c,stock,price,amount,name): ''' 买入函数 ''' passorder(23, 1101, c.account, str(stock), 5, 0, amount,name,1,name,c) def sell(c,stock,price,amount,name): ''' 自定义卖出函数 ''' passorder(24, 1101, c.account, str(stock), 5, 0, amount,name,1,name,c) def get_price(c,stock): ''' 获取最新价格 ''' tick=c.get_full_tick(stock_code=[stock]) tick=tick[stock] price=tick['lastPrice'] return price def adjust_amount(c,stock='',amount=''): ''' 调整数量 ''' if stock[:3] in ['110','113','123','127','128','111'] or stock[:2] in ['11','12']: amount=math.floor(amount/10)*10 else: amount=math.floor(amount/100)*100 return amount def check_is_trader_date_1(): ''' 检测是不是交易时间 ''' trader_time=text['交易时间段'] start_date=text['交易开始时间'] end_date=text['交易结束时间'] start_mi=text['开始交易分钟'] jhjj=text['是否参加集合竞价'] if jhjj=='是': jhjj_time=15 else: jhjj_time=30 loc=time.localtime() tm_hour=loc.tm_hour tm_min=loc.tm_min wo=loc.tm_wday if wo<=trader_time: if tm_hour>=start_date and tm_hour<=end_date: if tm_hour==9 and tm_min=start_mi: return True else: return False else: return False else: print('周末') return False #获取账户总权益m_dBalance def get_account(c,accountid,datatype): ''' 获取账户数据 ''' accounts = get_trade_detail_data(accountid, datatype, 'account') result={} for dt in accounts: result['总资产']=dt.m_dBalance result['净资产']=dt.m_dAssureAsset result['总市值']=dt.m_dInstrumentValue result['总负债']=dt.m_dTotalDebit result['可用金额']=dt.m_dAvailable result['盈亏']=dt.m_dPositionProfit return result #获取持仓信息{code.market:手数} def get_position(c,accountid,datatype): ''' 获取持股数据 ''' positions = get_trade_detail_data(accountid,datatype, 'position') data=pd.DataFrame() print('持股数量{}'.format(len(positions))) if len(positions)>0: df=pd.DataFrame() try: for dt in positions: df['股票代码']=[dt.m_strInstrumentID] df['市场类型']=[dt.m_strExchangeID] df['证券代码']=df['股票代码']+'.'+df['市场类型'] df['证券名称']=[dt.m_strInstrumentName] df['持仓量']=[dt.m_nVolume] df['可用数量']=[dt.m_nCanUseVolume] df['成本价']=[dt.m_dOpenPrice] df['市值']=[dt.m_dInstrumentValue] df['持仓成本']=[dt.m_dPositionCost] df['盈亏']=[dt.m_dPositionProfit] data=pd.concat([data,df],ignore_index=True) except Exception as e: print('获取持股隔离股票池有问题') data=pd.DataFrame() else: data=pd.DataFrame() return data def get_order(c,accountid,datatype): ''' 获取委托 ''' data=pd.DataFrame() orders = get_trade_detail_data(accountid,datatype, 'order') print('委托数量{}'.format(len(orders))) if len(orders)>0: df=pd.DataFrame() for o in orders: df['股票代码']=[o.m_strInstrumentID] df['市场类型']=[o.m_strExchangeID] df['证券代码']=df['股票代码']+'.'+df['市场类型'] df['买卖方向']=[o.m_nOffsetFlag] df['委托数量']=[o.m_nVolumeTotalOriginal] df['成交均价']=[o.m_dTradedPrice] df['成交数量']=[o.m_nVolumeTraded] df['成交金额']=[o.m_dTradeAmount] df['投资备注']=[o.m_strRemark] df['委托状态']=[o.m_nOrderStatus] data=pd.concat([data,df],ignore_index=True) else: data=pd.DataFrame() return data def get_deal(c,accountid,datatype): ''' 获取成交 ''' data=pd.DataFrame() deals = get_trade_detail_data(account, 'stock', 'deal') print('成交数量{}'.format(len(deals))) if len(deals): df=pd.DataFrame() for dt in deals: df['股票代码']=[dt.m_strInstrumentID] df['市场类型']=[dt.m_strExchangeID] df['证券代码']=df['股票代码']+'.'+df['市场类型'] df['证券名称']=[dt.m_strInstrumentName] df['买卖方向']=[dt.m_nOffsetFlag] df['成交价格']=[dt.m_dPrice] df['成交数量']=[dt.m_nVolume] df['成交金额']=[dt.m_dTradeAmount] data=pd.concat([data,df],ignore_index=True) else: data=pd.DataFrame() class xg_jq_data: 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 ``` #### 参与贡献 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/)