Stable Diffusion WebUI 模型下载速度很慢,但挂上梯子后速度狂飙

深度学习马化云 发表了文章 • 0 个评论 • 3217 次浏览 • 2023-04-16 00:38 • 来自相关话题

安装命令:$ git clone https ://github.com/AUTOMATIC1111/stable-diffusion-webui.git

$ cd stable-diffusion-webui

$ git checkout 22bcc7be428c94e9408f589966c2040187245d81

# 我们需要 CPU 版本的 torch
$ export TORCH_COMMAND="pip install torch==1.13.1 torchvision==0.14.1 --index-url https: //download.pytorch.org/whl/cpu"
$ export USE_NNPACK=0

# 前 4 个参数是为了让其运行在 CPU 上, 最后一个参数是让 WebUI 可以远程访问
$ bash webui.sh --skip-torch-cuda-test --no-half --precision full --use-cpu all --listen
不过安装实在太慢了。而且安装好了之后,如果下载模型,还要单独下载,也是奇慢。
 
试了下把梯子代理挂上,模型下载就飞快了





 





 
除了模型,还有一些checkpoint文件
Stable diffusion v1.4
stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt
 
Stable diffusion v1.5
stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.ckpt
 
lora模型
koreanDollLikeness_v15.safetensors
 
等等。
  查看全部
安装命令:
$ git clone https ://github.com/AUTOMATIC1111/stable-diffusion-webui.git

$ cd stable-diffusion-webui

$ git checkout 22bcc7be428c94e9408f589966c2040187245d81

# 我们需要 CPU 版本的 torch
$ export TORCH_COMMAND="pip install torch==1.13.1 torchvision==0.14.1 --index-url https: //download.pytorch.org/whl/cpu"
$ export USE_NNPACK=0

# 前 4 个参数是为了让其运行在 CPU 上, 最后一个参数是让 WebUI 可以远程访问
$ bash webui.sh --skip-torch-cuda-test --no-half --precision full --use-cpu all --listen

不过安装实在太慢了。而且安装好了之后,如果下载模型,还要单独下载,也是奇慢。
 
试了下把梯子代理挂上,模型下载就飞快了

20230415005.jpg

 

202304150061.jpg

 
除了模型,还有一些checkpoint文件
Stable diffusion v1.4
stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt
 
Stable diffusion v1.5
stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.ckpt
 
lora模型
koreanDollLikeness_v15.safetensors
 
等等。
 

没有显卡GPU,想用CPU玩Stable Diffusion 本地部署AI绘图吗? 手把手保姆教程

深度学习马化云 发表了文章 • 0 个评论 • 2095 次浏览 • 2023-04-15 13:16 • 来自相关话题

 





 





 





 





 
在网上看到那些美cry的AI生成的美女图片 ,你是不是也蠢蠢欲动想要按照自己的想法生成一副属于自己的女神照呢?

什么?你的电脑显卡没有显卡? 没关系,今天笔者带大家手把手在本地电脑上使用CPU部署Stable Diffusion+Lora AI绘画 模型。
 
什么是Stable Diffusion ?

Stable Diffusion 是一种通过文字描述创造出图像的 AI 模型. 它是一个开源软件, 有许多人愿意在网络上免费分享他们的计算资源, 使得新手可以在线尝试.

 
安装

本地部署的 Stable Diffusion 有更高的可玩性, 例如允许您替换模型文件, 细致的调整参数, 以及突破线上服务的道德伦理检查等. 鉴于我目前没有可供霍霍的 GPU, 因此我将在一台本地ubuntu上部署,因为Stable Diffusion 在运行过程中大概需要吃掉 12G 内存。如果你的电脑或者服务器没有16GB以上的内存,需要配置一个虚拟内存来扩展你的内存容量,当然,性能也打个折扣,毕竟是在硬盘上扩展的内存空间。

如果你的电脑内存大小大于16GB,可以忽略以下的操作:$ dd if=/dev/zero of=/mnt/swap bs=64M count=256
$ chmod 0600 /mnt/swap
$ mkswap /mnt/swap
$ swapon /mnt/swap笔者的电脑配置:





 
然后直接安装下载并安装 Stable Diffusion WebUI:
 
稍等片刻(依赖你的网速)





 
由于需要连接到github下载源码,所以如果网络不稳定掉线,需要重新运行安装命令就可以了。
 





 
重新运行:bash webui.sh --skip-torch-cuda-test --no-half --precision full --use-cpu all --listen
这个脚本会自动创建python的虚拟环境,并安装对应的pip依赖,一键到位,可谓贴心。果断要到github上给原作者加星
 





 
等待一段时间, 在浏览器中打开 127.0.0.1:7860 即可见到 UI 界面.
 
 
下载更多模型

模型, 有时称为检查点文件(checkpoint), 是预先训练的 Stable Diffusion 权重, 用于生成一般或特定的图像类型. 模型可以生成的图像取决于用于训练它们的数据. 如果训练数据中没有猫, 模型将无法产生猫的形象. 同样, 如果您仅使用猫图像训练模型, 则只会产生猫.

Stable Diffusion WebUI 运行时会自动下载 Stable Diffusion v1.5 模型. 下面提供了一些快速下载其它模型的命令.$ cd models/Stable-diffusion​# Stable diffusion v1.4
# 下面的URL超链接过长有省略号,需要右键复制url$ wget https://huggingface.co/CompVis ... .ckpt




# Stable diffusion v1.5$ wget https://huggingface.co/runwaym ... .ckpt# F222$ wget https://huggingface.co/acheong ... .ckpt# Anything V3$ wget
https://huggingface.co/Linaqru ... nsors

# Open Journey$ wget https://huggingface.co/prompth ... .ckpt# DreamShaper$ wget https://civitai.com/api/download/models/5636 -O dreamshaper_331BakedVae.safetensors# ChilloutMix$ wget https://civitai.com/api/download/models/11745 -O chilloutmix_NiPrunedFp32Fix.safetensors# Robo Diffusion$ wget
https://huggingface.co/nousr/r ... .ckpt

# Mo-di-diffusion$ wget
https://huggingface.co/nitroso ... .ckpt

# Inkpunk Diffusion$ wget
https://huggingface.co/Envvi/I ... .ckpt

修改配置文件

ui-config.json 内包含众多的设置项, 可按照个人的习惯修改部分默认值. 例如我的配置部分如下:{
"txt2img/Batch size/value": 4,
"txt2img/Width/value": 480,
"txt2img/Height/value": 270
}提示语示例model: chilloutmix_NiPrunedFp32Fix.safetensors

prompt: beautiful, masterpiece, best quality, extremely detailed face, perfect lighting, (1girl, solo, 1boy, 1girl, NemoNelly, Slight penetration, lying, on back, spread legs:1.5), street, crowd, ((skinny)), ((puffy eyes)), brown hair, medium hair, cowboy shot, medium breasts, swept bangs, walking, outdoors, sunshine, light_rays, fantasy, rococo, hair_flower,low tied hair, smile, half-closed eyes, dating, (nude), nsfw, (heavy breathing:1.5), tears, crying, blush, wet, sweat, <lora:koreanDollLikeness_v15:0.4>, <lora:povImminentPenetration_ipv1:0>, <lora:breastinclassBetter_v14:0.1>
prompt: paintings, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, age spot, (ugly:1.331), (duplicate:1.331), (morbid:1.21), (mutilated:1.21), (tranny:1.331), mutated hands, (poorly drawn hands:1.331), blurry, (bad anatomy:1.21), (bad proportions:1.331), extra limbs, (disfigured:1.331), (missing arms:1.331), (extra legs:1.331), (fused fingers:1.61051), (too many fingers:1.61051), (unclear eyes:1.331), bad hands, missing fingers, extra digit, bad body, pubic
上述提示词结尾引用了 3 个 Lora 模型, 需提前下载至 models/Lora 目录.$ cd models/Lora

$ wget
https://huggingface.co/amornln ... nsors




$ wget
https://huggingface.co/samle/s ... nsors

$ wget https://huggingface.co/jomcs/N ... nsors生成的效果图:





 
 
  查看全部
v2-6d1a26989d9d1f455abbdaa930f8bae3_r.jpg


v2-3f0519e151bbb99fa49934670ec8d0a4_r.jpg

 

v2-992a54d0863a4b1ab6cacc0fe597d81b_r.jpg

 

20230415001.jpg

 

v2-efee1a21df13b177267f31889efc5b40_r.jpg

 

v2-c2e1a2a3a1b0849b3f2b7efb3083fd6b_r.jpg

 
在网上看到那些美cry的AI生成的美女图片 ,你是不是也蠢蠢欲动想要按照自己的想法生成一副属于自己的女神照呢?

什么?你的电脑显卡没有显卡? 没关系,今天笔者带大家手把手在本地电脑上使用CPU部署Stable Diffusion+Lora AI绘画 模型。
 
什么是Stable Diffusion ?


Stable Diffusion 是一种通过文字描述创造出图像的 AI 模型. 它是一个开源软件, 有许多人愿意在网络上免费分享他们的计算资源, 使得新手可以在线尝试.


 
安装

本地部署的 Stable Diffusion 有更高的可玩性, 例如允许您替换模型文件, 细致的调整参数, 以及突破线上服务的道德伦理检查等. 鉴于我目前没有可供霍霍的 GPU, 因此我将在一台本地ubuntu上部署,因为Stable Diffusion 在运行过程中大概需要吃掉 12G 内存。如果你的电脑或者服务器没有16GB以上的内存,需要配置一个虚拟内存来扩展你的内存容量,当然,性能也打个折扣,毕竟是在硬盘上扩展的内存空间。

如果你的电脑内存大小大于16GB,可以忽略以下的操作:
$ dd if=/dev/zero of=/mnt/swap bs=64M count=256
$ chmod 0600 /mnt/swap
$ mkswap /mnt/swap
$ swapon /mnt/swap
笔者的电脑配置:

20230415004.jpg

 
然后直接安装下载并安装 Stable Diffusion WebUI:
 
稍等片刻(依赖你的网速)

20230415002.jpg

 
由于需要连接到github下载源码,所以如果网络不稳定掉线,需要重新运行安装命令就可以了。
 

20230415003.jpg

 
重新运行:
bash webui.sh --skip-torch-cuda-test --no-half --precision full --use-cpu all --listen

这个脚本会自动创建python的虚拟环境,并安装对应的pip依赖,一键到位,可谓贴心。果断要到github上给原作者加星
 

v2-a85a91949b0f08315abd104425ecf7ee_r-v1.jpg

 
等待一段时间, 在浏览器中打开 127.0.0.1:7860 即可见到 UI 界面.
 
 
下载更多模型

模型, 有时称为检查点文件(checkpoint), 是预先训练的 Stable Diffusion 权重, 用于生成一般或特定的图像类型. 模型可以生成的图像取决于用于训练它们的数据. 如果训练数据中没有猫, 模型将无法产生猫的形象. 同样, 如果您仅使用猫图像训练模型, 则只会产生猫.

Stable Diffusion WebUI 运行时会自动下载 Stable Diffusion v1.5 模型. 下面提供了一些快速下载其它模型的命令.
$ cd models/Stable-diffusion​
# Stable diffusion v1.4
# 下面的URL超链接过长有省略号,需要右键复制url
$ wget https://huggingface.co/CompVis ... .ckpt




# Stable diffusion v1.5
$ wget https://huggingface.co/runwaym ... .ckpt
# F222
$ wget https://huggingface.co/acheong ... .ckpt
# Anything V3
$ wget 
https://huggingface.co/Linaqru ... nsors

# Open Journey
$ wget https://huggingface.co/prompth ... .ckpt
# DreamShaper
$ wget https://civitai.com/api/download/models/5636 -O dreamshaper_331BakedVae.safetensors
# ChilloutMix
$ wget https://civitai.com/api/download/models/11745 -O chilloutmix_NiPrunedFp32Fix.safetensors
# Robo Diffusion
$ wget 
https://huggingface.co/nousr/r ... .ckpt

# Mo-di-diffusion
$ wget 
https://huggingface.co/nitroso ... .ckpt

# Inkpunk Diffusion
$ wget 
https://huggingface.co/Envvi/I ... .ckpt

修改配置文件

ui-config.json 内包含众多的设置项, 可按照个人的习惯修改部分默认值. 例如我的配置部分如下:
{
"txt2img/Batch size/value": 4,
"txt2img/Width/value": 480,
"txt2img/Height/value": 270
}
提示语示例
model: chilloutmix_NiPrunedFp32Fix.safetensors

prompt: beautiful, masterpiece, best quality, extremely detailed face, perfect lighting, (1girl, solo, 1boy, 1girl, NemoNelly, Slight penetration, lying, on back, spread legs:1.5), street, crowd, ((skinny)), ((puffy eyes)), brown hair, medium hair, cowboy shot, medium breasts, swept bangs, walking, outdoors, sunshine, light_rays, fantasy, rococo, hair_flower,low tied hair, smile, half-closed eyes, dating, (nude), nsfw, (heavy breathing:1.5), tears, crying, blush, wet, sweat, <lora:koreanDollLikeness_v15:0.4>, <lora:povImminentPenetration_ipv1:0>, <lora:breastinclassBetter_v14:0.1>
prompt: paintings, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, age spot, (ugly:1.331), (duplicate:1.331), (morbid:1.21), (mutilated:1.21), (tranny:1.331), mutated hands, (poorly drawn hands:1.331), blurry, (bad anatomy:1.21), (bad proportions:1.331), extra limbs, (disfigured:1.331), (missing arms:1.331), (extra legs:1.331), (fused fingers:1.61051), (too many fingers:1.61051), (unclear eyes:1.331), bad hands, missing fingers, extra digit, bad body, pubic

上述提示词结尾引用了 3 个 Lora 模型, 需提前下载至 models/Lora 目录.
$ cd models/Lora

$ wget
https://huggingface.co/amornln ... nsors




$ wget 
https://huggingface.co/samle/s ... nsors

$ wget https://huggingface.co/jomcs/N ... nsors
生成的效果图:

11102.png

 
 
 

QMT vs Ptrade 速度对比 (一) 历史行情获取速度

QMT李魔佛 发表了文章 • 0 个评论 • 2218 次浏览 • 2023-04-11 16:45 • 来自相关话题

众所周知(狗头),QMT是在你本地电脑运行的,包括行情获取,计算指标,选股选债,下单都在你的本地电脑执行。行情数据通过网络去券商服务器或者迅投(QMT)服务器获取,拿到数据在你的本地电脑处理,比如计算涨速,量比,然后再使用下单接口把下单指令通过网络提交到券商柜台,券商柜台接到QMT的委托指令后,再提交给交易所。

Ptrade(恒生电子)则是在券商部署的服务器上执行,你下载的Ptrade在你的本地电脑,只是负责写代码,把代码部署到券商服务器,然后在券商服务其执行你的策略,当然你的代码在券商服务器运行时是被加密的。行情获取,计算指标,下单委托都在券商机房内部执行,属于云策略的类型,策略部署好了,就不需要开着本地电脑观察它的状态。

对比环境均为同一个券商下的QMT和Ptrade,均为生产环境的实盘版本。(PS:温馨提示,平时少用模拟版本,bug多,交易不准,还浪费时间。我平时调试都直接在实盘上调试的,要对自己的策略有信心哈,至少回测过了的嘛O(∩_∩)O~~)

历史行情数据获取

目标:获取2022年到昨天的沪深300所有股票的日线收盘价数据。

QMT

获取行情数据 使用这个函数:ContextInfo.get_market_data()用法: ContextInfo.get_market_data(fields, stock_code = , start_time = '',
end_time = '', skip_paused = True, period = 'follow',
dividend_type = 'follow', count = -1)
 open -- 开盘价(str:numpy.float64);
high -- 最高价(str:numpy.float64);
low --最低价(str:numpy.float64);
close -- 收盘价(str:numpy.float64);
volume -- 交易量(str:numpy.float64);
money -- 交易金额(str:numpy.float64);
price -- 最新价(str:numpy.float64);
preclose -- 昨收盘价(str:numpy.float64)(仅日线返回);
high_limit -- 涨停价(str:numpy.float64)(仅日线返回);
low_limit -- 跌停价(str:numpy.float64)(仅日线返回);
unlimited -- 判断查询日是否无涨跌停限制(1:该日无涨跌停限制;0:该日有涨跌停限制)(str:numpy.float64)(仅日线返回);
 
在fields里面指定只获取close价格即可。

QMT测试代码如下:(需要的也可以后台留言回复获取)

[vscode里面的代码,需要复制到qmt里面执行]

把代码复制到QMT里面,然后切换到模型交易,在中间切换到实盘模式,就会运行上面代码。

注意,这里需要第一次运行上面的代码来计算时间,因为QMT会有个cache缓存机制,它会把曾经跑过的历史数据自动下载下来,保存到你的电脑硬盘里,从而加快QMT后续的读取速度,同样的数据没有必要每次再去网络上拉。

大部分情况下网络IO都会是任何一个量化交易系通最大的性能瓶颈。

运行得到下面的结果:







上面运行时间是22秒。不要惊讶哦,首次获取历史行情数据都是挺慢的。如果你的电脑网速够快,或者但在阿里云,腾讯云之类的云服务上跑,获取历史行情速度会有所提高。

在你运行了上面的代码之后,QMT会在某个时刻,在后台把数据下载到本地QMT安装目录下。








文件按照股票代码作为文件名存储。当然里面不是txt格式,而是QMT做了相应的封装的。上面按照修改日期排序,4月11日多了很多新的DAT数据文件,显然是刚刚生成的。

QMT在获取历史行情数据后,会有个触发器,在后台一次性保存大量的文件,所以QMT会在某一个瞬间,界面会出现卡顿,甚至无响应,而看任务管理器会看到内存飙升甚至爆满100%,有些新人菜鸟就认为QMT太占内存,太垃圾的结论,这也是片面的。实际上在数据完备的情况下,QMT需要的内存4GB就够的了。如果你经常会有扫描全市场股票代码历史数据的话,内存还是尽量选大一点的。如果无法避免内存突然飙升,可以每次把获取行情的股票代码列表减少,细分多几批获取,用时间换空间。

当然 QMT也提供了一个下载历史数据的一个菜单入口,用于在图形界面下手动下载历史行情,从而加速历史行情读取速度。








等数据下载完成后,

第二次跑上面的同一个代码,运行时间明显快了。








但用时还是要7.9秒,反复测试几次,获取时间依然是在6-8秒之间波动。 因为程序读取历史行情数据的一个个独立的文件,所以这里硬盘的性能因素对获取行情影响还是很大的。

笔者感觉7.9秒这个速度还是很慢的,换了台性能好一点的的windows机子,下载了历史数据后再跑了一次:







但用时依然在6秒左右。

所以个人是不推荐大家在tick策略里面,在盘中去获取历史数据的,这个动作应该在盘前就应该完成,把数据保存到内存列表或者dataframe变量中,盘中用的时候去取就可以了。 当然低频策略就无所谓啦。

Ptrade

操作上ptrade相对而言更加简洁,容易上手。

它的API设计和它对应的API文档更加规范,可读性更好。

直接把代码复制到量化->策略,新建策略,然后在交易里面添加策略,直接启动策略。代码设置定时运行,在启动策略后的一分钟后运行。








同样获取沪深300的日线数据,2022年1月到2023年4月10日。
get_price - 获取历史数据 get_price(security, start_date=None, end_date=None, frequency='1d', fields=None, fq=None, count=None)
运行 







上面的结果显示,Ptrade获取同样的历史数据耗时只有700毫秒,0.7秒左右。测试多几次,获取时间基本每次都比较平稳,在0.6-0.8秒之间。(下面打印的306不是沪深300的个数,而是获取到的日期的天数,它返回的结构虽然都是panel,但和QMT的轴有点不同)。

结论

总的来说,获取历史行情数据的速度,Ptrade是秒杀了QMT的,不在一个量级上的。

本来想继续对比实时行情,下单延时对比等等,但开盘时间有限,写了一下时间就不够用了。所以把教程拆分为多个系列,下一篇再对比QMT和PTrade的实时行情数据,下单回调等等啦。


如果想要自己测试文中的数据,可以获取代码,公众号 后台回复: 历史行情数据代码

参考API接口文档:

Ptrade: http://ptradeapi.com/

QMT: http://qmt.ptradeapi.com/
 
公众号: 查看全部
众所周知(狗头),QMT是在你本地电脑运行的,包括行情获取,计算指标,选股选债,下单都在你的本地电脑执行。行情数据通过网络去券商服务器或者迅投(QMT)服务器获取,拿到数据在你的本地电脑处理,比如计算涨速,量比,然后再使用下单接口把下单指令通过网络提交到券商柜台,券商柜台接到QMT的委托指令后,再提交给交易所。

Ptrade(恒生电子)则是在券商部署的服务器上执行,你下载的Ptrade在你的本地电脑,只是负责写代码,把代码部署到券商服务器,然后在券商服务其执行你的策略,当然你的代码在券商服务器运行时是被加密的。行情获取,计算指标,下单委托都在券商机房内部执行,属于云策略的类型,策略部署好了,就不需要开着本地电脑观察它的状态。

对比环境均为同一个券商下的QMT和Ptrade,均为生产环境的实盘版本。(PS:温馨提示,平时少用模拟版本,bug多,交易不准,还浪费时间。我平时调试都直接在实盘上调试的,要对自己的策略有信心哈,至少回测过了的嘛O(∩_∩)O~~)

历史行情数据获取

目标:获取2022年到昨天的沪深300所有股票的日线收盘价数据。

QMT

获取行情数据 使用这个函数:ContextInfo.get_market_data()
用法: ContextInfo.get_market_data(fields, stock_code = , start_time = '', 
end_time = '', skip_paused = True, period = 'follow',
dividend_type = 'follow', count = -1)

 
open -- 开盘价(str:numpy.float64);
high -- 最高价(str:numpy.float64);
low --最低价(str:numpy.float64);
close -- 收盘价(str:numpy.float64);
volume -- 交易量(str:numpy.float64);
money -- 交易金额(str:numpy.float64);
price -- 最新价(str:numpy.float64);
preclose -- 昨收盘价(str:numpy.float64)(仅日线返回);
high_limit -- 涨停价(str:numpy.float64)(仅日线返回);
low_limit -- 跌停价(str:numpy.float64)(仅日线返回);
unlimited -- 判断查询日是否无涨跌停限制(1:该日无涨跌停限制;0:该日有涨跌停限制)(str:numpy.float64)(仅日线返回);

 
在fields里面指定只获取close价格即可。

QMT测试代码如下:(需要的也可以后台留言回复获取)

[vscode里面的代码,需要复制到qmt里面执行]

把代码复制到QMT里面,然后切换到模型交易,在中间切换到实盘模式,就会运行上面代码。

注意,这里需要第一次运行上面的代码来计算时间,因为QMT会有个cache缓存机制,它会把曾经跑过的历史数据自动下载下来,保存到你的电脑硬盘里,从而加快QMT后续的读取速度,同样的数据没有必要每次再去网络上拉。

大部分情况下网络IO都会是任何一个量化交易系通最大的性能瓶颈。

运行得到下面的结果:


20230411015.jpg


上面运行时间是22秒。不要惊讶哦,首次获取历史行情数据都是挺慢的。如果你的电脑网速够快,或者但在阿里云,腾讯云之类的云服务上跑,获取历史行情速度会有所提高。

在你运行了上面的代码之后,QMT会在某个时刻,在后台把数据下载到本地QMT安装目录下。


20230411014.jpg



文件按照股票代码作为文件名存储。当然里面不是txt格式,而是QMT做了相应的封装的。上面按照修改日期排序,4月11日多了很多新的DAT数据文件,显然是刚刚生成的。

QMT在获取历史行情数据后,会有个触发器,在后台一次性保存大量的文件,所以QMT会在某一个瞬间,界面会出现卡顿,甚至无响应,而看任务管理器会看到内存飙升甚至爆满100%,有些新人菜鸟就认为QMT太占内存,太垃圾的结论,这也是片面的。实际上在数据完备的情况下,QMT需要的内存4GB就够的了。如果你经常会有扫描全市场股票代码历史数据的话,内存还是尽量选大一点的。如果无法避免内存突然飙升,可以每次把获取行情的股票代码列表减少,细分多几批获取,用时间换空间。

当然 QMT也提供了一个下载历史数据的一个菜单入口,用于在图形界面下手动下载历史行情,从而加速历史行情读取速度。


20230411017.jpg



等数据下载完成后,

第二次跑上面的同一个代码,运行时间明显快了。


20230411018.jpg



但用时还是要7.9秒,反复测试几次,获取时间依然是在6-8秒之间波动。 因为程序读取历史行情数据的一个个独立的文件,所以这里硬盘的性能因素对获取行情影响还是很大的。

笔者感觉7.9秒这个速度还是很慢的,换了台性能好一点的的windows机子,下载了历史数据后再跑了一次:


20230411019.jpg


但用时依然在6秒左右。

所以个人是不推荐大家在tick策略里面,在盘中去获取历史数据的,这个动作应该在盘前就应该完成,把数据保存到内存列表或者dataframe变量中,盘中用的时候去取就可以了。 当然低频策略就无所谓啦。

Ptrade

操作上ptrade相对而言更加简洁,容易上手。

它的API设计和它对应的API文档更加规范,可读性更好。

直接把代码复制到量化->策略,新建策略,然后在交易里面添加策略,直接启动策略。代码设置定时运行,在启动策略后的一分钟后运行。


20230411016.jpg



同样获取沪深300的日线数据,2022年1月到2023年4月10日。
get_price - 获取历史数据 get_price(security, start_date=None, end_date=None, frequency='1d', fields=None, fq=None, count=None)
运行 

20230411013.jpg



上面的结果显示,Ptrade获取同样的历史数据耗时只有700毫秒,0.7秒左右。测试多几次,获取时间基本每次都比较平稳,在0.6-0.8秒之间。(下面打印的306不是沪深300的个数,而是获取到的日期的天数,它返回的结构虽然都是panel,但和QMT的轴有点不同)。

结论

总的来说,获取历史行情数据的速度,Ptrade是秒杀了QMT的,不在一个量级上的。

本来想继续对比实时行情,下单延时对比等等,但开盘时间有限,写了一下时间就不够用了。所以把教程拆分为多个系列,下一篇再对比QMT和PTrade的实时行情数据,下单回调等等啦。


如果想要自己测试文中的数据,可以获取代码,公众号 后台回复: 历史行情数据代码

参考API接口文档:

Ptrade: http://ptradeapi.com/

QMT: http://qmt.ptradeapi.com/
 
公众号:

Ptrade QMT实盘策略记录 - 不定期更新

量化交易李魔佛 发表了文章 • 0 个评论 • 1994 次浏览 • 2023-04-03 15:27 • 来自相关话题

简单记录当前使用Ptrade和QMT编写策略的情况。(只记录大体的意思,不透露具体策略细节,除非是那种烂大街的策略,什么macd,均线,双低,小市值等等)
写出来的是已经实现且实盘稳定运行的;
涨停板;依赖ptrade的高速行情自动配合手动;两融账户的股票日内做T,持有底仓;股票小市值轮动+多因子可转债多因子(有N个版本+不同的排除因子 组合)可转债日内高频股票趋势动量ETF轮动套利脉冲卖出扫描
 
 
纯粹自己做的记录,便于自己平时复盘。






有兴趣的朋友可以关注公众号交流。 查看全部
简单记录当前使用Ptrade和QMT编写策略的情况。(只记录大体的意思,不透露具体策略细节,除非是那种烂大街的策略,什么macd,均线,双低,小市值等等)
写出来的是已经实现且实盘稳定运行的;
  1. 涨停板;依赖ptrade的高速行情自动配合手动;
  2. 两融账户的股票日内做T,持有底仓;
  3. 股票小市值轮动+多因子
  4. 可转债多因子(有N个版本+不同的排除因子 组合)
  5. 可转债日内高频
  6. 股票趋势动量
  7. ETF轮动套利
  8. 脉冲卖出扫描

 
 
纯粹自己做的记录,便于自己平时复盘。

20230403001.jpg


有兴趣的朋友可以关注公众号交流。

ptrade担保品买卖,融资买入,融券卖出,卖券还款,买券还券 下单后回调函数里面的结构

Ptrade李魔佛 发表了文章 • 0 个评论 • 1181 次浏览 • 2023-03-31 21:44 • 来自相关话题

【ptrade的稳定性,获取行情速度,实盘交易,回测速度无意不秒杀QMT的。
而对于不能安装第三方库的原因,不少菜鸟转而选择了QMT。有点可惜了ptrade。ptrade其实也可以联通外部数据。
ptrade软件设计层面和体验是企业级的,而QMT就呵呵哒,0售后技术支持,软件bug层出不穷。里面的某个别的工程师(袁姓)素质也是底下,我星球上的代码他也抄过去,抄过去后呢 放到他自己付费星球,而且还不止一篇。】
而ptrade相对而言,恒生电子的工程师服务就很到位,发送日志给他们,会在一天内分析结果告知你哪些出现问题了。
 
题外话说多了。
 
ptrade支持两融账户的量化操作。
如:担保品买卖,融资买入,融券卖出,卖券还款,买券还券margin_trade - 担保品买卖

margincash_open - 融资买入

margincash_close - 卖券还款

margincash_direct_refund - 直接还款

marginsec_open - 融券卖出

marginsec_close - 买券还券




它们之间的参数都比较相近:

margin_xxxx(security, amount, limit_price=None)

security:股票代码(str);

amount:交易数量,输入正数(int);

limit_price:买卖限价(float);
 
而用它们进行买卖操作后,在on_trade_response回调函数里面的机构提如下:
 
担保品买入:2023-03-31 14:41:02 - INFO - 生成订单,订单号:cd25d27f39854721aac99db13c9e9b73股票代码:601328.SS 数量:信用买入1000
2023-03-31 14:41:02 - INFO - {'error_info': '', 'stock_code': '601328.SS', 'order_id': 'cd25d27f39854721aac99db13c9e9b73', 'status': '2', 'price': 5.1, 'entrust_type': '9', 'amount': 1000, 'business_amount': 0.0, 'entrust_prop': '0', 'entrust_no': '1', 'order_time': '2023-03-31 14:35:53.776'}
2023-03-31 14:41:02 - INFO - {'business_amount': 1000, 'order_id': 'cd25d27f39854721aac99db13c9e9b73', 'stock_code': '601328.SS', 'entrust_bs': '1', 'entrust_no': '1', 'status': '8', 'business_balance': 5100.0, 'business_price': 5.1, 'business_id': '2', 'business_time': '2023-03-31 14:39:17'} 
 
 
  
 融资买入:2023-03-31 14:52:00 - INFO - 生成订单,订单号:01b7851d37014709bde3ec6ebe9e89c3股票代码:601328.SS 数量:融资买入100
2023-03-31 14:52:00 - INFO - {'price': 5.1, 'entrust_prop': '0', 'status': '2', 'entrust_type': '6', 'stock_code': '601328.SS', 'business_amount': 0.0, 'entrust_no': '3', 'order_time': '2023-03-31 14:46:51.620', 'error_info': '', 'amount': 100, 'order_id': '01b7851d37014709bde3ec6ebe9e89c3'}
2023-03-31 14:52:00 - INFO - {'business_id': '4', 'business_balance': 509.99999999999994, 'business_price': 5.1, 'order_id': '01b7851d37014709bde3ec6ebe9e89c3', 'business_time': '2023-03-31 14:50:14', 'status': '8', 'entrust_bs': '1', 'business_amount': 100, 'entrust_no': '3', 'stock_code': '601328.SS'} 
 
卖券还款2023-03-31 14:58:20 - INFO - start
2023-03-31 14:59:00 - INFO - 生成订单,订单号:20cef28ec52c4d41b09c80fc49167497股票代码:600269.SS 数量:卖券还款-200
2023-03-31 14:59:00 - INFO - {'business_amount': 0.0, 'amount': -200, 'stock_code': '600269.SS', 'error_info': '', 'order_time': '2023-03-31 14:53:51.375', 'price': 3.38, 'entrust_type': '6', 'status': '2', 'order_id': '20cef28ec52c4d41b09c80fc49167497', 'entrust_prop': '0', 'entrust_no': '5'}
2023-03-31 14:59:00 - INFO - {'status': '8', 'business_time': '2023-03-31 14:57:14', 'stock_code': '600269.SS', 'entrust_bs': '2', 'business_id': '6', 'business_balance': -676.0, 'business_amount': -200, 'order_id': '20cef28ec52c4d41b09c80fc49167497', 'business_price': 3.38, 'entrust_no': '5'}
返回的结构体和那个普通账户交易的回调函数基本一致的。
 
  查看全部

【ptrade的稳定性,获取行情速度,实盘交易,回测速度无意不秒杀QMT的。
而对于不能安装第三方库的原因,不少菜鸟转而选择了QMT。有点可惜了ptrade。ptrade其实也可以联通外部数据。
ptrade软件设计层面和体验是企业级的,而QMT就呵呵哒,0售后技术支持,软件bug层出不穷。里面的某个别的工程师(袁姓)素质也是底下,我星球上的代码他也抄过去,抄过去后呢 放到他自己付费星球,而且还不止一篇。】
而ptrade相对而言,恒生电子的工程师服务就很到位,发送日志给他们,会在一天内分析结果告知你哪些出现问题了。
 
题外话说多了。
 
ptrade支持两融账户的量化操作。
如:担保品买卖,融资买入,融券卖出,卖券还款,买券还券
margin_trade - 担保品买卖

margincash_open - 融资买入

margincash_close - 卖券还款

margincash_direct_refund - 直接还款

marginsec_open - 融券卖出

marginsec_close - 买券还券




它们之间的参数都比较相近:

margin_xxxx(security, amount, limit_price=None)

security:股票代码(str);

amount:交易数量,输入正数(int);

limit_price:买卖限价(float);
 
而用它们进行买卖操作后,在on_trade_response回调函数里面的机构提如下:
 
担保品买入:
2023-03-31 14:41:02 - INFO - 生成订单,订单号:cd25d27f39854721aac99db13c9e9b73股票代码:601328.SS 数量:信用买入1000
2023-03-31 14:41:02 - INFO - {'error_info': '', 'stock_code': '601328.SS', 'order_id': 'cd25d27f39854721aac99db13c9e9b73', 'status': '2', 'price': 5.1, 'entrust_type': '9', 'amount': 1000, 'business_amount': 0.0, 'entrust_prop': '0', 'entrust_no': '1', 'order_time': '2023-03-31 14:35:53.776'}
2023-03-31 14:41:02 - INFO - {'business_amount': 1000, 'order_id': 'cd25d27f39854721aac99db13c9e9b73', 'stock_code': '601328.SS', 'entrust_bs': '1', 'entrust_no': '1', 'status': '8', 'business_balance': 5100.0, 'business_price': 5.1, 'business_id': '2', 'business_time': '2023-03-31 14:39:17'}
 
 
 
  
 融资买入:
2023-03-31 14:52:00 - INFO - 生成订单,订单号:01b7851d37014709bde3ec6ebe9e89c3股票代码:601328.SS 数量:融资买入100
2023-03-31 14:52:00 - INFO - {'price': 5.1, 'entrust_prop': '0', 'status': '2', 'entrust_type': '6', 'stock_code': '601328.SS', 'business_amount': 0.0, 'entrust_no': '3', 'order_time': '2023-03-31 14:46:51.620', 'error_info': '', 'amount': 100, 'order_id': '01b7851d37014709bde3ec6ebe9e89c3'}
2023-03-31 14:52:00 - INFO - {'business_id': '4', 'business_balance': 509.99999999999994, 'business_price': 5.1, 'order_id': '01b7851d37014709bde3ec6ebe9e89c3', 'business_time': '2023-03-31 14:50:14', 'status': '8', 'entrust_bs': '1', 'business_amount': 100, 'entrust_no': '3', 'stock_code': '601328.SS'}
 
 
卖券还款
2023-03-31 14:58:20 - INFO - start
2023-03-31 14:59:00 - INFO - 生成订单,订单号:20cef28ec52c4d41b09c80fc49167497股票代码:600269.SS 数量:卖券还款-200
2023-03-31 14:59:00 - INFO - {'business_amount': 0.0, 'amount': -200, 'stock_code': '600269.SS', 'error_info': '', 'order_time': '2023-03-31 14:53:51.375', 'price': 3.38, 'entrust_type': '6', 'status': '2', 'order_id': '20cef28ec52c4d41b09c80fc49167497', 'entrust_prop': '0', 'entrust_no': '5'}
2023-03-31 14:59:00 - INFO - {'status': '8', 'business_time': '2023-03-31 14:57:14', 'stock_code': '600269.SS', 'entrust_bs': '2', 'business_id': '6', 'business_balance': -676.0, 'business_amount': -200, 'order_id': '20cef28ec52c4d41b09c80fc49167497', 'business_price': 3.38, 'entrust_no': '5'}

返回的结构体和那个普通账户交易的回调函数基本一致的。
 
 

Ptrade融资融券双均线 代码 讲解

Ptrade李魔佛 发表了文章 • 0 个评论 • 1423 次浏览 • 2023-03-31 02:08 • 来自相关话题

因为一些融资融券的函数只能在交易模块使用,所以如果需要模拟的话,可以使用模拟端进行交易。
 
def initialize(context):
# 初始化策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = "600300.SS"
set_universe(g.security)

def before_trading_start(context, data):
# 买入标识
g.order_buy_flag = False
# 卖出标识
g.order_sell_flag = False

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def handle_data(context, data):
# 得到十日历史价格
df = get_history(10, "1d", "close", g.security, fq=None, include=False)
# 得到五日均线价格
ma5 = round(df["close"][-5:].mean(), 3)
# 得到十日均线价格
ma10 = round(df["close"][-10:].mean(), 3)
# 取得昨天收盘价
price = data[g.security]["close"]
# 如果五日均线大于十日均线
if ma5 > ma10:
if not g.order_buy_flag:
# 获取最大可融资数量
amount = get_margincash_open_amount(g.security).get(g.security)
# 进行融资买入操作
margincash_open(g.security, amount)
# 记录这次操作
log.info("Buying %s Amount %s" % (g.security, amount))
# 当日已融资买入
g.order_buy_flag = True

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(g.security).amount > 0:
if not g.order_sell_flag:
# 获取标的卖券还款最大可卖数量
amount = get_margincash_close_amount(g.security).get(g.security)
# 进行卖券还款操作
margincash_close(g.security, -amount)
# 记录这次操作
log.info("Selling %s Amount %s" % (g.security, amount))
# 当日已卖券还款
g.order_sell_flag = True  查看全部
因为一些融资融券的函数只能在交易模块使用,所以如果需要模拟的话,可以使用模拟端进行交易。
 
def initialize(context):
# 初始化策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = "600300.SS"
set_universe(g.security)

def before_trading_start(context, data):
# 买入标识
g.order_buy_flag = False
# 卖出标识
g.order_sell_flag = False

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def handle_data(context, data):
# 得到十日历史价格
df = get_history(10, "1d", "close", g.security, fq=None, include=False)
# 得到五日均线价格
ma5 = round(df["close"][-5:].mean(), 3)
# 得到十日均线价格
ma10 = round(df["close"][-10:].mean(), 3)
# 取得昨天收盘价
price = data[g.security]["close"]
# 如果五日均线大于十日均线
if ma5 > ma10:
if not g.order_buy_flag:
# 获取最大可融资数量
amount = get_margincash_open_amount(g.security).get(g.security)
# 进行融资买入操作
margincash_open(g.security, amount)
# 记录这次操作
log.info("Buying %s Amount %s" % (g.security, amount))
# 当日已融资买入
g.order_buy_flag = True

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(g.security).amount > 0:
if not g.order_sell_flag:
# 获取标的卖券还款最大可卖数量
amount = get_margincash_close_amount(g.security).get(g.security)
# 进行卖券还款操作
margincash_close(g.security, -amount)
# 记录这次操作
log.info("Selling %s Amount %s" % (g.security, amount))
# 当日已卖券还款
g.order_sell_flag = True
 

Ptrade担保品买入卖出

Ptrade李魔佛 发表了文章 • 0 个评论 • 1183 次浏览 • 2023-03-31 01:31 • 来自相关话题

担保品卖出指的是融资融券交易当中,用自有资金进行买卖的行为

 
实际上是买卖股票,但在信用账户上,用只有资金买卖股票。
 
ptrade支持两融操作。
 
比如下面的示例代告诉我们,担保品买入股票的3个不同参数的效果:def initialize(context):
g.security = '600570.SS'
set_universe(g.security)

def handle_data(context, data):
# 以系统最新价委托
margin_trade(g.security, 100)
# 以72块价格下一个限价单
margin_trade(g.security, 100, limit_price=72)
# 以最优五档即时成交剩余撤销委托
margin_trade(g.security, 200, market_type=4) security:股票代码(str);

amount:交易数量,正数表示买入,负数表示卖出(int);

limit_price:买卖限价(float);

market_type:市价委托类型,上证非科创板股票支持参数1、4,上证科创板股票支持参数0、1、2、4,深证股票支持参数0、2、3、4、5(int);

0:对手方最优价格;
1:最优五档即时成交剩余转限价;
2:本方最优价格;
3:即时成交剩余撤销;
4:最优五档即时成交剩余撤销;
5:全额成交或撤单; 查看全部


担保品卖出指的是融资融券交易当中,用自有资金进行买卖的行为


 
实际上是买卖股票,但在信用账户上,用只有资金买卖股票。
 
ptrade支持两融操作。
 
比如下面的示例代告诉我们,担保品买入股票的3个不同参数的效果:
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)

def handle_data(context, data):
# 以系统最新价委托
margin_trade(g.security, 100)
# 以72块价格下一个限价单
margin_trade(g.security, 100, limit_price=72)
# 以最优五档即时成交剩余撤销委托
margin_trade(g.security, 200, market_type=4)
 
security:股票代码(str);

amount:交易数量,正数表示买入,负数表示卖出(int);

limit_price:买卖限价(float);

market_type:市价委托类型,上证非科创板股票支持参数1、4,上证科创板股票支持参数0、1、2、4,深证股票支持参数0、2、3、4、5(int);

0:对手方最优价格;
1:最优五档即时成交剩余转限价;
2:本方最优价格;
3:即时成交剩余撤销;
4:最优五档即时成交剩余撤销;
5:全额成交或撤单;

anaconda安装python报错 缺少:api-ms-win-core-path-l1-1-0.dll

python马化云 发表了文章 • 0 个评论 • 1614 次浏览 • 2023-03-30 18:16 • 来自相关话题

在win7的系统里面,使用anaconda安装python10,安装上了之后,激活虚拟环境: 然后运行python结果报错:




 
少了dll文件。
 
于是学网上(csdn)的方法进行修复,把缺的dll下载下来复制到system32的目录。
 
但是后面还是报错。
Python path configuration:
PYTHONHOME = (not set)
PYTHONPATH = (not set)
program name = 'python'
isolated = 0
environment = 1
user site = 1
import site = 1
sys._base_executable = '\u0158\x06'
sys.base_prefix = '.'
sys.base_exec_prefix = '.'
sys.executable = '\u0158\x06'
sys.prefix = '.'
sys.exec_prefix = '.'
sys.path = [
'C:\\anaconda\\python38.zip',
'.\\DLLs',
'.\\lib',
'',
]
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encodin
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x000013a8 (most recent call first):
后面才发现,win7的机子只能安装python3.8以下的版本,高版本会报错。
  查看全部
在win7的系统里面,使用anaconda安装python10,安装上了之后,激活虚拟环境: 然后运行python结果报错:
20230330010.jpg

 
少了dll文件。
 
于是学网上(csdn)的方法进行修复,把缺的dll下载下来复制到system32的目录。
 
但是后面还是报错。
Python path configuration:
PYTHONHOME = (not set)
PYTHONPATH = (not set)
program name = 'python'
isolated = 0
environment = 1
user site = 1
import site = 1
sys._base_executable = '\u0158\x06'
sys.base_prefix = '.'
sys.base_exec_prefix = '.'
sys.executable = '\u0158\x06'
sys.prefix = '.'
sys.exec_prefix = '.'
sys.path = [
'C:\\anaconda\\python38.zip',
'.\\DLLs',
'.\\lib',
'',
]
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encodin
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x000013a8 (most recent call first):

后面才发现,win7的机子只能安装python3.8以下的版本,高版本会报错。
 

国信如何运行miniQMT

QMT李魔佛 发表了文章 • 0 个评论 • 2415 次浏览 • 2023-03-30 02:31 • 来自相关话题

国信的QMT名字叫iQuant, 它也有属于自己的miniQMT。
不过它需要额外申请。就看你的经理愿不愿意帮你去申请了。
毕竟申请这个没有资金要求,纯粹看经理的心情了。申请需要打印纸质电子版文件并签字,拍照发给营业部审核。
 
而且开通了miniQMT后,只能拉取数据,无法进行交易,因为个人是没有交易权限的,只有机构才可以申请miniQMT的交易权限。
 这也是经理不愿意帮你开通的原因,他们有可能会说国信目前不支持miniQMT这样的胡话来推搪打发你。如果需要申请开通,可以联系文末二维码开通国信iquant和miniQMT,这位经理比较热心肠,只要申请,就可以帮你开通miniQMT权限。
 
如何打开国信的miniQMT?
 
国信的miniQMT并不是和iQuant绑定的,笔者怀疑是因为iQuant定制化过多,甚至把miniQMT给阉割了。以至于为了补回miniQMT,他们还得特意要下载一个QMT的客户端(其实这个就是其他券商的QMT客户端),然后使用这个客户端和xtquant通讯。
 
 
输入个人的账户和密码后,登录极速版,对,国信的极速版即使miniQMT了。勾选极简模式。 国信的miniQMT支持自动登录,这个比国金的要好。国金的由于没有自动登录,每天还得自己手动的登录一次。(笔者之前也提供了几个版本的自动登录脚本,需要的可以到星球获取)





 





 
 
行情源这里要注意,如果你选择的获取最新价,那么在获取行情数据的返回值里面,只有最新价格,没有5档委托价格。( 国信iquant并没有这个选择菜单,估计是深度定制了,删除了)。
 
由于没有交易权限,账户里面没有显示个人的持仓信息,直接是空白一片





然后把xtquant的文件夹复制到本地的python site-package目录下。用以下下载数据的代码测试一下:
 import pandas as pd
import datetime


def get_tick(code, start_time, end_time, period='tick'):
from xtquant import xtdata

xtdata.download_history_data(code, period=period, start_time=start_time, end_time=end_time)
data = xtdata.get_local_data(field_list=, stock_code=, period=period, count=10)
result_list = data df = pd.DataFrame(result_list)

df['time_str'] = df['time'].apply(lambda x: datetime.datetime.fromtimestamp(x / 1000.0))
return df


def process_timestamp(df, filename):
df = df.set_index('time_str')
result = df.resample('3S').first().ffill()
# result = result[(result.index >= '2022-07-20 09:30') & (result.index <= '2022-07-20 15:00')]
result = result.reset_index()
result.to_csv(filename + '.csv')


def dump_single_code_tick():
# 导出单个转债的tick数据
code='128022'
start_date = '20210113'
end_date = '20210130'

post_fix = 'SZ' if code.startswith('12') else 'SH'
code = '{}.{}'.format(code,post_fix)
filename = '{}'.format(code)
df = get_tick(code, start_date, end_date)
process_timestamp(df, filename)

dump_single_code_tick()保存上述代码为app.py
运行python app.py
 
稍等片刻,数据导出到当前路径,名字为:

128022.sz 
 
打开看一下,数据在csv里面的了。
 
可关注下面关注号; 如需要开通国信,可以后台回复:开通国信证券
 

  查看全部
国信的QMT名字叫iQuant, 它也有属于自己的miniQMT。
不过它需要额外申请。就看你的经理愿不愿意帮你去申请了。
毕竟申请这个没有资金要求,纯粹看经理的心情了。申请需要打印纸质电子版文件并签字,拍照发给营业部审核。
 
而且开通了miniQMT后,只能拉取数据,无法进行交易,因为个人是没有交易权限的,只有机构才可以申请miniQMT的交易权限。
 这也是经理不愿意帮你开通的原因,他们有可能会说国信目前不支持miniQMT这样的胡话来推搪打发你。如果需要申请开通,可以联系文末二维码开通国信iquant和miniQMT,这位经理比较热心肠,只要申请,就可以帮你开通miniQMT权限。
 
如何打开国信的miniQMT?
 
国信的miniQMT并不是和iQuant绑定的,笔者怀疑是因为iQuant定制化过多,甚至把miniQMT给阉割了。以至于为了补回miniQMT,他们还得特意要下载一个QMT的客户端(其实这个就是其他券商的QMT客户端),然后使用这个客户端和xtquant通讯。
 
 
输入个人的账户和密码后,登录极速版,对,国信的极速版即使miniQMT了。勾选极简模式。 国信的miniQMT支持自动登录,这个比国金的要好。国金的由于没有自动登录,每天还得自己手动的登录一次。(笔者之前也提供了几个版本的自动登录脚本,需要的可以到星球获取)

20230330002.jpg

 

20230330001.jpg

 
 
行情源这里要注意,如果你选择的获取最新价,那么在获取行情数据的返回值里面,只有最新价格,没有5档委托价格。( 国信iquant并没有这个选择菜单,估计是深度定制了,删除了)。
 
由于没有交易权限,账户里面没有显示个人的持仓信息,直接是空白一片

20230330003.jpg

然后把xtquant的文件夹复制到本地的python site-package目录下。用以下下载数据的代码测试一下:
 
import pandas as pd
import datetime


def get_tick(code, start_time, end_time, period='tick'):
from xtquant import xtdata

xtdata.download_history_data(code, period=period, start_time=start_time, end_time=end_time)
data = xtdata.get_local_data(field_list=, stock_code=
, period=period, count=10)
result_list = data
    df = pd.DataFrame(result_list)

df['time_str'] = df['time'].apply(lambda x: datetime.datetime.fromtimestamp(x / 1000.0))
return df


def process_timestamp(df, filename):
df = df.set_index('time_str')
result = df.resample('3S').first().ffill()
# result = result[(result.index >= '2022-07-20 09:30') & (result.index <= '2022-07-20 15:00')]
result = result.reset_index()
result.to_csv(filename + '.csv')


def dump_single_code_tick():
# 导出单个转债的tick数据
code='128022'
start_date = '20210113'
end_date = '20210130'

post_fix = 'SZ' if code.startswith('12') else 'SH'
code = '{}.{}'.format(code,post_fix)
filename = '{}'.format(code)
df = get_tick(code, start_date, end_date)
process_timestamp(df, filename)

dump_single_code_tick()
保存上述代码为app.py
运行python app.py
 
稍等片刻,数据导出到当前路径,名字为:

128022.sz 
 
打开看一下,数据在csv里面的了。
 
可关注下面关注号; 如需要开通国信,可以后台回复:开通国信证券
 

 

golang执行系统shell命令,并获取返回内容

Golang马化云 发表了文章 • 0 个评论 • 1377 次浏览 • 2023-03-26 11:42 • 来自相关话题

可以使用 os/exec 包中的 Command 函数执行 shell 命令,并使用 CombinedOutput 方法获取命令的输出结果和退出码。示例代码如下:import (
"fmt"
"os/exec"
)

func runCommand(command string) (string, error) {
cmd := exec.Command("sh", "-c", command)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
return string(output), nil
}

调用 runCommand 函数即可执行 shell 命令,并获取命令的输出结果。如果命令执行成功,则返回输出结果和 nil,否则返回空字符串和错误信息。需要注意的是,由于 CombinedOutput 方法会等待命令执行完毕才返回,因此在执行耗时较长的命令时可能会阻塞程序的执行。可以使用 Start 和 Wait 方法实现异步执行命令的效果。 查看全部
可以使用 os/exec 包中的 Command 函数执行 shell 命令,并使用 CombinedOutput 方法获取命令的输出结果和退出码。示例代码如下:
import (
"fmt"
"os/exec"
)

func runCommand(command string) (string, error) {
cmd := exec.Command("sh", "-c", command)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
return string(output), nil
}


调用 runCommand 函数即可执行 shell 命令,并获取命令的输出结果。如果命令执行成功,则返回输出结果和 nil,否则返回空字符串和错误信息。需要注意的是,由于 CombinedOutput 方法会等待命令执行完毕才返回,因此在执行耗时较长的命令时可能会阻塞程序的执行。可以使用 Start 和 Wait 方法实现异步执行命令的效果。

修改正在运行的docker容器,禁用重启自动启动

Linux马化云 发表了文章 • 0 个评论 • 1363 次浏览 • 2023-03-26 11:17 • 来自相关话题

启动拖慢了速度,尤其是一些只用一两次的镜像,每次还在电脑重启时容器跟随启动,太占用资源。
 
可以使用 docker update 命令修改容器的配置,示例命令如下:docker update --restart=no <容器ID或名称>

这条命令会将容器的重启策略设置为不重启,即禁用重启自动启动。如果需要启用自动启动,只需要将 --restart 参数的值改为 always 或 on-failure 等相应的选项即可。 

需要注意的是,修改容器的配置并不会立即生效,需要重启容器才能使修改生效。可以使用 docker restart 命令重启容器,示例命令如下:
docker restart <容器ID或名称>


执行这条命令后,容器会被重启并应用新的配置。 查看全部
启动拖慢了速度,尤其是一些只用一两次的镜像,每次还在电脑重启时容器跟随启动,太占用资源。
 
可以使用 docker update 命令修改容器的配置,示例命令如下:
docker update --restart=no <容器ID或名称>


这条命令会将容器的重启策略设置为不重启,即禁用重启自动启动。如果需要启用自动启动,只需要将 --restart 参数的值改为 always 或 on-failure 等相应的选项即可。 

需要注意的是,修改容器的配置并不会立即生效,需要重启容器才能使修改生效。可以使用 docker restart 命令重启容器,示例命令如下:
docker restart <容器ID或名称>



执行这条命令后,容器会被重启并应用新的配置。

国内免登录免注册的chatGPT套壳网站大全【 超全整理】

网络马化云 发表了文章 • 0 个评论 • 65334 次浏览 • 2023-03-20 12:35 • 来自相关话题

本地CPU部署的stable diffusion webui 环境,本地不受限,还可以生成色图黄图
 
还没有体验的朋友可以试试chatGPT的强大
 
PS: 目前部分可能需要科学上网才能访问了。




ChatGPT 镜像网站汇总
BAI Chat GPT3.5 免登录 https://chat.theb.ai

ChatGPT GPT3.5 免登录 https://www.aitoolgpt.com/

Chat For AI GPT3.5 免登录,限制5次提问 https://chatforai.com/

ChatGPT Web GPT3.5 免登录 https://freechatgpt.chat/

ChatGPT GPT3.5 免登录 https://fastgpt.app/

光速Ai GPT3.5 免登录,限制 https://ai.ls

ChatGPT演示 GPT3.5 免登录 https://chatgpt.ddiu.me/

免费GPT GPT3.5 免登录 https://freegpt.one/

FreeGPT GPT3.5 免登录 https://freegpt.cc

ChatGPT Hub GPT3.5 免费100次,Plus接口 https://www.mulaen.com/

TGGPT GPT3.5 登录很卡 https://chat.tgbot.co/chat

New Chat GPT3.5 需API https://fastgpt.app/

开发交流 GPT3.5 免登录 https://chat.yqcloud.top

Ai117 GPT3.5 免登录 https://ai117.com/

周报通 GPT3.5 写周报专用 https://zhoubaotong.com/zh
Fake ChatGPT 未知 免登录 https://gpt.sheepig.top/chat

AI EDU GPT3.5 需API https://chat.forchange.cn/

中文公益版 免登录 https://gpt.tool00.com/

免费ChatGPT(论坛支持) GPT3 免登录 https://openaizh.com/chatgpt.html
AI Chat Bot GPT3 免登录,不稳定 https://chat.gptocean.com/
Hi icu GPT3 部分付费 https://hi.icu/
Aicodehelper GPT3 免登录 https://aicodehelper.com/
ChatGPT Robot 其他 其他 https://ai.zecoba.cn/
Ai帮个忙 其他 工具箱 https://ai-toolbox.codefuture.top/
GPTZero 内容检测 内容检测 https://gptzero.me/
ChatGPT中文版 GPT3.5 免登录 https://chat35.com/chat另外还有chatGPT共享整理一批 注册好的免费chatGPT账户,从分享群里获取的,亲测有效
  查看全部
本地CPU部署的stable diffusion webui 环境,本地不受限,还可以生成色图黄图
 
还没有体验的朋友可以试试chatGPT的强大
 
PS: 目前部分可能需要科学上网才能访问了。

mmexport1679286871158.png
ChatGPT 镜像网站汇总
BAI Chat GPT3.5 免登录 https://chat.theb.ai

ChatGPT GPT3.5 免登录 https://www.aitoolgpt.com/

Chat For AI GPT3.5 免登录,限制5次提问 https://chatforai.com/

ChatGPT Web GPT3.5 免登录 https://freechatgpt.chat/

ChatGPT GPT3.5 免登录 https://fastgpt.app/

光速Ai GPT3.5 免登录,限制 https://ai.ls

ChatGPT演示 GPT3.5 免登录 https://chatgpt.ddiu.me/

免费GPT GPT3.5 免登录 https://freegpt.one/

FreeGPT GPT3.5 免登录 https://freegpt.cc

ChatGPT Hub GPT3.5 免费100次,Plus接口 https://www.mulaen.com/

TGGPT GPT3.5 登录很卡 https://chat.tgbot.co/chat

New Chat GPT3.5 需API https://fastgpt.app/

开发交流 GPT3.5 免登录 https://chat.yqcloud.top

Ai117 GPT3.5 免登录 https://ai117.com/

周报通 GPT3.5 写周报专用 https://zhoubaotong.com/zh
Fake ChatGPT 未知 免登录 https://gpt.sheepig.top/chat

AI EDU GPT3.5 需API https://chat.forchange.cn/

中文公益版 免登录 https://gpt.tool00.com/

免费ChatGPT(论坛支持) GPT3 免登录 https://openaizh.com/chatgpt.html
AI Chat Bot GPT3 免登录,不稳定 https://chat.gptocean.com/
Hi icu GPT3 部分付费 https://hi.icu/
Aicodehelper GPT3 免登录 https://aicodehelper.com/
ChatGPT Robot 其他 其他 https://ai.zecoba.cn/
Ai帮个忙 其他 工具箱 https://ai-toolbox.codefuture.top/
GPTZero 内容检测 内容检测 https://gptzero.me/
ChatGPT中文版 GPT3.5 免登录 https://chat35.com/chat
另外还有chatGPT共享整理一批 注册好的免费chatGPT账户,从分享群里获取的,亲测有效
 

ptrade QMT 动态止盈卖出 python代码实现

Ptrade李魔佛 发表了文章 • 0 个评论 • 1266 次浏览 • 2023-03-13 23:53 • 来自相关话题

帮你轻松实现自动止盈。
比如设置20%,那么会每天盘中扫描,可以精确到3S 一格,如果你的持仓股的收益率大于20%,它将会帮你自动卖出。
 
占坑 待续 》》》
帮你轻松实现自动止盈。
比如设置20%,那么会每天盘中扫描,可以精确到3S 一格,如果你的持仓股的收益率大于20%,它将会帮你自动卖出。
 
占坑 待续 》》》

linux下自制护眼,久坐提醒 python小程序

python李魔佛 发表了文章 • 0 个评论 • 1015 次浏览 • 2023-03-09 16:23 • 来自相关话题

很简单,在任意linux版本均可运行,python3环境;
保存为app.py
运行; python app.py
然后写到系统的crontab计划任务里面,每个40分钟执行几次,
屏幕会黑屏60s , 60可以自行设置。
 
挺好用的。import datetime as dt
import tkinter as tk
# Linux 护眼程序
sec = 60 # 休息时间 秒

root = tk.Tk()
root.config(bg='black')
root.wm_attributes('-topmost',1)
root.wm_attributes('-fullscreen',1)
L = tk.Label(root,font=('Consolas', 50), bg='black')
L.place(relx=0.5,rely=0.5,anchor=tk.CENTER)

# 改变的内容
msg = "{}\n 站起来 {} \n 动一动 {}\n{}"
now = dt.datetime.now()
aa = {0:'↑',1:'→',2:'↓',3:'←'}
bb = {0:'~~_↑_~~',1:'~_↑ ↑_~'}


for i in range(sec):
t = msg.format(sec-i,aa[i%4],bb[i%2],(now+dt.timedelta(seconds=i)).ctime())
c = 'Black' # 颜色可以搞随机换
root.after(i*1000,L.config,{'text':t,'fg':c})
root.after(sec*1000,root.destroy)

root.mainloop() 
 
PS: AI生成的image还真心不错呢。 就是太吃显存了





 
  查看全部
很简单,在任意linux版本均可运行,python3环境;
保存为app.py
运行; python app.py
然后写到系统的crontab计划任务里面,每个40分钟执行几次,
屏幕会黑屏60s , 60可以自行设置。
 
挺好用的。
import datetime as dt
import tkinter as tk
# Linux 护眼程序
sec = 60 # 休息时间 秒

root = tk.Tk()
root.config(bg='black')
root.wm_attributes('-topmost',1)
root.wm_attributes('-fullscreen',1)
L = tk.Label(root,font=('Consolas', 50), bg='black')
L.place(relx=0.5,rely=0.5,anchor=tk.CENTER)

# 改变的内容
msg = "{}\n 站起来 {} \n 动一动 {}\n{}"
now = dt.datetime.now()
aa = {0:'↑',1:'→',2:'↓',3:'←'}
bb = {0:'~~_↑_~~',1:'~_↑ ↑_~'}


for i in range(sec):
t = msg.format(sec-i,aa[i%4],bb[i%2],(now+dt.timedelta(seconds=i)).ctime())
c = 'Black' # 颜色可以搞随机换
root.after(i*1000,L.config,{'text':t,'fg':c})
root.after(sec*1000,root.destroy)

root.mainloop()
 
 
PS: AI生成的image还真心不错呢。 就是太吃显存了

Fp52VSzaMAcwxmR.jpeg

 
 

ptrade qmt的模拟账户能不用尽量不用,无尽的bug让你浪费时间 怀疑人生

Ptrade李魔佛 发表了文章 • 0 个评论 • 2050 次浏览 • 2023-03-02 15:57 • 来自相关话题

个人平时基本很少用模拟账户。但有时候又没有办法。实盘账户在跑,仓位无法挪腾出来测试(最近折腾的打板策略)
所以临时登录了模拟账户。 里面也挺悲剧的,初始化的500w资金,之前测试的时候随意买入的转债,很多都强赎了。而ptrade里面依然还在,导致大部分是亏损99%以上, 账上只剩可怜的88w,虚拟基金。
 
今天用ptrade获取A股市场所有的股票代码,居然调试了半小时,代码如下
def initialize(context):
# 初始化策略
g.security = "600570.SS"
set_universe(g.security)

def handle_data(context, data):
stock=get_Ashares()
log.info(stock)
输出的stock是[],没有任何数据。





上面的xxxxx is expired , close all positions by system. 是因为模拟账户上退市转债还依然挂在上面,清仓也清不掉。每次跑就循环一分钟输出。。
 
换了个券商的模拟账户,问题依然在,只好倒腾实盘账户。然后问题就解决了。
这个问题,在qmt上就更加严重了。 下次在星球上或者群里慢慢吐槽吧
 
  查看全部
个人平时基本很少用模拟账户。但有时候又没有办法。实盘账户在跑,仓位无法挪腾出来测试(最近折腾的打板策略)
所以临时登录了模拟账户。 里面也挺悲剧的,初始化的500w资金,之前测试的时候随意买入的转债,很多都强赎了。而ptrade里面依然还在,导致大部分是亏损99%以上, 账上只剩可怜的88w,虚拟基金。
 
今天用ptrade获取A股市场所有的股票代码,居然调试了半小时,代码如下
def initialize(context):
# 初始化策略
g.security = "600570.SS"
set_universe(g.security)

def handle_data(context, data):
stock=get_Ashares()
log.info(stock)

输出的stock是[],没有任何数据。

20230302012.jpg

上面的xxxxx is expired , close all positions by system. 是因为模拟账户上退市转债还依然挂在上面,清仓也清不掉。每次跑就循环一分钟输出。。
 
换了个券商的模拟账户,问题依然在,只好倒腾实盘账户。然后问题就解决了。
这个问题,在qmt上就更加严重了。 下次在星球上或者群里慢慢吐槽吧
 
 

qmt position对象里面有哪些属性?

QMT李魔佛 发表了文章 • 0 个评论 • 1333 次浏览 • 2023-02-27 22:12 • 来自相关话题

查看属性的代码:
  obj_list = get_trade_detail_data(ACCOUNT,'stock','position')
for obj in obj_list:
print(obj.m_strInstrumentID,obj.m_strInstrumentName,'----')
# 查看有哪些属性字段
print('='*10)
for item in dir(obj):
if not item.startswith('__'):
print(item)

print('='*10)
得到的position的内置属性有下面的:m_bIsToday
m_dAvgOpenPrice
m_dCloseAmount
m_dCloseProfit
m_dFloatProfit
m_dInstrumentValue
m_dLastPrice
m_dLastSettlementPrice
m_dMargin
m_dMarketValue
m_dOpenCost
m_dOpenPrice
m_dPositionCost
m_dPositionProfit
m_dProfitRate
m_dRealUsedMargin
m_dRedemptionVolume
m_dReferenceRate
m_dRoyalty
m_dSettlementPrice
m_dSingleCost
m_dStaticHoldMargin
m_dStockLastPrice
m_dStructFundVol
m_dTotalCost
m_eFutureTradeType
m_eSideFlag
m_nCanUseVolume
m_nCidIncrease
m_nCidIsDelist
m_nCidRateOfCurrentLine
m_nCidRateOfTotalValue
m_nCloseVolume
m_nCoveredVolume
m_nDirection
m_nEnableExerciseVolume
m_nFrozenVolume
m_nHedgeFlag
m_nLegId
m_nOnRoadVolume
m_nOptCombUsedVolume
m_nPREnableVolume
m_nVolume
m_nYesterdayVolume
m_strAccountID
m_strAccountKey
m_strComTradeID
m_strExchangeID
m_strExchangeName
m_strExpireDate
m_strInstrumentID
m_strInstrumentName
m_strOpenDate
m_strProductID
m_strProductName
m_strStockHolder
m_strTradeID
m_strTradingDay
m_xtTag
虽然有上面的属性,但是实际上很可能是空的,并没有值。






  查看全部
查看属性的代码:
 
    obj_list = get_trade_detail_data(ACCOUNT,'stock','position')
for obj in obj_list:
print(obj.m_strInstrumentID,obj.m_strInstrumentName,'----')
# 查看有哪些属性字段
print('='*10)
for item in dir(obj):
if not item.startswith('__'):
print(item)

print('='*10)

得到的position的内置属性有下面的:
m_bIsToday
m_dAvgOpenPrice
m_dCloseAmount
m_dCloseProfit
m_dFloatProfit
m_dInstrumentValue
m_dLastPrice
m_dLastSettlementPrice
m_dMargin
m_dMarketValue
m_dOpenCost
m_dOpenPrice
m_dPositionCost
m_dPositionProfit
m_dProfitRate
m_dRealUsedMargin
m_dRedemptionVolume
m_dReferenceRate
m_dRoyalty
m_dSettlementPrice
m_dSingleCost
m_dStaticHoldMargin
m_dStockLastPrice
m_dStructFundVol
m_dTotalCost
m_eFutureTradeType
m_eSideFlag
m_nCanUseVolume
m_nCidIncrease
m_nCidIsDelist
m_nCidRateOfCurrentLine
m_nCidRateOfTotalValue
m_nCloseVolume
m_nCoveredVolume
m_nDirection
m_nEnableExerciseVolume
m_nFrozenVolume
m_nHedgeFlag
m_nLegId
m_nOnRoadVolume
m_nOptCombUsedVolume
m_nPREnableVolume
m_nVolume
m_nYesterdayVolume
m_strAccountID
m_strAccountKey
m_strComTradeID
m_strExchangeID
m_strExchangeName
m_strExpireDate
m_strInstrumentID
m_strInstrumentName
m_strOpenDate
m_strProductID
m_strProductName
m_strStockHolder
m_strTradeID
m_strTradingDay
m_xtTag

虽然有上面的属性,但是实际上很可能是空的,并没有值。

20230227004.jpg


 

qmt 可转债 双低(阈值)轮动 实盘代码

QMT李魔佛 发表了文章 • 0 个评论 • 2052 次浏览 • 2023-02-26 15:18 • 来自相关话题

之前在星球埋的坑,答应群友写个qmt的双低可转债的轮动实盘代码。
用已有的ptrade的代码,然后部分获取行情和交易接口按照qmt的接口文档(http://qmt.ptradeapi.com )重写,就给了一版。(对,很早以前就有一版ptrade的转债双低的了)
 
无论是qmt还是ptrade,都只是一个工具,用熟悉了,都无所哪个好哪个不好。





 





 





 
 
完整代码在个人星球。
 
觉得之前星球太便宜了,不仅给了代码,还部署了接口免费使用,通过接口获取可转债的实时数据,强赎天数,规模,溢价率,评级等等一系列数据。 而且随着时间的推移,里面积累的数据,代码也越来越多,感觉这样对前面进去并不断续费的星友有点公平,尽管以后他们续费都直接打折扣。所以还是按照一些大v运营的意见,逐年涨价策略。
越往后的朋友,因为前面积累的内容越多,因此价格也随之增长。
 
当然有能力可以自己写接口,部署,实盘,获取三方数据的大v,就没必要加了。
  查看全部
之前在星球埋的坑,答应群友写个qmt的双低可转债的轮动实盘代码。
用已有的ptrade的代码,然后部分获取行情和交易接口按照qmt的接口文档(http://qmt.ptradeapi.com )重写,就给了一版。(对,很早以前就有一版ptrade的转债双低的了)
 
无论是qmt还是ptrade,都只是一个工具,用熟悉了,都无所哪个好哪个不好。

20230217003.jpg

 

20230226011.jpg

 

20230226012.jpg

 
 
完整代码在个人星球。
 
觉得之前星球太便宜了,不仅给了代码,还部署了接口免费使用,通过接口获取可转债的实时数据,强赎天数,规模,溢价率,评级等等一系列数据。 而且随着时间的推移,里面积累的数据,代码也越来越多,感觉这样对前面进去并不断续费的星友有点公平,尽管以后他们续费都直接打折扣。所以还是按照一些大v运营的意见,逐年涨价策略。
越往后的朋友,因为前面积累的内容越多,因此价格也随之增长。
 
当然有能力可以自己写接口,部署,实盘,获取三方数据的大v,就没必要加了。
 

qmt软件里面的快速计算是在什么模式下使用的?

QMT李魔佛 发表了文章 • 0 个评论 • 1274 次浏览 • 2023-02-25 13:35 • 来自相关话题

QMT 平台模型是根据行情驱动,逐 K 线运行的。
 
即点击运行模型时,模型是从第 0 根 K 线开始运行到最后一根 K 线(如想加快模型运行速度,可以策略编辑器 - 基本信息中设置快速计算,限制计算范围,只计算最新的指定数量的 K 线范围),每根 K 线调用一次 Python 模型中的 handlebar(ContextInfo) 函数。
 
也就是你点击“运行”按钮的时候,如果你的快速计算默认设置的是0,
 
handlebar里面的k线是从2005年1月1日运行的,即使你在代码里面设置了运行时间:
def init(ContextInfo):
print("==============start==========")
ContextInfo.start = '2023-02-20 10:00:00'
ContextInfo.end = '2023-02-23 10:00:00'或者在回测参数里面设置的时间:






都是不管用的。
 
需要在代码里添加一句:
if not ContextInfo.is_last_bar():
return 
 
或者 把快速计算的值设置为1, 就只会以最新的k线计算。也就是只会执行1次handlebar。





 
不得不说,qmt的说明文档很让人困惑的。笔者也多次吐槽了。
如果没有编程的朋友,不建议自己折腾了。不少编程大咖都惊呼这软件和文档入门太难,文档太扯淡。
如果需要qmt策略代码 和实盘代码 代写,可以在公众号后台留言:qmt代写
 
 
  查看全部
QMT 平台模型是根据行情驱动,逐 K 线运行的。
 
即点击运行模型时,模型是从第 0 根 K 线开始运行到最后一根 K 线(如想加快模型运行速度,可以策略编辑器 - 基本信息中设置快速计算,限制计算范围,只计算最新的指定数量的 K 线范围),每根 K 线调用一次 Python 模型中的 handlebar(ContextInfo) 函数。
 
也就是你点击“运行”按钮的时候,如果你的快速计算默认设置的是0,
 
handlebar里面的k线是从2005年1月1日运行的,即使你在代码里面设置了运行时间:
def init(ContextInfo):
print("==============start==========")
ContextInfo.start = '2023-02-20 10:00:00'
ContextInfo.end = '2023-02-23 10:00:00'
或者在回测参数里面设置的时间:

20230225001.jpg


都是不管用的。
 
需要在代码里添加一句:
    if not ContextInfo.is_last_bar():
return
 
 
或者 把快速计算的值设置为1, 就只会以最新的k线计算。也就是只会执行1次handlebar。

20230225002.jpg

 
不得不说,qmt的说明文档很让人困惑的。笔者也多次吐槽了。
如果没有编程的朋友,不建议自己折腾了。不少编程大咖都惊呼这软件和文档入门太难,文档太扯淡。
如果需要qmt策略代码 和实盘代码 代写,可以在公众号后台留言:qmt代写
 
 
 

qmt隔夜文件单(python代码实现)实盘代码

QMT李魔佛 发表了文章 • 0 个评论 • 1751 次浏览 • 2023-02-24 14:17 • 来自相关话题

 代码基于iquant平台编写。可以拿去参考参考。# encoding:gbk
import logging
import pandas as pd
from datetime import datetime, timedelta, time
from decimal import InvalidOperation
from decimal import Decimal as D
from READFILE import read_file

logging.basicConfig(level=logging.INFO)
# 挂单失败后的等待时长,以秒计
TIMEOUT_ON_FAIL_SEC = 30
# 规避 account_callback 的 Racing Condition
RUN_TIME_DELAY = 10

# global FILEPATH, DIR, PRICE, VOL, START_TIME, account
SH_pattern = r'^[1-9]\d{5}\.(sh|SH)$'
SZ_pattern = r'^(?!39)\d{6}\.(sz|SZ)$'
SH_prefix = ['5', '6', '9', '11']
SZ_prefix = ['0', '2', '30', '12', '159']
COLNAMES = ['direction', 'vol', 'price', 'start_time']


def init(ContextInfo):
ContextInfo.accID = account
ContextInfo.set_account(ContextInfo.accID)

ContextInfo.can_order = False
ContextInfo.all_order_done = False

if not load_file_order(ContextInfo):
load_sys_order(ContextInfo)

# load_file_order(ContextInfo)
ContextInfo.run_time("place_order", "{0}nSecond".format(TIMEOUT_ON_FAIL_SEC),
(datetime.now() + timedelta(seconds=RUN_TIME_DELAY)).strftime('%Y-%m-%d %H:%M:%S'), 'SH')


def account_callback(ContextInfo, accountInfo):
if not ContextInfo.can_order:
ContextInfo.can_order = True


def handlebar(ContextInfo):
return


def load_file_order(ContextInfo):
def _price_vol_filtering(row):
if not isinstance(row.start_time, time):
logging.warning('读取{0}指令时间失败: {1}'.format(row.name, row.start_time))
return None
if row.direction not in ['买', '卖']:
logging.warning('读取{0}买卖方向失败: {1}'.format(row.name, row.direction))
return None
try:
# parse start_time
curr_start_time = datetime.now().strftime('%Y-%m-%d ') + row.start_time.strftime('%H:%M:%S')
curr_start_time = datetime.strptime(curr_start_time, '%Y-%m-%d %H:%M:%S')
# parse direction
curr_direction = 23 if row.direction == '买' else 24
# parse price and vol
price = D(row.price)
vol = int(row.vol)
return pd.Series([curr_direction, vol, price, curr_start_time])
except InvalidOperation:
logging.warning("读取 {0} 指令价格失败: {1}".format(row.name, row.price))
return None
except ValueError:
logging.warning('读取 {0} 下单总量失败: {1}'.format(row.name, row.vol))
return None

def _name_parser(asset_name):
# 目前默认用户输入.SH 或.SZ时标的名称正确
if '.SH' in asset_name or '.SZ' in asset_name:
# todo: SH/SZ_pattern regex check here?
return asset_name
else:
raise ValueError('{0} 标的代码不合法'.format(asset_name))

try:
tmp_df = read_file(FILEPATH, names=COLNAMES, index_col=0)
except:
logging.warning('读取挂单配置文件失败或挂单配置文件为空,尝试交易读取配置面板参数')
return None
if tmp_df.empty:
logging.warning('读取挂单配置文件失败或挂单配置文件为空,尝试交易读取配置面板参数')
return None

tmp_df.index = tmp_df.index.to_series().astype(str)
tmp_df.index = tmp_df.index.str.strip()
tmp_df.index = tmp_df.index.str.upper()
tmp_df.index = tmp_df.index.to_series().apply(_name_parser).dropna()
tmp_df = tmp_df.apply(_price_vol_filtering, axis=1, broadcast=True).dropna()
if tmp_df.empty:
logging.warning('读取挂单配置文件失败或挂单配置文件为空,尝试交易读取配置面板参数')
return False

tmp_df.set_axis(COLNAMES, axis='columns', inplace=True)
# 挂单成功Flag
tmp_df['finished'] = [False] * tmp_df.shape[0]
ContextInfo.order_df = tmp_df
ContextInfo.set_universe(ContextInfo.order_df.index.tolist())
return True


def load_sys_order(ContextInfo):
try:
asset_name = ContextInfo.stockcode + '.' + ContextInfo.market
ContextInfo.set_universe([asset_name])
direction = 23 if DIR == '买入' else 24
start_time = datetime.strptime(datetime.now().strftime('%Y%m%d') + str(START_TIME), '%Y%m%d%H%M%S')
price = D(PRICE)
vol = int(VOL)
except BaseException:
raise ValueError("读取策略面板交易配置失败。请尝试修正挂单配置文件或者策略面板参数。")

price = float(price)
ContextInfo.order_df = pd.DataFrame(data=[direction, vol, price, start_time], index=COLNAMES,
columns=[asset_name]).T
ContextInfo.order_df['finished'] = False
return


def place_order(ContextInfo):
if not ContextInfo.can_order or ContextInfo.all_order_done:
return
for curr_asset in ContextInfo.get_universe():
if not ContextInfo.order_df.loc[curr_asset].finished \
and datetime.now() > ContextInfo.order_df.loc[curr_asset].start_time:
curr_order = ContextInfo.order_df.loc[curr_asset]
direction = int(curr_order.direction)
txt_direction = '买入' if direction == 23 else '卖出'
price = float(D(curr_order.price))
vol = int(curr_order.vol)
order_remark = '隔日文件挂单: 以 {0} {1} {2}'.format(price, txt_direction, curr_asset)
passorder(direction, 1101, ContextInfo.accID, curr_asset, 11, price, vol, order_remark, 1, order_remark,
ContextInfo)
ContextInfo.order_df.loc[curr_asset, 'finished'] = True

ContextInfo.all_order_done = all(ContextInfo.order_df['finished'].tolist())


def order_callback(ContextInfo, orderInfo):
curr_asset = orderInfo.m_strInstrumentID + '.' + orderInfo.m_strExchangeID
curr_remark = orderInfo.m_strRemark
curr_status = orderInfo.m_nOrderStatus
if '隔日文件挂单' in curr_remark and curr_status == 57:
ContextInfo.order_df.loc[curr_asset, 'finished'] = False
ContextInfo.all_order_done = False
logging.error('{0} 隔日文件挂单:报单废单 (柜台返回失败),原因:{1} 尝试重报'.format(curr_asset, orderInfo.m_strCancelInfo))
elif '隔日文件挂单' in curr_remark and curr_status == 50:
logging.info('{0} 隔日文件挂单:报单成功'.format(curr_asset))
return


def orderError_callback(ContextInfo, orderArgs, errMsg):
curr_asset = orderArgs.orderCode
if '隔日文件挂单' in orderArgs.strategyName:
ContextInfo.order_df.loc[curr_asset, 'finished'] = False
ContextInfo.all_order_done = False
logging.error('{0} 隔日文件挂单:账号下单异常 (COS/iQuant校验失败), 错误消息:{1} 尝试重报'.format(curr_asset, errMsg))
return






 把上述代码复制到iquant里面,然后部署到策略运行,运行策略,切换为实盘 查看全部
20230224003.jpg

 代码基于iquant平台编写。可以拿去参考参考。
# encoding:gbk
import logging
import pandas as pd
from datetime import datetime, timedelta, time
from decimal import InvalidOperation
from decimal import Decimal as D
from READFILE import read_file

logging.basicConfig(level=logging.INFO)
# 挂单失败后的等待时长,以秒计
TIMEOUT_ON_FAIL_SEC = 30
# 规避 account_callback 的 Racing Condition
RUN_TIME_DELAY = 10

# global FILEPATH, DIR, PRICE, VOL, START_TIME, account
SH_pattern = r'^[1-9]\d{5}\.(sh|SH)$'
SZ_pattern = r'^(?!39)\d{6}\.(sz|SZ)$'
SH_prefix = ['5', '6', '9', '11']
SZ_prefix = ['0', '2', '30', '12', '159']
COLNAMES = ['direction', 'vol', 'price', 'start_time']


def init(ContextInfo):
ContextInfo.accID = account
ContextInfo.set_account(ContextInfo.accID)

ContextInfo.can_order = False
ContextInfo.all_order_done = False

if not load_file_order(ContextInfo):
load_sys_order(ContextInfo)

# load_file_order(ContextInfo)
ContextInfo.run_time("place_order", "{0}nSecond".format(TIMEOUT_ON_FAIL_SEC),
(datetime.now() + timedelta(seconds=RUN_TIME_DELAY)).strftime('%Y-%m-%d %H:%M:%S'), 'SH')


def account_callback(ContextInfo, accountInfo):
if not ContextInfo.can_order:
ContextInfo.can_order = True


def handlebar(ContextInfo):
return


def load_file_order(ContextInfo):
def _price_vol_filtering(row):
if not isinstance(row.start_time, time):
logging.warning('读取{0}指令时间失败: {1}'.format(row.name, row.start_time))
return None
if row.direction not in ['买', '卖']:
logging.warning('读取{0}买卖方向失败: {1}'.format(row.name, row.direction))
return None
try:
# parse start_time
curr_start_time = datetime.now().strftime('%Y-%m-%d ') + row.start_time.strftime('%H:%M:%S')
curr_start_time = datetime.strptime(curr_start_time, '%Y-%m-%d %H:%M:%S')
# parse direction
curr_direction = 23 if row.direction == '买' else 24
# parse price and vol
price = D(row.price)
vol = int(row.vol)
return pd.Series([curr_direction, vol, price, curr_start_time])
except InvalidOperation:
logging.warning("读取 {0} 指令价格失败: {1}".format(row.name, row.price))
return None
except ValueError:
logging.warning('读取 {0} 下单总量失败: {1}'.format(row.name, row.vol))
return None

def _name_parser(asset_name):
# 目前默认用户输入.SH 或.SZ时标的名称正确
if '.SH' in asset_name or '.SZ' in asset_name:
# todo: SH/SZ_pattern regex check here?
return asset_name
else:
raise ValueError('{0} 标的代码不合法'.format(asset_name))

try:
tmp_df = read_file(FILEPATH, names=COLNAMES, index_col=0)
except:
logging.warning('读取挂单配置文件失败或挂单配置文件为空,尝试交易读取配置面板参数')
return None
if tmp_df.empty:
logging.warning('读取挂单配置文件失败或挂单配置文件为空,尝试交易读取配置面板参数')
return None

tmp_df.index = tmp_df.index.to_series().astype(str)
tmp_df.index = tmp_df.index.str.strip()
tmp_df.index = tmp_df.index.str.upper()
tmp_df.index = tmp_df.index.to_series().apply(_name_parser).dropna()
tmp_df = tmp_df.apply(_price_vol_filtering, axis=1, broadcast=True).dropna()
if tmp_df.empty:
logging.warning('读取挂单配置文件失败或挂单配置文件为空,尝试交易读取配置面板参数')
return False

tmp_df.set_axis(COLNAMES, axis='columns', inplace=True)
# 挂单成功Flag
tmp_df['finished'] = [False] * tmp_df.shape[0]
ContextInfo.order_df = tmp_df
ContextInfo.set_universe(ContextInfo.order_df.index.tolist())
return True


def load_sys_order(ContextInfo):
try:
asset_name = ContextInfo.stockcode + '.' + ContextInfo.market
ContextInfo.set_universe([asset_name])
direction = 23 if DIR == '买入' else 24
start_time = datetime.strptime(datetime.now().strftime('%Y%m%d') + str(START_TIME), '%Y%m%d%H%M%S')
price = D(PRICE)
vol = int(VOL)
except BaseException:
raise ValueError("读取策略面板交易配置失败。请尝试修正挂单配置文件或者策略面板参数。")

price = float(price)
ContextInfo.order_df = pd.DataFrame(data=[direction, vol, price, start_time], index=COLNAMES,
columns=[asset_name]).T
ContextInfo.order_df['finished'] = False
return


def place_order(ContextInfo):
if not ContextInfo.can_order or ContextInfo.all_order_done:
return
for curr_asset in ContextInfo.get_universe():
if not ContextInfo.order_df.loc[curr_asset].finished \
and datetime.now() > ContextInfo.order_df.loc[curr_asset].start_time:
curr_order = ContextInfo.order_df.loc[curr_asset]
direction = int(curr_order.direction)
txt_direction = '买入' if direction == 23 else '卖出'
price = float(D(curr_order.price))
vol = int(curr_order.vol)
order_remark = '隔日文件挂单: 以 {0} {1} {2}'.format(price, txt_direction, curr_asset)
passorder(direction, 1101, ContextInfo.accID, curr_asset, 11, price, vol, order_remark, 1, order_remark,
ContextInfo)
ContextInfo.order_df.loc[curr_asset, 'finished'] = True

ContextInfo.all_order_done = all(ContextInfo.order_df['finished'].tolist())


def order_callback(ContextInfo, orderInfo):
curr_asset = orderInfo.m_strInstrumentID + '.' + orderInfo.m_strExchangeID
curr_remark = orderInfo.m_strRemark
curr_status = orderInfo.m_nOrderStatus
if '隔日文件挂单' in curr_remark and curr_status == 57:
ContextInfo.order_df.loc[curr_asset, 'finished'] = False
ContextInfo.all_order_done = False
logging.error('{0} 隔日文件挂单:报单废单 (柜台返回失败),原因:{1} 尝试重报'.format(curr_asset, orderInfo.m_strCancelInfo))
elif '隔日文件挂单' in curr_remark and curr_status == 50:
logging.info('{0} 隔日文件挂单:报单成功'.format(curr_asset))
return


def orderError_callback(ContextInfo, orderArgs, errMsg):
curr_asset = orderArgs.orderCode
if '隔日文件挂单' in orderArgs.strategyName:
ContextInfo.order_df.loc[curr_asset, 'finished'] = False
ContextInfo.all_order_done = False
logging.error('{0} 隔日文件挂单:账号下单异常 (COS/iQuant校验失败), 错误消息:{1} 尝试重报'.format(curr_asset, errMsg))
return






 把上述代码复制到iquant里面,然后部署到策略运行,运行策略,切换为实盘

qmt的文档写的有点稀烂

QMT李魔佛 发表了文章 • 0 个评论 • 1267 次浏览 • 2023-02-21 12:41 • 来自相关话题

在部署QMT 在线文档的时候,还是忍不住吐槽下它的文档。
 这也是当时不用QMT的一个重要原因。
 
不仅仅是文档,而且还有它的函数接口的涉及。
 
比如最常用的交易函数,passorder综合交易下单 passorder()
用法: passorder(opType, orderType, accountid, orderCode, prType, modelprice, volume[, strategyName, quickTrade, userOrderId], ContextInfo)
里面有11个参数,可选参数有2个。 对于一个常用函数来说,这个参数有点多了。
 
而更为令人费解的,是它参数里面额设定值
比如第一个opType,操作类型。
 
里面有59个数字:期货六键:

0:开多

1:平昨多

2:平今多

3:开空

4:平昨空

5:平今空

期货四键:

6:平多,优先平今

7:平多,优先平昨

8:平空,优先平今

9:平空,优先平昨

期货两键:

10:卖出,如有多仓,优先平仓,优先平今,如有余量,再开空

11:卖出,如有多仓,优先平仓,优先平昨,如有余量,再开空

12:买入,如有空仓,优先平仓,优先平今,如有余量,再开多

13:买入,如有空仓,优先平仓,优先平昨,如有余量,再开多

14:买入,不优先平仓

15:卖出,不优先平仓

股票买卖:

23:股票买入,或沪港通、深港通股票买入

24:股票卖出,或沪港通、深港通股票卖出

融资融券:

27:融资买入

28:融券卖出

29:买券还券

30:直接还券

31:卖券还款

32:直接还款

33:信用账号股票买入

34:信用账号股票卖出

组合交易:

25:组合买入,或沪港通、深港通的组合买入

26:组合卖出,或沪港通、深港通的组合卖出

27:融资买入

28:融券卖出

29:买券还券

31:卖券还款

33:信用账号股票买入

34:信用账号股票卖出

40:期货组合开多

43:期货组合开空

46:期货组合平多,优先平今

47:期货组合平多,优先平昨

48:期货组合平空,优先平今

49:期货组合平空,优先平昨

期权交易:

50:买入开仓

51:卖出平仓

52:卖出开仓

53:买入平仓

54:备兑开仓

55:备兑平仓

56:认购行权

57:认沽行权

58:证券锁定

59:证券解锁
它把期货,股票,期权所有品种压缩到一起,通过参数数字来辨认交易类别。
 
那么我们来看一看一个例子,就拿一个官网的一个例子来说:
 
最简单的例子:passorder(23,1101,account,s,11,14.00,100,2,ContextInfo)
一般人看了上面的代码,里面全部是数字,简直就像灾难一样。 但是我要明白它的交易品种和交易逻辑,
就得对着文档去查,编号23是啥,1101是啥,11,14又是啥。
 
如果我是代码reviewer,底下的员工这种文档,或者写代码的人,提交上这样的代码,绝对100%是要reject这个提交的。
 
然后orderType 更加让人吐血。。
 1101:单股、单账号、普通、股/手方式下单

1102:单股、单账号、普通、金额(元)方式下单(只支持股票)

1113:单股、单账号、总资产、比例 [0 ~ 1] 方式下单

1123:单股、单账号、可用、比例[0 ~ 1]方式下单

1201:单股、账号组(无权重)、普通、股/手方式下单

1202:单股、账号组(无权重)、普通、金额(元)方式下单(只支持股票)

1213:单股、账号组(无权重)、总资产、比例 [0 ~ 1] 方式下单

1223:单股、账号组(无权重)、可用、比例 [0 ~ 1] 方式下单

2101:组合、单账号、普通、按组合股票数量(篮子中股票设定的数量)方式下单 > 对应 volume 的单位为篮子的份

2102:组合、单账号、普通、按组合股票权重(篮子中股票设定的权重)方式下单 > 对应 volume 的单位为元

2103:组合、单账号、普通、按账号可用方式下单 > (底层篮子股票怎么分配?答:按可用资金比例后按篮子中股票权重分配,如用户没填权重则按相等权重分配)只对股票篮子支持

2201:组合、账号组(无权重)、普通、按组合股票数量方式下单

2202:组合、账号组(无权重)、普通、按组合股票权重方式下单



这排列组合,谁能记得住,逼着你去查文档,或者每次复制粘贴旧代码。
 
然后下单 类型,继续来各种枚举:
 -1:无效(实际下单时,需要用交易面板交易函数那设定的选价类型)

0:卖5价

1:卖4价

2:卖3价

3:卖2价

4:卖1价

5:最新价

6:买1价

7:买2价(组合不支持)

8:买3价(组合不支持)

9:买4价(组合不支持)

10:买5价(组合不支持)

11:(指定价)模型价(只对单股情况支持,对组合交易不支持)

12:涨跌停价

13:挂单价

14:对手价

27:市价即成剩撤(仅对股票期权申报有效)

28:市价即全成否则撤(仅对股票期权申报有效)

29:市价剩转限价(仅对股票期权申报有效)

42:最优五档即时成交剩余撤销申报(仅对上交所申报有效)

43:最优五档即时成交剩转限价申报(仅对上交所申报有效)

44:对手方最优价格委托(仅对深交所申报有效)

45:本方最优价格委托(仅对深交所申报有效)

46:即时成交剩余撤销委托(仅对深交所申报有效)

47:最优五档即时成交剩余撤销委托(仅对深交所申报有效)

48:全额成交或撤销委托(仅对深交所申报有效)

49:科创板盘后定价
会不会用常量定义个值给客户调用呢?
 passorder(
ContextInfo.TYPE_STOCK,

ContextInfo.TYPE_BUY,
100,
ContextInfo.LIMIT_PRICE,
ContextInfo)
没有标注类型:
虽然python是若类型的语言,可是qmt底层是c++,有些参数不对,就会导致异常:
比如交易软件:
 
比如下单函数passorder的参数列表:
volume,下单数量(股 / 手 / 元 / %)

passorder(opType, orderType, accountID, orderCode, prType, price, volume, ContextInfo)

根据 orderType 值最后一位确定 volume 的单位:

单股下单时:

1:股 / 手

2:金额(元)

3:比例(%)这个类型如果用了浮点,前面类型用了以股为但是,是会报错的,因为不存在100.11 股这样的非100单位的下单数据。
 
看完不想吐槽了,一群文科生设计的软件。。。





  查看全部
在部署QMT 在线文档的时候,还是忍不住吐槽下它的文档。
 这也是当时不用QMT的一个重要原因。
 
不仅仅是文档,而且还有它的函数接口的涉及。
 
比如最常用的交易函数,passorder
综合交易下单 passorder()
用法: passorder(opType, orderType, accountid, orderCode, prType, modelprice, volume[, strategyName, quickTrade, userOrderId], ContextInfo)

里面有11个参数,可选参数有2个。 对于一个常用函数来说,这个参数有点多了。
 
而更为令人费解的,是它参数里面额设定值
比如第一个opType,操作类型。
 
里面有59个数字:
期货六键:

0:开多

1:平昨多

2:平今多

3:开空

4:平昨空

5:平今空

期货四键:

6:平多,优先平今

7:平多,优先平昨

8:平空,优先平今

9:平空,优先平昨

期货两键:

10:卖出,如有多仓,优先平仓,优先平今,如有余量,再开空

11:卖出,如有多仓,优先平仓,优先平昨,如有余量,再开空

12:买入,如有空仓,优先平仓,优先平今,如有余量,再开多

13:买入,如有空仓,优先平仓,优先平昨,如有余量,再开多

14:买入,不优先平仓

15:卖出,不优先平仓

股票买卖:

23:股票买入,或沪港通、深港通股票买入

24:股票卖出,或沪港通、深港通股票卖出

融资融券:

27:融资买入

28:融券卖出

29:买券还券

30:直接还券

31:卖券还款

32:直接还款

33:信用账号股票买入

34:信用账号股票卖出

组合交易:

25:组合买入,或沪港通、深港通的组合买入

26:组合卖出,或沪港通、深港通的组合卖出

27:融资买入

28:融券卖出

29:买券还券

31:卖券还款

33:信用账号股票买入

34:信用账号股票卖出

40:期货组合开多

43:期货组合开空

46:期货组合平多,优先平今

47:期货组合平多,优先平昨

48:期货组合平空,优先平今

49:期货组合平空,优先平昨

期权交易:

50:买入开仓

51:卖出平仓

52:卖出开仓

53:买入平仓

54:备兑开仓

55:备兑平仓

56:认购行权

57:认沽行权

58:证券锁定

59:证券解锁

它把期货,股票,期权所有品种压缩到一起,通过参数数字来辨认交易类别。
 
那么我们来看一看一个例子,就拿一个官网的一个例子来说:
 
最简单的例子:
passorder(23,1101,account,s,11,14.00,100,2,ContextInfo)

一般人看了上面的代码,里面全部是数字,简直就像灾难一样。 但是我要明白它的交易品种和交易逻辑,
就得对着文档去查,编号23是啥,1101是啥,11,14又是啥。
 
如果我是代码reviewer,底下的员工这种文档,或者写代码的人,提交上这样的代码,绝对100%是要reject这个提交的。
 
然后orderType 更加让人吐血。。
 
1101:单股、单账号、普通、股/手方式下单

1102:单股、单账号、普通、金额(元)方式下单(只支持股票)

1113:单股、单账号、总资产、比例 [0 ~ 1] 方式下单

1123:单股、单账号、可用、比例[0 ~ 1]方式下单

1201:单股、账号组(无权重)、普通、股/手方式下单

1202:单股、账号组(无权重)、普通、金额(元)方式下单(只支持股票)

1213:单股、账号组(无权重)、总资产、比例 [0 ~ 1] 方式下单

1223:单股、账号组(无权重)、可用、比例 [0 ~ 1] 方式下单

2101:组合、单账号、普通、按组合股票数量(篮子中股票设定的数量)方式下单 > 对应 volume 的单位为篮子的份

2102:组合、单账号、普通、按组合股票权重(篮子中股票设定的权重)方式下单 > 对应 volume 的单位为元

2103:组合、单账号、普通、按账号可用方式下单 > (底层篮子股票怎么分配?答:按可用资金比例后按篮子中股票权重分配,如用户没填权重则按相等权重分配)只对股票篮子支持

2201:组合、账号组(无权重)、普通、按组合股票数量方式下单

2202:组合、账号组(无权重)、普通、按组合股票权重方式下单



这排列组合,谁能记得住,逼着你去查文档,或者每次复制粘贴旧代码。
 
然后下单 类型,继续来各种枚举:
 
-1:无效(实际下单时,需要用交易面板交易函数那设定的选价类型)

0:卖5价

1:卖4价

2:卖3价

3:卖2价

4:卖1价

5:最新价

6:买1价

7:买2价(组合不支持)

8:买3价(组合不支持)

9:买4价(组合不支持)

10:买5价(组合不支持)

11:(指定价)模型价(只对单股情况支持,对组合交易不支持)

12:涨跌停价

13:挂单价

14:对手价

27:市价即成剩撤(仅对股票期权申报有效)

28:市价即全成否则撤(仅对股票期权申报有效)

29:市价剩转限价(仅对股票期权申报有效)

42:最优五档即时成交剩余撤销申报(仅对上交所申报有效)

43:最优五档即时成交剩转限价申报(仅对上交所申报有效)

44:对手方最优价格委托(仅对深交所申报有效)

45:本方最优价格委托(仅对深交所申报有效)

46:即时成交剩余撤销委托(仅对深交所申报有效)

47:最优五档即时成交剩余撤销委托(仅对深交所申报有效)

48:全额成交或撤销委托(仅对深交所申报有效)

49:科创板盘后定价

会不会用常量定义个值给客户调用呢?
 
passorder(
ContextInfo.TYPE_STOCK,

ContextInfo.TYPE_BUY,
100,
ContextInfo.LIMIT_PRICE,
ContextInfo)

没有标注类型:
虽然python是若类型的语言,可是qmt底层是c++,有些参数不对,就会导致异常:
比如交易软件:
 
比如下单函数passorder的参数列表:
volume,下单数量(股 / 手 / 元 / %)

passorder(opType, orderType, accountID, orderCode, prType, price, volume, ContextInfo)

根据 orderType 值最后一位确定 volume 的单位:

单股下单时:

1:股 / 手

2:金额(元)

3:比例(%)
这个类型如果用了浮点,前面类型用了以股为但是,是会报错的,因为不存在100.11 股这样的非100单位的下单数据。
 
看完不想吐槽了,一群文科生设计的软件。。。

3fc3af7e327ac67c475223f8424004fd.jpg

 

为什么我的QMT安装目录下没有miniqmt的包xtquant

QMT李魔佛 发表了文章 • 0 个评论 • 1238 次浏览 • 2023-02-20 21:00 • 来自相关话题

今天有位群友,qmt新手,说看了我的公众号,想搞miniQMT,结果发现安装了国盛的QMT之后没有发现xtquant的目录。





 



 
他安装的也是实盘正式版本的QMT。
 
那么问题出现在哪里呢?
 
主要问题在于它没有在qmt内部 下载内置的python库。
 





 
经过这个下载过程后。
 
然后就可以看到有site-packages了





 

 
  查看全部
今天有位群友,qmt新手,说看了我的公众号,想搞miniQMT,结果发现安装了国盛的QMT之后没有发现xtquant的目录。

20230220185141623.png

 
20230220012.jpg

 
他安装的也是实盘正式版本的QMT。
 
那么问题出现在哪里呢?
 
主要问题在于它没有在qmt内部 下载内置的python库。
 

mmexport1676896038788.png

 
经过这个下载过程后。
 
然后就可以看到有site-packages了

20230220013.jpg

 

 
 

qmt iquant最新接口文档

QMT李魔佛 发表了文章 • 0 个评论 • 1522 次浏览 • 2023-02-19 15:16 • 来自相关话题

申请了个二级域名,作为QMT iQuant的接口文档。懒得再去搞新的域名了,凑合这用,和ptrade的接口文档拼在一个根域名下面
 
http://qmt.ptradeapi.com





 





 





 
除了官方的接口文档,还加入了一些个人平时编写的写法与回测,实盘代码。 不定期更新。
 
欢迎关注收藏。 查看全部
申请了个二级域名,作为QMT iQuant的接口文档。懒得再去搞新的域名了,凑合这用,和ptrade的接口文档拼在一个根域名下面
 
http://qmt.ptradeapi.com

20230219003.jpg

 

20230219004.jpg

 

20230219005.jpg

 
除了官方的接口文档,还加入了一些个人平时编写的写法与回测,实盘代码。 不定期更新。
 
欢迎关注收藏。

整理一批 注册好的免费chatGPT账户,从分享群里获取的,亲测有效

网络马化云 发表了文章 • 0 个评论 • 4029 次浏览 • 2023-02-16 12:51 • 来自相关话题

 
请勿随意修改密码: ChatGPT共享账号
账号1:vickye89@hotmail.com
密码:LeZ25X5dwL
账号2:eugeniev552@hotmail.com
密码2:4w95MnvIvc
账号3:ayakonewuyo@hotmail.com
密码3:q8UCd2lST4
账号4:ludmillasteb9@hotmail.com
密码4:7sb54Oii8I
账号5:chr89kuchto@hotmail.com
密码5:Cea7IQj5ud
账号6:emil03mk@hotmail.com
密码6:ENC82hip2A
账号7:lydiavn9ktutoky@hotmail.com
密码7:6351VsZz25
账号8:tulagj3@hotmail.com
密码8:Wx99eCqer7
账号9:prue56zjehle@hotmail.com
密码9:8398k84X85
账号10:vernitagq2@hotmail.com
密码10:geFfr4H0x9
账号11:kirstiealtqw@hotmail.com
密码11:1FBbV8OJg9
账号12:ralphnamer32d@hotmail.com
密码12:F85T86YtbL
账号13:celinabullievmu@hotmail.com
密码13:OqTz0lj525
账号14:chanafdidelaet@hotmail.com
密码14:6x3CM4pPYY
账号15:alita07pbogdon@hotmail.com
密码15:Umppl1ylc0
账号16:averilltxgt@hotmail.com
密码16:94cymN2p42
账号17:mobyfotohy7@hotmail.com
密码17:c8iJi0Fd
账号18:muficylequ9@hotmail.com
密码18:5p0KWJf1D
账号19:naehahogujo0@hotmail.com
密码19:xgH5o3jKV
账号20:naejexelibu@hotmail.com
密码20:fZg44fVeh
账号21:naezhaeshequsito@outlook.com
密码21:PtRbh31IF
账号22:neladeroka@hotmail.com
密码22:McTk3Qrz
账号23:pyvohywaeli@outlook.com
密码23:Ehk9d5QFz4
账号24:qadakidone@hotmail.com
密码24:I836s6941q
账号25:qaraesisheby9@hotmail.com
密码25:UQkJim80c
账号26:qaxiberasipy@outlook.com
密码26:XVYluIYy2P
账号27:qeluzhaelagy4@hotmail.com
密码27:8qZEl20fR
账号28:qobiluno7@hotmail.com
密码28:4KiM2C0q9
账号29:qupipaeshe1@outlook.com
密码29:4j9NSpGHEZ
账号30:qyshymisifi0@hotmail.com
密码30:Sfp9D0UNK4
账号31:raehotushawo@hotmail.com
密码31:2d0H8o9L




https://chat.openai.com/auth/login​
ChatGPT登录地址 ChatGPT
 
需要配合梯子使用,效果更佳。
如果显示:






就是要搭梯子了
 
更多数据,请关注公众号,后台回复:chatgpt账户 查看全部
20230216001.jpg

 
请勿随意修改密码: 
ChatGPT共享账号
账号1:vickye89@hotmail.com
密码:LeZ25X5dwL
账号2:eugeniev552@hotmail.com
密码2:4w95MnvIvc
账号3:ayakonewuyo@hotmail.com
密码3:q8UCd2lST4
账号4:ludmillasteb9@hotmail.com
密码4:7sb54Oii8I
账号5:chr89kuchto@hotmail.com
密码5:Cea7IQj5ud
账号6:emil03mk@hotmail.com
密码6:ENC82hip2A
账号7:lydiavn9ktutoky@hotmail.com
密码7:6351VsZz25
账号8:tulagj3@hotmail.com
密码8:Wx99eCqer7
账号9:prue56zjehle@hotmail.com
密码9:8398k84X85
账号10:vernitagq2@hotmail.com
密码10:geFfr4H0x9
账号11:kirstiealtqw@hotmail.com
密码11:1FBbV8OJg9
账号12:ralphnamer32d@hotmail.com
密码12:F85T86YtbL
账号13:celinabullievmu@hotmail.com
密码13:OqTz0lj525
账号14:chanafdidelaet@hotmail.com
密码14:6x3CM4pPYY
账号15:alita07pbogdon@hotmail.com
密码15:Umppl1ylc0
账号16:averilltxgt@hotmail.com
密码16:94cymN2p42
账号17:mobyfotohy7@hotmail.com
密码17:c8iJi0Fd
账号18:muficylequ9@hotmail.com
密码18:5p0KWJf1D
账号19:naehahogujo0@hotmail.com
密码19:xgH5o3jKV
账号20:naejexelibu@hotmail.com
密码20:fZg44fVeh
账号21:naezhaeshequsito@outlook.com
密码21:PtRbh31IF
账号22:neladeroka@hotmail.com
密码22:McTk3Qrz
账号23:pyvohywaeli@outlook.com
密码23:Ehk9d5QFz4
账号24:qadakidone@hotmail.com
密码24:I836s6941q
账号25:qaraesisheby9@hotmail.com
密码25:UQkJim80c
账号26:qaxiberasipy@outlook.com
密码26:XVYluIYy2P
账号27:qeluzhaelagy4@hotmail.com
密码27:8qZEl20fR
账号28:qobiluno7@hotmail.com
密码28:4KiM2C0q9
账号29:qupipaeshe1@outlook.com
密码29:4j9NSpGHEZ
账号30:qyshymisifi0@hotmail.com
密码30:Sfp9D0UNK4
账号31:raehotushawo@hotmail.com
密码31:2d0H8o9L




https://chat.openai.com/auth/login​
ChatGPT登录地址 ChatGPT
 
需要配合梯子使用,效果更佳。
如果显示:

20230216002.jpg


就是要搭梯子了
 
更多数据,请关注公众号,后台回复:chatgpt账户

【白嫖服务器】render.com上部署flask程序

网络马化云 发表了文章 • 0 个评论 • 1421 次浏览 • 2023-02-14 15:43 • 来自相关话题

要在Render.com上部署Flask应用程序,可以按照以下步骤进行操作:
1. 注册Render.com帐户并创建一个新的Web服务。

2. 在“添加服务”页面上选择“Web服务”并选择“自定义”作为服务类型。
 
3. 选择一个适合您的Flask应用程序的服务器和端口。
 
4. 在“高级”选项卡中添加一个名为“WEB_COMMAND”的环境变量,其值为“gunicorn your_app_name:app”(替换your_app_name为您的应用程序名称)。
 
5. 在“高级”选项卡中添加一个名为“WEB_CONCURRENCY”的环境变量,其值为应用程序的工作进程数(例如2)。
 
6. 将您的Flask应用程序代码推送到GitHub或其他源代码管理库中,并将其链接到Render.com服务。
 
7. 等待几分钟,Render.com将自动构建和部署您的Flask应用程序。

完成以上步骤后,您的Flask应用程序将已经成功部署在Render.com上。
 
示例代码:from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello, World!'上面是app.py 的内容
 




 
同步到github上后,绑定域名,运行得到: 





 
是不是很简单呢?
 
网站可以免费解析25个域名,超过的需要收费。不过一般人应该不会超过那么多的域名的了吧。
 

Starting February 1, 2022, we will begin charging $0.60 per custom domain per month beyond the first 25 custom domains for a web service or static site. The first 25 custom domains for web services and static sites will continue to be free.


 
 
 
  查看全部
要在Render.com上部署Flask应用程序,可以按照以下步骤进行操作:
1. 注册Render.com帐户并创建一个新的Web服务。

2. 在“添加服务”页面上选择“Web服务”并选择“自定义”作为服务类型。
 
3. 选择一个适合您的Flask应用程序的服务器和端口。
 
4. 在“高级”选项卡中添加一个名为“WEB_COMMAND”的环境变量,其值为“gunicorn your_app_name:app”(替换your_app_name为您的应用程序名称)。
 
5. 在“高级”选项卡中添加一个名为“WEB_CONCURRENCY”的环境变量,其值为应用程序的工作进程数(例如2)。
 
6. 将您的Flask应用程序代码推送到GitHub或其他源代码管理库中,并将其链接到Render.com服务。
 
7. 等待几分钟,Render.com将自动构建和部署您的Flask应用程序。

完成以上步骤后,您的Flask应用程序将已经成功部署在Render.com上。
 
示例代码:
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello, World!'
上面是app.py 的内容
 
20230214004.jpg

 
同步到github上后,绑定域名,运行得到: 

20230214006.jpg

 
是不是很简单呢?
 
网站可以免费解析25个域名,超过的需要收费。不过一般人应该不会超过那么多的域名的了吧。
 


Starting February 1, 2022, we will begin charging $0.60 per custom domain per month beyond the first 25 custom domains for a web service or static site. The first 25 custom domains for web services and static sites will continue to be free.



 
 
 
 

迅投qmt入门教程(一)

QMT李魔佛 发表了文章 • 0 个评论 • 8679 次浏览 • 2023-02-06 19:43 • 来自相关话题

很早想写一个qmt教程的,无奈平时90%时间都用的ptrade。之前想把教程写好了再发出来,不过这样只会越拖越久,为了让自己填这个坑,先把文章发出来,按照平时正常的量化学习的路径,从简单到复杂。 慢慢记录,形成个系列教程。 有疑问的朋友可以到笔者的公众号或者知识星球去提问吧。(见文末)
 
1. 准备:
 
首先得开一个支持qmt的券商,目前市面上支持qmt的券商越来越丰富了。
 
初学者可以开一个门槛第一点的,一般入金1w-2w 不等,就可以申请开通了。 
 
鉴于以学习为目的,真正投入到实盘中的资金不会很大,所以初始阶段也不一定就找万一免五的券商,毕竟目前要给免五,资金门槛比较高,一般要100w甚至以上。
 
笔者推荐国信,国金的qmt, 门槛只要1-2w就足够了,股票费率在万一,可转债万0.4-万0.5。适合初学者,这两家也可以在虚拟机运行,适合苹果mac的用户。 需要的朋友也可以在公众号后台留言: qmt开通





 
2. 假设已经在券商那里开通了qmt功能,接下来就开始进入教学:
 
这里以国信的qmt(iquant)为例:
 
首先要做的就是下载python库。 这个python库指的是qmt的python库,它的版本是3.6.8; 如果你只用qmt内置的python,你就不用自己到网上下载python安装程序,只需要在qmt的设置里面,点一下按钮,就可以安装python库。这里用默认的系统路径就可以了。
 





 
3. 第一个量化程序 hello world
 
新建策略后:
在编辑器里面输入下面的代码:#encoding:gbk

def init(ContextInfo):
print('hello world')

def handlebar(ContextInfo):
#计算当前主图的cci
print("handle bar")
点击回测:
得到输出结果




 
这里介绍2个概念:(3)Handlebar

handlebar 是整个 Python 模型中的核心执行函数。当模型从数据层获取到运行所需要的数据之后,会对数据集上的每一根 bar,调用一次 handlebar 函数,处理当前这根 bar 上的数据。也就是说,用户模型的核心逻辑都是写在该函数中的,如获取数据,设置下单条件等。在 handlebar 中处理完数据后,用户可以通过 paint 方法将需要绘图输出的结果返回给界面。界面会将输出结果如实的展示出来。 (4)ContextInfo

ContextInfo 是整个 Python 框架中的一个核心对象。它包含了各种与 Python 底层框架交互的 API 方法,也是一个全局的上下文环境,可以在 init 以及 handlebar 这两个函数中自由地传递用户创建的各种自定义数据。





文绉绉的,实际写一个策略,必须包含下面两个函数,而且参数也要一致,参数名随意,不过用默认的就好了。你随便改成没有意义的字符,后面自己看代码也是很麻烦。def init(ContextInfo):
pass

def handlebar(ContextInfo):
pass
 
init 和 handlebar 是 Python 模型中最重要的方法,也是唯二由 C++ 直接调用的方法,所有的执行代码都尽量写在这两个方法中或由其中的函数调用。【个人不太喜欢这样】
 
回测时间设置,在右边的菜单栏,有个回测参数,里面设置时间;在菜单“基本信息”里面 ,可以设置回测的时间间隔,可以使用分钟线,日线,小时等等不同周期,不过无法做到tick的回测。最小的只能到分钟。
 
但是如果你有秒的tick数据,自己写个回测框架也是可以做到秒级的tick级别的回测。很早前笔者就在星球上提供了完整的源码和数据,初学者也可以拿着去改,只要后续更新tick数据,就可以不断的回测策略的最新状态。
 
你写的回测实盘python代码,是保存在本地的文件夹的:
C:\iquant_gx\python, 前面的C:\iquant_gx 是你的iquant安装路径。
 
而且底下也有很多的现成的代码:





 
部分代码可以直接用pycharm就可以打开,没有加密的,但也有一些是加密了的。
比如这个自动逆回购是现成的:





对,这里就有,很多人还到处找人写;# encoding:gbk
import logging
from datetime import datetime, timedelta
from decimal import Decimal as D
from decimal import InvalidOperation

logging.basicConfig(level=logging.INFO)

# 挂单失败后的等待时长,以秒计
TIMEOUT_ON_FAIL_SEC = 30
# 等待account_callback的时长
# RUN_TIME_DELAY = 30

# how is this not defined in package??
MORNING_START = datetime.strptime(datetime.now().strftime('%Y%m%d') + '093000', '%Y%m%d%H%M%S')
MORNING_END = datetime.strptime(datetime.now().strftime('%Y%m%d') + '113000', '%Y%m%d%H%M%S')
NOON_START = datetime.strptime(datetime.now().strftime('%Y%m%d') + '130000', '%Y%m%d%H%M%S')
NOON_END = datetime.strptime(datetime.now().strftime('%Y%m%d') + '153000', '%Y%m%d%H%M%S')

# for SH only
TRANS_COST_1D = D('5e-6')
TRANS_COST_LONG = D('1.5e-7')
TRANS_COST_MAX = 100

# ORDER LIMITS
SH_UPPER = 1e7
SH_LOWER = 1e5
SZ_UPPER = 1e8
SZ_LOWER = 1e3

# ASSET NAME DICT
SH_REV_REPO = {'上交所1天': '204001.SH', '上交所2天': '204002.SH', '上交所3天': '204003.SH',
'上交所4天': '204004.SH', '上交所7天': '204007.SH', '上交所14天': '204014.SH',
'上交所28天': '204028.SH', '上交所91天': '204091.SH', '上交所182天': '204182.SH',
}

SZ_REV_REPO = {'深交所3天': '131800.SZ', '深交所7天': '131801.SZ', '深交所14天': '131802.SZ',
'深交所28天': '131803.SZ', '深交所91天': '131805.SZ', '深交所182天': '131806.SZ',
'深交所4天': '131809.SZ', '深交所1天': '131810.SZ', '深交所2天': '131811.SZ',
}


def init(ContextInfo):
ContextInfo.accID = account
ContextInfo.set_account(ContextInfo.accID)
ContextInfo.use_all_cap = False if ALL_CAP == '否' else True

# global trading control, set to False if detected error on user's side
# stop() does not halt strat
ContextInfo.order_control = False

if not ContextInfo.use_all_cap:
try:
ContextInfo.dollar_vol = float(D(DOLLAR_VOL))
except InvalidOperation:
ContextInfo.order_control = True
raise ValueError('读取资金量失败')
else:
if DOLLAR_VOL != '':
logging.warning('已设定使用全部账户资金,忽略所设置资金量')

try:
ContextInfo.start_time = datetime.strptime(datetime.now().strftime('%Y%m%d') + str(START_TIME), '%Y%m%d%H%M%S')
ContextInfo.asset_name = SH_REV_REPO[ASSET_NAME]
except KeyError:
ContextInfo.asset_name = SZ_REV_REPO[ASSET_NAME]
except ValueError as error:
if 'unconverted data remains' in str(error):
ContextInfo.order_control = True
raise ValueError('读取挂单时间失败')

if not (MORNING_END > ContextInfo.start_time >= MORNING_START) \
and not (NOON_END > ContextInfo.start_time >= NOON_START):
ContextInfo.order_control = True
raise ValueError('挂单时间不在可交易时间内')

ContextInfo.can_order = False
ContextInfo.order_done = False

if not ContextInfo.order_control:
ContextInfo.run_time("place_order", "{0}nSecond".format(TIMEOUT_ON_FAIL_SEC),
ContextInfo.start_time.strftime('%Y-%m-%d %H:%M:%S'), 'SH')


def account_callback(ContextInfo, accountInfo):
if not ContextInfo.can_order:
ContextInfo.can_order = True
if ContextInfo.use_all_cap:
ContextInfo.dollar_vol = accountInfo.m_dAvailable
else:
if ContextInfo.dollar_vol > accountInfo.m_dAvailable:
ContextInfo.order_control = True
raise ValueError('下单额度大于账户可用资金')

# check if order satisfies lower limit for each exchange
if ('SH' in ContextInfo.asset_name and ContextInfo.dollar_vol < SH_LOWER) \
or ('SZ' in ContextInfo.asset_name and ContextInfo.dollar_vol < SZ_LOWER):
ContextInfo.order_control = True
raise ValueError('下单额度低于交易所最低限额')

# checks dollar_vol and rounds the total amount
if 'SH' in ContextInfo.asset_name and ContextInfo.dollar_vol % SH_LOWER != 0:
ContextInfo.dollar_vol = (ContextInfo.dollar_vol // SH_LOWER) * SH_LOWER
logging.warning('下单额度已规整为:{0}'.format(ContextInfo.dollar_vol))
elif 'SZ' in ContextInfo.asset_name and ContextInfo.dollar_vol % SZ_LOWER != 0:
ContextInfo.dollar_vol = (ContextInfo.dollar_vol // SZ_LOWER) * SZ_LOWER
logging.warning('下单额度已规整为:{0}'.format(ContextInfo.dollar_vol))

'''
if 'SH' in ContextInfo.asset_name:
num_batch_order = int(ContextInfo.dollar_vol // SH_UPPER)
remain_order = ContextInfo.dollar_vol - num_batch_order * SH_UPPER
if ContextInfo.asset_name == '204001.SH':
transaction_cost = TRANS_COST_MAX * num_batch_order + remain_order * TRANS_COST_1D
else:
transaction_cost = TRANS_COST_MAX * num_batch_order + remain_order * TRANS_COST_LONG
if transaction_cost + ContextInfo.dollar_vol > accountInfo.m_dAvailable:
ContextInfo.order_control = True
raise ValueError('可用资金不足以垫付交易金额与手续费')
'''

ContextInfo.remain_vol = ContextInfo.dollar_vol


def handlebar(ContextInfo):
return


def place_order(ContextInfo):
if not ContextInfo.can_order or ContextInfo.order_control:
return

if not ContextInfo.order_done:
if 'SH' in ContextInfo.asset_name:
num_batch_order = int(ContextInfo.remain_vol // SH_UPPER)
remain_order = ContextInfo.remain_vol - num_batch_order * SH_UPPER
for _ in range(num_batch_order):
order_remark = '国债逆回购:尝试报单{0}元 {1}'.format(SH_UPPER, ContextInfo.asset_name)
passorder(24, 1102, ContextInfo.accID, ContextInfo.asset_name, 5, -1, SH_UPPER, order_remark, 1,
order_remark, ContextInfo)
else:
num_batch_order = int(ContextInfo.remain_vol // SZ_UPPER)
remain_order = ContextInfo.remain_vol - num_batch_order * SZ_UPPER
for _ in range(num_batch_order):
order_remark = '国债逆回购:尝试报单{0}元 {1}'.format(SZ_UPPER, ContextInfo.asset_name)
passorder(24, 1102, ContextInfo.accID, ContextInfo.asset_name, 5, -1, SZ_UPPER, order_remark, 1,
order_remark, ContextInfo)

order_remark = '国债逆回购:尝试报单{0}元 {1}'.format(remain_order, ContextInfo.asset_name)
passorder(24, 1102, ContextInfo.accID, ContextInfo.asset_name, 5, -1, remain_order, order_remark, 1,
order_remark, ContextInfo)

ContextInfo.remain_vol = 0
ContextInfo.order_done = True


def order_callback(ContextInfo, orderInfo):
curr_remark = orderInfo.m_strRemark
curr_status = orderInfo.m_nOrderStatus

if '国债逆回购' in curr_remark and ContextInfo.asset_name in curr_remark and curr_status == 57:
ContextInfo.order_done = False
# up the leftover dollar vol by failed amount
# logging.info('reported trade amount:{0}, reported_trade_volume:{1}'.format(orderInfo.m_dTradeAmount, orderInfo.m_nVolumeTotal))
# 单张100元
ContextInfo.remain_vol += orderInfo.m_nVolumeTotal * 100
if '交易时间不合法' in orderInfo.m_strCancelInfo:
ContextInfo.order_control = True
raise ValueError('国债逆回购:未能在交易时间内完成下单,停止报单。余量{0}元未报'.format(ContextInfo.remain_vol))
logging.warning('国债逆回购:报单废单,原因:\"{0}\",尝试重报'.format(orderInfo.m_strCancelInfo))
elif '国债逆回购' in curr_remark and ContextInfo.asset_name in curr_remark and curr_status == 50:
logging.info('国债逆回购:报单{0}元成功'.format(orderInfo.m_nVolumeTotal * 100))
return




待续,不定期更新


 
 
公众号:

星球:

 
 
 
  查看全部
很早想写一个qmt教程的,无奈平时90%时间都用的ptrade。之前想把教程写好了再发出来,不过这样只会越拖越久,为了让自己填这个坑,先把文章发出来,按照平时正常的量化学习的路径,从简单到复杂。 慢慢记录,形成个系列教程。 有疑问的朋友可以到笔者的公众号或者知识星球去提问吧。(见文末)
 
1. 准备:
 
首先得开一个支持qmt的券商,目前市面上支持qmt的券商越来越丰富了。
 
初学者可以开一个门槛第一点的,一般入金1w-2w 不等,就可以申请开通了。 
 
鉴于以学习为目的,真正投入到实盘中的资金不会很大,所以初始阶段也不一定就找万一免五的券商,毕竟目前要给免五,资金门槛比较高,一般要100w甚至以上。
 
笔者推荐国信,国金的qmt, 门槛只要1-2w就足够了,股票费率在万一,可转债万0.4-万0.5。适合初学者,这两家也可以在虚拟机运行,适合苹果mac的用户。 需要的朋友也可以在公众号后台留言: qmt开通

20230206005.jpg

 
2. 假设已经在券商那里开通了qmt功能,接下来就开始进入教学:
 
这里以国信的qmt(iquant)为例:
 
首先要做的就是下载python库。 这个python库指的是qmt的python库,它的版本是3.6.8; 如果你只用qmt内置的python,你就不用自己到网上下载python安装程序,只需要在qmt的设置里面,点一下按钮,就可以安装python库。这里用默认的系统路径就可以了。
 

20230206006.jpg

 
3. 第一个量化程序 hello world
 
新建策略后:
在编辑器里面输入下面的代码:
#encoding:gbk

def init(ContextInfo):
print('hello world')

def handlebar(ContextInfo):
#计算当前主图的cci
print("handle bar")

点击回测:
得到输出结果
20230206007.jpg

 
这里介绍2个概念:
(3)Handlebar

handlebar 是整个 Python 模型中的核心执行函数。当模型从数据层获取到运行所需要的数据之后,会对数据集上的每一根 bar,调用一次 handlebar 函数,处理当前这根 bar 上的数据。也就是说,用户模型的核心逻辑都是写在该函数中的,如获取数据,设置下单条件等。在 handlebar 中处理完数据后,用户可以通过 paint 方法将需要绘图输出的结果返回给界面。界面会将输出结果如实的展示出来。
 
(4)ContextInfo

ContextInfo 是整个 Python 框架中的一个核心对象。它包含了各种与 Python 底层框架交互的 API 方法,也是一个全局的上下文环境,可以在 init 以及 handlebar 这两个函数中自由地传递用户创建的各种自定义数据。





文绉绉的,实际写一个策略,必须包含下面两个函数,而且参数也要一致,参数名随意,不过用默认的就好了。你随便改成没有意义的字符,后面自己看代码也是很麻烦。
def init(ContextInfo):
pass

def handlebar(ContextInfo):
pass

 
init 和 handlebar 是 Python 模型中最重要的方法,也是唯二由 C++ 直接调用的方法,所有的执行代码都尽量写在这两个方法中或由其中的函数调用。【个人不太喜欢这样】
 
回测时间设置,在右边的菜单栏,有个回测参数,里面设置时间;在菜单“基本信息”里面 ,可以设置回测的时间间隔,可以使用分钟线,日线,小时等等不同周期,不过无法做到tick的回测。最小的只能到分钟。
 
但是如果你有秒的tick数据,自己写个回测框架也是可以做到秒级的tick级别的回测。很早前笔者就在星球上提供了完整的源码和数据,初学者也可以拿着去改,只要后续更新tick数据,就可以不断的回测策略的最新状态。
 
你写的回测实盘python代码,是保存在本地的文件夹的:
C:\iquant_gx\python, 前面的C:\iquant_gx 是你的iquant安装路径。
 
而且底下也有很多的现成的代码:

20230206008.jpg

 
部分代码可以直接用pycharm就可以打开,没有加密的,但也有一些是加密了的。
比如这个自动逆回购是现成的:

20230206010.jpg

对,这里就有,很多人还到处找人写;
# encoding:gbk
import logging
from datetime import datetime, timedelta
from decimal import Decimal as D
from decimal import InvalidOperation

logging.basicConfig(level=logging.INFO)

# 挂单失败后的等待时长,以秒计
TIMEOUT_ON_FAIL_SEC = 30
# 等待account_callback的时长
# RUN_TIME_DELAY = 30

# how is this not defined in package??
MORNING_START = datetime.strptime(datetime.now().strftime('%Y%m%d') + '093000', '%Y%m%d%H%M%S')
MORNING_END = datetime.strptime(datetime.now().strftime('%Y%m%d') + '113000', '%Y%m%d%H%M%S')
NOON_START = datetime.strptime(datetime.now().strftime('%Y%m%d') + '130000', '%Y%m%d%H%M%S')
NOON_END = datetime.strptime(datetime.now().strftime('%Y%m%d') + '153000', '%Y%m%d%H%M%S')

# for SH only
TRANS_COST_1D = D('5e-6')
TRANS_COST_LONG = D('1.5e-7')
TRANS_COST_MAX = 100

# ORDER LIMITS
SH_UPPER = 1e7
SH_LOWER = 1e5
SZ_UPPER = 1e8
SZ_LOWER = 1e3

# ASSET NAME DICT
SH_REV_REPO = {'上交所1天': '204001.SH', '上交所2天': '204002.SH', '上交所3天': '204003.SH',
'上交所4天': '204004.SH', '上交所7天': '204007.SH', '上交所14天': '204014.SH',
'上交所28天': '204028.SH', '上交所91天': '204091.SH', '上交所182天': '204182.SH',
}

SZ_REV_REPO = {'深交所3天': '131800.SZ', '深交所7天': '131801.SZ', '深交所14天': '131802.SZ',
'深交所28天': '131803.SZ', '深交所91天': '131805.SZ', '深交所182天': '131806.SZ',
'深交所4天': '131809.SZ', '深交所1天': '131810.SZ', '深交所2天': '131811.SZ',
}


def init(ContextInfo):
ContextInfo.accID = account
ContextInfo.set_account(ContextInfo.accID)
ContextInfo.use_all_cap = False if ALL_CAP == '否' else True

# global trading control, set to False if detected error on user's side
# stop() does not halt strat
ContextInfo.order_control = False

if not ContextInfo.use_all_cap:
try:
ContextInfo.dollar_vol = float(D(DOLLAR_VOL))
except InvalidOperation:
ContextInfo.order_control = True
raise ValueError('读取资金量失败')
else:
if DOLLAR_VOL != '':
logging.warning('已设定使用全部账户资金,忽略所设置资金量')

try:
ContextInfo.start_time = datetime.strptime(datetime.now().strftime('%Y%m%d') + str(START_TIME), '%Y%m%d%H%M%S')
ContextInfo.asset_name = SH_REV_REPO[ASSET_NAME]
except KeyError:
ContextInfo.asset_name = SZ_REV_REPO[ASSET_NAME]
except ValueError as error:
if 'unconverted data remains' in str(error):
ContextInfo.order_control = True
raise ValueError('读取挂单时间失败')

if not (MORNING_END > ContextInfo.start_time >= MORNING_START) \
and not (NOON_END > ContextInfo.start_time >= NOON_START):
ContextInfo.order_control = True
raise ValueError('挂单时间不在可交易时间内')

ContextInfo.can_order = False
ContextInfo.order_done = False

if not ContextInfo.order_control:
ContextInfo.run_time("place_order", "{0}nSecond".format(TIMEOUT_ON_FAIL_SEC),
ContextInfo.start_time.strftime('%Y-%m-%d %H:%M:%S'), 'SH')


def account_callback(ContextInfo, accountInfo):
if not ContextInfo.can_order:
ContextInfo.can_order = True
if ContextInfo.use_all_cap:
ContextInfo.dollar_vol = accountInfo.m_dAvailable
else:
if ContextInfo.dollar_vol > accountInfo.m_dAvailable:
ContextInfo.order_control = True
raise ValueError('下单额度大于账户可用资金')

# check if order satisfies lower limit for each exchange
if ('SH' in ContextInfo.asset_name and ContextInfo.dollar_vol < SH_LOWER) \
or ('SZ' in ContextInfo.asset_name and ContextInfo.dollar_vol < SZ_LOWER):
ContextInfo.order_control = True
raise ValueError('下单额度低于交易所最低限额')

# checks dollar_vol and rounds the total amount
if 'SH' in ContextInfo.asset_name and ContextInfo.dollar_vol % SH_LOWER != 0:
ContextInfo.dollar_vol = (ContextInfo.dollar_vol // SH_LOWER) * SH_LOWER
logging.warning('下单额度已规整为:{0}'.format(ContextInfo.dollar_vol))
elif 'SZ' in ContextInfo.asset_name and ContextInfo.dollar_vol % SZ_LOWER != 0:
ContextInfo.dollar_vol = (ContextInfo.dollar_vol // SZ_LOWER) * SZ_LOWER
logging.warning('下单额度已规整为:{0}'.format(ContextInfo.dollar_vol))

'''
if 'SH' in ContextInfo.asset_name:
num_batch_order = int(ContextInfo.dollar_vol // SH_UPPER)
remain_order = ContextInfo.dollar_vol - num_batch_order * SH_UPPER
if ContextInfo.asset_name == '204001.SH':
transaction_cost = TRANS_COST_MAX * num_batch_order + remain_order * TRANS_COST_1D
else:
transaction_cost = TRANS_COST_MAX * num_batch_order + remain_order * TRANS_COST_LONG
if transaction_cost + ContextInfo.dollar_vol > accountInfo.m_dAvailable:
ContextInfo.order_control = True
raise ValueError('可用资金不足以垫付交易金额与手续费')
'''

ContextInfo.remain_vol = ContextInfo.dollar_vol


def handlebar(ContextInfo):
return


def place_order(ContextInfo):
if not ContextInfo.can_order or ContextInfo.order_control:
return

if not ContextInfo.order_done:
if 'SH' in ContextInfo.asset_name:
num_batch_order = int(ContextInfo.remain_vol // SH_UPPER)
remain_order = ContextInfo.remain_vol - num_batch_order * SH_UPPER
for _ in range(num_batch_order):
order_remark = '国债逆回购:尝试报单{0}元 {1}'.format(SH_UPPER, ContextInfo.asset_name)
passorder(24, 1102, ContextInfo.accID, ContextInfo.asset_name, 5, -1, SH_UPPER, order_remark, 1,
order_remark, ContextInfo)
else:
num_batch_order = int(ContextInfo.remain_vol // SZ_UPPER)
remain_order = ContextInfo.remain_vol - num_batch_order * SZ_UPPER
for _ in range(num_batch_order):
order_remark = '国债逆回购:尝试报单{0}元 {1}'.format(SZ_UPPER, ContextInfo.asset_name)
passorder(24, 1102, ContextInfo.accID, ContextInfo.asset_name, 5, -1, SZ_UPPER, order_remark, 1,
order_remark, ContextInfo)

order_remark = '国债逆回购:尝试报单{0}元 {1}'.format(remain_order, ContextInfo.asset_name)
passorder(24, 1102, ContextInfo.accID, ContextInfo.asset_name, 5, -1, remain_order, order_remark, 1,
order_remark, ContextInfo)

ContextInfo.remain_vol = 0
ContextInfo.order_done = True


def order_callback(ContextInfo, orderInfo):
curr_remark = orderInfo.m_strRemark
curr_status = orderInfo.m_nOrderStatus

if '国债逆回购' in curr_remark and ContextInfo.asset_name in curr_remark and curr_status == 57:
ContextInfo.order_done = False
# up the leftover dollar vol by failed amount
# logging.info('reported trade amount:{0}, reported_trade_volume:{1}'.format(orderInfo.m_dTradeAmount, orderInfo.m_nVolumeTotal))
# 单张100元
ContextInfo.remain_vol += orderInfo.m_nVolumeTotal * 100
if '交易时间不合法' in orderInfo.m_strCancelInfo:
ContextInfo.order_control = True
raise ValueError('国债逆回购:未能在交易时间内完成下单,停止报单。余量{0}元未报'.format(ContextInfo.remain_vol))
logging.warning('国债逆回购:报单废单,原因:\"{0}\",尝试重报'.format(orderInfo.m_strCancelInfo))
elif '国债逆回购' in curr_remark and ContextInfo.asset_name in curr_remark and curr_status == 50:
logging.info('国债逆回购:报单{0}元成功'.format(orderInfo.m_nVolumeTotal * 100))
return




待续,不定期更新


 
 
公众号:

星球:

 
 
 
 

qmt界面的运行和回测按钮功能有什么不同?

QMT李魔佛 发表了文章 • 0 个评论 • 1206 次浏览 • 2023-02-06 19:00 • 来自相关话题

他们二者的区别:
 
在模型编辑器中,有“回测”和“运行”两个按钮,分别代表两种模式,它们之间的区别如下:
(1)回测模式指策略以历史行情为依据,以回测参数中的开始时间、结束时间为回测时间区间进行运
算,投资者可观察该策略在历史行情所获得的年化收益率、夏普比率、最大回撤、信息比率等指标表
现。

(2)运行模式指策略根据实时行情信号进行运算,以主图行情开始时间到当前时间为运行区间,进行策
略的模拟运行,但不进行真实的委托。

注:如果需要向模拟/实盘柜台发送真实的委托,请将策略加入到“模型交易”中。
盘后运行可能会有抽风现象。

回测的时候日期问题,只能选副图,不知道为何 查看全部

20230206004.jpg

他们二者的区别:
 
在模型编辑器中,有“回测”和“运行”两个按钮,分别代表两种模式,它们之间的区别如下:
(1)回测模式指策略以历史行情为依据,以回测参数中的开始时间、结束时间为回测时间区间进行运
算,投资者可观察该策略在历史行情所获得的年化收益率、夏普比率、最大回撤、信息比率等指标表
现。

(2)运行模式指策略根据实时行情信号进行运算,以主图行情开始时间到当前时间为运行区间,进行策
略的模拟运行,但不进行真实的委托。

注:如果需要向模拟/实盘柜台发送真实的委托,请将策略加入到“模型交易”中。
盘后运行可能会有抽风现象。

回测的时候日期问题,只能选副图,不知道为何

Ptrade基本期货策略

Ptrade李魔佛 发表了文章 • 0 个评论 • 1341 次浏览 • 2023-02-04 14:17 • 来自相关话题

ptrade本身支持期货交易,开通账户绑定就可以了。
新建策略的时候选择:期货即可。





 
 
 1. 买入开仓
 
不同期货品种每一跳的价格变动都不一样,limit_price入参的时候要参考对应品种的价格变动规则,如limit_price不做入参则会以交易的行情快照最新价或者回测的分钟最新价进行报单;

根据交易所规则,每天结束时会取消所有未完成交易;
 
 
def initialize(context):
g.security = ['IF1712.CCFX', 'CU1806.XSGE']
set_universe(g.security)

def handle_data(context, data):
#买入开仓
buy_open('IF1712.CCFX', 1)

#买入开仓(限定点数为52220)
buy_open('CU1806.XSGE', 1, limit_price=52220)
2. 卖出平仓
def initialize(context):
g.security = ['IF1712.CCFX', 'CU1806.XSGE']
set_universe(g.security)

def handle_data(context, data):
#卖出平仓
sell_close('IF1712.CCFX', 1)
#卖出平今仓(限定点数为52220)
sell_close ('CU1806.XSGE', 1, limit_price=52220, close_today=True)
#卖出平仓(限定点数为52220)
sell_close ('CU1806.XSGE', 1, limit_price=52220)
3. 获取合约信息
get_instruments- 获取合约信息
 
get_instruments(contract)


返回

FutureParams对象,主要返回的字段为:

contract_code -- 合约代码,str类型;
contract_name -- 合约名称,str类型;
exchange -- 交易所:大商所、郑商所、上期所、中金所,str类型;
trade_unit -- 交易单位,int类型;
contract_multiplier -- 合约乘数,float类型;
delivery_date -- 交割日期,str类型;
listing_date -- 上市日期,str类型;
trade_code -- 交易代码,str类型;
margin_rate -- 保证金比例,float类型;

 
代码示例:
def initialize(context):
g.security = ["CU2112.XSGE", "IF2112.CCFX"]
set_universe(g.security)

def before_trading_start(context, data):
# 获取股票池代码合约信息
for security in g.security:
info = get_instruments(security)
log.info(info)

def handle_data(context, data):
pass 查看全部
ptrade本身支持期货交易,开通账户绑定就可以了。
新建策略的时候选择:期货即可。

20230204005.jpg

 
 
 1. 买入开仓
 
不同期货品种每一跳的价格变动都不一样,limit_price入参的时候要参考对应品种的价格变动规则,如limit_price不做入参则会以交易的行情快照最新价或者回测的分钟最新价进行报单;

根据交易所规则,每天结束时会取消所有未完成交易;
 
 
def initialize(context):
g.security = ['IF1712.CCFX', 'CU1806.XSGE']
set_universe(g.security)

def handle_data(context, data):
#买入开仓
buy_open('IF1712.CCFX', 1)

#买入开仓(限定点数为52220)
buy_open('CU1806.XSGE', 1, limit_price=52220)

2. 卖出平仓
def initialize(context):
g.security = ['IF1712.CCFX', 'CU1806.XSGE']
set_universe(g.security)

def handle_data(context, data):
#卖出平仓
sell_close('IF1712.CCFX', 1)
#卖出平今仓(限定点数为52220)
sell_close ('CU1806.XSGE', 1, limit_price=52220, close_today=True)
#卖出平仓(限定点数为52220)
sell_close ('CU1806.XSGE', 1, limit_price=52220)

3. 获取合约信息
get_instruments- 获取合约信息
 
get_instruments(contract)


返回

FutureParams对象,主要返回的字段为:

contract_code -- 合约代码,str类型;
contract_name -- 合约名称,str类型;
exchange -- 交易所:大商所、郑商所、上期所、中金所,str类型;
trade_unit -- 交易单位,int类型;
contract_multiplier -- 合约乘数,float类型;
delivery_date -- 交割日期,str类型;
listing_date -- 上市日期,str类型;
trade_code -- 交易代码,str类型;
margin_rate -- 保证金比例,float类型;


 
代码示例:
def initialize(context):
g.security = ["CU2112.XSGE", "IF2112.CCFX"]
set_universe(g.security)

def before_trading_start(context, data):
# 获取股票池代码合约信息
for security in g.security:
info = get_instruments(security)
log.info(info)

def handle_data(context, data):
pass

ptrade获取分时成交数据-LEVEL2数据逐笔数据

Ptrade李魔佛 发表了文章 • 0 个评论 • 2161 次浏览 • 2023-02-04 12:27 • 来自相关话题

在接口文档 http://ptradeapi.com/#get_tick_direction
中提供了获取分时成交的数据。
 
使用场景
该函数在交易模块可用

接口说明
该接口用于获取当日分时成交行情数据。

注意事项:

1、沪深市场都有分时成交数据;

2、分时成交数据需开通level2行情才有数据推送,否则无数据返回;
返回字段:
返回
返回一个OrderedDict对象,包含每只代码的分时成交行情数据。(OrderedDict([(),()...]))

返回结果字段介绍:

time_stamp: 时间戳毫秒级(str:numpy.int64);
hq_px: 价格(str:numpy.float64);
hq_px64: 价格(str:numpy.int64)(行情暂不支持,返回均为0);
business_amount: 成交数量(str:numpy.int64);
business_balance: 成交金额(str:numpy.int64);
business_count: 成交笔数(str:numpy.int64);
business_direction: 成交方向(0:卖,1:买,2:平盘)(str:numpy.int64);
amount: 持仓量(str:numpy.int64)(行情暂不支持,返回均为0);
start_index: 分笔关联的逐笔开始序号(str:numpy.int64)(行情暂不支持,返回均为0);
end_index: 分笔关联的逐笔结束序号(str:numpy.int64)(行情暂不支持,返回均为0);
示例代码:
def initialize(context):
g.security = '000001.SZ'
set_universe(g.security)

def handle_data(context, data):
#获取000001.SZ的分时成交数据
direction_data = get_tick_direction(g.security)
log.info(direction_data)
#获取指定股票列表分时成交数据
direction_data = get_tick_direction(['000002.SZ','000032.SZ'])
log.info(direction_data)
#获取成交量
business_amount = direction_data['000002.SZ']['business_amount']
log.info('分时成交的成交量为:%s' % business_amount)
不过在handle_bar中或者tick_data中,实际行情推送最快也要3s,所以拿到的level2的是切片数据,即使拿到很多数据,可是行情获取时间间隔还是3s, 无法做到和qmt那样的level2逐笔订阅驱动。还有level2数据需要收费。ptrade目前常用的几个券商都不支持level2的。
 
目前有万一免五的qmt ptrade量化交易接口的券商吗?
 

 
  查看全部
在接口文档 http://ptradeapi.com/#get_tick_direction
中提供了获取分时成交的数据。
 
使用场景
该函数在交易模块可用

接口说明
该接口用于获取当日分时成交行情数据。

注意事项:

1、沪深市场都有分时成交数据;

2、分时成交数据需开通level2行情才有数据推送,否则无数据返回;

返回字段:
返回
返回一个OrderedDict对象,包含每只代码的分时成交行情数据。(OrderedDict([(),()...]))

返回结果字段介绍:

time_stamp: 时间戳毫秒级(str:numpy.int64);
hq_px: 价格(str:numpy.float64);
hq_px64: 价格(str:numpy.int64)(行情暂不支持,返回均为0);
business_amount: 成交数量(str:numpy.int64);
business_balance: 成交金额(str:numpy.int64);
business_count: 成交笔数(str:numpy.int64);
business_direction: 成交方向(0:卖,1:买,2:平盘)(str:numpy.int64);
amount: 持仓量(str:numpy.int64)(行情暂不支持,返回均为0);
start_index: 分笔关联的逐笔开始序号(str:numpy.int64)(行情暂不支持,返回均为0);
end_index: 分笔关联的逐笔结束序号(str:numpy.int64)(行情暂不支持,返回均为0);

示例代码:
def initialize(context):
g.security = '000001.SZ'
set_universe(g.security)

def handle_data(context, data):
#获取000001.SZ的分时成交数据
direction_data = get_tick_direction(g.security)
log.info(direction_data)
#获取指定股票列表分时成交数据
direction_data = get_tick_direction(['000002.SZ','000032.SZ'])
log.info(direction_data)
#获取成交量
business_amount = direction_data['000002.SZ']['business_amount']
log.info('分时成交的成交量为:%s' % business_amount)

不过在handle_bar中或者tick_data中,实际行情推送最快也要3s,所以拿到的level2的是切片数据,即使拿到很多数据,可是行情获取时间间隔还是3s, 无法做到和qmt那样的level2逐笔订阅驱动。还有level2数据需要收费。ptrade目前常用的几个券商都不支持level2的。
 
目前有万一免五的qmt ptrade量化交易接口的券商吗?
 

 
 

ptrade移除当前ST股

Ptrade李魔佛 发表了文章 • 0 个评论 • 1031 次浏览 • 2023-02-04 12:14 • 来自相关话题

 
下面代码移除创业板,科创板还有当前被ST的股票。也可以任意组合,移除。
可以参考上一篇:http://30daydo.com/article/44569
 
def remove_st_stock(all_stock_list):
st_dict = get_stock_status(all_stock_list, query_type='ST', query_date=None)
st_list = []
for k, v in st_dict.items():
if v:
st_list.append(k)
return st_list

MARKET_DICT = {0: '科创板', 1: '创业板', }
IGNORE_MARKET = [0, 1]

def all_codes_in_market():
all_stock_set = set(get_Ashares(date=None))
for ignore_code in IGNORE_MARKET:
market = MARKET_DICT.get(ignore_code)
if market == '科创板':
all_stock_set = all_stock_set - set(filter(lambda x: x.startswith('68'), all_stock_set))
if market == '创业板':
all_stock_set = all_stock_set - set(filter(lambda x: x.startswith('3'), all_stock_set))

return all_stock_set


def create_target(context):
all_stock_set = all_codes_in_market()
st_list = remove_st_stock(list(all_stock_set))
all_stock_set = all_stock_set - set(st_list)
return all_stock_set
调用方式:

stock_target = create_target(None)
 
这样返回的股票就被排除了科创板,创业板,ST股票。
 

 
  查看全部
 
下面代码移除创业板,科创板还有当前被ST的股票。也可以任意组合,移除。
可以参考上一篇:http://30daydo.com/article/44569
 
def remove_st_stock(all_stock_list):
st_dict = get_stock_status(all_stock_list, query_type='ST', query_date=None)
st_list = []
for k, v in st_dict.items():
if v:
st_list.append(k)
return st_list

MARKET_DICT = {0: '科创板', 1: '创业板', }
IGNORE_MARKET = [0, 1]

def all_codes_in_market():
all_stock_set = set(get_Ashares(date=None))
for ignore_code in IGNORE_MARKET:
market = MARKET_DICT.get(ignore_code)
if market == '科创板':
all_stock_set = all_stock_set - set(filter(lambda x: x.startswith('68'), all_stock_set))
if market == '创业板':
all_stock_set = all_stock_set - set(filter(lambda x: x.startswith('3'), all_stock_set))

return all_stock_set


def create_target(context):
all_stock_set = all_codes_in_market()
st_list = remove_st_stock(list(all_stock_set))
all_stock_set = all_stock_set - set(st_list)
return all_stock_set

调用方式:

stock_target = create_target(None)
 
这样返回的股票就被排除了科创板,创业板,ST股票。
 

 
 

ptrade排除A股创业板,科创板的股票

Ptrade李魔佛 发表了文章 • 0 个评论 • 1257 次浏览 • 2023-02-04 10:48 • 来自相关话题

由于创业板和科创板的股票波动会比沪深主板的要大,所以如果想要按照某些策略,排除这两个板块的股票,可以使用下面的方法:
 
MARKET_DICT = {0: '科创板', 1: '创业板', }
IGNORE_MARKET = [0, 1]

def create_target(context):

all_stock_set = set(get_Ashares(date=None))
for ignore_code in IGNORE_MARKET:
market = MARKET_DICT.get(ignore_code)
if market == '科创板':
all_stock_set = all_stock_set - set(filter(lambda x:x.startswith('68'),all_stock_set))
if market == '创业板':
all_stock_set = all_stock_set - set(filter(lambda x:x.startswith('3'),all_stock_set))

return all_stock_set
返回的all_stock_set就是排除了创业板,科创板的股票列表。
 
ptrade接口文档:http://ptradeapi.com
  查看全部
由于创业板和科创板的股票波动会比沪深主板的要大,所以如果想要按照某些策略,排除这两个板块的股票,可以使用下面的方法:
 
MARKET_DICT = {0: '科创板', 1: '创业板', }
IGNORE_MARKET = [0, 1]

def create_target(context):

all_stock_set = set(get_Ashares(date=None))
for ignore_code in IGNORE_MARKET:
market = MARKET_DICT.get(ignore_code)
if market == '科创板':
all_stock_set = all_stock_set - set(filter(lambda x:x.startswith('68'),all_stock_set))
if market == '创业板':
all_stock_set = all_stock_set - set(filter(lambda x:x.startswith('3'),all_stock_set))

return all_stock_set

返回的all_stock_set就是排除了创业板,科创板的股票列表。
 
ptrade接口文档:http://ptradeapi.com