通知设置 新通知
Ptrade基本期货策略
李魔佛 发表了文章 • 0 个评论 • 1610 次浏览 • 2023-02-04 14:17
新建策略的时候选择:期货即可。
1. 买入开仓
不同期货品种每一跳的价格变动都不一样,limit_price入参的时候要参考对应品种的价格变动规则,如limit_price不做入参则会以交易的行情快照最新价或者回测的分钟最新价进行报单;
根据交易所规则,每天结束时会取消所有未完成交易;
def initialize(context):
g.security = ['IF1712.CCFX', 'CU1806.XSGE']
set_universe(g.security)
def handle_data(context, data):
#买入开仓
buy_open('IF1712.CCFX', 1)
#买入开仓(限定点数为52220)
buy_open('CU1806.XSGE', 1, limit_price=52220)
2. 卖出平仓
def initialize(context):
g.security = ['IF1712.CCFX', 'CU1806.XSGE']
set_universe(g.security)
def handle_data(context, data):
#卖出平仓
sell_close('IF1712.CCFX', 1)
#卖出平今仓(限定点数为52220)
sell_close ('CU1806.XSGE', 1, limit_price=52220, close_today=True)
#卖出平仓(限定点数为52220)
sell_close ('CU1806.XSGE', 1, limit_price=52220)
3. 获取合约信息
get_instruments- 获取合约信息
get_instruments(contract)
返回
FutureParams对象,主要返回的字段为:
contract_code -- 合约代码,str类型;
contract_name -- 合约名称,str类型;
exchange -- 交易所:大商所、郑商所、上期所、中金所,str类型;
trade_unit -- 交易单位,int类型;
contract_multiplier -- 合约乘数,float类型;
delivery_date -- 交割日期,str类型;
listing_date -- 上市日期,str类型;
trade_code -- 交易代码,str类型;
margin_rate -- 保证金比例,float类型;
代码示例:
def initialize(context):
g.security = ["CU2112.XSGE", "IF2112.CCFX"]
set_universe(g.security)
def before_trading_start(context, data):
# 获取股票池代码合约信息
for security in g.security:
info = get_instruments(security)
log.info(info)
def handle_data(context, data):
pass 查看全部
新建策略的时候选择:期货即可。
1. 买入开仓
不同期货品种每一跳的价格变动都不一样,limit_price入参的时候要参考对应品种的价格变动规则,如limit_price不做入参则会以交易的行情快照最新价或者回测的分钟最新价进行报单;
根据交易所规则,每天结束时会取消所有未完成交易;
def initialize(context):
g.security = ['IF1712.CCFX', 'CU1806.XSGE']
set_universe(g.security)
def handle_data(context, data):
#买入开仓
buy_open('IF1712.CCFX', 1)
#买入开仓(限定点数为52220)
buy_open('CU1806.XSGE', 1, limit_price=52220)
2. 卖出平仓
def initialize(context):
g.security = ['IF1712.CCFX', 'CU1806.XSGE']
set_universe(g.security)
def handle_data(context, data):
#卖出平仓
sell_close('IF1712.CCFX', 1)
#卖出平今仓(限定点数为52220)
sell_close ('CU1806.XSGE', 1, limit_price=52220, close_today=True)
#卖出平仓(限定点数为52220)
sell_close ('CU1806.XSGE', 1, limit_price=52220)
3. 获取合约信息
get_instruments- 获取合约信息
get_instruments(contract)
返回
FutureParams对象,主要返回的字段为:
contract_code -- 合约代码,str类型;
contract_name -- 合约名称,str类型;
exchange -- 交易所:大商所、郑商所、上期所、中金所,str类型;
trade_unit -- 交易单位,int类型;
contract_multiplier -- 合约乘数,float类型;
delivery_date -- 交割日期,str类型;
listing_date -- 上市日期,str类型;
trade_code -- 交易代码,str类型;
margin_rate -- 保证金比例,float类型;
代码示例:
def initialize(context):
g.security = ["CU2112.XSGE", "IF2112.CCFX"]
set_universe(g.security)
def before_trading_start(context, data):
# 获取股票池代码合约信息
for security in g.security:
info = get_instruments(security)
log.info(info)
def handle_data(context, data):
pass
ptrade获取分时成交数据-LEVEL2数据逐笔数据
李魔佛 发表了文章 • 0 个评论 • 2536 次浏览 • 2023-02-04 12:27
中提供了获取分时成交的数据。
使用场景
该函数在交易模块可用
接口说明
该接口用于获取当日分时成交行情数据。
注意事项:
1、沪深市场都有分时成交数据;
2、分时成交数据需开通level2行情才有数据推送,否则无数据返回;
返回字段:
返回
返回一个OrderedDict对象,包含每只代码的分时成交行情数据。(OrderedDict([(),()...]))
返回结果字段介绍:
time_stamp: 时间戳毫秒级(str:numpy.int64);
hq_px: 价格(str:numpy.float64);
hq_px64: 价格(str:numpy.int64)(行情暂不支持,返回均为0);
business_amount: 成交数量(str:numpy.int64);
business_balance: 成交金额(str:numpy.int64);
business_count: 成交笔数(str:numpy.int64);
business_direction: 成交方向(0:卖,1:买,2:平盘)(str:numpy.int64);
amount: 持仓量(str:numpy.int64)(行情暂不支持,返回均为0);
start_index: 分笔关联的逐笔开始序号(str:numpy.int64)(行情暂不支持,返回均为0);
end_index: 分笔关联的逐笔结束序号(str:numpy.int64)(行情暂不支持,返回均为0);
示例代码:
def initialize(context):
g.security = '000001.SZ'
set_universe(g.security)
def handle_data(context, data):
#获取000001.SZ的分时成交数据
direction_data = get_tick_direction(g.security)
log.info(direction_data)
#获取指定股票列表分时成交数据
direction_data = get_tick_direction(['000002.SZ','000032.SZ'])
log.info(direction_data)
#获取成交量
business_amount = direction_data['000002.SZ']['business_amount']
log.info('分时成交的成交量为:%s' % business_amount)
不过在handle_bar中或者tick_data中,实际行情推送最快也要3s,所以拿到的level2的是切片数据,即使拿到很多数据,可是行情获取时间间隔还是3s, 无法做到和qmt那样的level2逐笔订阅驱动。还有level2数据需要收费。ptrade目前常用的几个券商都不支持level2的。
目前有万一免五的qmt ptrade量化交易接口的券商吗?
查看全部
中提供了获取分时成交的数据。
使用场景
该函数在交易模块可用
接口说明
该接口用于获取当日分时成交行情数据。
注意事项:
1、沪深市场都有分时成交数据;
2、分时成交数据需开通level2行情才有数据推送,否则无数据返回;
返回字段:
返回
返回一个OrderedDict对象,包含每只代码的分时成交行情数据。(OrderedDict([(),()...]))
返回结果字段介绍:
time_stamp: 时间戳毫秒级(str:numpy.int64);
hq_px: 价格(str:numpy.float64);
hq_px64: 价格(str:numpy.int64)(行情暂不支持,返回均为0);
business_amount: 成交数量(str:numpy.int64);
business_balance: 成交金额(str:numpy.int64);
business_count: 成交笔数(str:numpy.int64);
business_direction: 成交方向(0:卖,1:买,2:平盘)(str:numpy.int64);
amount: 持仓量(str:numpy.int64)(行情暂不支持,返回均为0);
start_index: 分笔关联的逐笔开始序号(str:numpy.int64)(行情暂不支持,返回均为0);
end_index: 分笔关联的逐笔结束序号(str:numpy.int64)(行情暂不支持,返回均为0);
示例代码:
def initialize(context):
g.security = '000001.SZ'
set_universe(g.security)
def handle_data(context, data):
#获取000001.SZ的分时成交数据
direction_data = get_tick_direction(g.security)
log.info(direction_data)
#获取指定股票列表分时成交数据
direction_data = get_tick_direction(['000002.SZ','000032.SZ'])
log.info(direction_data)
#获取成交量
business_amount = direction_data['000002.SZ']['business_amount']
log.info('分时成交的成交量为:%s' % business_amount)
不过在handle_bar中或者tick_data中,实际行情推送最快也要3s,所以拿到的level2的是切片数据,即使拿到很多数据,可是行情获取时间间隔还是3s, 无法做到和qmt那样的level2逐笔订阅驱动。还有level2数据需要收费。ptrade目前常用的几个券商都不支持level2的。
目前有万一免五的qmt ptrade量化交易接口的券商吗?
ptrade移除当前ST股
李魔佛 发表了文章 • 0 个评论 • 1183 次浏览 • 2023-02-04 12:14
下面代码移除创业板,科创板还有当前被ST的股票。也可以任意组合,移除。
可以参考上一篇:http://30daydo.com/article/44569
def remove_st_stock(all_stock_list):
st_dict = get_stock_status(all_stock_list, query_type='ST', query_date=None)
st_list = []
for k, v in st_dict.items():
if v:
st_list.append(k)
return st_list
MARKET_DICT = {0: '科创板', 1: '创业板', }
IGNORE_MARKET = [0, 1]
def all_codes_in_market():
all_stock_set = set(get_Ashares(date=None))
for ignore_code in IGNORE_MARKET:
market = MARKET_DICT.get(ignore_code)
if market == '科创板':
all_stock_set = all_stock_set - set(filter(lambda x: x.startswith('68'), all_stock_set))
if market == '创业板':
all_stock_set = all_stock_set - set(filter(lambda x: x.startswith('3'), all_stock_set))
return all_stock_set
def create_target(context):
all_stock_set = all_codes_in_market()
st_list = remove_st_stock(list(all_stock_set))
all_stock_set = all_stock_set - set(st_list)
return all_stock_set
调用方式:
stock_target = create_target(None)
这样返回的股票就被排除了科创板,创业板,ST股票。
查看全部
下面代码移除创业板,科创板还有当前被ST的股票。也可以任意组合,移除。
可以参考上一篇:http://30daydo.com/article/44569
def remove_st_stock(all_stock_list):
st_dict = get_stock_status(all_stock_list, query_type='ST', query_date=None)
st_list = []
for k, v in st_dict.items():
if v:
st_list.append(k)
return st_list
MARKET_DICT = {0: '科创板', 1: '创业板', }
IGNORE_MARKET = [0, 1]
def all_codes_in_market():
all_stock_set = set(get_Ashares(date=None))
for ignore_code in IGNORE_MARKET:
market = MARKET_DICT.get(ignore_code)
if market == '科创板':
all_stock_set = all_stock_set - set(filter(lambda x: x.startswith('68'), all_stock_set))
if market == '创业板':
all_stock_set = all_stock_set - set(filter(lambda x: x.startswith('3'), all_stock_set))
return all_stock_set
def create_target(context):
all_stock_set = all_codes_in_market()
st_list = remove_st_stock(list(all_stock_set))
all_stock_set = all_stock_set - set(st_list)
return all_stock_set
调用方式:
stock_target = create_target(None)
这样返回的股票就被排除了科创板,创业板,ST股票。
ptrade排除A股创业板,科创板的股票
李魔佛 发表了文章 • 0 个评论 • 1488 次浏览 • 2023-02-04 10:48
MARKET_DICT = {0: '科创板', 1: '创业板', }
IGNORE_MARKET = [0, 1]
def create_target(context):
all_stock_set = set(get_Ashares(date=None))
for ignore_code in IGNORE_MARKET:
market = MARKET_DICT.get(ignore_code)
if market == '科创板':
all_stock_set = all_stock_set - set(filter(lambda x:x.startswith('68'),all_stock_set))
if market == '创业板':
all_stock_set = all_stock_set - set(filter(lambda x:x.startswith('3'),all_stock_set))
return all_stock_set
返回的all_stock_set就是排除了创业板,科创板的股票列表。
ptrade接口文档:http://ptradeapi.com
查看全部
MARKET_DICT = {0: '科创板', 1: '创业板', }
IGNORE_MARKET = [0, 1]
def create_target(context):
all_stock_set = set(get_Ashares(date=None))
for ignore_code in IGNORE_MARKET:
market = MARKET_DICT.get(ignore_code)
if market == '科创板':
all_stock_set = all_stock_set - set(filter(lambda x:x.startswith('68'),all_stock_set))
if market == '创业板':
all_stock_set = all_stock_set - set(filter(lambda x:x.startswith('3'),all_stock_set))
return all_stock_set
返回的all_stock_set就是排除了创业板,科创板的股票列表。
ptrade接口文档:http://ptradeapi.com
ptrade如何获取某天的全市场股票代码?
李魔佛 发表了文章 • 0 个评论 • 1724 次浏览 • 2023-02-04 03:19
在ptrade的接口文档http://ptradeapi.com 里面可以查到,
get_Ashares – 获取指定日期A股代码列表
get_Ashares(date=None)
如果不指定日期,则获取单天的A股所有股票的股票代码。
如果在回测的时候,获取的是回测单天额所有股票代码; 如果指定日期,则获取的是指定日期的所有A股股票代码。
get_Ashares – 获取指定日期A股代码列表get_Ashares(date=None)使用场景
该函数在研究、回测、交易模块可用
接口说明
该接口用于获取指定日期沪深市场的所有A股代码列表
注意事项:
1、在回测中,date不入参默认取回测日期,默认值会随着回测日期变化而变化,等于context.current_dt
2、在研究中,date不入参默认取当天日期
3、在交易中,date不入参默认取当天日期
参数
date:格式为YYYYmmdd
返回
股票代码列表,list类型(list[str,...])
让我们来测试一下:
拿到的股票个数是4912个。
然后我对着通达信的所有A股数据比较了一下,get_Ashares 获取的数据不包括北交所,新三板创新创业的股票,也就是不包括4和8开头的股票数据,但包含沪深主板,创业板,科创板的股票数据。
查看全部
在ptrade的接口文档http://ptradeapi.com 里面可以查到,
get_Ashares – 获取指定日期A股代码列表
get_Ashares(date=None)
如果不指定日期,则获取单天的A股所有股票的股票代码。
如果在回测的时候,获取的是回测单天额所有股票代码; 如果指定日期,则获取的是指定日期的所有A股股票代码。
get_Ashares – 获取指定日期A股代码列表get_Ashares(date=None)使用场景
该函数在研究、回测、交易模块可用
接口说明
该接口用于获取指定日期沪深市场的所有A股代码列表
注意事项:
1、在回测中,date不入参默认取回测日期,默认值会随着回测日期变化而变化,等于context.current_dt
2、在研究中,date不入参默认取当天日期
3、在交易中,date不入参默认取当天日期
参数
date:格式为YYYYmmdd
返回
股票代码列表,list类型(list[str,...])
让我们来测试一下:
拿到的股票个数是4912个。
然后我对着通达信的所有A股数据比较了一下,get_Ashares 获取的数据不包括北交所,新三板创新创业的股票,也就是不包括4和8开头的股票数据,但包含沪深主板,创业板,科创板的股票数据。
ptrade生产环境在开盘交易时间无法回测,有什么办法可以解决?
李魔佛 发表了文章 • 0 个评论 • 1847 次浏览 • 2023-01-06 12:07
在正式环境下,多个券商的ptrade都无法进行回测。
但也有办法解决。 就是使用ptrade的仿真客户端。 仿真客户端并连接实盘交易。所以没有这个时间的限制。
笔者在几个券商的上的仿真客户端都可以在交易时间使用回测功能。
可能部分仿真客户端需要申请才给开通的。
查看全部
ptrade回测结束后执行某个函数,比如保存回测结果
李魔佛 发表了文章 • 0 个评论 • 1162 次浏览 • 2023-01-01 17:56
官方文档只提供一个每天盘后执行的函数,没有函数可以在回测结束后,固定执行某些操作。
比如我回测过程保存的历史交易记录,收益率等,要如何保存? 虽然可以在回测的时候,每个交易日保存一次。
但是这样就需要在回测的时候按照天打开文件,盘后写入一次。 使用一个全局对象操作,显得很啰嗦。
那么有没有办法可以做在回测结束后一次性 保存操作呢?
答案是有的。也很简单。 适用于ptrade,qmt。
https://t.zsxq.com/09yigu5dy
查看全部
官方文档只提供一个每天盘后执行的函数,没有函数可以在回测结束后,固定执行某些操作。
比如我回测过程保存的历史交易记录,收益率等,要如何保存? 虽然可以在回测的时候,每个交易日保存一次。
但是这样就需要在回测的时候按照天打开文件,盘后写入一次。 使用一个全局对象操作,显得很啰嗦。
那么有没有办法可以做在回测结束后一次性 保存操作呢?
答案是有的。也很简单。 适用于ptrade,qmt。
https://t.zsxq.com/09yigu5dy
ptrade回测 获取回测当天的分时数据
李魔佛 发表了文章 • 0 个评论 • 1442 次浏览 • 2023-01-01 15:45
ptrade api的文档第3条表明,
3、数据返回内容不包括当天数据。
也就是用get_price是拿不到回测当天的数据。
比如下面的例子:
def initialize(context):
# 初始化策略
run_daily(context, execute, '09:36')
def handle_data(context, data):
pass
def execute(context):
current = context.blotter.current_dt.strftime('%Y-%m-%d')
log.info(current)
security='128025.SZ'
df = get_price(security, start_date=None, end_date=None, frequency='1m', fields=None, fq=None, count=10)
log.info(df)
返回的数据:
2023-01-01 15:31:21 开始运行回测, 策略名称: 四叶草-指定时间价格
2022-12-01 09:36:00 - INFO - 2022-12-01
2022-12-01 09:36:00 - INFO - open high low close volume \
2022-11-30 14:51:00 276.510 276.560 274.626 275.500 217510.0
2022-11-30 14:52:00 275.240 278.638 275.205 278.398 363820.0
2022-11-30 14:53:00 278.485 278.895 276.660 277.479 307570.0
2022-11-30 14:54:00 277.337 278.440 276.660 278.440 239370.0
2022-11-30 14:55:00 279.900 287.113 279.900 287.113 853170.0
2022-11-30 14:56:00 287.113 288.526 286.533 288.125 581860.0
2022-11-30 14:57:00 288.126 291.800 287.909 291.361 523580.0
2022-11-30 14:58:00 291.500 292.980 291.500 291.800 36480.0
2022-11-30 14:59:00 291.800 291.800 291.800 291.800 0.0
2022-11-30 15:00:00 292.510 292.510 292.510 292.510 421398.0
回测日期是2022-12-01日,每天09:36运行,那10根数据。
但返回的数据是昨天的收盘前的10根分时数据。并非当天9:36分开始拿10根bar。
如果把日期数据也固定,
df = get_price(security, start_date='2022-12-01', end_date=None, frequency='1m', fields=None, fq=None, count=10)
实际拿到的数据是空的,也就是无法拿到当天的数据。
正确的用法:
def initialize(context):
# 初始化策略
run_daily(context, execute, '09:36')
def handle_data(context, data):
pass
def execute(context):
current = context.blotter.current_dt.strftime('%Y-%m-%d')
log.info(current)
security='128025.SZ'
count=6
df=get_history(count, frequency='1m', field='close', security_list=security, fq=None, include=False, fill='nan')
log.info(df)
返回的数据:
欢迎关注公众号 查看全部
ptrade api的文档第3条表明,
3、数据返回内容不包括当天数据。
也就是用get_price是拿不到回测当天的数据。
比如下面的例子:
def initialize(context):
# 初始化策略
run_daily(context, execute, '09:36')
def handle_data(context, data):
pass
def execute(context):
current = context.blotter.current_dt.strftime('%Y-%m-%d')
log.info(current)
security='128025.SZ'
df = get_price(security, start_date=None, end_date=None, frequency='1m', fields=None, fq=None, count=10)
log.info(df)
返回的数据:
2023-01-01 15:31:21 开始运行回测, 策略名称: 四叶草-指定时间价格
2022-12-01 09:36:00 - INFO - 2022-12-01
2022-12-01 09:36:00 - INFO - open high low close volume \
2022-11-30 14:51:00 276.510 276.560 274.626 275.500 217510.0
2022-11-30 14:52:00 275.240 278.638 275.205 278.398 363820.0
2022-11-30 14:53:00 278.485 278.895 276.660 277.479 307570.0
2022-11-30 14:54:00 277.337 278.440 276.660 278.440 239370.0
2022-11-30 14:55:00 279.900 287.113 279.900 287.113 853170.0
2022-11-30 14:56:00 287.113 288.526 286.533 288.125 581860.0
2022-11-30 14:57:00 288.126 291.800 287.909 291.361 523580.0
2022-11-30 14:58:00 291.500 292.980 291.500 291.800 36480.0
2022-11-30 14:59:00 291.800 291.800 291.800 291.800 0.0
2022-11-30 15:00:00 292.510 292.510 292.510 292.510 421398.0
回测日期是2022-12-01日,每天09:36运行,那10根数据。
但返回的数据是昨天的收盘前的10根分时数据。并非当天9:36分开始拿10根bar。
如果把日期数据也固定,
df = get_price(security, start_date='2022-12-01', end_date=None, frequency='1m', fields=None, fq=None, count=10)
实际拿到的数据是空的,也就是无法拿到当天的数据。
正确的用法:
def initialize(context):
# 初始化策略
run_daily(context, execute, '09:36')
def handle_data(context, data):
pass
def execute(context):
current = context.blotter.current_dt.strftime('%Y-%m-%d')
log.info(current)
security='128025.SZ'
count=6
df=get_history(count, frequency='1m', field='close', security_list=security, fq=None, include=False, fill='nan')
log.info(df)
返回的数据:
欢迎关注公众号
Ptrade获取可转债强赎数据
李魔佛 发表了文章 • 0 个评论 • 1752 次浏览 • 2022-12-21 15:50
所以在可转债的策略里面,把强赎的转债排除掉,是一个不错的因子。
但内置的ptrade接口数据并无提供任何转债相关的数据。
不过笔者这里提供了一个自研的数据接口。
http://ptradeapi.com/#%E5%8F%AF%E8%BD%AC%E5%80%BA%E5%BC%BA%E8%B5%8E%E4%B8%8E%E6%95%B0%E6%97%A5%E5%AD%90
方便在ptrade里面调用。
查看全部
所以在可转债的策略里面,把强赎的转债排除掉,是一个不错的因子。
但内置的ptrade接口数据并无提供任何转债相关的数据。
不过笔者这里提供了一个自研的数据接口。
http://ptradeapi.com/#%E5%8F%AF%E8%BD%AC%E5%80%BA%E5%BC%BA%E8%B5%8E%E4%B8%8E%E6%95%B0%E6%97%A5%E5%AD%90
方便在ptrade里面调用。
Ptrade API 文档
李魔佛 发表了文章 • 0 个评论 • 1847 次浏览 • 2022-12-18 20:18
Ptrade多策略如何编写?
李魔佛 发表了文章 • 0 个评论 • 1755 次浏览 • 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存储
点击查看大图
这样存储有一个好处,就是如果你想中途修改策略持仓,可以直接修改这个文本文件。比如你的策略不小心买入了一只强赎的转债,你想手动卖掉,那么很简单,你只要在这个json文件里面把对应的持仓删除,再把他的市值加到可用资金里面去即可。 用法是相当灵活。
需要完整代码或者指导的朋友可以关注下面公众号和知识星球。
Ptrade拆单 分批下单 python代码 可转债/股票
李魔佛 发表了文章 • 0 个评论 • 1788 次浏览 • 2022-11-10 00:35
所以如果资金量大,就需要拆单操作。
交易代码部分,如果设置 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张,都是有可能的,这也足以说明,可转债的流动性问题,滑点是很难被忽略的。
当然,这是轮动调仓的时候,金额较大的情况下拆单。如果高频交易下就不能这么操作了。
具体怎么写,可以关注个人公众号与知识星球。
知识星球原文:
如需要代写量化策略实盘代码,可以到个人公众号【可转债量化分析】后台留言。
查看全部
所以如果资金量大,就需要拆单操作。
交易代码部分,如果设置 SPLIT_ORDER_ENABLE = True 即进行拆单操作:
在交易部分:(省略部分不相关代码)
if SPLIT_ORDER_ENABLE:BUY_DIRECTION 为买,值是1,一个常量
split_order(code, BUY_DIRECTION, amount)
else:
buy_price = round(buy_price, 3)
ret = order(code, amount, limit_price=buy_price)
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张,都是有可能的,这也足以说明,可转债的流动性问题,滑点是很难被忽略的。
当然,这是轮动调仓的时候,金额较大的情况下拆单。如果高频交易下就不能这么操作了。
具体怎么写,可以关注个人公众号与知识星球。
知识星球原文:
如需要代写量化策略实盘代码,可以到个人公众号【可转债量化分析】后台留言。
Ptrade里写策略坑比较多的地方(一)
李魔佛 发表了文章 • 0 个评论 • 1862 次浏览 • 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
类似这样的问题在很多函数里面都有。
2. 部分成交 的主推函数
如果一个订单,部分成交,会先触发部分成交主推; 然后最后一个部分成交,反而会触发全部成交主推。
细想,似乎也是合理的,只是,你在全部成交里面返回的成交数量,实际只是最后一次部分成交的量。
3. 想到再写
更多更新 可以参看个人知识星球或者公众号。
Ptrade量化交易之 拆单买入卖出操作
李魔佛 发表了文章 • 0 个评论 • 1982 次浏览 • 2022-09-30 16:20
注:代码里面针对的是可转债交易,股票的话把这一行:
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实盘代码,欢迎关注个人知识星球 查看全部
注:代码里面针对的是可转债交易,股票的话把这一行:
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挂单后撤单函数 实现
李魔佛 发表了文章 • 0 个评论 • 1772 次浏览 • 2022-09-29 16:40
所以也需要有撤单,重新挂的动作。
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而不自知。等到实盘了用真金白银 得到了教训,还不如早期跟一两个人有经验的人学习,甚至找个代写代码就好了。
当然,能力超强,精力旺盛的大神就无视了,这个人折腾起来什么都可以搞得有模有样。
查看全部
所以也需要有撤单,重新挂的动作。
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在一个循环事件里 能否不断获取股票实时价格?
李魔佛 发表了文章 • 0 个评论 • 1741 次浏览 • 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可以看到价格也是基本没个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,双低 低价 低溢价 规模多因子轮动】