PTrade

PTrade

Ptrade QMT 哪家费率最便宜,门槛最低?

券商万一免五绫波丽 发表了文章 • 0 个评论 • 182 次浏览 • 2022-11-27 19:09 • 来自相关话题

最近咨询的朋友很多。这里做个汇总,可以节省大家的时间。 
笔者只会推荐合适的券商和量化接口给你,而不会推荐坑爹的券商给你。
 
如果你不信任,绕路即可,莫浪费大家时间。或者你有好的资源或者券商,你也可以推荐给我,可以给你发红包,奖励你提供有用的情报信息。
 
目前支持ptrade,qmt可以股票可以免五(0.1元起步)的券商,只有国盛,需要的可以找我开。 但是有入金门槛,ptrade门槛30w, qmt 的门槛50w。 国盛的ptrade可以链接外网。其他家的不行。但国盛的qmt不支持运行在云服务器。
 
其他家的qmt是支持的云服务器的,但国金的qmt会每天自动退出,需要每次手动点击登录,我也写了一个自动登录的小脚本,开完户的朋友可以拿去用用。
 
门槛低的国信,适合新手使用,但是没有miniqmt,这个东西也不一定适合你。 真的需要这个功能,在qmt里面可以写一段代码,让它把下单接口变成http指令,把下单功能独立出来,也是可以的。不过这个属于进阶功能。 需要的也可以把代码给你。
 
笔者用过大部分券商的ptrade qmt,所以个人的指导与推荐还是很有指导意见的。 写过的策略也大部分人(99%)多, 平台好坏,坑的多寡,哪里有雷,都已经摸清摸楚。 可以大大节省你们的时间。 当然你也可以忽略,自己去折腾折腾。选ptrade 还是qmt,然后哪个券商,什么费率。
 





 
需要开户或者可以提供更低费用的资源的可以加微信:
 

  查看全部
最近咨询的朋友很多。这里做个汇总,可以节省大家的时间。 
笔者只会推荐合适的券商和量化接口给你,而不会推荐坑爹的券商给你。
 
如果你不信任,绕路即可,莫浪费大家时间。或者你有好的资源或者券商,你也可以推荐给我,可以给你发红包,奖励你提供有用的情报信息。
 
目前支持ptrade,qmt可以股票可以免五(0.1元起步)的券商,只有国盛,需要的可以找我开。 但是有入金门槛,ptrade门槛30w, qmt 的门槛50w。 国盛的ptrade可以链接外网。其他家的不行。但国盛的qmt不支持运行在云服务器。
 
其他家的qmt是支持的云服务器的,但国金的qmt会每天自动退出,需要每次手动点击登录,我也写了一个自动登录的小脚本,开完户的朋友可以拿去用用。
 
门槛低的国信,适合新手使用,但是没有miniqmt,这个东西也不一定适合你。 真的需要这个功能,在qmt里面可以写一段代码,让它把下单接口变成http指令,把下单功能独立出来,也是可以的。不过这个属于进阶功能。 需要的也可以把代码给你。
 
笔者用过大部分券商的ptrade qmt,所以个人的指导与推荐还是很有指导意见的。 写过的策略也大部分人(99%)多, 平台好坏,坑的多寡,哪里有雷,都已经摸清摸楚。 可以大大节省你们的时间。 当然你也可以忽略,自己去折腾折腾。选ptrade 还是qmt,然后哪个券商,什么费率。
 
mmexport1669547412034.png


 
需要开户或者可以提供更低费用的资源的可以加微信:
 

 

Ptrade多策略如何编写?

Ptrade李魔佛 发表了文章 • 0 个评论 • 328 次浏览 • 2022-11-16 11:33 • 来自相关话题

多策略需要解决的一个最主要的问题,就是仓位管理。
 
系统自带的读取仓位函数需要你重写。
 
目前使用一个类来管理仓位:
 
初始化部分:class PositionManager():

def __init__(self):
if SINGLE_FACTOR not in [1, 2, 3, 4]:
raise ValueError('策略数字有误')

self.strategy = SINGLE_FACTOR
NOTEBOOK_PATH = '/home/fly/notebook/'
# self.filename = NOTEBOOK_PATH + 'S-{}.txt'.format(self.strategy)
self.filename = NOTEBOOK_PATH + personal_define_filename
self.portfolio = self.read()
log.info(self.portfolio)
self.write()

def init_data(self):
js_data = {
'cash': CASH,
'strategy': self.strategy,
'positions': ,
'portfolio_value': None,
'positions_value': None,
'capital_used': None,
'start_date': datetime.datetime.now().strftime('%Y%m%d%H%M%S'),
'current_day': 0,
}
数据需要收盘后保存到文件,数据库也行;不过考虑到大部分ptrade(除了国盛,需要开通的可以联系公众号:可转债量化分析)都没有连接外网功能,所以最简单的方式就是写入文件,纯粹的文本文件。
 
目前笔者使用json存储





 点击查看大图
 
这样存储有一个好处,就是如果你想中途修改策略持仓,可以直接修改这个文本文件。比如你的策略不小心买入了一只强赎的转债,你想手动卖掉,那么很简单,你只要在这个json文件里面把对应的持仓删除,再把他的市值加到可用资金里面去即可。 用法是相当灵活。
 
需要完整代码或者指导的朋友可以关注下面公众号和知识星球。
 
 

 

 
  查看全部
多策略需要解决的一个最主要的问题,就是仓位管理。
 
系统自带的读取仓位函数需要你重写。
 
目前使用一个类来管理仓位:
 
初始化部分:
class PositionManager():

def __init__(self):
if SINGLE_FACTOR not in [1, 2, 3, 4]:
raise ValueError('策略数字有误')

self.strategy = SINGLE_FACTOR
NOTEBOOK_PATH = '/home/fly/notebook/'
# self.filename = NOTEBOOK_PATH + 'S-{}.txt'.format(self.strategy)
self.filename = NOTEBOOK_PATH + personal_define_filename
self.portfolio = self.read()
log.info(self.portfolio)
self.write()

def init_data(self):
js_data = {
'cash': CASH,
'strategy': self.strategy,
'positions': ,
'portfolio_value': None,
'positions_value': None,
'capital_used': None,
'start_date': datetime.datetime.now().strftime('%Y%m%d%H%M%S'),
'current_day': 0,
}

数据需要收盘后保存到文件,数据库也行;不过考虑到大部分ptrade(除了国盛,需要开通的可以联系公众号:可转债量化分析)都没有连接外网功能,所以最简单的方式就是写入文件,纯粹的文本文件。
 
目前笔者使用json存储

20221116001.jpg

 点击查看大图
 
这样存储有一个好处,就是如果你想中途修改策略持仓,可以直接修改这个文本文件。比如你的策略不小心买入了一只强赎的转债,你想手动卖掉,那么很简单,你只要在这个json文件里面把对应的持仓删除,再把他的市值加到可用资金里面去即可。 用法是相当灵活。
 
需要完整代码或者指导的朋友可以关注下面公众号和知识星球。
 
 

 

 
 

Ptrade拆单 分批下单 python代码 可转债/股票

Ptrade李魔佛 发表了文章 • 0 个评论 • 188 次浏览 • 2022-11-10 00:35 • 来自相关话题

在转债市场,部分转债的流动性很差,有时候连成交100张也需要等待一段时间。

所以如果资金量大,就需要拆单操作。

交易代码部分,如果设置 SPLIT_ORDER_ENABLE = True 即进行拆单操作:


在交易部分:(省略部分不相关代码) if SPLIT_ORDER_ENABLE:
split_order(code, BUY_DIRECTION, amount)
else:
buy_price = round(buy_price, 3)
ret = order(code, amount, limit_price=buy_price)BUY_DIRECTION 为买,值是1,一个常量

SELL_DIRECTION为卖,值为-1,也是一个常量,传入拆单函数中
 
 
拆单函数提取出来:def split_order(code, direction, target_count):
'''
拆单
:param code: 股票代码
:param direction: 买:1 卖:-1
:param target_count: 总共要卖的股数
:return:
'''

count = int(target_count / EACH_ORDER_COUNT)
# 例如:560张, 200 张一单, 2次 + 最后一次160 张

remain_count = target_count % EACH_ORDER_COUNT

for i in range(count):
ret = order(code, direction * EACH_ORDER_COUNT)
time.sleep(SPLIT_ORDER_DELAY) # 拆开的单子等待一个时间,再下另外一单

if direction == 1: # 买的时候需要整数,卖则不需要
remain_count = int(remain_count / 10) * 10

if remain_count > 0:
ret = order(code, direction * remain_count)常用的操作都类似,写成模块方便下次调用。写多了就是套模块。
 
在可转债实盘中,拆单后每笔下单200张,就是每次200张下一次单,因为有可能不是马上成交,所以还需要一段等待延时,再去下单;不然你的拆单也变得没有意义,因为委托那里都是挂的你的单,并没有被消化掉。
 












可以看到实盘交易日志,即使拆单为200张一笔,外加一段延时,成交张数也是稀稀拉拉的,出现了不少的部分成交;也就是一次连200张都未成交完成;一笔200张的,部分成交10张,20张,都是有可能的,这也足以说明,可转债的流动性问题,滑点是很难被忽略的。

当然,这是轮动调仓的时候,金额较大的情况下拆单。如果高频交易下就不能这么操作了。 
具体怎么写,可以关注个人公众号与知识星球。

知识星球原文:





 
如需要代写量化策略实盘代码,可以到个人公众号【可转债量化分析】后台留言。
 
 
 
  查看全部
在转债市场,部分转债的流动性很差,有时候连成交100张也需要等待一段时间。

所以如果资金量大,就需要拆单操作。

交易代码部分,如果设置 SPLIT_ORDER_ENABLE = True 即进行拆单操作:


在交易部分:(省略部分不相关代码)
                if SPLIT_ORDER_ENABLE:
split_order(code, BUY_DIRECTION, amount)
else:
buy_price = round(buy_price, 3)
ret = order(code, amount, limit_price=buy_price)
BUY_DIRECTION 为买,值是1,一个常量

SELL_DIRECTION为卖,值为-1,也是一个常量,传入拆单函数中
 
 
拆单函数提取出来:
def split_order(code, direction, target_count):
'''
拆单
:param code: 股票代码
:param direction: 买:1 卖:-1
:param target_count: 总共要卖的股数
:return:
'''

count = int(target_count / EACH_ORDER_COUNT)
# 例如:560张, 200 张一单, 2次 + 最后一次160 张

remain_count = target_count % EACH_ORDER_COUNT

for i in range(count):
ret = order(code, direction * EACH_ORDER_COUNT)
time.sleep(SPLIT_ORDER_DELAY) # 拆开的单子等待一个时间,再下另外一单

if direction == 1: # 买的时候需要整数,卖则不需要
remain_count = int(remain_count / 10) * 10

if remain_count > 0:
ret = order(code, direction * remain_count)
常用的操作都类似,写成模块方便下次调用。写多了就是套模块。
 
在可转债实盘中,拆单后每笔下单200张,就是每次200张下一次单,因为有可能不是马上成交,所以还需要一段等待延时,再去下单;不然你的拆单也变得没有意义,因为委托那里都是挂的你的单,并没有被消化掉。
 

20221110002.jpg



20221110003.jpg


可以看到实盘交易日志,即使拆单为200张一笔,外加一段延时,成交张数也是稀稀拉拉的,出现了不少的部分成交;也就是一次连200张都未成交完成;一笔200张的,部分成交10张,20张,都是有可能的,这也足以说明,可转债的流动性问题,滑点是很难被忽略的。

当然,这是轮动调仓的时候,金额较大的情况下拆单。如果高频交易下就不能这么操作了。 
具体怎么写,可以关注个人公众号与知识星球。

知识星球原文:

20221110001.jpg

 
如需要代写量化策略实盘代码,可以到个人公众号【可转债量化分析】后台留言。
 
 
 
 

Ptrade里写策略坑比较多的地方(一)

Ptrade李魔佛 发表了文章 • 0 个评论 • 269 次浏览 • 2022-11-03 11:26 • 来自相关话题

总结一些,给过来人少踩些坑
 1. 后缀符号不统一
这个是天煞的产品涉及的问题。 好好地代码后缀,比如 深圳市场的 有时候出现 300333.SZ , 有时候结构体里面却会是 300333.XSHE,
 
比如返回的orders 字典,里面用的是 00333.XSHE,而仓位的结构体 position 里面用的缺失 .sz





 
类似这样的问题在很多函数里面都有。
 
2. 部分成交 的主推函数
如果一个订单,部分成交,会先触发部分成交主推; 然后最后一个部分成交,反而会触发全部成交主推。
细想,似乎也是合理的,只是,你在全部成交里面返回的成交数量,实际只是最后一次部分成交的量。
 
3. 想到再写
更多更新 可以参看个人知识星球或者公众号。

 
 
  查看全部
总结一些,给过来人少踩些坑
 1. 后缀符号不统一
这个是天煞的产品涉及的问题。 好好地代码后缀,比如 深圳市场的 有时候出现 300333.SZ , 有时候结构体里面却会是 300333.XSHE,
 
比如返回的orders 字典,里面用的是 00333.XSHE,而仓位的结构体 position 里面用的缺失 .sz

20221103001.jpg

 
类似这样的问题在很多函数里面都有。
 
2. 部分成交 的主推函数
如果一个订单,部分成交,会先触发部分成交主推; 然后最后一个部分成交,反而会触发全部成交主推。
细想,似乎也是合理的,只是,你在全部成交里面返回的成交数量,实际只是最后一次部分成交的量。
 
3. 想到再写
更多更新 可以参看个人知识星球或者公众号。

 
 
 

Ptrade量化交易之 拆单买入卖出操作

Ptrade李魔佛 发表了文章 • 0 个评论 • 383 次浏览 • 2022-09-30 16:20 • 来自相关话题

在交易过程中,如果遇到成交量小的股票或者可转债,etf,稍微买多一些会对现价造成冲击,价格容易被你自己拉起来。所以假如你的交易量很大的话,一般最好使用拆单操作。 可以参考下面的python拆单代码:
 注:代码里面针对的是可转债交易,股票的话把这一行:

remain_count=int(remain_count/10)*10 改为

remain_count=int(remain_count/100)*100 就可以了

股票100股整数倍买,转债是10张倍数买。


code,direction,target_count : 第一个代码,第二个买卖方向,第三个是目标数目
 

each_order_count = 100 # 每单的股数,张数

def split_order(code,direction,target_count):
'''
拆单
:param code: 股票代码
:param direction: 买:1 卖:-1
:param target_count: 总共要卖的股数
:return:
'''

SPLIT_ORDER_DELAY =1
each_order_count = 100 # 每单的股数,张数
count = int(target_count/each_order_count)
remain_count = target_count%each_order_count

for i in range(count):
ret = order(code,direction*each_order_count)
time.sleep(SPLIT_ORDER_DELAY)

if direction==1:
remain_count=int(remain_count/10)*10 # 可转债买的时候只能10的倍数交易,

if remain_count>0:
ret = order(code,direction*each_order_count)
 
更多ptrade实盘代码,欢迎关注个人知识星球 查看全部
在交易过程中,如果遇到成交量小的股票或者可转债,etf,稍微买多一些会对现价造成冲击,价格容易被你自己拉起来。所以假如你的交易量很大的话,一般最好使用拆单操作。 可以参考下面的python拆单代码:
 注:代码里面针对的是可转债交易,股票的话把这一行:

remain_count=int(remain_count/10)*10 改为

remain_count=int(remain_count/100)*100 就可以了

股票100股整数倍买,转债是10张倍数买。


code,direction,target_count : 第一个代码,第二个买卖方向,第三个是目标数目
 

each_order_count = 100 # 每单的股数,张数

def split_order(code,direction,target_count):
'''
拆单
:param code: 股票代码
:param direction: 买:1 卖:-1
:param target_count: 总共要卖的股数
:return:
'''

SPLIT_ORDER_DELAY =1
each_order_count = 100 # 每单的股数,张数
count = int(target_count/each_order_count)
remain_count = target_count%each_order_count

for i in range(count):
ret = order(code,direction*each_order_count)
time.sleep(SPLIT_ORDER_DELAY)

if direction==1:
remain_count=int(remain_count/10)*10 # 可转债买的时候只能10的倍数交易,

if remain_count>0:
ret = order(code,direction*each_order_count)

 
更多ptrade实盘代码,欢迎关注个人知识星球

Ptrade挂单后撤单函数 实现

Ptrade李魔佛 发表了文章 • 0 个评论 • 331 次浏览 • 2022-09-29 16:40 • 来自相关话题

在ptrade的每一笔挂单,都不一定能够保证很成功,比如刚挂了单,股票就飞了。
 所以也需要有撤单,重新挂的动作。
  order(code,amount) # 买入或者卖出

time.sleep(CANCEL_ORDER_TIME) # 等待片刻

cancel_order_reorder(context) # 进入撤单函数
中间需要有个等待时间。
1。 买入后,并不一定买上成交,需要一点时间消化,尤其是量大的单子,得要慢慢吃掉。
2。 成交回报并不是实时的。记住,ptrade的成交回报是有个延时,约9秒。 也就是你成交后,立即调用get_positions函数 看看你持仓,是无法看到你刚刚买入的股票数据的。
 
比如:
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)

def handle_data(context, data):
order(g.security,100)
position = get_position(g.security)
log.info(position)这样你是无法获取的你的持仓的。
 
 
下面的示例代码,获取还在挂单的委托单子,然后逐个撤销,重新按照最新的市价下单。
 
def cancel_order_reorder(context):
'''
取消订单,重新下单
:return:
'''

open_orders = get_open_orders()

for _order in open_orders:
_id = _order.id
amount=_order.amount
filled=_order.filled
next_amount = amount-filled
code = _order.symbol
log.info('撤单{} - {}'.format(code,next_amount))
cancel_order(_id)

# time.sleep(1)
log.info('重新下单{} 数量{}'.format(code,next_amount))
order(code,next_amount)
 
后话:
很多投资者没有编程基础,学习起来会很吃力,耗费大量的时间,得不偿失。写出来的代码也是很多bug而不自知。等到实盘了用真金白银 得到了教训,还不如早期跟一两个人有经验的人学习,甚至找个代写代码就好了。
 当然,能力超强,精力旺盛的大神就无视了,这个人折腾起来什么都可以搞得有模有样。 
  查看全部
在ptrade的每一笔挂单,都不一定能够保证很成功,比如刚挂了单,股票就飞了。
 所以也需要有撤单,重新挂的动作。
 
    order(code,amount) # 买入或者卖出

time.sleep(CANCEL_ORDER_TIME) # 等待片刻

cancel_order_reorder(context) # 进入撤单函数

中间需要有个等待时间。
1。 买入后,并不一定买上成交,需要一点时间消化,尤其是量大的单子,得要慢慢吃掉。
2。 成交回报并不是实时的。记住,ptrade的成交回报是有个延时,约9秒。 也就是你成交后,立即调用get_positions函数 看看你持仓,是无法看到你刚刚买入的股票数据的。
 
比如:
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)

def handle_data(context, data):
order(g.security,100)
position = get_position(g.security)
log.info(position)
这样你是无法获取的你的持仓的。
 
 
下面的示例代码,获取还在挂单的委托单子,然后逐个撤销,重新按照最新的市价下单。
 
def cancel_order_reorder(context):
'''
取消订单,重新下单
:return:
'''

open_orders = get_open_orders()

for _order in open_orders:
_id = _order.id
amount=_order.amount
filled=_order.filled
next_amount = amount-filled
code = _order.symbol
log.info('撤单{} - {}'.format(code,next_amount))
cancel_order(_id)

# time.sleep(1)
log.info('重新下单{} 数量{}'.format(code,next_amount))
order(code,next_amount)

 
后话:
很多投资者没有编程基础,学习起来会很吃力,耗费大量的时间,得不偿失。写出来的代码也是很多bug而不自知。等到实盘了用真金白银 得到了教训,还不如早期跟一两个人有经验的人学习,甚至找个代写代码就好了。
 当然,能力超强,精力旺盛的大神就无视了,这个人折腾起来什么都可以搞得有模有样。 
 

Ptrade在一个循环事件里 能否不断获取股票实时价格?

Ptrade李魔佛 发表了文章 • 0 个评论 • 294 次浏览 • 2022-09-28 10:53 • 来自相关话题

假设在一个事件循环里:
如:
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

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 可以看到价格也是基本没个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 

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
可以看到价格也是基本没个3s更新一次。
 
 
 
更多ptrade实盘代码,请常见个人星球。
【可转债追涨杀跌日内T+0,双低 低价 低溢价 规模多因子轮动】

20220928002.jpg

 

20220928001.jpg

 

 
 

ptrade 微信通知

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 320 次浏览 • 2022-09-20 10:29 • 来自相关话题

对于节假日,ptrade经常会被暂停维护。 而有时候维护后需要你手动去重启策略。
 
所以情况多了,经常会忘记,手动登录进去重启。导致策略没有运行。
 
所以办法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()
  查看全部
对于节假日,ptrade经常会被暂停维护。 而有时候维护后需要你手动去重启策略。
 
所以情况多了,经常会忘记,手动登录进去重启。导致策略没有运行。
 
所以办法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()

 

Ptrade的回测程序是在本地运行还是远程服务器? 关闭ptrade后原来运行的回测还可以继续运行吗?

回复

量化交易-Ptrade-QMT李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 428 次浏览 • 2022-09-11 21:07 • 来自相关话题

Ptrade与QMT 获取可转债基础数据,溢价率,剩余规模,评级,双低,是否强赎

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 555 次浏览 • 2022-09-08 22:25 • 来自相关话题

Ptrade和qmt的内置数据接口,对于可转债的数据支持很少。只有基础的可转债价格,成交量。





 
搜索接口文档,关键字 可转债 , 只有可怜的一个接口。并且这个接口还是最近才提供的。
 
基本没有可转债的其他基础数据。
 
比如 溢价率,剩余规模,评级,双低,到期,强赎。





 
笔者也为了方便,跨平台,把数据调用抽离出来,写成可以调用  接口的方式。





 
用的post请求方式。
 
这样无论是ptrade还是qmt,还是平时写的选股web页面, 都可以直接调用同一个数据源。 而你只需要维护一个数据数据源。






 
需要接口的,可以加入星球 或者 开通ptrade/QMT 的同时 获取。

  查看全部
Ptrade和qmt的内置数据接口,对于可转债的数据支持很少。只有基础的可转债价格,成交量。

20220908003.png

 
搜索接口文档,关键字 可转债 , 只有可怜的一个接口。并且这个接口还是最近才提供的。
 
基本没有可转债的其他基础数据。
 
比如 溢价率,剩余规模,评级,双低,到期,强赎。

20220908004.png

 
笔者也为了方便,跨平台,把数据调用抽离出来,写成可以调用  接口的方式。

20220908005.png

 
用的post请求方式。
 
这样无论是ptrade还是qmt,还是平时写的选股web页面, 都可以直接调用同一个数据源。 而你只需要维护一个数据数据源。


20220908006.png

 
需要接口的,可以加入星球 或者 开通ptrade/QMT 的同时 获取。

 

ptrade和qmt的内置代码编辑器,哪个比较好用?

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 451 次浏览 • 2022-09-05 11:24 • 来自相关话题

ptrade和qmt的内置代码编辑器,哪个比较好用?
 
答:都十分渣,半斤八两。更裸手在记事本写代码差不多的感觉。 尤其对于新人,经常可能会因为一些拼写错误,换行等问题,折腾一天,才能找到原因,至少pycharm对没有引用的变量是变灰的,语法错误是红的,快速帮助定位错误。(我自己就亲身经历过这种调试惨案,太惨痛。)
 
 
  查看全部
ptrade和qmt的内置代码编辑器,哪个比较好用?
 
答:都十分渣,半斤八两。更裸手在记事本写代码差不多的感觉。 尤其对于新人,经常可能会因为一些拼写错误,换行等问题,折腾一天,才能找到原因,至少pycharm对没有引用的变量是变灰的,语法错误是红的,快速帮助定位错误。(我自己就亲身经历过这种调试惨案,太惨痛。)
 
 
 

Ptrade支持reits回测和交易吗?

回复

量化交易-Ptrade-QMT李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 502 次浏览 • 2022-09-02 00:27 • 来自相关话题

Ptrade 逆回购+自动申购新股可转债

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 439 次浏览 • 2022-08-24 20:03 • 来自相关话题

分享一些最基本的ptrade代码实盘例子。 持续更新,喜欢的朋友请关注本站哦。
本站所有代码均经过实盘验证。# 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软件-量化-回测 里,新建策略,复制全文粘贴进去,周期选分钟,再到交易里新增交易

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-QMT李魔佛 发表了文章 • 0 个评论 • 391 次浏览 • 2022-08-22 18:46 • 来自相关话题

注意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版本: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)要求 报错:

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 380 次浏览 • 2022-08-22 17:42 • 来自相关话题

关于持久化

为什么要做持久化处理

服务器异常、策略优化等诸多场景,都会使得正在进行的模拟盘和实盘策略存在中断后再重启的需求,但是一旦交易中止后,策略中存储在内存中的全局变量就清空了,因此通过持久化处理为量化交易保驾护航必不可少。

量化框架持久化处理

使用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






 
 

欢迎关注公众号 查看全部
关于持久化

为什么要做持久化处理

服务器异常、策略优化等诸多场景,都会使得正在进行的模拟盘和实盘策略存在中断后再重启的需求,但是一旦交易中止后,策略中存储在内存中的全局变量就清空了,因此通过持久化处理为量化交易保驾护航必不可少。

量化框架持久化处理

使用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



mmexport1661160949191.jpg

 
 

欢迎关注公众号

不同券商的ptrade的异同

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 1024 次浏览 • 2022-06-17 16:36 • 来自相关话题

国盛vs湘财
 
1. 湘财无法访问外网,国盛的可以

2. 




get_cb_list 获取可转债列表 的 国盛没有

get_history 获取历史数据函数
 get_history(5, frequency='1d', field='close', security_list=['123084.SZ'], fq=None, include=False, fill='nan')国盛是没有fill参数的。
 
 
 
持续更新。。。待续
 
Ptrade开户联系:

  查看全部
国盛vs湘财
 
1. 湘财无法访问外网,国盛的可以

2. 
20220617001.png

get_cb_list 获取可转债列表 的 国盛没有

get_history 获取历史数据函数
 
get_history(5, frequency='1d', field='close', security_list=['123084.SZ'], fq=None, include=False, fill='nan')
国盛是没有fill参数的。
 
 
 
持续更新。。。待续
 
Ptrade开户联系:

 

ptrade qmt量化平台收费吗?

券商万一免五李魔佛 回复了问题 • 2 人关注 • 1 个回复 • 1555 次浏览 • 2022-07-13 17:04 • 来自相关话题

开通Ptrade Python量化接口 国金证券/国盛证券

股票绫波丽 发表了文章 • 0 个评论 • 9812 次浏览 • 2021-07-06 08:40 • 来自相关话题

目前不少在A股做量化的大部分使用tushare,优矿,米筐,聚宽等等,无论教程,还是实际操作,基本没见有教怎么用程序下单,实盘交易的。

而退而求其次使用按键精灵,模拟点击交易软件进行点击下单,非常不稳定,无法判断下单后是否成交,也无法实时获取行情数据。如果使用tushare或者新浪接口数据,扫描一次全市场的行情用时很久且不稳定,等扫描结束,再下单,此时价格可能已经是几分钟前的了,且此类接口调用次数多是会被封IP的。

笔者使用的是券商提供的量化软件:Ptrade。是恒生电子研发的提供给机构使用的程序化交易软件。提供策略回测,下单API接口,实时行情获取,并且使用的开发语言python,易于上手。

策略回测与实盘交易




研究页面

研究页面,熟悉python jupyter notebook的朋友对这个界面肯定很熟悉。

研究的页面实际就运行你逐行输出调试程序,了解每个函数的具体使用,或者你策略的中途结果调试。





 
回测策略

实际代码需要在回测策略里面写,写完后确定无误,就可以放在仿真环境下真实运行。如果你运行得到的结果很满意,那么就可以直接部署到实盘服务器上。实盘服务器是在券商那边,不需要个人购买服务器,也不需要本地开着这个Ptrade,就是说不需要在个人电脑上一直开着跑,你的最终代码和程序是在券商服务器上部署与运行,除非有报错异常停止,不然在你不暂停或者停止的前提下,可以一直运行下去。












条件满足后下单

可视化量化

同时也提供一些常见的现成的量化策略,选中后只要鼠标点点点也能够自动化跑这些策略了,当然里面很多参数都可以用鼠标点点点修改。





 
接口文档也非常详细:




 
一些常见策略代码:

集合竞价追涨停策略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)
pass

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def handle_data(context, data):
security = g.security

#得到十日历史价格
df = get_history(10, '1d', 'close', security, fq=None, include=False)

# 得到五日均线价格
ma5 = round(df['close'][-5:].mean(), 3)

# 得到十日均线价格
ma10 = round(df['close'][-10:].mean(), 3)

# 取得昨天收盘价
price = data[security]['close']

# 得到当前资金余额
cash = context.portfolio.cash

# 如果当前有余额,并且五日均线大于十日均线
if ma5 > ma10:
# 用所有 cash 买入股票
order_value(security, cash)
# 记录这次买入
log.info("Buying %s" % (security))

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(security).amount > 0:
# 全部卖出
order_target(security, 0)
# 记录这次卖出
log.info("Selling %s" % (security))
 
tick级别均线策略

通俗点就是按照秒级别进行操作。def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
#每3秒运行一次主函数
run_interval(context, func, seconds=3)

#盘前准备历史数据
def before_trading_start(context, data):
history = get_history(10, '1d', 'close', g.security, fq='pre', include=False)
g.close_array = history['close'].values

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def func(context):

stock = g.security

#获取最新价
snapshot = get_snapshot(stock)
price = snapshot[stock]['last_px']

# 得到五日均线价格
days = 5
ma5 = get_MA_day(stock, days, g.close_array[-4:], price)
# 得到十日均线价格
days = 10
ma10 = get_MA_day(stock, days, g.close_array[-9:], price)

# 得到当前资金余额
cash = context.portfolio.cash

# 如果当前有余额,并且五日均线大于十日均线
if ma5 > ma10:
# 用所有 cash 买入股票
order_value(stock, cash)
# 记录这次买入
log.info("Buying %s" % (stock))

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(stock).amount > 0:
# 全部卖出
order_target(stock, 0)
# 记录这次卖出
log.info("Selling %s" % (stock))

#计算实时均线函数
def get_MA_day(stock,days,close_array,current_price):
close_sum = close_array[-(days-1):].sum()
MA = (current_price + close_sum)/days
return MA

def handle_data(context, data):
pass
 
macd策略def f_expma(N,m,EXPMA1,price):
a = m/(N+1)
EXPMA2 = a * price + (1 - a)*EXPMA1
return EXPMA2 #2为后一天值

#定义macd函数,输入平滑系数参数、前一日值,输出当日值
def macd(N1,N2,N3,m,EXPMA12_1,EXPMA26_1,DEA1,price):
EXPMA12_2 = f_expma(N1,m,EXPMA12_1,price)
EXPMA26_2 = f_expma(N2,m,EXPMA26_1,price)
DIF2 = EXPMA12_2 - EXPMA26_2
a = m/(N3+1)
DEA2 = a * DIF2 + (1 - a)*DEA1
BAR2=2*(DIF2-DEA2)
return EXPMA12_2,EXPMA26_2,DIF2,DEA2,BAR2

def initialize(context):
global init_price
init_price = None
# 获取沪深300股票
g.security = get_index_stocks('000300.SS')
#g.security = ['600570.SS']
# 设置我们要操作的股票池, 这里我们只操作一支股票
set_universe(g.security)

def handle_data(context, data):
# 获取历史数据,这里只获取了2天的数据,如果希望最终MACD指标结果更准确最好是获取
# 从股票上市至今的所有历史数据,即增加获取的天数
close_price = get_history(2, '1d', field='close', security_list=g.security)
#如果是停牌不进行计算
for security in g.security:
if data[security].is_open >0:
global init_price,EXPMA12_1,EXPMA26_1,EXPMA12_2,EXPMA26_2,DIF1,DIF2,DEA1,DEA2
if init_price is None:
init_price = close_price[security].mean()#nan和N-1个数,mean为N-1个数的均值
EXPMA12_1 = init_price
EXPMA26_1 = init_price
DIF1 = init_price
DEA1 = init_price
# m用于计算平滑系数a=m/(N+1)
m = 2.0
#设定指数平滑基期数
N1 = 12
N2 = 26
N3 = 9
EXPMA12_2,EXPMA26_2,DIF2,DEA2,BAR2 = macd(N1,N2,N3,m,EXPMA12_1,EXPMA26_1,DEA1,close_price[security][-1])
# 取得当前价格
current_price = data[security].price
# 取得当前的现金
cash = context.portfolio.cash
# DIF、DEA均为正,DIF向上突破DEA,买入信号参考
if DIF2 > 0 and DEA2 > 0 and DIF1 < DEA1 and DIF2 > DEA2:
# 计算可以买多少只股票
number_of_shares = int(cash/current_price)
# 购买量大于0时,下单
if number_of_shares > 0:
# 以市单价买入股票,日回测时即是开盘价
order(security, +number_of_shares)
# 记录这次买入
log.info("Buying %s" % (security))
# DIF、DEA均为负,DIF向下突破DEA,卖出信号参考
elif DIF2 < 0 and DEA2 < 0 and DIF1 > DEA1 and DIF2 < DEA2 and get_position(security).amount > 0:
# 卖出所有股票,使这只股票的最终持有量为0
order_target(security, 0)
# 记录这次卖出
log.info("Selling %s" % (security))
# 将今日的值赋给全局变量作为下一次前一日的值
DEA1 = DEA2
DIF1 = DIF2
EXPMA12_1 = EXPMA12_2
EXPMA26_1 = EXPMA26_2
 
软件与交易接口开通条件:

开通该券商后,存入资金指定资金即可开通。开通后股票交易费率万一

本身券商的交易费率为股票万一,可转债沪百万分之五,深十万分之五,基金万0.5,非常厚道。
 
不太了解量化行业的可以了解下,不少面向机构的量化交易软件的佣金是万2.5的,且开户门槛高,基本是500W以上,比如华泰的matic量化的门槛是1千万元起步。

所以笔者还是很推荐目前该券商的量化交易接口。

需要开通咨询了解的朋友可以扫码联系:


开通券商账户后可以 可以先试用,再考虑是否开通量化接口权限 查看全部
目前不少在A股做量化的大部分使用tushare,优矿,米筐,聚宽等等,无论教程,还是实际操作,基本没见有教怎么用程序下单,实盘交易的。

而退而求其次使用按键精灵,模拟点击交易软件进行点击下单,非常不稳定,无法判断下单后是否成交,也无法实时获取行情数据。如果使用tushare或者新浪接口数据,扫描一次全市场的行情用时很久且不稳定,等扫描结束,再下单,此时价格可能已经是几分钟前的了,且此类接口调用次数多是会被封IP的。

笔者使用的是券商提供的量化软件:Ptrade。是恒生电子研发的提供给机构使用的程序化交易软件。提供策略回测,下单API接口,实时行情获取,并且使用的开发语言python,易于上手。

策略回测与实盘交易
UrD5TUnxZD.png

研究页面

研究页面,熟悉python jupyter notebook的朋友对这个界面肯定很熟悉。

研究的页面实际就运行你逐行输出调试程序,了解每个函数的具体使用,或者你策略的中途结果调试。

Hc8f4UtMfW.png

 
回测策略

实际代码需要在回测策略里面写,写完后确定无误,就可以放在仿真环境下真实运行。如果你运行得到的结果很满意,那么就可以直接部署到实盘服务器上。实盘服务器是在券商那边,不需要个人购买服务器,也不需要本地开着这个Ptrade,就是说不需要在个人电脑上一直开着跑,你的最终代码和程序是在券商服务器上部署与运行,除非有报错异常停止,不然在你不暂停或者停止的前提下,可以一直运行下去。

Pig1iRRQnP.png



25YjBEdOqa.png


条件满足后下单

可视化量化

同时也提供一些常见的现成的量化策略,选中后只要鼠标点点点也能够自动化跑这些策略了,当然里面很多参数都可以用鼠标点点点修改。

kTmn9iOXaS.png

 
接口文档也非常详细:
v4QFDpHNpd.png

 
一些常见策略代码:

集合竞价追涨停策略
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)
pass

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def handle_data(context, data):
security = g.security

#得到十日历史价格
df = get_history(10, '1d', 'close', security, fq=None, include=False)

# 得到五日均线价格
ma5 = round(df['close'][-5:].mean(), 3)

# 得到十日均线价格
ma10 = round(df['close'][-10:].mean(), 3)

# 取得昨天收盘价
price = data[security]['close']

# 得到当前资金余额
cash = context.portfolio.cash

# 如果当前有余额,并且五日均线大于十日均线
if ma5 > ma10:
# 用所有 cash 买入股票
order_value(security, cash)
# 记录这次买入
log.info("Buying %s" % (security))

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(security).amount > 0:
# 全部卖出
order_target(security, 0)
# 记录这次卖出
log.info("Selling %s" % (security))

 
tick级别均线策略

通俗点就是按照秒级别进行操作。
def initialize(context):
# 初始化此策略
# 设置我们要操作的股票池, 这里我们只操作一支股票
g.security = '600570.SS'
set_universe(g.security)
#每3秒运行一次主函数
run_interval(context, func, seconds=3)

#盘前准备历史数据
def before_trading_start(context, data):
history = get_history(10, '1d', 'close', g.security, fq='pre', include=False)
g.close_array = history['close'].values

#当五日均线高于十日均线时买入,当五日均线低于十日均线时卖出
def func(context):

stock = g.security

#获取最新价
snapshot = get_snapshot(stock)
price = snapshot[stock]['last_px']

# 得到五日均线价格
days = 5
ma5 = get_MA_day(stock, days, g.close_array[-4:], price)
# 得到十日均线价格
days = 10
ma10 = get_MA_day(stock, days, g.close_array[-9:], price)

# 得到当前资金余额
cash = context.portfolio.cash

# 如果当前有余额,并且五日均线大于十日均线
if ma5 > ma10:
# 用所有 cash 买入股票
order_value(stock, cash)
# 记录这次买入
log.info("Buying %s" % (stock))

# 如果五日均线小于十日均线,并且目前有头寸
elif ma5 < ma10 and get_position(stock).amount > 0:
# 全部卖出
order_target(stock, 0)
# 记录这次卖出
log.info("Selling %s" % (stock))

#计算实时均线函数
def get_MA_day(stock,days,close_array,current_price):
close_sum = close_array[-(days-1):].sum()
MA = (current_price + close_sum)/days
return MA

def handle_data(context, data):
pass

 
macd策略
def f_expma(N,m,EXPMA1,price):
a = m/(N+1)
EXPMA2 = a * price + (1 - a)*EXPMA1
return EXPMA2 #2为后一天值

#定义macd函数,输入平滑系数参数、前一日值,输出当日值
def macd(N1,N2,N3,m,EXPMA12_1,EXPMA26_1,DEA1,price):
EXPMA12_2 = f_expma(N1,m,EXPMA12_1,price)
EXPMA26_2 = f_expma(N2,m,EXPMA26_1,price)
DIF2 = EXPMA12_2 - EXPMA26_2
a = m/(N3+1)
DEA2 = a * DIF2 + (1 - a)*DEA1
BAR2=2*(DIF2-DEA2)
return EXPMA12_2,EXPMA26_2,DIF2,DEA2,BAR2

def initialize(context):
global init_price
init_price = None
# 获取沪深300股票
g.security = get_index_stocks('000300.SS')
#g.security = ['600570.SS']
# 设置我们要操作的股票池, 这里我们只操作一支股票
set_universe(g.security)

def handle_data(context, data):
# 获取历史数据,这里只获取了2天的数据,如果希望最终MACD指标结果更准确最好是获取
# 从股票上市至今的所有历史数据,即增加获取的天数
close_price = get_history(2, '1d', field='close', security_list=g.security)
#如果是停牌不进行计算
for security in g.security:
if data[security].is_open >0:
global init_price,EXPMA12_1,EXPMA26_1,EXPMA12_2,EXPMA26_2,DIF1,DIF2,DEA1,DEA2
if init_price is None:
init_price = close_price[security].mean()#nan和N-1个数,mean为N-1个数的均值
EXPMA12_1 = init_price
EXPMA26_1 = init_price
DIF1 = init_price
DEA1 = init_price
# m用于计算平滑系数a=m/(N+1)
m = 2.0
#设定指数平滑基期数
N1 = 12
N2 = 26
N3 = 9
EXPMA12_2,EXPMA26_2,DIF2,DEA2,BAR2 = macd(N1,N2,N3,m,EXPMA12_1,EXPMA26_1,DEA1,close_price[security][-1])
# 取得当前价格
current_price = data[security].price
# 取得当前的现金
cash = context.portfolio.cash
# DIF、DEA均为正,DIF向上突破DEA,买入信号参考
if DIF2 > 0 and DEA2 > 0 and DIF1 < DEA1 and DIF2 > DEA2:
# 计算可以买多少只股票
number_of_shares = int(cash/current_price)
# 购买量大于0时,下单
if number_of_shares > 0:
# 以市单价买入股票,日回测时即是开盘价
order(security, +number_of_shares)
# 记录这次买入
log.info("Buying %s" % (security))
# DIF、DEA均为负,DIF向下突破DEA,卖出信号参考
elif DIF2 < 0 and DEA2 < 0 and DIF1 > DEA1 and DIF2 < DEA2 and get_position(security).amount > 0:
# 卖出所有股票,使这只股票的最终持有量为0
order_target(security, 0)
# 记录这次卖出
log.info("Selling %s" % (security))
# 将今日的值赋给全局变量作为下一次前一日的值
DEA1 = DEA2
DIF1 = DIF2
EXPMA12_1 = EXPMA12_2
EXPMA26_1 = EXPMA26_2

 
软件与交易接口开通条件:

开通该券商后,存入资金指定资金即可开通。开通后股票交易费率万一

本身券商的交易费率为股票万一,可转债沪百万分之五,深十万分之五,基金万0.5,非常厚道。
 
不太了解量化行业的可以了解下,不少面向机构的量化交易软件的佣金是万2.5的,且开户门槛高,基本是500W以上,比如华泰的matic量化的门槛是1千万元起步。

所以笔者还是很推荐目前该券商的量化交易接口。

需要开通咨询了解的朋友可以扫码联系:


开通券商账户后可以 可以先试用,再考虑是否开通量化接口权限

Ptrade的回测程序是在本地运行还是远程服务器? 关闭ptrade后原来运行的回测还可以继续运行吗?

回复

量化交易-Ptrade-QMT李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 428 次浏览 • 2022-09-11 21:07 • 来自相关话题

Ptrade支持reits回测和交易吗?

回复

量化交易-Ptrade-QMT李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 502 次浏览 • 2022-09-02 00:27 • 来自相关话题

ptrade可以交易可转债吗?

回复

量化交易-Ptrade-QMT李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 934 次浏览 • 2022-06-10 00:39 • 来自相关话题

ptrade qmt量化平台收费吗?

回复

券商万一免五李魔佛 回复了问题 • 2 人关注 • 1 个回复 • 1555 次浏览 • 2022-07-13 17:04 • 来自相关话题

Ptrade QMT 哪家费率最便宜,门槛最低?

券商万一免五绫波丽 发表了文章 • 0 个评论 • 182 次浏览 • 2022-11-27 19:09 • 来自相关话题

最近咨询的朋友很多。这里做个汇总,可以节省大家的时间。 
笔者只会推荐合适的券商和量化接口给你,而不会推荐坑爹的券商给你。
 
如果你不信任,绕路即可,莫浪费大家时间。或者你有好的资源或者券商,你也可以推荐给我,可以给你发红包,奖励你提供有用的情报信息。
 
目前支持ptrade,qmt可以股票可以免五(0.1元起步)的券商,只有国盛,需要的可以找我开。 但是有入金门槛,ptrade门槛30w, qmt 的门槛50w。 国盛的ptrade可以链接外网。其他家的不行。但国盛的qmt不支持运行在云服务器。
 
其他家的qmt是支持的云服务器的,但国金的qmt会每天自动退出,需要每次手动点击登录,我也写了一个自动登录的小脚本,开完户的朋友可以拿去用用。
 
门槛低的国信,适合新手使用,但是没有miniqmt,这个东西也不一定适合你。 真的需要这个功能,在qmt里面可以写一段代码,让它把下单接口变成http指令,把下单功能独立出来,也是可以的。不过这个属于进阶功能。 需要的也可以把代码给你。
 
笔者用过大部分券商的ptrade qmt,所以个人的指导与推荐还是很有指导意见的。 写过的策略也大部分人(99%)多, 平台好坏,坑的多寡,哪里有雷,都已经摸清摸楚。 可以大大节省你们的时间。 当然你也可以忽略,自己去折腾折腾。选ptrade 还是qmt,然后哪个券商,什么费率。
 





 
需要开户或者可以提供更低费用的资源的可以加微信:
 

  查看全部
最近咨询的朋友很多。这里做个汇总,可以节省大家的时间。 
笔者只会推荐合适的券商和量化接口给你,而不会推荐坑爹的券商给你。
 
如果你不信任,绕路即可,莫浪费大家时间。或者你有好的资源或者券商,你也可以推荐给我,可以给你发红包,奖励你提供有用的情报信息。
 
目前支持ptrade,qmt可以股票可以免五(0.1元起步)的券商,只有国盛,需要的可以找我开。 但是有入金门槛,ptrade门槛30w, qmt 的门槛50w。 国盛的ptrade可以链接外网。其他家的不行。但国盛的qmt不支持运行在云服务器。
 
其他家的qmt是支持的云服务器的,但国金的qmt会每天自动退出,需要每次手动点击登录,我也写了一个自动登录的小脚本,开完户的朋友可以拿去用用。
 
门槛低的国信,适合新手使用,但是没有miniqmt,这个东西也不一定适合你。 真的需要这个功能,在qmt里面可以写一段代码,让它把下单接口变成http指令,把下单功能独立出来,也是可以的。不过这个属于进阶功能。 需要的也可以把代码给你。
 
笔者用过大部分券商的ptrade qmt,所以个人的指导与推荐还是很有指导意见的。 写过的策略也大部分人(99%)多, 平台好坏,坑的多寡,哪里有雷,都已经摸清摸楚。 可以大大节省你们的时间。 当然你也可以忽略,自己去折腾折腾。选ptrade 还是qmt,然后哪个券商,什么费率。
 
mmexport1669547412034.png


 
需要开户或者可以提供更低费用的资源的可以加微信:
 

 

Ptrade多策略如何编写?

Ptrade李魔佛 发表了文章 • 0 个评论 • 328 次浏览 • 2022-11-16 11:33 • 来自相关话题

多策略需要解决的一个最主要的问题,就是仓位管理。
 
系统自带的读取仓位函数需要你重写。
 
目前使用一个类来管理仓位:
 
初始化部分:class PositionManager():

def __init__(self):
if SINGLE_FACTOR not in [1, 2, 3, 4]:
raise ValueError('策略数字有误')

self.strategy = SINGLE_FACTOR
NOTEBOOK_PATH = '/home/fly/notebook/'
# self.filename = NOTEBOOK_PATH + 'S-{}.txt'.format(self.strategy)
self.filename = NOTEBOOK_PATH + personal_define_filename
self.portfolio = self.read()
log.info(self.portfolio)
self.write()

def init_data(self):
js_data = {
'cash': CASH,
'strategy': self.strategy,
'positions': ,
'portfolio_value': None,
'positions_value': None,
'capital_used': None,
'start_date': datetime.datetime.now().strftime('%Y%m%d%H%M%S'),
'current_day': 0,
}
数据需要收盘后保存到文件,数据库也行;不过考虑到大部分ptrade(除了国盛,需要开通的可以联系公众号:可转债量化分析)都没有连接外网功能,所以最简单的方式就是写入文件,纯粹的文本文件。
 
目前笔者使用json存储





 点击查看大图
 
这样存储有一个好处,就是如果你想中途修改策略持仓,可以直接修改这个文本文件。比如你的策略不小心买入了一只强赎的转债,你想手动卖掉,那么很简单,你只要在这个json文件里面把对应的持仓删除,再把他的市值加到可用资金里面去即可。 用法是相当灵活。
 
需要完整代码或者指导的朋友可以关注下面公众号和知识星球。
 
 

 

 
  查看全部
多策略需要解决的一个最主要的问题,就是仓位管理。
 
系统自带的读取仓位函数需要你重写。
 
目前使用一个类来管理仓位:
 
初始化部分:
class PositionManager():

def __init__(self):
if SINGLE_FACTOR not in [1, 2, 3, 4]:
raise ValueError('策略数字有误')

self.strategy = SINGLE_FACTOR
NOTEBOOK_PATH = '/home/fly/notebook/'
# self.filename = NOTEBOOK_PATH + 'S-{}.txt'.format(self.strategy)
self.filename = NOTEBOOK_PATH + personal_define_filename
self.portfolio = self.read()
log.info(self.portfolio)
self.write()

def init_data(self):
js_data = {
'cash': CASH,
'strategy': self.strategy,
'positions': ,
'portfolio_value': None,
'positions_value': None,
'capital_used': None,
'start_date': datetime.datetime.now().strftime('%Y%m%d%H%M%S'),
'current_day': 0,
}

数据需要收盘后保存到文件,数据库也行;不过考虑到大部分ptrade(除了国盛,需要开通的可以联系公众号:可转债量化分析)都没有连接外网功能,所以最简单的方式就是写入文件,纯粹的文本文件。
 
目前笔者使用json存储

20221116001.jpg

 点击查看大图
 
这样存储有一个好处,就是如果你想中途修改策略持仓,可以直接修改这个文本文件。比如你的策略不小心买入了一只强赎的转债,你想手动卖掉,那么很简单,你只要在这个json文件里面把对应的持仓删除,再把他的市值加到可用资金里面去即可。 用法是相当灵活。
 
需要完整代码或者指导的朋友可以关注下面公众号和知识星球。
 
 

 

 
 

Ptrade拆单 分批下单 python代码 可转债/股票

Ptrade李魔佛 发表了文章 • 0 个评论 • 188 次浏览 • 2022-11-10 00:35 • 来自相关话题

在转债市场,部分转债的流动性很差,有时候连成交100张也需要等待一段时间。

所以如果资金量大,就需要拆单操作。

交易代码部分,如果设置 SPLIT_ORDER_ENABLE = True 即进行拆单操作:


在交易部分:(省略部分不相关代码) if SPLIT_ORDER_ENABLE:
split_order(code, BUY_DIRECTION, amount)
else:
buy_price = round(buy_price, 3)
ret = order(code, amount, limit_price=buy_price)BUY_DIRECTION 为买,值是1,一个常量

SELL_DIRECTION为卖,值为-1,也是一个常量,传入拆单函数中
 
 
拆单函数提取出来:def split_order(code, direction, target_count):
'''
拆单
:param code: 股票代码
:param direction: 买:1 卖:-1
:param target_count: 总共要卖的股数
:return:
'''

count = int(target_count / EACH_ORDER_COUNT)
# 例如:560张, 200 张一单, 2次 + 最后一次160 张

remain_count = target_count % EACH_ORDER_COUNT

for i in range(count):
ret = order(code, direction * EACH_ORDER_COUNT)
time.sleep(SPLIT_ORDER_DELAY) # 拆开的单子等待一个时间,再下另外一单

if direction == 1: # 买的时候需要整数,卖则不需要
remain_count = int(remain_count / 10) * 10

if remain_count > 0:
ret = order(code, direction * remain_count)常用的操作都类似,写成模块方便下次调用。写多了就是套模块。
 
在可转债实盘中,拆单后每笔下单200张,就是每次200张下一次单,因为有可能不是马上成交,所以还需要一段等待延时,再去下单;不然你的拆单也变得没有意义,因为委托那里都是挂的你的单,并没有被消化掉。
 












可以看到实盘交易日志,即使拆单为200张一笔,外加一段延时,成交张数也是稀稀拉拉的,出现了不少的部分成交;也就是一次连200张都未成交完成;一笔200张的,部分成交10张,20张,都是有可能的,这也足以说明,可转债的流动性问题,滑点是很难被忽略的。

当然,这是轮动调仓的时候,金额较大的情况下拆单。如果高频交易下就不能这么操作了。 
具体怎么写,可以关注个人公众号与知识星球。

知识星球原文:





 
如需要代写量化策略实盘代码,可以到个人公众号【可转债量化分析】后台留言。
 
 
 
  查看全部
在转债市场,部分转债的流动性很差,有时候连成交100张也需要等待一段时间。

所以如果资金量大,就需要拆单操作。

交易代码部分,如果设置 SPLIT_ORDER_ENABLE = True 即进行拆单操作:


在交易部分:(省略部分不相关代码)
                if SPLIT_ORDER_ENABLE:
split_order(code, BUY_DIRECTION, amount)
else:
buy_price = round(buy_price, 3)
ret = order(code, amount, limit_price=buy_price)
BUY_DIRECTION 为买,值是1,一个常量

SELL_DIRECTION为卖,值为-1,也是一个常量,传入拆单函数中
 
 
拆单函数提取出来:
def split_order(code, direction, target_count):
'''
拆单
:param code: 股票代码
:param direction: 买:1 卖:-1
:param target_count: 总共要卖的股数
:return:
'''

count = int(target_count / EACH_ORDER_COUNT)
# 例如:560张, 200 张一单, 2次 + 最后一次160 张

remain_count = target_count % EACH_ORDER_COUNT

for i in range(count):
ret = order(code, direction * EACH_ORDER_COUNT)
time.sleep(SPLIT_ORDER_DELAY) # 拆开的单子等待一个时间,再下另外一单

if direction == 1: # 买的时候需要整数,卖则不需要
remain_count = int(remain_count / 10) * 10

if remain_count > 0:
ret = order(code, direction * remain_count)
常用的操作都类似,写成模块方便下次调用。写多了就是套模块。
 
在可转债实盘中,拆单后每笔下单200张,就是每次200张下一次单,因为有可能不是马上成交,所以还需要一段等待延时,再去下单;不然你的拆单也变得没有意义,因为委托那里都是挂的你的单,并没有被消化掉。
 

20221110002.jpg



20221110003.jpg


可以看到实盘交易日志,即使拆单为200张一笔,外加一段延时,成交张数也是稀稀拉拉的,出现了不少的部分成交;也就是一次连200张都未成交完成;一笔200张的,部分成交10张,20张,都是有可能的,这也足以说明,可转债的流动性问题,滑点是很难被忽略的。

当然,这是轮动调仓的时候,金额较大的情况下拆单。如果高频交易下就不能这么操作了。 
具体怎么写,可以关注个人公众号与知识星球。

知识星球原文:

20221110001.jpg

 
如需要代写量化策略实盘代码,可以到个人公众号【可转债量化分析】后台留言。
 
 
 
 

Ptrade里写策略坑比较多的地方(一)

Ptrade李魔佛 发表了文章 • 0 个评论 • 269 次浏览 • 2022-11-03 11:26 • 来自相关话题

总结一些,给过来人少踩些坑
 1. 后缀符号不统一
这个是天煞的产品涉及的问题。 好好地代码后缀,比如 深圳市场的 有时候出现 300333.SZ , 有时候结构体里面却会是 300333.XSHE,
 
比如返回的orders 字典,里面用的是 00333.XSHE,而仓位的结构体 position 里面用的缺失 .sz





 
类似这样的问题在很多函数里面都有。
 
2. 部分成交 的主推函数
如果一个订单,部分成交,会先触发部分成交主推; 然后最后一个部分成交,反而会触发全部成交主推。
细想,似乎也是合理的,只是,你在全部成交里面返回的成交数量,实际只是最后一次部分成交的量。
 
3. 想到再写
更多更新 可以参看个人知识星球或者公众号。

 
 
  查看全部
总结一些,给过来人少踩些坑
 1. 后缀符号不统一
这个是天煞的产品涉及的问题。 好好地代码后缀,比如 深圳市场的 有时候出现 300333.SZ , 有时候结构体里面却会是 300333.XSHE,
 
比如返回的orders 字典,里面用的是 00333.XSHE,而仓位的结构体 position 里面用的缺失 .sz

20221103001.jpg

 
类似这样的问题在很多函数里面都有。
 
2. 部分成交 的主推函数
如果一个订单,部分成交,会先触发部分成交主推; 然后最后一个部分成交,反而会触发全部成交主推。
细想,似乎也是合理的,只是,你在全部成交里面返回的成交数量,实际只是最后一次部分成交的量。
 
3. 想到再写
更多更新 可以参看个人知识星球或者公众号。

 
 
 

Ptrade量化交易之 拆单买入卖出操作

Ptrade李魔佛 发表了文章 • 0 个评论 • 383 次浏览 • 2022-09-30 16:20 • 来自相关话题

在交易过程中,如果遇到成交量小的股票或者可转债,etf,稍微买多一些会对现价造成冲击,价格容易被你自己拉起来。所以假如你的交易量很大的话,一般最好使用拆单操作。 可以参考下面的python拆单代码:
 注:代码里面针对的是可转债交易,股票的话把这一行:

remain_count=int(remain_count/10)*10 改为

remain_count=int(remain_count/100)*100 就可以了

股票100股整数倍买,转债是10张倍数买。


code,direction,target_count : 第一个代码,第二个买卖方向,第三个是目标数目
 

each_order_count = 100 # 每单的股数,张数

def split_order(code,direction,target_count):
'''
拆单
:param code: 股票代码
:param direction: 买:1 卖:-1
:param target_count: 总共要卖的股数
:return:
'''

SPLIT_ORDER_DELAY =1
each_order_count = 100 # 每单的股数,张数
count = int(target_count/each_order_count)
remain_count = target_count%each_order_count

for i in range(count):
ret = order(code,direction*each_order_count)
time.sleep(SPLIT_ORDER_DELAY)

if direction==1:
remain_count=int(remain_count/10)*10 # 可转债买的时候只能10的倍数交易,

if remain_count>0:
ret = order(code,direction*each_order_count)
 
更多ptrade实盘代码,欢迎关注个人知识星球 查看全部
在交易过程中,如果遇到成交量小的股票或者可转债,etf,稍微买多一些会对现价造成冲击,价格容易被你自己拉起来。所以假如你的交易量很大的话,一般最好使用拆单操作。 可以参考下面的python拆单代码:
 注:代码里面针对的是可转债交易,股票的话把这一行:

remain_count=int(remain_count/10)*10 改为

remain_count=int(remain_count/100)*100 就可以了

股票100股整数倍买,转债是10张倍数买。


code,direction,target_count : 第一个代码,第二个买卖方向,第三个是目标数目
 

each_order_count = 100 # 每单的股数,张数

def split_order(code,direction,target_count):
'''
拆单
:param code: 股票代码
:param direction: 买:1 卖:-1
:param target_count: 总共要卖的股数
:return:
'''

SPLIT_ORDER_DELAY =1
each_order_count = 100 # 每单的股数,张数
count = int(target_count/each_order_count)
remain_count = target_count%each_order_count

for i in range(count):
ret = order(code,direction*each_order_count)
time.sleep(SPLIT_ORDER_DELAY)

if direction==1:
remain_count=int(remain_count/10)*10 # 可转债买的时候只能10的倍数交易,

if remain_count>0:
ret = order(code,direction*each_order_count)

 
更多ptrade实盘代码,欢迎关注个人知识星球

Ptrade挂单后撤单函数 实现

Ptrade李魔佛 发表了文章 • 0 个评论 • 331 次浏览 • 2022-09-29 16:40 • 来自相关话题

在ptrade的每一笔挂单,都不一定能够保证很成功,比如刚挂了单,股票就飞了。
 所以也需要有撤单,重新挂的动作。
  order(code,amount) # 买入或者卖出

time.sleep(CANCEL_ORDER_TIME) # 等待片刻

cancel_order_reorder(context) # 进入撤单函数
中间需要有个等待时间。
1。 买入后,并不一定买上成交,需要一点时间消化,尤其是量大的单子,得要慢慢吃掉。
2。 成交回报并不是实时的。记住,ptrade的成交回报是有个延时,约9秒。 也就是你成交后,立即调用get_positions函数 看看你持仓,是无法看到你刚刚买入的股票数据的。
 
比如:
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)

def handle_data(context, data):
order(g.security,100)
position = get_position(g.security)
log.info(position)这样你是无法获取的你的持仓的。
 
 
下面的示例代码,获取还在挂单的委托单子,然后逐个撤销,重新按照最新的市价下单。
 
def cancel_order_reorder(context):
'''
取消订单,重新下单
:return:
'''

open_orders = get_open_orders()

for _order in open_orders:
_id = _order.id
amount=_order.amount
filled=_order.filled
next_amount = amount-filled
code = _order.symbol
log.info('撤单{} - {}'.format(code,next_amount))
cancel_order(_id)

# time.sleep(1)
log.info('重新下单{} 数量{}'.format(code,next_amount))
order(code,next_amount)
 
后话:
很多投资者没有编程基础,学习起来会很吃力,耗费大量的时间,得不偿失。写出来的代码也是很多bug而不自知。等到实盘了用真金白银 得到了教训,还不如早期跟一两个人有经验的人学习,甚至找个代写代码就好了。
 当然,能力超强,精力旺盛的大神就无视了,这个人折腾起来什么都可以搞得有模有样。 
  查看全部
在ptrade的每一笔挂单,都不一定能够保证很成功,比如刚挂了单,股票就飞了。
 所以也需要有撤单,重新挂的动作。
 
    order(code,amount) # 买入或者卖出

time.sleep(CANCEL_ORDER_TIME) # 等待片刻

cancel_order_reorder(context) # 进入撤单函数

中间需要有个等待时间。
1。 买入后,并不一定买上成交,需要一点时间消化,尤其是量大的单子,得要慢慢吃掉。
2。 成交回报并不是实时的。记住,ptrade的成交回报是有个延时,约9秒。 也就是你成交后,立即调用get_positions函数 看看你持仓,是无法看到你刚刚买入的股票数据的。
 
比如:
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)

def handle_data(context, data):
order(g.security,100)
position = get_position(g.security)
log.info(position)
这样你是无法获取的你的持仓的。
 
 
下面的示例代码,获取还在挂单的委托单子,然后逐个撤销,重新按照最新的市价下单。
 
def cancel_order_reorder(context):
'''
取消订单,重新下单
:return:
'''

open_orders = get_open_orders()

for _order in open_orders:
_id = _order.id
amount=_order.amount
filled=_order.filled
next_amount = amount-filled
code = _order.symbol
log.info('撤单{} - {}'.format(code,next_amount))
cancel_order(_id)

# time.sleep(1)
log.info('重新下单{} 数量{}'.format(code,next_amount))
order(code,next_amount)

 
后话:
很多投资者没有编程基础,学习起来会很吃力,耗费大量的时间,得不偿失。写出来的代码也是很多bug而不自知。等到实盘了用真金白银 得到了教训,还不如早期跟一两个人有经验的人学习,甚至找个代写代码就好了。
 当然,能力超强,精力旺盛的大神就无视了,这个人折腾起来什么都可以搞得有模有样。 
 

Ptrade在一个循环事件里 能否不断获取股票实时价格?

Ptrade李魔佛 发表了文章 • 0 个评论 • 294 次浏览 • 2022-09-28 10:53 • 来自相关话题

假设在一个事件循环里:
如:
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

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 可以看到价格也是基本没个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 

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
可以看到价格也是基本没个3s更新一次。
 
 
 
更多ptrade实盘代码,请常见个人星球。
【可转债追涨杀跌日内T+0,双低 低价 低溢价 规模多因子轮动】

20220928002.jpg

 

20220928001.jpg

 

 
 

ptrade 微信通知

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 320 次浏览 • 2022-09-20 10:29 • 来自相关话题

对于节假日,ptrade经常会被暂停维护。 而有时候维护后需要你手动去重启策略。
 
所以情况多了,经常会忘记,手动登录进去重启。导致策略没有运行。
 
所以办法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()
  查看全部
对于节假日,ptrade经常会被暂停维护。 而有时候维护后需要你手动去重启策略。
 
所以情况多了,经常会忘记,手动登录进去重启。导致策略没有运行。
 
所以办法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()

 

Ptrade与QMT 获取可转债基础数据,溢价率,剩余规模,评级,双低,是否强赎

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 555 次浏览 • 2022-09-08 22:25 • 来自相关话题

Ptrade和qmt的内置数据接口,对于可转债的数据支持很少。只有基础的可转债价格,成交量。





 
搜索接口文档,关键字 可转债 , 只有可怜的一个接口。并且这个接口还是最近才提供的。
 
基本没有可转债的其他基础数据。
 
比如 溢价率,剩余规模,评级,双低,到期,强赎。





 
笔者也为了方便,跨平台,把数据调用抽离出来,写成可以调用  接口的方式。





 
用的post请求方式。
 
这样无论是ptrade还是qmt,还是平时写的选股web页面, 都可以直接调用同一个数据源。 而你只需要维护一个数据数据源。






 
需要接口的,可以加入星球 或者 开通ptrade/QMT 的同时 获取。

  查看全部
Ptrade和qmt的内置数据接口,对于可转债的数据支持很少。只有基础的可转债价格,成交量。

20220908003.png

 
搜索接口文档,关键字 可转债 , 只有可怜的一个接口。并且这个接口还是最近才提供的。
 
基本没有可转债的其他基础数据。
 
比如 溢价率,剩余规模,评级,双低,到期,强赎。

20220908004.png

 
笔者也为了方便,跨平台,把数据调用抽离出来,写成可以调用  接口的方式。

20220908005.png

 
用的post请求方式。
 
这样无论是ptrade还是qmt,还是平时写的选股web页面, 都可以直接调用同一个数据源。 而你只需要维护一个数据数据源。


20220908006.png

 
需要接口的,可以加入星球 或者 开通ptrade/QMT 的同时 获取。

 

ptrade和qmt的内置代码编辑器,哪个比较好用?

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 451 次浏览 • 2022-09-05 11:24 • 来自相关话题

ptrade和qmt的内置代码编辑器,哪个比较好用?
 
答:都十分渣,半斤八两。更裸手在记事本写代码差不多的感觉。 尤其对于新人,经常可能会因为一些拼写错误,换行等问题,折腾一天,才能找到原因,至少pycharm对没有引用的变量是变灰的,语法错误是红的,快速帮助定位错误。(我自己就亲身经历过这种调试惨案,太惨痛。)
 
 
  查看全部
ptrade和qmt的内置代码编辑器,哪个比较好用?
 
答:都十分渣,半斤八两。更裸手在记事本写代码差不多的感觉。 尤其对于新人,经常可能会因为一些拼写错误,换行等问题,折腾一天,才能找到原因,至少pycharm对没有引用的变量是变灰的,语法错误是红的,快速帮助定位错误。(我自己就亲身经历过这种调试惨案,太惨痛。)
 
 
 

Ptrade 逆回购+自动申购新股可转债

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 439 次浏览 • 2022-08-24 20:03 • 来自相关话题

分享一些最基本的ptrade代码实盘例子。 持续更新,喜欢的朋友请关注本站哦。
本站所有代码均经过实盘验证。# 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软件-量化-回测 里,新建策略,复制全文粘贴进去,周期选分钟,再到交易里新增交易

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-QMT李魔佛 发表了文章 • 0 个评论 • 391 次浏览 • 2022-08-22 18:46 • 来自相关话题

注意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版本: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)要求 报错:

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 380 次浏览 • 2022-08-22 17:42 • 来自相关话题

关于持久化

为什么要做持久化处理

服务器异常、策略优化等诸多场景,都会使得正在进行的模拟盘和实盘策略存在中断后再重启的需求,但是一旦交易中止后,策略中存储在内存中的全局变量就清空了,因此通过持久化处理为量化交易保驾护航必不可少。

量化框架持久化处理

使用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






 
 

欢迎关注公众号 查看全部
关于持久化

为什么要做持久化处理

服务器异常、策略优化等诸多场景,都会使得正在进行的模拟盘和实盘策略存在中断后再重启的需求,但是一旦交易中止后,策略中存储在内存中的全局变量就清空了,因此通过持久化处理为量化交易保驾护航必不可少。

量化框架持久化处理

使用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



mmexport1661160949191.jpg

 
 

欢迎关注公众号

Ptrade下单接口 order,order_target, order_value,order_target_value的区别

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 514 次浏览 • 2022-08-11 23:57 • 来自相关话题

order_target 接口通过持仓数量比较将入参的目标数量转换成需要交易的成交,传入 order
接口

order_value 接口通过 金额/限价 或者 金额/默认最新价 两种方式转换成需要交易的数量,
传入 order 接口

order_target_value 接口通过持仓金额比较得到需要交易的金额, 金额/限价 或者 金额/默
认最新价 两种方式转换成需要交易的数量,传入 order 接口




所以其他几个接口都是对order的封装。
 
order接口的逻辑:order 接口:
一、
先判断 limit_price 是否传入,传入则用传入价格限价,不传入则最新价代替,都是
限价方式报单。二、
判断隔夜单和交易时间,交易时间(9:10(系统可配)~15:00)范围的订单会马上
加入未处理订单队列,其他订单先放到一个队列,等时间到交易时间就放到未处理订单
队列三、
未处理订单队列的订单会进行限价判断,如果没有传入限价就按当前最新价处理,
然后报柜台
  

欢迎关注公众号 查看全部
order_target 接口通过持仓数量比较将入参的目标数量转换成需要交易的成交,传入 order
接口

order_value 接口通过 金额/限价 或者 金额/默认最新价 两种方式转换成需要交易的数量,
传入 order 接口

order_target_value 接口通过持仓金额比较得到需要交易的金额, 金额/限价 或者 金额/默
认最新价 两种方式转换成需要交易的数量,传入 order 接口




所以其他几个接口都是对order的封装。
 
order接口的逻辑:
order 接口:
一、
先判断 limit_price 是否传入,传入则用传入价格限价,不传入则最新价代替,都是
限价方式报单。
二、
判断隔夜单和交易时间,交易时间(9:10(系统可配)~15:00)范围的订单会马上
加入未处理订单队列,其他订单先放到一个队列,等时间到交易时间就放到未处理订单
队列
三、
未处理订单队列的订单会进行限价判断,如果没有传入限价就按当前最新价处理,
然后报柜台

  

欢迎关注公众号

Ptrade抢新上市的可转债

量化交易-Ptrade-QMT李魔佛 发表了文章 • 0 个评论 • 450 次浏览 • 2022-08-11 10:20 • 来自相关话题

更新:早上的单子如期挂上了。只是成交量太少,轮不动我的。不过也好,省点心,不用每次盯盘操作。





 
PS: 也不是每一只都是去抢,还是需要提前判断下。规模小的优先。
 

欢迎关注公众号 查看全部
更新:早上的单子如期挂上了。只是成交量太少,轮不动我的。不过也好,省点心,不用每次盯盘操作。

20220811002.png

 
PS: 也不是每一只都是去抢,还是需要提前判断下。规模小的优先。
 

欢迎关注公众号