金字塔决策交易系统

用户名  找回密码
 

微信登录

微信扫一扫,快速登录

帖子
查看: 13445|回复: 6

常用代码模板

[复制链接]

37

主题

1万

帖子

6万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
wenarm
发表于 2021-10-26 10:00 | 显示全部楼层 |阅读模式
本帖最后由 技术009 于 2025-5-27 15:32 编辑

1#:
1.1 分钟级别提前下单模板
1.2 收盘前x分钟平仓(分钟级别)
1.3 开盘后X分钟移仓换月-后台程序化
1.4 量比
1.5 周期判断
1.6 距离最近一个收盘时间的间隔(夜盘或白盘)
1.7 白盘开盘价格
1.8 macd红绿柱面积
1.9 按照资金计算下单手数

2#
2.1 K线绘制
2.2 条件持续满足的周期数
2.3 判断是否有夜盘
2.4 本周第N个交易日
2.5 小数点位判断
2.6 股票涨跌停判断
2.7 开盘K定位
2.8 均线变色
2.9 过去N个K的收盘价,比当前收盘价大的次数
3#
3.1 EMA算法拆解
3.2 换手率
3.3 提取品种代码
3.4 计算账户持仓的品种数
3.5 最近N次金叉到死叉或者死叉到金叉 区间的最高价
3.6 最近N周期最高最低价连线
3.7 当前K是大周期K下的第多少个小周期K
3.8 LLT 算法的PEL实现
3.9 判断大周期K自身最高最低价出现的时间顺序
4#
4.1 盘口的内外盘字段算法
4.2 延迟下单(后台程序化)
4.3 获取当前合约成交量排名结果(返回对应的月份)
4.4 距离收盘K的周期数
4.5 获取指定时间段的高低价
4.6 主买主卖统计
4.7 昨日此时的数据
4.8 占位~
4.9 金叉死叉点的近似值
5#:
5.1 金叉区间最高值到死叉区间最低值连线
5.2  macd小引用大调用无未来的处理方式
5.3 N周期内成交量第M大的K对应的收盘价
5.4 仅使用当日数据计算MACD
6#:
6.1 分笔周期上判断空开、多开、双开、双平、空平、多平、多换、空换状态  
6.2 国内期货每个交易小节提前n秒平仓范例













金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

举报

21

主题

1万

帖子

1万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
FireScript
发表于 2022-6-17 15:05 | 显示全部楼层
本帖最后由 资深技术05 于 2025-7-9 10:55 编辑

分钟级别提前下单模板7.0之前的版本:
[PEL] 复制代码
1
2
3
4
abb:=(time0-timetot0(dynainfo(207))<=tq) or not(islastbar);//注意:6.23 以后版本,图表上使用islastbar函数,请勿勾选仅刷最后一根K
if abb then begin
    ......
end

7.0以后版本:
[PEL] 复制代码
1
2
3
4
5
tq:=10;//提前的秒数
abb:=remainingtime(time)<=tq or not(islastbar);//注意:6.23 以后版本,图表上使用islastbar函数,请勿勾选仅刷最后一根K
if abb then begin
     
end


收盘前x分钟平仓
说明:提前的时间必须在最后一根k的范围内。否则采用(time < xxxx and time > xxxx)的方式进行控制。
注意 这段代码仅适用于分钟级别的。即只能计算提前N分钟的情况。
[PEL] 复制代码
1
2
3
4
5
6
7
8
//abb2:timetot0(dynainfo(207))-timetot0(ref(time,1)),NODRAW;//K线已经进行过的时间
M1: T0TOTIME(TIMETOT0(CLOSETIME(0))-60); //收盘前1分钟
M15:T0TOTIME(TIMETOT0(CLOSETIME(0))-60*15); //收盘前15分钟
 
if (M1<=DYNAINFO(207) and ISLASTBAR) or (time=190000 and not(ISLASTBAR)) then begin //注意:6.23 以后版本,图表上使用islastbar函数,请勿勾选仅刷最后一根K
    sell(1,holding,MARKET);
    sellshort(1,holding,MARKET);
end


更普适的方式,包含全部收盘节点的方式:
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
n:=3;
m:=if(closetime(4)=closetime(0),4,3);
for i=0 to m do
begin
abb:=remainingtime(closetime(i)),nodraw;
if  (abb<n and abb>=0) and closetime(i)=time then
begin
DRAWTEXT(1,L,'收盘平仓',COLORRED,0);
收盘平多:sell(1,holding,market);
收盘平空:sellshort(1,holding,market);
break;
end
end


开盘后X分钟移仓换月(后台程序化可用)
说明:监控账户栏持仓。未对远期合约进行处理。
移步到改贴下:开盘后X分钟移仓换月-后台程序化 - BBS (weistock.com)

量比
1分钟上运行有效
[PEL] 复制代码
1
2
LB1:SUM(V,TODAYBAR)/(OPENMINUTES(time)-1)/(ref(sum(vol,SUMBARS(TODAYBAR=1,5)),TODAYBAR)/OPENMINUTES(CLOSETIME(0))/5);//期货
LB2:SUM(V,TODAYBAR)/(OPENMINUTES(time)-1)/(ref(sum(vol,SUMBARS(TODAYBAR=1,5)),TODAYBAR)/240/5);//股票




周期判断

[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
IF DATATYPE=0 THEN 分笔:1;
IF DATATYPE=1 THEN 1分钟:1;
IF DATATYPE=2 THEN 5分钟:5;
IF DATATYPE=3 THEN 15分钟:15;
IF DATATYPE=4 THEN 30分钟:30;
IF DATATYPE=5 THEN 60分钟:60;
IF DATATYPE=6 THEN 日:1;
IF DATATYPE=7 then 周:1;
IF DATATYPE=8 then 月:1;
IF DATATYPE=9 THEN 年:1;
IF DATATYPE=12 THEN 季度:1;
IF DATATYPE=15 THEN 半年:1;
IF DATATYPE=16 then 节气:1;
IF DATATYPE=17 THEN 3分钟:3;
IF DATATYPE=18 THEN 10分钟:10;
IF DATATYPE=10 THEN N日:DATATYPEMORE(0);
IF DATATYPE=11 THEN N小时:DATATYPEMORE(1);
IF DATATYPE=13 THEN N分钟:DATATYPEMORE(2);
IF DATATYPE=14 THEN N秒:DATATYPEMORE(3);
IF DATATYPE=19 THEN N笔:DATATYPEMORE(4);


距离最近一个收盘时间的间隔(夜盘或白盘
[PEL] 复制代码
1
2
3
day_CloseSecond:=TIMETOT0(CLOSETIME(0)) - TIMETOT0(time);
night_CloseSecond:=TIMETOT0(CLOSETIME(1)) - TIMETOT0(time);
CloseSecond:IF(TIMEZONECONVER(090000)<time,day_CloseSecond,night_CloseSecond),NODRAW;


白盘开盘价格

[PEL] 复制代码
1
2
aa:BARSSINCE2(TIMEZONECONVER(090000)<time,TODAYBAR);
bb:VALUEWHEN(AA=0 ,OPEN);


macd红绿柱面积
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//macd红绿柱面积计算
//可计算前面任意位置的macd区间面积
//先通过sumbars定位金叉/死叉的位置,然后利用ref回溯到当时的位置 使用sum计算区间累计的值
//需要计算红柱,则需要回事到死叉位置,因为死叉位置前面就是一个完整的红柱区间,反之依然
 
//不区分红绿柱,只计算面积,红绿需要额外判断
diff :=ema(close,12) - ema(close,26);
dea  :=ema(diff,9);
macd :=2*(diff-dea);
 
macd_jc:=cross(macd,0);//金叉
macd_sc:=cross(0,macd);//死叉
 
n1:=sumbars(macd_jc,1);//最近一次金叉距离当前K的周期跨度
n2:=sumbars(macd_sc,1);//最近一次死叉距离当前K的周期跨度
n3:=sumbars(macd_jc,2);//上上次金叉距离当前K的周期跨度
n4:=sumbars(macd_sc,2);//上上次死叉距离当前K的周期跨度
 
 
 
//上一个已经结束的完整红柱面积
上一个红柱面积和:=ref(sum(macd,n1),n2);
//上上一个已经结束的完整红柱面积
上上一个红柱面积和:=ref(sum(macd,n1),n4);
 
 
//上一个已经结束的完整绿柱面积
上一个绿柱面积和:=ref(sum(macd,n2),n1);
//上上一个已经结束的完整绿柱面积
上上一个绿柱面积和:=ref(sum(macd,n2),n3);
 
 
//指当前进行中的macd区间,可能是红柱区间 也可能是绿柱区间,根据累计的值可以 判断是红柱还是绿柱。
当前区间面积:sum(macd,min(n1,n2));

按照资金计算下单手数
[PEL] 复制代码
1
2
3
4
5
6
7
8
9
input:zj(10000,1,1000000,1);
下单资金量:=zj;
MarginRatio:=TACCOUNT(41);//多头保证金比率. 这个要把合约信息设置里面的费率设置正确,否则函数取到的值可能是不对的。
bzj:=Close*Multiplier*MarginRatio;//一手保证金占用
ss1:=Intpart(下单资金量/(bzj));//根据资金ZJ计算的开仓手数
 
//最终结果
//ss1可能会有计算出为0 的情况,而恰好为手数参数为0在函数中是满仓开的含义。因此再次处理下,当ss1为0情况下默认按下一手处理。
ss:if(ss1>0,ss1,1);
















金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

举报

21

主题

1万

帖子

1万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
FireScript
发表于 2022-6-17 15:37 | 显示全部楼层
本帖最后由 资深技术05 于 2025-1-6 14:54 编辑

K线绘制
系统没有直接绘制指定颜色K的函数。因此这里是 利用绘制柱体的函数分别绘制 K线柱体和上下影线的方式来处理。
[PEL] 复制代码
1
2
3
4
5
6
7
8
条件:cross(ma(c,5),ma(c,10));//满足条件时候绘制 指定颜色的K。用户可自行定义这里的条件。
 
 
cd:=c>=o;//区分阴阳线的,与上面条件无关
STICKLINE(条件 ,C,o,8,if(cd,1,0),COLORYELLOW);//绘制柱体
//绘制上下影线
STICKLINE(条件,if(not(cd),O,c),h,0,if(cd,1,0),COLORYELLOW);
STICKLINE(条件,if(cd,O,c),L,0,if(cd,1,0),COLORYELLOW);


条件持续满足的周期数
以换手率连续大于5%的持续周期为例,其他类似的如连续阳线周期数也是相同的处理方式:
[PEL] 复制代码
1
2
3
4
5
6
7
8
VARIABLE:mark:=0;//使用全局变量进行记录
INPUT:M(5,1,100,1);
换手率:(vol/(FINANCEex(60,0,0,'')/100))/100,NODRAW;
 
if 换手率>=5 then mark:=mark+1;//满足条件时候 全局变量累加
if 换手率<5 then mark:=0;//不满足条件时候 全局变量重置
 
连续周期数:mark;//换手率连续大于5的周期数

也可以使用SUMBARS 函数。
[PEL] 复制代码
1
连续周期数2:SUMBARS(换手率<5,1)-1;


2种方式的区别是,第一种更准确,但是代码多,统计的变量多的时候不方便。如果某种条件存在完全没满足过的情况,那么第二种方式是可能返回错误的,需要额外处理下的。
判断是否有夜盘
[PEL] 复制代码
1
cd:CLOSETIME(4)=CLOSETIME(0);//返回1表示有夜盘,否则没夜盘。仅限国内期货品种

本周第N个交易日

[PEL] 复制代码
1
2
WT:=CALLSTOCK('',vtDATE,7,0);
CT:BARSLAST(WT<>ref(wt,1))+1;

小数点位判断
[PEL] 复制代码
1
2
//注意 NUMTOSTR(MINDIFF,6) 这里的第二个参数 决定了能判断的小数点位的上限。
lo:STRLEN(STRTRIMRIGHT(NUMTOSTR(MINDIFF,6) , '0'))-2;//最小变动价位的小数点位数

股票涨跌停判断
含非主板,ST股 等情况的处理.需要特别留意的是,这里涨跌停的判断请勿在复权时候判断,复权的数据会引发一些偏差,导致判断错误
[PEL] 复制代码
1
2
3
4
5
6
7
8
9
d1:callstock('',vtclose,6,-1);//昨日收盘价
isst:strfind(stkname,'st',1);//是否st
iszb:(strleft(stklabel,2)='60' or strleft(stklabel,2)='00');//区分是否主板
ztv:if(isst,if(iszb,0.05,0.10),if(iszb,0.1,0.2));//创业板规则复杂,涨跌停数值不确定,最好不要应用在这上面。
 
//这里的处理是为了处理数学上计算的偏差
ztp:round((ztv+1)*round(d1/0.01))/100;//涨停价
dtp:round((-ztv+1)*round(d1/0.01))/100;//跌停价
zt:ztp=ROUNDS(c,2);//仅对主板a股以及科创,创业板有效。

开盘K定位
含夜盘,午盘,下午盘
[PEL] 复制代码
1
2
3
4
5
6
7
8
d:=STRLEFT(NUMTOSTR(time,0),2);//截取K线字符串前2位
cd1:(d='13' and not(ref(d='13',1)) and time>=130000 AND STRICMP(MARKETLABEL,'ZJ')<>0) or (TODAYBAR=1 and MARKETLABEL='ZJ');//白盘开盘位置
cd2:(d='17' and not(ref(d='17',1)) and  STRICMP(MARKETLABEL,'ZJ')<>0) or (MARKETLABEL='ZJ' and d='13' and not(ref(d='13',1)) ) ;//下午盘开盘位置判断
cd3:ref(time,1)=CLOSETIME(4) and time<130000;//夜盘开盘位置判断
 
 
DRAWICON(cd2 or cd1 or cd3,H,1);
//仅国内期货品种下有效。未考虑其他市场的有效性

另一套算法是这样处理的,这种方式没有进行字符串处理,某些情况下字符串处理可能会占用较多资源,这种情况下可以用下面这种方式:
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
MarketType:=VALUEWHEN(BARPOS=1,STRICMP(MARKETLABEL,'ZJ')=0);//返回1 表示是中金所
 
N0:=TODAYBAR;
cd:=CLOSETIME(4)=CLOSETIME(0);//返回1表示有夜盘,否则没夜盘。仅限国内期货品种
t1:if(cd,2,1);
 
cd0:=BARSSINCE2(time>010000,N0)+1;//夜盘开盘位置
cd1:=BARSSINCE2(time>OPENTIME(t1),N0)+1;//白盘开盘位置
cd2:=BARSSINCE2(time>OPENTIME(t1+2),N0)+1;//下午盘开盘位置               
 
if MarketType  then
begin
cd2:=BARSSINCE2(time>OPENTIME(2),N0)+1;//中金下午盘开盘位置                
end

均线变色
系统暂时没有可直接进行均线变色的函数,因此均线变色效果都是通过不同颜色的指标拼接而来的
有2种处理方式:
[PEL] 复制代码
1
2
3
ma1:=ma(c,10);
red:if(ma1>c or cross(c,ma1),c,drawnull),colorred;
green:if(ma1<c or cross(ma1,c),c,drawnull),colorgreen;


[PEL] 复制代码
1
2
3
4
5
ma3:ma(c,10);
ma4:=ma(c,20),;
 
PARTLINE(ma4>ma3 or cross(ma4,ma3) , ma4,COLORRED);
PARTLINE(ma4<ma3 or cross(ma3,ma4) , ma4,COLORGREEN);

过去N个K的收盘价,比当前收盘价大的次数
利用了PERCENTRANK来处理即可。具体原理看下函数说明里的例子大致就能理解了。
[PEL] 复制代码
1
2
INPUT:N(5,1,500,1);
Z:N-PERCENTRANK(C,N+1 ,C ,3)*N;













金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

举报

21

主题

1万

帖子

1万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
FireScript
发表于 2022-6-20 15:14 | 显示全部楼层
本帖最后由 技术009 于 2022-12-6 10:10 编辑

ema算法拆解
PEL里面自行构建EMA算法。拆解算法后,用户可以计算特定一段的EMA,比如只计算当日的EMA。
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
N:=10;//相当于ema的参数N
X:=C;//相当于ema参数x
 
VARIABLE:ema_:=0;
//ema
if BARPOS=1 then ema_:=X;
ema_:=if(BARPOS>1,(2*x+(N-1)*ema_)/(N+1),ema_);
ema_show:ema_;//最后结果
 
x2:ema(c,10);//对照这个校验即可

换手率
[PEL] 复制代码
1
换手率:(vol/(FINANCEex(60,0,0,'')/100))/100


提取品种代码
如AG12提取到 ‘AG’,Y00提取到 ‘Y’,在某些特定场景下会用到。比如拼接特定的超全局变量名称,方便进行和品种相关联的某些记录。

[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
STR:=STRTRIMRIGHT( STKLABEL, '0123456789');
 
//双年份合约,豆一和白糖虽然取消双年份,但是金字塔为保证老用户策略的正常操作,所以保持不变。因此依旧需要区分。
if STRCMP(STR,'AY')=0 or  STRCMP(STR,'BUY')=0 OR  STRCMP(STR,'SRY')=0 THEN BEGIN
 STR:=STRREPLACE(STR , 'Y','X' );
END
 
 
//区分处理原油和其他品种的连续代码
STR00:=IF(STRCMP(STR,'SC')=0,STRCAT(STR , '0000'),STRCAT( STR, '00'));
EXPLAIN( 1, STR00 );

计算账户持仓的品种数
THOLDCOUNT 本身是可以读取账户栏条数的,但是相同品种多空是分开。所以获取到的结果不是直接当前账户持仓的品种数量。
以下代码可以忽略多空差异,直接获得实际品种数目。(还可以结合上面的“提取品种代码”范例里的方式,把相同品种的不同月份的品种汇总,比如ag01,ag02合并,最终只统计出大的品种类别)
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
TH:=THOLDCOUNT('');
TEMP_STR:='';//保存品种代码集合
j:=0;
FOR I=1 TO TH do
BEGIN
HLABEL:= THOLDINDEXLABEL(I,'');
//判断当前代码集合中是否已经存在,不存在则进行统计。存在则不进入统计
if STRFIND( TEMP_STR, ','&HLABEL,1 )=0 then
begin
//将不在代码集合中的品种添加到代码集合中。
TEMP_STR:=STRCAT( TEMP_STR, ','&HLABEL );
j:=j+1;
end
end    
show:j;//j的值就是实际品种数量

最近N次金叉到死叉或者死叉到金叉 区间的最高价
找到最近的第N个金叉或者死叉位置,然后计算这个金叉到下一个死叉,或者这个死叉到下一个金叉的区间 对应的最高价。
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
input:p(26,20,100,8),s(12,5,40,4),m(9,2,60,6);//参数设置
 
INPUT:N(1,1,200,1);//参数N
DIFF := EMA(CLOSE,S) - EMA(CLOSE,P);
DEA  : =EMA(DIFF,M);
MACD1 : =2*(DIFF-DEA), COLORSTICK;
 
macdjc:=cross(diff,dea);//macd金叉
macdsc:=cross(dea,diff);
 
N1:=SUMBARS(macdjc,N);//最近N次金叉位置
N2:=SUMBARS(macdsc,N);//最近N次死叉位置
LEN:=SUMBARS(macdjc OR macdsc,1);
 
//最近第N个死叉到金叉的最高价
H1:REF(HHV(H,LEN),N1+1);
//最近第N个金叉到死叉的最高价
H2:REF(HHV(H,LEN),N2+1);


最近N周期最高最低价连线
指标只能在序列模式下运行;基于最新K位置的N周期的范围
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
INPUT:N(20,1,1000,1);
//该指标,请在序列模式下运行
Len:DATACOUNT-BARPOS,NODRAW;
 
Hv:refx(hhv(h,N),Len),NODRAW;
Lv:refx(llv(l,N),Len),NODRAW;
 
//因为不能确定高低点谁在前,谁在后
 
DRAWLINE(Len<=N-1 and h>=Hv,h ,Len<=N-1 and l<=Lv,l,1);
DRAWLINE(Len<=N-1 and l<=Lv,l ,Len<=N-1 and h>=Hv,h,1);
 
//说明:在N周期的高低点之间连线


当前K是大周期K下的第多少个小周期K
以调用60分钟周期为例
[PEL] 复制代码
1
2
3
4
5
//被调用的指标A
//t:time;
 
t:"A.t#MIN60";
result:BARSLAST(t<>ref(t,1))+1;//当前K是60分钟下的第几个5分钟K

LLT 算法的PEL实现
系统自带的PYTHON范例有LLT均线,以下是PEL实现方式。
[PEL] 复制代码
1
2
3
4
5
6
7
INPUT:N(30,1,500,1);
a:=2/(N+1);
a2:=pow(a,2);
VARIABLE:LLT:=C;
if BARPOS<=2 THEN  LLT:=C;
IF BARPOS>2 THEN LLT:=(a-(a2/4))*c  +   ((a2/2)*c[BARPOS-1])-(a-(3*a2/4))*c[BARPOS-2]+2*(1-a)*LLT- (POW((1-a),2))*LLT[BARPOS-2];
show:LLT;//输出结果

判断大周期K自身最高最低价出现的时间顺序
K线的高低价是一个统计结果,这个结果不包含在时间上他们出现的先后顺序。有时候在图表的大周期策略进行回测时候,这个问题会造成
回测的失真。比如在大周期进行止盈止损。这时候就应该判断下高低价的出现顺序以避免回测上的错误信号。
在大周期上可以通过调用在小周期上的统计结果来进行这个判断,涉及到多个指标调用。
大周期上运行的指标:
[PEL] 复制代码
1
cd:STKINDI('','M.cd',0,1,0);//直接调用在1分钟上的判断结果。返回1表示最高价后出现。

其他2个被调用的指标:
指标M,注意这个指标下涉及到对第三个指标的调用,对第三个指标的调用必须和需要运行的大周期一致:
[PEL] 复制代码
1
2
3
4
5
t:"AA.t#MIN60";//这里的调用必须和前面运行的大周期一致,否则无效!
len0:BARSLAST(t<>ref(t,1))+1;//当前K是60分钟下的第几个小周期K
llen:LLVBARS(l,len0);//最低价位置,(返回值是从0开始的)
hlen:HHVBARS(h,len0);//最高价位置
cd:hlen<llen;//根据这个判断高低价出现的顺序


指标AA:
[PEL] 复制代码
1
t:time;







金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

举报

21

主题

1万

帖子

1万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
FireScript
发表于 2022-6-28 10:52 | 显示全部楼层
本帖最后由 技术009 于 2025-5-27 15:31 编辑

盘口的内外盘字段的算法
以下代码只能在分笔周期上运行;这里没使用SUM函数执行累加的操作,是因为在这里用全局变量做累计计算效率更高,用sum可能会比较卡。
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
VARIABLE:外盘:=0,内盘:=0;
if TODAYBAR=1 then
begin
外盘:=0;
内盘:=0;
end
外盘:=外盘+BUYVOL;
内盘:=内盘+SELLVOL;
show1:外盘;
show2:内盘;

延迟下单(后台程序化)
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
//运行在活跃品种;固定时间间隔设置的小一点(比如1秒),如果设置的检测间隔较大会导致延迟下单出现时间误差
GLOBALVARIABLE:mark:=0;
buycd:1;//开仓条件
if buycd and mark=0 then //buycd必须是完整的开仓条件,包含开仓的所有判断因素在内。
begin
extgbdataset ('ti',currenttime);  //满足条件记录下现在的时间
mark:=1;
end
 
 
延迟:TIMETOT0(currenttime)  - TIMETOT0(extgbdata('ti'));
 
if 延迟>30 and mark=1 then
begin
tbuy(1,1,mkt);
mark:=0;
end


获取当前合约成交量排名结果(月份)
获取当前成交量排名第1-4(参数可调)的品种合约月份;默认按照合约有12个月份处理,少于12个月份的也可以处理;以下代码对双年份合约无效,可自行尝试调整兼容双年份合约
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//以下代码对非双年份合约有效(SC,AY,SRY,BUY等是双年份合约)
INPUT:N(41,12,1);//需要获取的排序位数,如N=4,默认最终获取前四名的数值结果。
VARIABLE:codeArr[12]:='',volArr[12]:=0,sortArr[N]:=0;//codeArr 品种代码数组;volArr 成交量数组;sortArr 排序结果数组,默认长度是4
STR:=STRTRIMRIGHT( STKLABEL, '0123456789');
 
 
//生成每个月的合约代码 并存入到数组中。这个只在第一个K上运行下。字符串相关操作比较消耗资源,没必要每个分笔来都进行一次。
if BARPOS=1 then
begin
for i=1 to 12 do //默认按照该品种有12个月份的合约。
begin
codeArr[i]:= STRCAT(str,STRRIGHT(NUMTOSTR(i/100,2),2));       
end
end
 
if ISLASTBAR then //将成交量填充到数组里面去. 这里可以自行调整,可以是成交量也可以是其他的什么值,自行选择处理即可。
begin
for j=1 to 12 do
begin
code:=codeArr[j];//code就是合约代码       
vox:=CALLSTOCK(code,vtvol,6,0);
volArr[j]:=if(vox>=0,vox,0);//不活跃品种,获取到的成交量可能是负值,这里处理下确保没有负值。
end               
end
 
 
if ISLASTBAR then //利用线性函数取最大成交量的索引(就是月份数值),每次取值完成后 可以把这个最大值重置为0,这样可以依次获取成交量最大的前几名了。
begin
for j=1 to N do
begin
index:=MFAMAX(volArr,12);
sortArr[j]:=index;
volArr[index]:=0;
 
end
end
 
x1:sortArr[1];//第一的月份
x2:sortArr[2];//第二的月份
x3:sortArr[3];
x4:sortArr[4];

距离收盘K的周期数
注意,不适用于 :1.周期跨中间的休盘时间 且没有选择“交易时间划分”不饱和周期。2.分笔级别周期
[PEL] 复制代码
1
2
3
4
t1:VALUEWHEN(time=CLOSETIME(0),timetot0(time)-timetot0(ref(time,1))),NODRAW;;//周期对应的秒数
t2:timetot0(CLOSETIME(0))-time0,NODRAW;//距离收盘K的跨度(秒)
 
Len:t2/t1;//收盘K位置输出值为0,前一个K为1,以此类推。

获取指定的时间段的高低价
如11:00-11:30 之间的最高最低价。
[PEL] 复制代码
1
2
3
4
m:=if(time=150000,1,0);
//十一点到十一点半之前的最高值。如果当前位置在11点之前,则取得昨日这个时间段的值。如果在11-11:30之间则取得11点到当前位置的最高价。
hh:VALUEWHEN(time<=153000 and time>=150000,hhv(h,BARSLAST(m=1)+1));
ll:VALUEWHEN(time<=153000 and time>=150000,llv(l,BARSLAST(m=1)+1));
如果时间段跨交易日,则需要修改下。如下午14:30到夜盘21:30 之间最高最低价。
[PEL] 复制代码
1
2
3
4
m:=if(time=183000,1,0);
//十一点到十一点半之前的最高值。如果当前位置在11点之前,则取得昨日这个时间段的值。如果在11-11:30之间则取得11点到当前位置的最高价。
hh:VALUEWHEN((time<=190000 and time>=183000) or time<13000,hhv(h,BARSLAST(m=1)+1));
ll:VALUEWHEN((time<=190000 and time>=183000) or time<13000,llv(l,BARSLAST(m=1)+1));

重点是用time函数描述出 这个连续区间就行了。
主买主卖统计
获取当前周期的主买和主卖。原理是 在分笔周期统计,当前周期跨周期调用结果。
注意,历史交易日上需要有历史分笔数据,指标才能正常运行;由于运行在分笔周期上,数据量较大,初始加载运行时候可能会卡顿,尤其是跨多个交易日时候。
被调用指标AX:
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
VARIABLE:by:=0,sy:=0;//这里用全局变量累加,因为不用全局变量累加,分笔周期数据量大直接用sum函数 这里会卡顿。
if TODAYBAR=1 then
begin
by:=0;
sy:=0;        
end
sy:=sy+BUYVOL;
by:=by+SELLVOL;
x1:sy;
x2:by;


运行的指标:
[PEL] 复制代码
1
2
3
4
5
by:STKINDI('','AX1.x1',0,0,0),NODRAW;
sy:STKINDI('','AX1.x2',0,0,0),NODRAW;
 
cby:if(TODAYBAR=1,by, by-ref(by,1)),NODRAW;//当前周期主买
csy:if(TODAYBAR=1,sy,sy-ref(sy,1)),NODRAW;//当前周期主卖

昨日此时的数据
新建一个指标作为被调用指标(lastday)。比如始终获取昨日当前时间的某个指标值,如收盘价。另外对期货品种因为存在特定节假日最后一个交易日没有夜盘等情况,以下代码是不适用的。

[PEL] 复制代码
1
2
dayLen:ref(TODAYBAR,TODAYBAR);//必须交易时间坐标,否则这个取值会有问题
lastV:ref(C,DAYLEN);
然后实际取值的指标:
[PEL] 复制代码
1
lastday:STKINDI('','lastday.lastV',2,1,0),NODRAW;//引用时候指定为交易时间坐标


金叉死叉点的近似值

K线图上指标线,本质是点图,只是出于图形效果需求,系统渲染成连续线条。所以是没有函数能取到线条交叉位置的值(这里就是指图形界面的交叉点,而不是指金叉死叉对应的K)。
但是可以用下面近似算法来进行获取,存在一定的误差,通常越是平缓的曲线误差越小。

[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
MA1:MA(CLOSE,40);
MA2:MA(CLOSE,90);
 
jc1:CROSS(MA1,MA2);
sc1:CROSS(MA2,MA1);
 
LEN1:=SUMBARS(JC1 OR SC1,1);
LEN2:=SUMBARS(JC1 OR SC1,2);
 
jsz:(ma(ma1,2)+ma(ma2,2))/2,NODRAW;//近似值

光标移动到发生金叉或者死叉的位置,并在纵向上移到交叉点的价格位置。 可以看到误差很小。
截图202209271419485295.png




金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

举报

21

主题

1万

帖子

1万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
FireScript
发表于 2022-9-27 17:08 | 显示全部楼层
本帖最后由 技术009 于 2023-3-31 10:13 编辑

金叉区间最高值到死叉区间最低值连线

因为使用了BACKSET函数。指标必须在序列模式下
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
ma10:ma(c,10);
ma20:ma(c,20);
majc:cross(ma10,ma20);
masc:cross(ma20,ma10);
 
LEN1:=BARSLAST(majc)+1;
LEN2:=BARSLAST(masc)+1;
 
redH_location:=HHVBARS(c,len1);
greenL_location:=LLVBARS(c,LEN2);
 
S1:BACKSET(masc,redH_location+1);//在死叉时候 将前面金叉区间最高值所在位置到当前位置的S1重置为1 这样 在高点位置实际存在一个S1的金叉
S2:BACKSET(majc,greenL_location+1);
 
DRAWICON(cross(s1,0),h,1);
DRAWICON(cross(s2,0),L,2);
 
DRAWLINE(cross(s1,0),H,cross(s2,0) OR ISLASTBAR,L,0);
DRAWLINE(cross(s2,0),L,cross(s1,0) OR ISLASTBAR,H,0);


实际效果:
截图202209271708207534.png


macd小引用大调用无未来的处理方式
这里以小周期调用日线macd为例:
原理很简单就是利用日线上一周期的结果 和小周期当前的C 按照macd和ema算法二次构造来实现,其他的类似ma,kdj均可以按照这个思路重构代码。(其实现在的内存保留模式,即6.23之后的逐K+仅刷最后一个K模式  是会保存当时调用到的实时的大周期指标的数值的,但是图表上一旦触发重刷,这些调用结果就会被最新的大周期数值覆盖掉了。因此可以说盘中运行时候调用的值其实是没有未来的,但是历史信号是纯回测结果,用本例的代码处理下能使得历史和最新信号保存逻辑一致性)
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
input:p(26,20,100,8),s(12,5,40,4),m(9,2,60,6);
 
 
EMA_S1:="EXPMA.M1##DAY"(S);
EMA_P1:="EXPMA.M1##DAY"(P);
DEA1:="MACD.DEA##DAY";
 
 
EMA_S0:=(2*C+(S-1)*EMA_S1)/(S+1);//当前的EMA(CLOSE,S)
EMA_P0:=(2*C+(P-1)*EMA_P1)/(P+1);//当前的EMA(CLOSE,p)
 
DIFF0:=EMA_S0-EMA_P0;//当前的DIFF
DEA0:=(2*DIFF0+(M-1)*DEA1)/(M+1);
MACD0 :2*(DIFF0-DEA0), COLORSTICK;


kdj也能做类似的处理,不过稍微麻烦点,需要新建一个指标XZ,作为被调用指标:
XZ:
[PEL] 复制代码
1
2
3
4
5
6
7
8
input:n(9,1,100,10),p1(3,2,40,4),p2(3,2,40,4);//参数设置
RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;
K:SMA(RSV,P1,1);
D:SMA(K,P2,1);
J:3*K-2*D,NODRAW;
 
llv1:llv(l,N-1);
hhv1:hhv(h,N-1);


然后进行算法拆解重组的代码如下:
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
input:n(9,1,100,10),p1(3,2,40,4),p2(3,2,40,4);//参数设置
k1:="XZ.K##DAY"(n,p1,p2);
d1:="XZ.D##DAY"(n,p1,p2);
llv1:="XZ.llv1##DAY"(n,p1,p2);
hhv1:="XZ.hhv1##DAY"(n,p1,p2);
rsv2:=(c-min(llv1,l))/(max(h,hhv1)-min(llv1,l))*100;
 
k2:(rsv2+(P1-1)*k1)/P1;
D2:(k2+(P2-1)*d1)/P2;
j2:(3*k2-2*d2);

系统自带的DMI 指标也可以拆解,以小周期调用30分钟大周期为例。先新建一个mx作为被调用指标:
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
INPUT:P(14,1,200,1),M(6,1,200,1);
T:TIME;
V1:MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(LOW-REF(CLOSE,1)));
TR1:SUM(V1,P);//调用1
HD := HIGH-REF(HIGH,1);
LD := REF(LOW,1)-LOW;
  
DMP: SUM(IF(HD>0 AND HD>LD,HD,0),P);//调用2-3
DMM: SUM(IF(LD>0 AND LD>HD,LD,0),P);
PDI: DMP*100/TR1;
MDI: DMM*100/TR1;
  
ADX: MA(ABS(MDI-PDI)/(MDI+PDI)*100,M);
RADX:REF(ADX,M);


然后当前周期下进行调用:
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
LAST_C:=CALLSTOCK('',vtCLOSE,4,-1);
LAST_H:=CALLSTOCK('',vtHIGH,4,-1);
LAST_L:=CALLSTOCK('',vtLOW,4,-1);
  
INPUT:P(14,1,200,1),M(6,1,200,1);
T:="MX.T#MIN30";
  
TR1X:="MX.TR1##MIN30"(P-1,M);
LEN:=BARSLAST(REF(T,1)<>T)+1;
H1:=HHV(H,LEN);
L1:=LLV(L,LEN);
  
TR1:=TR1X+MAX(MAX(H1-L1,ABS(H1-LAST_C)),ABS(L1-LAST_C));
  
HD := H1-LAST_H;
LD := LAST_L-L1;
  
DMPX:="MX.DMP##MIN30"(P-1,M);
DMP:DMPX+IF(HD>0 AND HD>LD,HD,0);
  
DMMX:="MX.DMM##MIN30"(P-1,M);
DMM:DMMX+IF(LD>0 AND LD>HD,LD,0);
  
PDI: DMP*100/TR1;
MDI: DMM*100/TR1;
ADXX:="MX.ADX##MIN30"(P,M-1);
ADX:(ADXX*(M-1)+(ABS(MDI-PDI)/(MDI+PDI)*100))/M;
RADX:="MX.RADX#MIN30";
ADXR:(ADX+RADX)/2


需要注意是的DMI算法的拆解,如果要调整为其他周期:
1.其中涉及到的跨周期调用都要改周期,包括调用K数据的周期以及若干个跨周期跨指标调用的。都必须调整为相应的目标周期。
2.不适用于调用日线。日线周期则需要进一步调整代码。这个建议客户自行理解了其中思路之后,自行尝试下,并不是很复杂。

N周期内成交量第M大的K对应的收盘价
[PEL] 复制代码
1
2
3
INPUT:N(20,1,100,1),M(1,1,20,1);
NV:VOL*10000+c;//合成的数,保证成交量大的一定排序优先
CM:LARGE(nv,N ,M)-LARGE(vol,N ,M)*10000;//把c解出来

根据品种情况要调整NV的算法,保证成交量大的一定排序在前面。尤其是某些品种价格高的,成交量低的情况下,NV里面就乘10000可能都不够。
仅使用当日数据计算MACD
这个算法 涉及到对ema算法的拆解,参考了前面的3.1的例子。首先新建一个指标A1,这个指标是单纯计算当日的ema数值用的:
[PEL] 复制代码
1
2
3
4
5
6
7
8
INPUT:N(10,1,100,1);
X:=C;//相当于ema参数x
 
VARIABLE:ema_:=0;
//ema
if BARPOS=1 or TODAYBAR=1 then ema_:=X;
ema_:=if(BARPOS>1,(2*x+(N-1)*ema_)/(N+1),ema_);
ema1:ema_;//最后结果


然后计算当日macd数值的代码,这里是基于1分钟周期的:
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
input:p(26,20,100,8),s(12,5,40,4),m(9,2,60,6);
 
EMA_P:="A1.ema1#MIN1"(p);
EMA_S:="A1.ema1#MIN1"(s);
 
DIFF :EMA_S - EMA_P;//快线
 
VARIABLE:DEA_:=0;
 
if  BARPOS=1 or TODAYBAR=1 then DEA_:=DIFF;
DEA_:=if(BARPOS>1,(2*DIFF+(m-1)*DEA_)/(m+1),DEA_);
DEA  : DEA_;
MACD1 :2*(DIFF-DEA), COLORSTICK;


金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

举报

37

主题

1万

帖子

6万

积分

Rank: 8Rank: 8

等级: 超级版主

注册:
2021-5-18
曾用名:
wenarm
 楼主| 发表于 2023-12-11 10:52 | 显示全部楼层
本帖最后由 技术009 于 2025-5-7 13:12 编辑

分笔周期上判断空开、多开、双开、双平、空平、多平、多换、空换状态

[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
增仓:OPENINT-REF(OPENINT,1);
现手:VOL;
//多开:以卖价为成交价并且增仓为正值。
多开:增仓>0 AND 增仓<现手 and BUYVOL;
 
//空开:以买价为成交价并且增仓为正值。
空开:增仓>0 AND 增仓<现手 and SELLVOL;
 
//多平:以买价为成交价并且增仓为负值。
多平:增仓<0 and close=BIDPRICE;
 
//空平:以卖价为成交价并且增仓为负值。
空平:增仓<0 and close=ASKPRICE;
 
 
//双开:现手与增仓的值相同。
双开:现手=增仓;
 
//双平:现手与增仓的绝对值相同。
双平:现手=abs(增仓);
 
 
//多换:增仓为0,并且最新成交价与卖价相同(主动买)。
多换:增仓=0 and close=ASKPRICE;
 
//空换:增仓为0,并且最新成交价与买价相同(主动卖)。
空换:增仓=0 and close=BIDPRICE;




国内期货每个交易小节提前n秒平仓范例
[PEL] 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//每个交易小节提前平仓时间(秒)
N:=10;
 
 
COND1:=0;
COND2:=0;
COND3:=0;
COND4:=0;
 
//判断国内不同市场下的交易小节时间是否存在。
if CLOSETIME(1)<>-1 then BEGIN
        COND1:=REMAININGTIME(CLOSETIME(1))<=N AND REMAININGTIME(CLOSETIME(1))>=0;
end
 
if CLOSETIME(2)<>-1 then BEGIN
        COND2:=REMAININGTIME(CLOSETIME(2))<=N AND REMAININGTIME(CLOSETIME(2))>=0;
end
 
if CLOSETIME(3)<>-1 then BEGIN
        COND3:=REMAININGTIME(CLOSETIME(3))<=N AND REMAININGTIME(CLOSETIME(3))>=0;
end
 
if CLOSETIME(4)<>-1 then BEGIN
        COND4:=REMAININGTIME(CLOSETIME(4))<=N AND REMAININGTIME(CLOSETIME(4))>=0;
end
 
 
//提前平仓条件
COND: COND1=1 OR COND2=1  OR COND3=1  OR COND4=1;
 
if cond=1 then BEGIN
        sell(HOLDING>0,HOLDING,MARKET);
        sellshort(HOLDING<0,HOLDING,MARKET);       
END

金字塔提供一对一VIP专业技术指导服务,技术团队实时响应您的日常使用问题与策略编写。联系电话:021-20339086
回复

举报

您需要登录后才可以回帖 登录 | 微信登录

本版积分规则

手机版|小黑屋|上海金之塔信息技术有限公司 ( 沪ICP备13035422号 )

GMT+8, 2025-7-21 14:29 , Processed in 0.109889 second(s), 26 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表