Ptrade在一个循环事件里 能否不断获取股票实时价格?
假设在一个事件循环里:
如:
run_daily(context, get_price, '09:44')
定义的get_price 函数,
然后get_price函数里面有一个死循环,不断地获取价格。
因为ptrade的行情切片 是每3秒更新的一次的,如果行情没更新,那么当前的价格也是过去最近的一个3s的价格。
现在问题是,在一个固定的时间里面,不断地读取价格函数,能获取到最新的价格吗 ?
我们用代码实践一下:
输出的结果:
为了更为直观,过滤掉另外一只可转债
只保留一只
更多ptrade实盘代码,请常见个人星球。
【可转债追涨杀跌日内T+0,双低 低价 低溢价 规模多因子轮动】
收起阅读 »
如:
run_daily(context, get_price, '09:44')
定义的get_price 函数,
然后get_price函数里面有一个死循环,不断地获取价格。
因为ptrade的行情切片 是每3秒更新的一次的,如果行情没更新,那么当前的价格也是过去最近的一个3s的价格。
现在问题是,在一个固定的时间里面,不断地读取价格函数,能获取到最新的价格吗 ?
我们用代码实践一下:
import time
def initialize(context):
# 初始化策略
run_daily(context, get_price, '09:44')
def handle_data(context, data):
pass
def get_price(context):
for i in range(10):
target_list =['113585.SS','123057.SZ']
bond_gear_price_target = get_gear_price(target_list)
for code in target_list:
price = bond_gear_price_target[code]['offer_grp'][1][0]
log.info('code: {} price {} '.format(code,price))
time.sleep(1)
输出的结果:
2022-09-28 10:31:00 - INFO - code: 113585.SS price 169.147
2022-09-28 10:31:00 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:01 - INFO - code: 113585.SS price 169.147
2022-09-28 10:31:01 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:02 - INFO - code: 113585.SS price 169.156
2022-09-28 10:31:02 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:03 - INFO - code: 113585.SS price 169.156
2022-09-28 10:31:03 - INFO - code: 128053.SZ price 144.8
2022-09-28 10:31:04 - INFO - code: 113585.SS price 169.199
2022-09-28 10:31:04 - INFO - code: 128053.SZ price 144.8
2022-09-28 10:31:05 - INFO - code: 113585.SS price 169.199
2022-09-28 10:31:05 - INFO - code: 128053.SZ price 144.8
2022-09-28 10:31:06 - INFO - code: 113585.SS price 169.199
2022-09-28 10:31:06 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:07 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:07 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:08 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:08 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:09 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:09 - INFO - code: 128053.SZ price 144.746
2022-09-28 10:31:10 - INFO - code: 113585.SS price 169.066
2022-09-28 10:31:10 - INFO - code: 128053.SZ price 144.746
2022-09-28 10:31:11 - INFO - code: 113585.SS price 169.066
2022-09-28 10:31:11 - INFO - code: 128053.SZ price 144.746
2022-09-28 10:31:12 - INFO - code: 113585.SS price 169.066
2022-09-28 10:31:12 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:13 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:13 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:14 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:14 - INFO - code: 128053.SZ price 144.785
2022-09-28 10:31:15 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:15 - INFO - code: 128053.SZ price 144.692
2022-09-28 10:31:16 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:16 - INFO - code: 128053.SZ price 144.692
2022-09-28 10:31:17 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:17 - INFO - code: 128053.SZ price 144.692
2022-09-28 10:31:18 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:18 - INFO - code: 128053.SZ price 144.691
2022-09-28 10:31:19 - INFO - code: 113585.SS price 169.062
2022-09-28 10:31:19 - INFO - code: 128053.SZ price 144.691
2022-09-28 10:31:20 - INFO - code: 113585.SS price 169.062
为了更为直观,过滤掉另外一只可转债
只保留一只
2022-09-28 10:31:00 - INFO - code: 113585.SS price 169.147可以看到价格也是基本没个3s更新一次。
2022-09-28 10:31:01 - INFO - code: 113585.SS price 169.147
2022-09-28 10:31:02 - INFO - code: 113585.SS price 169.156
2022-09-28 10:31:03 - INFO - code: 113585.SS price 169.156
2022-09-28 10:31:04 - INFO - code: 113585.SS price 169.199
2022-09-28 10:31:05 - INFO - code: 113585.SS price 169.199
2022-09-28 10:31:06 - INFO - code: 113585.SS price 169.199
2022-09-28 10:31:07 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:08 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:09 - INFO - code: 113585.SS price 169.068
2022-09-28 10:31:10 - INFO - code: 113585.SS price 169.066
2022-09-28 10:31:11 - INFO - code: 113585.SS price 169.066
更多ptrade实盘代码,请常见个人星球。
【可转债追涨杀跌日内T+0,双低 低价 低溢价 规模多因子轮动】
收起阅读 »
国庆节 微信头像红旗 制作 附 python代码 和 红旗素材
国庆节的时候,很多地方都会升挂国旗,庆祝祖国一年一度的节日。
给自己制作国旗头像,是一件很有意义的事。微信官方就曾经举办过活动。
制作国旗头像的方法有很多,本文给大家介绍用Python制作渐变的微信国旗头像。
渐变的国旗头像效果非常好看。
制作方式也很简单,下面介绍实现方法,可以复制本文的代码,制作属于自己的国旗头像。
1.准备国旗图片
声明:严禁非法使用国旗图片。在国旗图片下载页面下方有《国旗法》等相关规定。
本文使用1024像素的图片。
2.准备头像图片
登录自己的微信,打开个人信息,点击头像,点击右上角的三个点,将图片保存到手机,
然后将图片传到电脑上。
为了不失一般性,本文使用的图片是我从网络上获取的一张600*600像素的头像图片。
准备好后,将国旗图片和头像图片拷贝到代码同一个目录下。
代码实现
先安装Python中用于处理图片的pillow库。
安装完成后,使用pillow库来制作国旗头像。
只需要十几行代码就能实现。完整代码如下。
到此为止,已经制作好了国旗头像了。
下面是代码的详细结束:
代码介绍:
本文介绍了用Python制作微信国旗头像的方法。在本文的代码中,以左上角为圆心,离圆心越远越透明,可以修改key值,调整国旗透明变化的范围。
如果需要制作其他渐变类型,如以右上角为圆心逐渐透明、从左侧向右侧逐渐透明、从上到下逐渐透明等,可以修改国旗渐变部分的代码、翻转图片等。
收起阅读 »
给自己制作国旗头像,是一件很有意义的事。微信官方就曾经举办过活动。
制作国旗头像的方法有很多,本文给大家介绍用Python制作渐变的微信国旗头像。
渐变的国旗头像效果非常好看。
制作方式也很简单,下面介绍实现方法,可以复制本文的代码,制作属于自己的国旗头像。
1.准备国旗图片
声明:严禁非法使用国旗图片。在国旗图片下载页面下方有《国旗法》等相关规定。
本文使用1024像素的图片。
2.准备头像图片
登录自己的微信,打开个人信息,点击头像,点击右上角的三个点,将图片保存到手机,
然后将图片传到电脑上。
为了不失一般性,本文使用的图片是我从网络上获取的一张600*600像素的头像图片。
准备好后,将国旗图片和头像图片拷贝到代码同一个目录下。
代码实现
先安装Python中用于处理图片的pillow库。
pip install pillow
安装完成后,使用pillow库来制作国旗头像。
只需要十几行代码就能实现。完整代码如下。
# coding=utf-8
from PIL import Image
import math
key = 3.2# 修改key值可以调整国旗的范围,推荐2~4之间的数字,支持小数
motherland_flag = Image.open('flag-1024.png')
head_picture = Image.open('mmexport1663893338571.png')
# 截图国旗上的五颗五角星
flag_width, flag_height = motherland_flag.size
crop_flag = motherland_flag.crop((66, 0, flag_height+66, flag_height))
# 将国旗截图处理成颜色渐变
for i in range(flag_height):
for j in range(flag_height):
color = crop_flag.getpixel((i, j))
distance = int(math.sqrt(i*i + j*j))
alpha = 255 - int(distance//key)
new_color = (*color[0:-1], alpha if alpha > 0 else 0)
crop_flag.putpixel((i, j), new_color)
# 修改渐变图片的尺寸,适应头像大小,粘贴到头像上
new_crop_flag = crop_flag.resize(head_picture.size)
head_picture.paste(new_crop_flag, (0, 0), new_crop_flag)
# 保存自己的国旗头像
head_picture.save('国旗头像.png')
到此为止,已经制作好了国旗头像了。
下面是代码的详细结束:
代码介绍:
代码介绍:
导入需要使用的Python库,pillow库用于对图片进行截取、大小修改、粘贴等处理。math库用于计算像素点的距离。
使用Image.open()方法,读取准备好的国旗图片和头像图片到代码中。
对国旗图片进行截取,获取一张正方形的图片,截取时调整截取位置,保证5颗五角星完整展示在截图中。
crop()方法中传入的是一个(left, upper, right, lower)的元组,分别是截图的左、上、右、下像素位置。
将正方形国旗截图设置成透明度渐变的图片。国旗图片的模式默认是RGBA,本文需要的刚好是RGBA(red,green,blue,alpha)模式的图片,RGBA模式的图片颜色值是一个长度为4的元组,我们修改不同像素点的A值即可将图片设置成渐变。
本文是以国旗左上角为圆心,离圆心越远的像素点A值越小,像素点越透明。使用getpixel()和putpixel()两个方法来获取和重设像素点的颜色值,使用math.sqrt()计算像素点距离。
将渐变图片的大小转换成和头像的大小一样,然后粘贴到图片顶层。使用resize()方法重设图片大小,使用paste()方法粘贴图片。
保存图片,此时的微信头像图片上已经粘贴了透明渐变的国旗图片,微信国旗头像制作完成。
本文介绍了用Python制作微信国旗头像的方法。在本文的代码中,以左上角为圆心,离圆心越远越透明,可以修改key值,调整国旗透明变化的范围。
如果需要制作其他渐变类型,如以右上角为圆心逐渐透明、从左侧向右侧逐渐透明、从上到下逐渐透明等,可以修改国旗渐变部分的代码、翻转图片等。
收起阅读 »
ptrade 微信通知
对于节假日,ptrade经常会被暂停维护。 而有时候维护后需要你手动去重启策略。
所以情况多了,经常会忘记,手动登录进去重启。导致策略没有运行。
所以办法1,在盘前函数加入 微信通知,在交易日,如果盘前(8:30分左右),没有收到微信提醒,那么就需要即使登录到ptrade进行手动重启。
代码如下:
差不多这样就可以了。
不过笔者一般会使用另外一个种方式,因为如果哪一天没有收到,意味这ptrade没有起来,但你没有收到,你也就忘了这么一回事。 所以笔者的做法是,正常情况下不推送,而在ptrade不启动的时候才推送到微信。
下回更新。待续
# 继续更新
每天盘前,ptrade会到mysql插入一条数据,比如当天的日期
然后有个程序每天定时去读取mysql,如果读不到数据,就发送数据给微信即可。
收起阅读 »
所以情况多了,经常会忘记,手动登录进去重启。导致策略没有运行。
所以办法1,在盘前函数加入 微信通知,在交易日,如果盘前(8:30分左右),没有收到微信提醒,那么就需要即使登录到ptrade进行手动重启。
代码如下:
def notify(content=''):
send_qywx(
'微信id', '微信key', 'agent', info=content,
touser= '你的微信名字',
)
def before_trading_start(context, data):
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
notify('Ptrade 盘前运行{}'.format(now))
差不多这样就可以了。
不过笔者一般会使用另外一个种方式,因为如果哪一天没有收到,意味这ptrade没有起来,但你没有收到,你也就忘了这么一回事。 所以笔者的做法是,正常情况下不推送,而在ptrade不启动的时候才推送到微信。
下回更新。待续
# 继续更新
每天盘前,ptrade会到mysql插入一条数据,比如当天的日期
然后有个程序每天定时去读取mysql,如果读不到数据,就发送数据给微信即可。
class DBSelector():
'''
数据库选择类
'''
def get_engine(self):
from sqlalchemy import create_engine
try:
engine = create_engine(
'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USER, PASSWORD, MYSQL_HOST, MYSQL_PORT, MYSQL_DB))
except Exception as e:
log.error(e)
return None
return engine
def get_mysql_conn(self, db):
import pymysql
try:
conn = pymysql.connect(host=MYSQL_HOST, port=MYSQL_PORT, user=USER, password=PASSWORD, db=db,
charset='utf8')
except Exception as e:
log.error(e)
return None
else:
return conn
def main():
now = datetime.datetime.now()
if not now.weekday():
print('not week day')
return
db = DBSelector()
conn = db.get_mysql_conn('ptrade')
cursor = conn.cursor()
sql_str = 'select count(*) from `ptrade_runing_status` where `date`=%s limit 1'
date = now.strftime('%Y-%m-%d')
cursor.execute(sql_str, (date,))
result = cursor.fetchone()
if result[0] == 0:
send_message_via_wechat('{} ptrade没有启动!'.format(now))
if __name__=='__main__':
main()
收起阅读 »
百度搜索居然支持搜索微信公众号了?!
今天搜索了一些内容,发现公众的内容居然显示在百度搜索结果的第一位,有点神奇。估计两个大厂签订了某些合作协议,流量互通了。 其实早就应该开放了,现在很多优质内容都往公众号流入。 但是这些优质内容只有少部分人浏览。 牛人不会有很多时间看别人群,看别人朋友圈,所以他们接触公众号的内容比较少。
这导致微信公众号里面沉淀的内容 在闭环里面得不得很好利用。 比如一些写程序代码的公众号,一般人都是看到好的,收藏起来,然后在PC浏览器上看。 手机屏幕看代码, 体验十分不好的。
同样,百度也多了一个数据源,不至于被csdn和一些内容农场长期霸占首页的搜索结果。
最受影响的应该是搜狗搜索引擎。不过这个搜索引擎也是及其垃圾,以前用来搜索微信公众号内容,只能完全匹配字样,同义词,近义词的搜索效果很差,出来的内容也不知道按照什么排序,往往得不到自己想要的内容。
收起阅读 »
程序员是怎样删除安卓手机的垃圾文件?
有一台vivo的手机,用了也就1-2年,64GB的内部存储已经所剩无几了,并且每次清理垃圾文件,并无法清理一些系统产生的垃圾文件。
以至于手机的的可用空间越来越少,内置的清理垃圾的功能越来越鸡肋。而第三方的垃圾清理应用只会引来更多的垃圾文件。
身为一名程序员,就得用geek一点的方法彻底删除垃圾文件,尽可能地释放系统的空间。
由于平时使用的开发环境是Linux,所以下面环境是在Linux下操作,windows的用户应该也可以在git bash下操作。
手机usb 连接电脑
使用usb线连接linux电脑,不一定要adb的功能,但需要电脑能够识别手机的内部存储即可。
然后点击“内部存储设备”, 在文件内右键,进入Terminal 终端。
执行命令
简单解释一下这个语句。 就是显示当前目录下,第一层目录的占用存储大小情况。-h, human效果,人性化,自动转换文件大小单位。
--max-depth 是显示目录层级数目,如果选择2-3-4等目录,则会把子目录,子子目录的存储大小都显示出来,不过运行数据也会随之变慢。
上面命令一下子就把手机根目录下所有的目录的占用大小都列出来了。可以看到上面红框的地方,是一些缓存没用的东西,我们直接用命令 rm -rf 删除。
或者也可以在文件管理器里面直接删除。
如果有些目录底下有多层目录,那么就是把--max-depth 的值调大一些。 这样就知道他子目录的占用空间情况。
如果只想看看微信文件夹下的空间占用,可以指定目录:
这样就知道哪个目录占用的空间最大,然后点击进去,把没用的目录逐个删除。
经过笔者的测试,使用上述操作后,手机可用存储空间释放了40%的空间。主要是一些app下载的内容,由于app被清理了,结果这些下载内容成了孤立的文件,没有索引到对应的app,一直残留在手机内存。
收起阅读 »
以至于手机的的可用空间越来越少,内置的清理垃圾的功能越来越鸡肋。而第三方的垃圾清理应用只会引来更多的垃圾文件。
身为一名程序员,就得用geek一点的方法彻底删除垃圾文件,尽可能地释放系统的空间。
由于平时使用的开发环境是Linux,所以下面环境是在Linux下操作,windows的用户应该也可以在git bash下操作。
手机usb 连接电脑
使用usb线连接linux电脑,不一定要adb的功能,但需要电脑能够识别手机的内部存储即可。
然后点击“内部存储设备”, 在文件内右键,进入Terminal 终端。
执行命令
du . -h --max-depth=1
简单解释一下这个语句。 就是显示当前目录下,第一层目录的占用存储大小情况。-h, human效果,人性化,自动转换文件大小单位。
--max-depth 是显示目录层级数目,如果选择2-3-4等目录,则会把子目录,子子目录的存储大小都显示出来,不过运行数据也会随之变慢。
上面命令一下子就把手机根目录下所有的目录的占用大小都列出来了。可以看到上面红框的地方,是一些缓存没用的东西,我们直接用命令 rm -rf 删除。
或者也可以在文件管理器里面直接删除。
如果有些目录底下有多层目录,那么就是把--max-depth 的值调大一些。 这样就知道他子目录的占用空间情况。
如果只想看看微信文件夹下的空间占用,可以指定目录:
du /Weixin/ -h --max-depth=3
这样就知道哪个目录占用的空间最大,然后点击进去,把没用的目录逐个删除。
经过笔者的测试,使用上述操作后,手机可用存储空间释放了40%的空间。主要是一些app下载的内容,由于app被清理了,结果这些下载内容成了孤立的文件,没有索引到对应的app,一直残留在手机内存。
收起阅读 »
ubuntu/linux 64位 安装 kdb+ (需要证书授权)附下载地址
kdb+是一款高速小巧的时序数据库。32位的版本个人可以随意使用。
64位的版本需要申请授权证书。
申请后得到邮件,里面会有证书。
还有64位软件下载地址。文件还是小巧,几百k。没想到一个排名第二的时序数据库,体积居然不到1M。
需要kdb+ 64位安装文件,可以到文末获取。
下载下来解压。
比如解压到目录:
~/tool/l64/
目录下有一个文件夹 l64和一个q.k的文件
l64子文件夹下只有一个文件q , 他是一个可执行文件。在linux下的命令行可以直接运行 ./q
然后把证书文件拷贝到目录 ~/tool/l64/
这时如果直接运行 ./q 但是会报错.
这是因为没有设置环境变量。
windows下也需要设置环境部,linux同理也需要。
linux:
export QHOME="/home/root/tool/l64/"
或者放到bashrc文件里面。
正常运行,会显示 q)
kdb+ 64位安装文件获取方式:
关注后 回复 kdb+
收起阅读 »
64位的版本需要申请授权证书。
申请后得到邮件,里面会有证书。
还有64位软件下载地址。文件还是小巧,几百k。没想到一个排名第二的时序数据库,体积居然不到1M。
需要kdb+ 64位安装文件,可以到文末获取。
下载下来解压。
比如解压到目录:
~/tool/l64/
目录下有一个文件夹 l64和一个q.k的文件
l64子文件夹下只有一个文件q , 他是一个可执行文件。在linux下的命令行可以直接运行 ./q
$ ./q提示缺失证书。
KDB+ 4.0 2022.05.11 Copyright (C) 1993-2022 Kx Systems
l64/ 4()core 23934MB xda xda-linux 127.0.1.1
'licence error: k4.lic
然后把证书文件拷贝到目录 ~/tool/l64/
这时如果直接运行 ./q 但是会报错.
$ ./q -p 5001
KDB+ 4.0 2022.05.11 Copyright (C) 1993-2022 Kx Systems
l64/ 4(24)core 23934MB xda xda-linux 127.0.1.1 EXPIRE 2023.07.18 xxxxx@126.com KXCE #
'2022.09.04T11:34:18.272 couldn't connect to license daemon -- exiting
这是因为没有设置环境变量。
windows下也需要设置环境部,linux同理也需要。
linux:
export QHOME="/home/root/tool/l64/"
或者放到bashrc文件里面。
正常运行,会显示 q)
kdb+ 64位安装文件获取方式:
关注后 回复 kdb+
收起阅读 »
从零开始 手撸一个回测框架 (以可转债双低,低溢价为例)
因为优矿大部分可转债接口开始收费了,之前星球上分享的回测代码基本也跑不了。不过在关停转收费之前,已经把所需的数据下载下来,而最近的数据通过集思录补充既可。
Mysql 数据
下面是代码主框架,目前通过之前优矿的导出的csv数据 ,计算 各个因子。 通过不同权重评分,进行轮动。
双低和低溢价选债轮动:
上面是主要框架代码, 根据数据来驱动交易。 可以根据不同的时间日期进行回测交易。不同持有个数,不同轮动功能天数。【完整代码可以常见 知识星球】
运行: python main.py
运行后会自动保存一个excel文件:
并且可以生成收益率曲线图:
完整代码与数据可以参考星球代码:
收起阅读 »
Mysql 数据
下面是代码主框架,目前通过之前优矿的导出的csv数据 ,计算 各个因子。 通过不同权重评分,进行轮动。
class DataFeed:
def __init__(self):
self.csv_path = CSV_PATH
self.position = {}
self.HighValue = 0
self.Start_Cash = 1000000 # 初始资金
self.MyCash = self.Start_Cash
self.Withdraw = 0
self.daily_netvalue =
self.current_day = 0
self.PosValue = 0
self.threshold = 0 # 阈值
self.HighValue = self.Start_Cash
self.date_list, self.source = self.feed()
self.day_count = 0
def unpossibile(self, df, date):
# 剔除当日涨停的转债,买不入
raise_limited_dict = {
'2022-04-08': ['127057', ],
'2022-07-27': ['127065', ],
'2022-07-28': ['127065', ],
}
target_list = raise_limited_dict.get(date, None)
if target_list is None:
return df
return df.drop(index=target_list, axis=1)
def feed(self):
df = pd.read_csv(self.csv_path,
encoding='utf8',
dtype={'tickerEqu': str, 'tickerBond': str, 'secID_x': str},
)
del df['Unnamed: 0']
df['tradeDate'] = pd.to_datetime(df['tradeDate'], format='%Y-%m-%d')
df = df.set_index('tradeDate')
date_set = set(df.index.tolist())
date_list = list(map(lambda x: x.strftime('%Y-%m-%d'), date_set))
date_list.sort()
return date_list, df
def filters(self, df, today):
# 过滤条件,可添加多个条件
df = self.unpossibile(df, today)
return df
def logprint(self, current):
log.info('当前日期{}'.format(current))
def run(self):
for current in self.date_list:
if current < START_DATE or current > END_DATE:
continue
if self.day_count % FREQ != 0:
self.get_daily_netvalue(current)
else:
self.handle_data(current)
self.day_count += 1
self.after_trade()
双低和低溢价选债轮动:
上面是主要框架代码, 根据数据来驱动交易。 可以根据不同的时间日期进行回测交易。不同持有个数,不同轮动功能天数。【完整代码可以常见 知识星球】
运行: python main.py
运行后会自动保存一个excel文件:
并且可以生成收益率曲线图:
完整代码与数据可以参考星球代码:
收起阅读 »
python获取通达信可转债日线和分时数据
昨天看到优矿平台公告,开始对大部分数据获取接口进行收费。
除了优矿,还有哪些可以获取可转债日线,甚至分时tick数据呢?当然笔者压箱底里面还有很多可用数据源的。本文就简单介绍其中一个,下通达信数据源。
安装
使用pip安装第三方库pytdx
分时数据
下面6行python代码, 就可以获取通达信的可转债分时数据。
如果需要遍历当前最新可转债代码,需要结合前面的文章。【注意这代码会定期更新,因网站架构或者字段是不定时变动】
不过前面的接口只能读取800条数据,以一天240条数据计算,只能读取2天多的数据量,对于需要更多数据的朋友来说,肯定不够的。或者有一个办法,把上面代码写成定时任务,就可以每天收盘后自动存储对应的数据。
如果需要更多的历史数据,那么可以使用pytdx的另外一个功能,那就是使用python读取通达信本地数据文件。
先用通达信同步1分钟(或5分钟)数据到本地.
选择沪深京分钟线,当然,其他数据你也可以选择。勾选一分钟线数据或者5分钟线数据,还有日期。不过这里日期会有限制,只能下载100天的1分钟线,或者500天的5分钟线。所以如果长期需要这个数据,你可以每隔一段时间下载一次。
数据保存路径:通达信安装目录的 vipdoc 子目录
如果你需要更久的历史数据,可以到网上找找,下载下来后按照下面代码读取即可。
得到dataframe对象后,接着可以保存为excel,数据库都很简单了。一条语句的事情。
可转债日线数据
当然,能够获取到分钟数据,对于日线数据更加不在话下了。日线数据并没有日期限制,想下多少有多少。
如果想获取正股或者其他股票数据,只需要把代码替换成正股股票代码即可。
如果分钟数据还不满足,还可以使用更小粒度的tick数据。下回有空再继续介绍,敬请关注。
欢迎关注公众号 收起阅读 »
除了优矿,还有哪些可以获取可转债日线,甚至分时tick数据呢?当然笔者压箱底里面还有很多可用数据源的。本文就简单介绍其中一个,下通达信数据源。
安装
使用pip安装第三方库pytdx
pip install pytdx
分时数据
下面6行python代码, 就可以获取通达信的可转债分时数据。
from pytdx.hq import TdxHq_API
api = TdxHq_API()
with api.connect('119.147.212.81', 7709):
data = api.get_security_bars(7, 0, '123045', 0, 240) # 123045 为转债代码 ,240 为获取 240个转债数据
df = api.to_df(data)
df=df.sort_values('datetime')
如果需要遍历当前最新可转债代码,需要结合前面的文章。【注意这代码会定期更新,因网站架构或者字段是不定时变动】
不过前面的接口只能读取800条数据,以一天240条数据计算,只能读取2天多的数据量,对于需要更多数据的朋友来说,肯定不够的。或者有一个办法,把上面代码写成定时任务,就可以每天收盘后自动存储对应的数据。
如果需要更多的历史数据,那么可以使用pytdx的另外一个功能,那就是使用python读取通达信本地数据文件。
先用通达信同步1分钟(或5分钟)数据到本地.
选择沪深京分钟线,当然,其他数据你也可以选择。勾选一分钟线数据或者5分钟线数据,还有日期。不过这里日期会有限制,只能下载100天的1分钟线,或者500天的5分钟线。所以如果长期需要这个数据,你可以每隔一段时间下载一次。
数据保存路径:通达信安装目录的 vipdoc 子目录
比如我的通达信客户端安装在 c:\new_tdx 下,
即
c:\new_tdx\vipdoc\sz\lday\ 下是深圳的日k线数据
c:\new_tdx\vipdoc\sh\lday\ 下是上海的日k线数据
c:\new_tdx\vipdoc\sh\minline\ 下是上海的分钟线数据
c:\new_tdx\vipdoc\sz\minline\ 下是深圳的分钟线数据
如果你需要更久的历史数据,可以到网上找找,下载下来后按照下面代码读取即可。
from pytdx.reader import TdxMinBarReader
path='/home/xda/Downloads/sz128014.lc1'
reader = TdxMinBarReader()
df = reader.get_df(path)
#df.to_excel('tick.xlsx') # 导出为excel
得到dataframe对象后,接着可以保存为excel,数据库都很简单了。一条语句的事情。
可转债日线数据
当然,能够获取到分钟数据,对于日线数据更加不在话下了。日线数据并没有日期限制,想下多少有多少。
api = TdxHq_API()
api = api.connect('119.147.212.81', 7709)
data=api.get_k_data('123045', '2020-05-01', '2022-08-26') # 123045 为可转债代码,可以替换任意代码
data.to_excel('k-line.xlsx')
如果想获取正股或者其他股票数据,只需要把代码替换成正股股票代码即可。
如果分钟数据还不满足,还可以使用更小粒度的tick数据。下回有空再继续介绍,敬请关注。
欢迎关注公众号 收起阅读 »
6行python代码 获取通达信的可转债分时数据
6行python代码 获取通达信的可转债分时数据。
如果需要遍历当前最新可转债代码(集思录),需要结合前面的文章。
公众号:
收起阅读 »
from pytdx.hq import TdxHq_API点击查看大图
api = TdxHq_API()
with api.connect('119.147.212.81', 7709):
data = api.get_security_bars(7, 0, '123045', 0, 240) # 123045 为转债代码 ,240 为获取 240个转债数据
df = api.to_df(data)
df=df.sort_values('datetime')
如果需要遍历当前最新可转债代码(集思录),需要结合前面的文章。
公众号:
收起阅读 »
Ptrade 逆回购+自动申购新股可转债
分享一些最基本的ptrade代码实盘例子。 持续更新,喜欢的朋友请关注本站哦。
本站所有代码均经过实盘验证。
上面代码设定在13:30分申购新股,新债;
在14:57分申购深圳逆回购R-001
喜欢的朋友拿去,欢迎转载。
欢迎关注公众号
收起阅读 »
本站所有代码均经过实盘验证。
# ptrade软件-量化-回测 里,新建策略,复制全文粘贴进去,周期选分钟,再到交易里新增交易
import time
def reverse_repurchase(context):
cash = context.portfolio.cash
amount = int(cash/1000)*10
log.info(amount)
order('131810.SZ', -1*amount) # 深圳逆回购,
def ipo(context):
ipo_stocks_order()
def initialize(context):
g.flag = False
log.info("initialize g.flag=" + str(g.flag) )
run_daily(context, reverse_repurchase, '14:57')
run_daily(context, ipo, '13:30')
def before_trading_start(context, data):
pass
def handle_data(context, data):
pass
def on_order_response(context, order_list):
# 该函数会在委托回报返回时响应
log.info(order_list)
上面代码设定在13:30分申购新股,新债;
在14:57分申购深圳逆回购R-001
喜欢的朋友拿去,欢迎转载。
欢迎关注公众号
收起阅读 »
Ptrade 获取当天可转债代码列表
注意Ptrade版本:2022版,旧版应该不行的。
可以在开盘的时候获取所有可转债列表。
如果需要获取可转债溢价率,评级,剩余规模,强赎等数据,可以调用我之前提供的接口。
需要的可以关注个人星球和公众号。
欢迎关注公众号
收起阅读 »
可以在开盘的时候获取所有可转债列表。
def initialize(context):
run_daily(context, get_trade_cb_list, "9:25")
def before_trading_start(context, data):
# 每日清空,避免取到昨日市场代码表
g.trade_cb_list =
def handle_data(context, data):
pass
# 获取当天可交易的可转债代码列表
def get_trade_cb_list(context):
cb_list = get_cb_list()
cb_snapshot = get_snapshot(cb_list)
# 代码有行情快照并且交易状态不在暂停交易、停盘、长期停盘、退市状态的判定为可交易代码
g.trade_cb_list = [cb_code for cb_code in cb_list if
cb_snapshot.get(cb_code, {}).get("trade_status") not in
[None, "HALT", "SUSP", "STOPT", "DELISTED"]]
log.info("当天可交易的可转债代码列表为:%s" % g.trade_cb_list)
如果需要获取可转债溢价率,评级,剩余规模,强赎等数据,可以调用我之前提供的接口。
需要的可以关注个人星球和公众号。
欢迎关注公众号
收起阅读 »
Ptrade里面的 持久化 (pickle)要求 报错:
关于持久化
为什么要做持久化处理
服务器异常、策略优化等诸多场景,都会使得正在进行的模拟盘和实盘策略存在中断后再重启的需求,但是一旦交易中止后,策略中存储在内存中的全局变量就清空了,因此通过持久化处理为量化交易保驾护航必不可少。
量化框架持久化处理
使用pickle模块保存股票池、账户信息、订单信息、全局变量g定义的变量等内容。
注意事项:
框架会在before_trading_start(隔日开始)、handle_data、after_trading_end事件后触发持久化信息更新及保存操作;
券商升级/环境重启后恢复交易时,框架会先执行策略initialize函数再执行持久化信息恢复操作。
如果持久化信息保存有策略定义的全局对象g中的变量,将会以持久化信息中的变量覆盖掉initialize函数中初始化的该变量。
1 全局变量g中不能被序列化的变量将不会被保存。
您可在initialize中初始化该变量时名字以'__'开头;
2 涉及到IO(打开的文件,实例化的类对象等)的对象是不能被序列化的;
3 全局变量g中以'__'开头的变量为私有变量,持久化时将不会被保存;
示例代码:
其实官方文档说了这么多,实际意思就是 类和涉及IO的 变量 不能序列化,导致不能在g中作为全局变量,如果要作为全局变量,需要 用2个前下划线__ 命名,比如 g.__db = Bond()
class Bond:
pass
不然就会报错:
欢迎关注公众号 收起阅读 »
为什么要做持久化处理
服务器异常、策略优化等诸多场景,都会使得正在进行的模拟盘和实盘策略存在中断后再重启的需求,但是一旦交易中止后,策略中存储在内存中的全局变量就清空了,因此通过持久化处理为量化交易保驾护航必不可少。
量化框架持久化处理
使用pickle模块保存股票池、账户信息、订单信息、全局变量g定义的变量等内容。
注意事项:
框架会在before_trading_start(隔日开始)、handle_data、after_trading_end事件后触发持久化信息更新及保存操作;
券商升级/环境重启后恢复交易时,框架会先执行策略initialize函数再执行持久化信息恢复操作。
如果持久化信息保存有策略定义的全局对象g中的变量,将会以持久化信息中的变量覆盖掉initialize函数中初始化的该变量。
1 全局变量g中不能被序列化的变量将不会被保存。
您可在initialize中初始化该变量时名字以'__'开头;
2 涉及到IO(打开的文件,实例化的类对象等)的对象是不能被序列化的;
3 全局变量g中以'__'开头的变量为私有变量,持久化时将不会被保存;
示例代码:
class Test(object):
count = 5
def print_info(self):
self.count += 1
log.info("a" * self.count)
def initialize(context):
g.security = "600570.SS"
set_universe(g.security)
# 初始化无法被序列化类对象,并赋值为私有变量,落地持久化信息时跳过保存该变量
g.__test_class = Test()
def handle_data(context, data):
# 调用私有变量中定义的方法
g.__test_class.print_info()
其实官方文档说了这么多,实际意思就是 类和涉及IO的 变量 不能序列化,导致不能在g中作为全局变量,如果要作为全局变量,需要 用2个前下划线__ 命名,比如 g.__db = Bond()
class Bond:
pass
不然就会报错:
_pickle.PickingError: Can't pick <class 'IOEngine.user_module : attribute loopup
欢迎关注公众号 收起阅读 »
虚拟机 云服务器 运行qmt 方案
点击查看大图
众所周知,部分券商(国盛证券)限制了虚拟机登录QMT。
比如在vmare中安装了QMT,可以在QMT的信息里面看到:
点击查看大图
比如上面的截图, 如果和实体机的设备信息做一个对比,可以看到,虚拟机下的QMT的硬盘序列号(红框的位置) 是空的,而实体物理机下,红框的硬盘序列号 是有内容的。 所以一个办法是尝试修改这个硬盘序列号。
或者换一个支持虚拟机的券商。其实这个限制是券商端定制的功能,部分券商并没有限制虚拟机禁止登陆QMT的。
比如国金证券的QMT,可以在虚拟机或者云服务器上登录。费率也可以万一免五,参考文章:
http://www.30daydo.com/article/44479 收起阅读 »
通过mini qmt xtdata获取tick数据 python代码
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
上面python代码传入一个代码,和初试时间,需要的周期数据(分钟,秒,日等),就可以返回一个dataframe格式的数据了。
欢迎关注公众号 收起阅读 »
Ptrade下单接口 order,order_target, order_value,order_target_value的区别
order_target 接口通过持仓数量比较将入参的目标数量转换成需要交易的成交,传入 order
接口
order_value 接口通过 金额/限价 或者 金额/默认最新价 两种方式转换成需要交易的数量,
传入 order 接口
order_target_value 接口通过持仓金额比较得到需要交易的金额, 金额/限价 或者 金额/默
认最新价 两种方式转换成需要交易的数量,传入 order 接口
所以其他几个接口都是对order的封装。
order接口的逻辑:
order 接口:
一、
先判断 limit_price 是否传入,传入则用传入价格限价,不传入则最新价代替,都是
限价方式报单。
二、
判断隔夜单和交易时间,交易时间(9:10(系统可配)~15:00)范围的订单会马上
加入未处理订单队列,其他订单先放到一个队列,等时间到交易时间就放到未处理订单
队列
三、
未处理订单队列的订单会进行限价判断,如果没有传入限价就按当前最新价处理,
然后报柜台
欢迎关注公众号 收起阅读 »
去除导流公众号的网站 油猴脚本
先安装油猴工具。然后导入下面的油猴脚本
去除博客导流公众号
绕过openwrite公众号导流
去除博客导流公众号
// ==UserScript==
// @name 去除博客导流公众号
// @namespace http://tampermonkey.net/
// @version 1.0.0
// @description 去除openwrite“博客导流公众号”功能
// @author You
// @include http*://*
// @grant none
// ==/UserScript==
(function() {
'use strict';
destroyBTWPlugin();
function destroyBTWPlugin() {
// 判断是否有插件
const hasBTWPlugin = typeof BTWPlugin == "function"
if (hasBTWPlugin) {
// 获取属性
const plugin = new BTWPlugin().options;
if (plugin) {
// 删除元素
const read_more_wrap = document.getElementById("read-more-wrap")
if (read_more_wrap) {
read_more_wrap.remove();
}
// 删除样式
const ctner = document.getElementById(plugin.id)
if (ctner) {
ctner.removeAttribute("style");
}
}
}
}
})();
绕过openwrite公众号导流
// ==UserScript==收起阅读 »
// @name 绕过openwrite公众号导流
// @namespace http://tampermonkey.net/
// @version 1.6
// @description 去除openwrite“博客导流公众号”功能
// @author GoodbyeNJN
// @license GPLv3
// @match *://*/*
// @grant none
// ==/UserScript==
/**
* openwrite 脚本基本逻辑:
* 函数名和属性名储存在一个数组中(搜索“阅读全文”可定位到),取值时通过对应的索引取出对应的值。
* 先构造一个对象(搜索“const .* = function”可定位到),在下方不远处给它的 prototype 上添加 options 和 init。
* 点击弹窗中的“提交”按钮时,触发回调(搜索“alert”可定位到),解析后具体代码如下:
* function () {
* const val = $("#btw-modal-input").val();
* if (val === "") {
* alert("请输入校验码!");
* $("#btw-modal-input").focus();
* return;
* }
* const { blogId } = btw.options
* const api = "https://my.openwrite.cn/code/check";
* const url = "" + api + "?blogId=" + blogId + "&code=" + val + "";
* $.get(url, function (res) {
* if (res.result === true) {
* localStorage.setItem("TOKEN_" + blogId + "", blogId);
* $("#btw-modal-wrap, #read-more-wrap").remove();
* $("#" + btw.options.id + "").height("");
* } else {
* alert("校验码有误!");
* }
* });
* }
*/
"use strict";
const READ_MORE_ID = "read-more-wrap";
/**
* 判断是否存在插件
*/
const hasBtwPlugin = () => {
const hasBTWPlugin = typeof BTWPlugin === "function";
const hasJquery = typeof $ === "function";
return hasBTWPlugin && hasJquery;
};
/**
* 判断是否存在“阅读全文”按钮
*/
const hasReadMoreBtn = () => {
return !!document.getElementById(READ_MORE_ID);
};
/**
* 获取插件初始化选项
*/
const getOptions = () => {
return (
BTWPlugin.prototype.options || {
id: "container",
blogId: "",
name: "",
qrcode: "",
keyword: "",
}
);
};
/**
* 监听“阅读全文”按钮的出现
* 用于首次触发该脚本且无按钮时,监听后续的按钮出现事件
*/
const listenReadMoreBtnShow = fn => {
const observer = new MutationObserver(mutations =>
mutations.forEach(mutation =>
mutation.addedNodes.forEach(node => {
if (node.id === READ_MORE_ID) {
observer.disconnect();
fn();
}
}),
),
);
const { id } = getOptions();
const parent = document.getElementById(id);
parent && observer.observe(parent, { childList: true });
};
/**
* 监听部分 history 改动事件
* 用于 spa 页面路由变化时自动展示全文
*/
const listenHistoryChange = fn => {
const wrap = type => {
const fn = history[type];
return function (...args) {
const res = fn.apply(this, args);
const e = new Event(type);
e.arguments = args;
window.dispatchEvent(e);
return res;
};
};
history.pushState = wrap("pushState");
history.replaceState = wrap("replaceState");
window.addEventListener("replaceState", fn);
window.addEventListener("pushState", fn);
window.addEventListener("hashchange", fn);
};
/**
* 展示全文
*/
const showHiddenText = () => {
const { id, blogId } = getOptions();
console.log("id:", id);
localStorage.setItem(`TOKEN_${blogId}`, blogId);
$(`#${READ_MORE_ID}`).remove();
$(`#${id}`).height("");
};
(function () {
if (!hasBtwPlugin()) {
return;
}
$().ready(() => {
listenHistoryChange(showHiddenText);
if (hasReadMoreBtn()) {
showHiddenText();
} else {
listenReadMoreBtnShow(showHiddenText);
}
});
})();
可转债多因子回测 优矿代码
可转债里面可用因子很多,一般人最常用的就是溢价率,双低,价格等。
实际运用里面,可以加入很多很多因子,比如正股涨跌幅,正股波动率,转债到期时间,正股ROE等等多大几十个因子。
之前写了一个多因子回测的优矿python代码,用户可以自己修改参数,
比如下面的正股波动率因子,
Bond_Volatility_ENABLE = True 设为True,就是回测过程加入这个因子,设为False就忽略这个因子。
下面的
Bond_Volatility_DAYS 为N天内的正股波动率,一般设置30天,20天内就够了,因为一年之前的即使波动很大,那对当前转债的影响也很小。
TOP_RIPPLE 选择波动率最大的前面N只转债
举个例子,下面转债是根据其对应正股的30天里的波动率选出来的。(当前是8月5日,也就是7月5日到8月5日之间的数据)。
计算波动率具体代码如下;
每个因子写成一个类。
这样可以不用修改主代码,就可以无限地添加,修改因子。
上面是部分过滤因子,也就是不满足的都会被移除。 比如规模大于10亿的会移除。
然后得到的结果,进行因子评分。
每个权重赋予一个权重分最高是1,最低是0,如果你想回测 低溢价率 策略,只需要把其他因子的权重全部设置为0,溢价率设置为1即可。双底的话就是 溢价率和价格各为0.5 就可以了。
设置好参数后,设置你要回测的时间,持仓周期,持有个数等可调参数。
稍等片刻就会有结果了。因子越多,运行时间会增加。一般几分钟就可以得到几年来的回测结果。
中途可以查看日志
完整代码以及运行流程可到知识星球咨询了解。
欢迎关注公众号 收起阅读 »
实际运用里面,可以加入很多很多因子,比如正股涨跌幅,正股波动率,转债到期时间,正股ROE等等多大几十个因子。
之前写了一个多因子回测的优矿python代码,用户可以自己修改参数,
比如下面的正股波动率因子,
Bond_Volatility_ENABLE = True
Bond_Volatility_DAYS = 30
TOP_RIPPLE = 50
Bond_Volatility_LOG_ENABLE = True # 波动率日志开关
Bond_Volatility_ENABLE = True 设为True,就是回测过程加入这个因子,设为False就忽略这个因子。
下面的
Bond_Volatility_DAYS 为N天内的正股波动率,一般设置30天,20天内就够了,因为一年之前的即使波动很大,那对当前转债的影响也很小。
TOP_RIPPLE 选择波动率最大的前面N只转债
举个例子,下面转债是根据其对应正股的30天里的波动率选出来的。(当前是8月5日,也就是7月5日到8月5日之间的数据)。
计算波动率具体代码如下;
每个因子写成一个类。
这样可以不用修改主代码,就可以无限地添加,修改因子。
# 基类
class ConditionFilter:
def filters(self, *args, **kwargs):
if self.enable:
return self.fun(*args, **kwargs)
else:
return True
def fun(self, *args, **kwargs):
# 继承的实现这个函数
raise NotImplemented
上面是部分过滤因子,也就是不满足的都会被移除。 比如规模大于10亿的会移除。
然后得到的结果,进行因子评分。
# 权重 溢价率、转债价格、正股N天涨幅,正股ROE
weights = {'溢价率': 0, '转债价格': 1, '正股N天涨幅': 0, '正股ROE': 0, '规模': 0}
每个权重赋予一个权重分最高是1,最低是0,如果你想回测 低溢价率 策略,只需要把其他因子的权重全部设置为0,溢价率设置为1即可。双底的话就是 溢价率和价格各为0.5 就可以了。
设置好参数后,设置你要回测的时间,持仓周期,持有个数等可调参数。
稍等片刻就会有结果了。因子越多,运行时间会增加。一般几分钟就可以得到几年来的回测结果。
中途可以查看日志
完整代码以及运行流程可到知识星球咨询了解。
欢迎关注公众号 收起阅读 »
ptrade策略代码:集合竞价追涨停策略
这个是示例代码,我们来大体讲解一下:
分解讲解:
initialize是初始化函数,一定要有的函数。在策略运行时首先运行的,而且只会运行一次。
set_universe(g.security) 在把标的代码放进去。这里是 '600570.SS' 记得要有后缀,上证股票用 .SS ,深圳股票用.SZ。
run_daily(context, aggregate_auction_func, time='9:23')
这一行是设定每天运行一次。这个策略是日线级别的,所以每天只要运行一次就可以了。 分别传入3个参数。
第一个参数固定是context,第二个要执行的函数名,记住只能传函数名,不能把括号也加进去,第三个参数,是运行的时间,现在设定在 9:23
那么接下来就是要实现上面那个函数名了: aggregate_auction_func,这个名字可以随意定义
stock = g.security , g是全局变量,用来在上下文中传递数据。这里就是上面的'600570.SS'
snapshot = get_snapshot(stock)
这个就是获取行情数据,当前的价格
up_limit = snapshot[stock]['up_px']
拿到这个标的的涨停价
if float(price) >= float(up_limit):
这个是当前价格大于涨停板价格(主要考虑了四舍五入,用于大号比较安全)
order(g.security, 100, limit_price=up_limit)
这个就是下单函数。
买入100股,不限价,市价成交。
然后就可以点击运行交易。
程序每天都会自动交易。
欢迎关注公众号
收起阅读 »
def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
#每天9:23分运行集合竞价处理函数
run_daily(context, aggregate_auction_func, time='9:23')
def aggregate_auction_func(context):
stock = g.security
#最新价
snapshot = get_snapshot(stock)
price = snapshot[stock]['last_px']
#涨停价
up_limit = snapshot[stock]['up_px']
#如果最新价不小于涨停价,买入
if float(price) >= float(up_limit):
order(g.security, 100, limit_price=up_limit)
def handle_data(context, data):
pass
分解讲解:
def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
#每天9:23分运行集合竞价处理函数
run_daily(context, aggregate_auction_func, time='9:23')
initialize是初始化函数,一定要有的函数。在策略运行时首先运行的,而且只会运行一次。
set_universe(g.security) 在把标的代码放进去。这里是 '600570.SS' 记得要有后缀,上证股票用 .SS ,深圳股票用.SZ。
run_daily(context, aggregate_auction_func, time='9:23')
这一行是设定每天运行一次。这个策略是日线级别的,所以每天只要运行一次就可以了。 分别传入3个参数。
第一个参数固定是context,第二个要执行的函数名,记住只能传函数名,不能把括号也加进去,第三个参数,是运行的时间,现在设定在 9:23
那么接下来就是要实现上面那个函数名了: aggregate_auction_func,这个名字可以随意定义
def aggregate_auction_func(context):
stock = g.security
#最新价
snapshot = get_snapshot(stock)
price = snapshot[stock]['last_px']
#涨停价
up_limit = snapshot[stock]['up_px']
#如果最新价不小于涨停价,买入
if float(price) >= float(up_limit):
order(g.security, 100, limit_price=up_limit)
stock = g.security , g是全局变量,用来在上下文中传递数据。这里就是上面的'600570.SS'
snapshot = get_snapshot(stock)
这个就是获取行情数据,当前的价格
up_limit = snapshot[stock]['up_px']
拿到这个标的的涨停价
if float(price) >= float(up_limit):
这个是当前价格大于涨停板价格(主要考虑了四舍五入,用于大号比较安全)
order(g.security, 100, limit_price=up_limit)
这个就是下单函数。
买入100股,不限价,市价成交。
然后就可以点击运行交易。
程序每天都会自动交易。
欢迎关注公众号
收起阅读 »