金字塔决策交易系统

标题: 求技术人员帮忙写策略 [打印本页]

作者: 半生瓜    时间: 2023-8-7 10:33
标题: 求技术人员帮忙写策略
交易策略:
交易品种数量N
5日均线突破40日均线,同时9日新高后开多。(收盘前2点58分钟执行)
开仓数量=总资金*0.3/N/3/每手乘数/ATR
5日均线跌破40日均线,同时9日新低后开空。(收盘前2点58分钟执行
开仓数量=总资金*0.3/N/3/每手乘数/ATR
开仓后最高点回落3倍ATR止损止盈
要求:
1.需要公用总资金回测
2.一共有6个参数,5日均线,40日均线,9日新高,0.3的总资金止损,单品种最高点回落3倍ATR,交易品种数量N,这6个参数需要列出来,方便我到时候参数优化。
3.如果回测不能够实现2点58分下单,那就用收盘价下单。






作者: 技术009    时间: 2023-8-7 13:20
"开仓后最高点回落3倍ATR止损止盈" ATR是一个动态的值。你这个回落三倍ATR是以什么位置的atr来计算的?

目前图表模型不支持多品种公用资金的回测方式。
作者: 半生瓜    时间: 2023-8-7 13:23
技术009 发表于 2023-8-7 13:20
"开仓后最高点回落3倍ATR止损止盈" ATR是一个动态的值。你这个回落三倍ATR是以什么位置的atr来计算的?

...

当日算前14日的ATR,图表不支持,我用专业版测试账号先回测一下,麻烦老师帮忙写一下吧。
作者: 技术009    时间: 2023-8-7 13:26
前14日的ATR? 你意思你这里atr是指获取前面历史的一个静态atr值吗。
作者: 半生瓜    时间: 2023-8-7 13:32
技术009 发表于 2023-8-7 13:26
前14日的ATR? 你意思你这里atr是指获取前面历史的一个静态atr值吗。

是的,获取历史数据,但是是动态的。每一天获取的前面14日的真实波动幅度总和,然后再除以14,求出14日的ATR。
作者: 技术009    时间: 2023-8-7 15:56
[PEL] 复制代码
input:n1(5,1,500,1),n2(40,1,1000,1),m(9,2,1000,1),q(0.3,0.01,1,0.01),y(3,1,100,1),n(6,1,300,1);
globalvariable:at:=0;//记录开仓前的总资产
globalvariable:maxp:=0;//开仓后最高价或者最低价

ma5:ma(c,n1);
ma40:ma(c,n2);


kd:ma5>ma40 and h=hhv(h,m);
kk:ma40<ma5 and l=llv(l,m);


atr:"atr.atr"(14);
ss:=tasset*0.3/(n*3*multiplier*atr);


tcd:time>=185800;

//实际运行中这里建议换成dynainfo(  7) 获取最新值
最新价:c;

多持仓:tbuyholdingex('','',2);
空持仓:tsellholdingex('','',2);

多均价:tavgenterpriceex2('','',0);
空均价:tavgenterpriceex2('','',1);

多可用:tbuyholdingex('','',1);
空可用:tsellholdingex('','',1);



if kd and 多可用=0 and  tcd then
begin
tbuy(1,ss,mkt);
at:=tasset;
end

if kk and 空可用=0  and tcd then
begin
tbuyshort(1,ss,mkt);
at:=tasset;
end



多均价:=tavgenterpriceex2('','',0);
//持仓后,更新开多后的最高价
if tbuyholdingex('','',1)<>0 then
begin
if maxp=0 then maxp:=多均价;
if 最新价>maxp then begin
maxp:=最新价;
end
end


空均价:=tavgenterpriceex2('','',1);
//持仓后,更新开空后的最低价
if tsellholdingex('','',1)<>0  then
begin
if  maxp=0 then maxp:=空均价;
if 最新价<maxp then
begin
maxp:=最新价;         
end

end

//从盈利最高价回撤 y倍atr平仓
if (maxp-最新价)>=y*atr and 多可用>0 then
begin
tsell(1,0,mkt);
maxp:=0;       
end


if (最新价-maxp)>=y*atr and 空可用>0 then
begin
tsellshort(1,0,mkt);
maxp:=0;       
end

//总资产亏损30% 平仓。以开仓时候的资产总值作为基准值来计算浮亏百分百。
if  (at-tasset)/at>=q  and  (多可用>0 or 空可用>0)then
begin
tsell(多可用>0,0,mkt);
tsellshort(空可用>0,0,mkt);
maxp:=0;       
end


仅供参考,建议根据测试效果 自行做进一步调整。


作者: 半生瓜    时间: 2023-8-7 16:06
技术009 发表于 2023-8-7 15:56
[mw_shl_code=pel,true]input:n1(5,1,500,1),n2(40,1,1000,1),m(9,2,1000,1),q(0.3,0.01,1,0.01),y(3,1,100 ...

老师,辛苦你了,这个金子塔的语法也不懂,不知道符合不符合我的要求,能在每一行写个注释吗?另外总资金亏损30%不需要平仓。
我的0.3是总资金的止损,分配到比如十个品种,每个品种就是3%,然后根据ATR,止损宽度3倍,以及每手乘数算出开仓手数。
作者: 半生瓜    时间: 2023-8-7 16:28
另外这个怎么实现后台程序化回测,就是500万回测全品种,而不是每个品种100万。
作者: 技术009    时间: 2023-8-7 16:29
回测参考:https://www.weistock.com/docs/HE ... 9B%9E%E6%B5%8B.html

“另外总资金亏损30%不需要平仓。” 你可以把那部分代码直接注释掉即可。

作者: 半生瓜    时间: 2023-8-7 16:59
老师,这个回测出来后怎么什么都没有,策略写的有问题还是我回测过程有问题?
作者: 技术009    时间: 2023-8-7 17:12
你看下委托明细。应该是你手数算法有问题,导致手数太大,无法正常开仓了吧
作者: 半生瓜    时间: 2023-8-7 17:24
在哪里看委托明细呀?
作者: 技术009    时间: 2023-8-7 17:25
回测结果的界面。  或者你这样 你手工把下单手数改成1 你再回测看下。
作者: 半生瓜    时间: 2023-8-7 17:36
老师,你把下好的策略导入到软件试一下吧,看看哪里出问题了,应该还是代码的问题,我不太会弄。
作者: 技术009    时间: 2023-8-8 09:13
前面已经告诉你了,你下单手数的计算逻辑并不合理,导致开仓手数太大,无法产生实际有效的成交。

你如果不改你下单手数的计算逻辑,你这个模型永远都没有回测结果。我本地ss改成固定值1 就是可以正常回测的、
作者: 半生瓜    时间: 2023-8-8 10:23
昨天开平仓问题说的不太清楚,开仓的前提必须是该品种空仓,空仓后开仓(多空),开仓后平仓,平仓以后才能再开仓,不能出现开仓以后还未止损直接反手的情况。
然后开仓手数的逻辑我再说一下,就是总资金的30%作为总资金单次止损,除以品种数量(比如10个),每个品种分配3%的总资金作为单笔止损金额。然后单笔止损金额除以N倍ATR,除以每手乘数,算出来开仓手数。
举个例子:100万资金,10个品种,开仓今天的鸡蛋(14日的ATR为63),计算开仓手数。
100 0000*0.3=30 0000元         总资金的单次总止损
30 0000/10=30000                  单个品种的单笔止损金额
30000/3=10000                       单笔止损除以止损倍数算出一倍ATR波动的金额
10000/63=158.7                      一倍ATR波动的价格除以ATR 算出开仓的数量吨数
158/5=31.6                             开仓吨数除以每手乘数算出开仓手数(取整)
开仓手数=总资金*总止损系数/品种数量/止损宽度/ATR/每手乘数
现在我手动交易就是这么算的,因此开仓逻辑是没有问题的
作者: 技术009    时间: 2023-8-8 10:55
需要确认下几个细节:
1.你这里的atr 你取的是日线上的计算结果,是无论当前什么周期,都是以日线结果来计算,还是说如果你运行的是1分钟,就用1分钟的atr来算?
2.
回撤3倍atr 平仓。你应该是指价格回撤3倍atr吧。比如上面的鸡蛋,你开仓后最高价是 4360,回撤3倍atr就是:4360-3*63 。
另外这个atr也一直会因为价格变化 而变化的,你开仓时候atr可能是63,现在可能是另外一个值。所以这个回撤3倍atr,你是以当前最新的atr来算回撤,还是开仓时候的,这个是有很大差别的。比如你开仓时候是63,现在大概是26.     2种处理方式,你平仓价位完全不一样的。

麻烦确认下上面的这些细节呢。

作者: 半生瓜    时间: 2023-8-8 11:09
1.我只做日线,所以按日线的结果计算ATR。
2.无论开仓平仓,都是根据当日的ATR最新值计算的。开仓根据当日的ATR波动值计算开仓手数,平仓根据最高价反向走3倍当日ATR值平仓的。
另外能设置成收盘前5秒执行开平仓吗?
作者: 技术009    时间: 2023-8-8 11:15
针对2.

以最高价当时的atr。比如最高价时候,价格100,atr 10. 那就是回撤到70平仓。

还是说 只要满足:持仓期最高价-最新价>=3*当前最新atr 即平仓。

收盘前平仓可以实现。但是你这个开仓不也是快收盘时候操作的嘛?
作者: 半生瓜    时间: 2023-8-8 11:17
准确的说是收盘前5秒满足:持仓期最高价-收盘前5秒的价格>=3*当前最新atr 平仓。
作者: 半生瓜    时间: 2023-8-8 11:33
细节1.     持仓期最高价-收盘前5秒的价格>=3*当前最新atr 平仓,大于号前边得加上绝对值,如果是开空不加绝对值就是负数了。
细节2.     开仓手数要取整。
作者: 技术009    时间: 2023-8-8 14:07
本帖最后由 技术009 于 2023-8-8 14:14 编辑

[PEL] 复制代码
//n1,n2是均线参数;m是高点判定周期,默认值是9;
//q是总资金的百分百
//n是品种数,这里建议回测品种数 和这个参数保持一致。否则代码本身无法知道你回测的品种数量的。
//y是表示3倍ATR回撤的参数
input:n1(5,1,500,1),n2(40,1,1000,1),m(9,2,1000,1),q(0.3,0.01,1,0.01),y(3,1,100,1),n(10,1,300,1);


//均线1,均线2.
ma5:ma(c,n1);
ma40:ma(c,n2);

//5日均线上穿40日均线,注意这里不是大于 是上穿.
kd:cross(ma5,ma40) and h=hhv(h,m);
kk:cross(ma40,ma5) and l=llv(l,m);

//调用日线当前最新的ATR值
atr:"atr.atr#DAY"(14);
//进行手数的计算,不用取值,下单时候系统会自动处理的
ss:tasset*q/(n*3*multiplier*atr);


//时间条件。回测中无法精确控制时间,因此在回测时候直接按照日线收盘时候作为条件处理,实际运行中则判断当前时间是否大于等于145955;
//不建议在不活跃品种中使用这个时间控制
tcd:1;
//实际运行时候注释上面这句,把下面这句注释去掉
//tcd:CURRENTTIME>=145955;


//实际运行中这里建议换成dynainfo(  7) 获取最新值
最新价:c;

多可用:tbuyholdingex('','',1);
空可用:tsellholdingex('','',1);

净持仓:多可用+空可用;

//开多
if kd and 多可用=0 and 净持仓=0 and  tcd then
begin
tbuy(1,ss,mkt);
end

//开空
if kk and 空可用=0  and  净持仓=0 and tcd then
begin
tbuyshort(1,ss,mkt);
end


//表示当前品种持仓期间最高盈利价格的全局变量名称
strx:STKLABEL&'_maxp';

maxp:=EXTGBDATA(strx);//开仓后最高价或者最低价
多均价:=tavgenterpriceex2('','',0);
//持仓后,更新开多后的最高价
if tbuyholdingex('','',1)<>0 then
begin
if maxp=0 then maxp:=多均价;
if 最新价>maxp then begin
EXTGBDATASET(strx,最新价);        
end
end


空均价:=tavgenterpriceex2('','',1);
//持仓后,更新开空后的最低价
if tsellholdingex('','',1)<>0  then
begin
if  maxp=0 then maxp:=空均价;
if 最新价<maxp then
begin
EXTGBDATASET(strx,最新价);        
end

end

//从盈利最高价回撤 y倍atr平多仓
if (maxp-最新价)>=y*abs(atr) and 多可用>0 then
begin
tsell(1,0,mkt);
EXTGBDATASET(strx,0);         
end


if (最新价-maxp)>=y*abs(atr) and 空可用>0 then
begin
tsellshort(1,0,mkt);
EXTGBDATASET(strx,0);         
end





几个需要注意的点:

1.代码逻辑 在回测中无法完全体现,这个主要是回测机制缘故。收盘前5秒这个部分无法体现出来。
在日线上回测都是只能以日线结束时候的价格来操作。我在代码中tcd附近注释中有详细说明。
实际跑模拟或者实盘时候,务必按照注释说明 使用能在实际运行中奏效的代码。

2.下单条件里的均线条件是按照金叉死叉来的,不是均线大于和小于条件,这个有区别,所以额外说明下。按照金叉死叉 你这个开仓信号其实不会很多。  最高最低价是按照日线最高价是新高来的,不是按照你下单时候的价格是新高。比如今天日内最高价是100,收盘附近价格是80,只要100满足了新高 就开仓。  








3.资金控制这块,实际运行中和回测中恐怕都无法很好的控制。 主要你平仓必然是不同品种错位的,这样会释放资金的。 可能第一次开仓时候都是基于相同的总资金。但是后续就无法再按照这个初始资金来了。比如都是1号开仓的,4号时候出现第一个平仓的品种。其他品种还在持仓。这样的错位会让你的资金分配 逻辑变的复杂。   所以这块的逻辑可能还需要进一步调整,反正在回测上是无法很好的体现出效果来。

4.参数说明在注释中有简单说明,建议自行阅读下开头的注释部分。


设置相关的:
务必多补充些历史日线数据,否则你这个回测不出效果:
(, 下载次数: 268)