前言:
这是一个代码框架,其中部分灵感来自阿火的策略、guotx2010的VBA教程和王峰的一句话(如果你注重效率,那么金字塔提供的全局变量数据库的速度完全可以超越INI文件的),所以在此向各位前辈致谢!
适用本框架的前提:
不使用金字塔规定不能用于if ... then中的函数(如统计函数、未来函数等)、采用走完K线、且K线走完后信号就固定下来的(即未来不会发生改变)、使用新图表交易函数、勾选“仅刷最后一根K线”
步骤:
第一步:创建3个自定义函数,创建方法在此不详述,VBA代码如下:
\'定义4个动态数组保存信号和信号发生日期和时间
dim dates()
dim times()
dim values()
dim SigCounts()
SigCount = 0
Function INSERTSIG(Formula,SIGNUM,D,T,H)
\'通过VBA数组记录信号以及信号发生的时间,当最新信号发出时执行一次
INSERTSIG=0
On Error Resume Next
dates(SIGNUM).AddBack(D)
if err.number<>0 then
INSERTSIG=1
exit function
end if
times(SIGNUM).AddBack(T)
values(SIGNUM).AddBack(H)
if dates(SIGNUM).Count>SigCounts(SIGNUM) and SigCounts(SIGNUM)>0 then
dates(SIGNUM).RemoveAt(0)
times(SIGNUM).RemoveAt(0)
values(SIGNUM).RemoveAt(0)
end if
End Function
Function READSIG(Formula,SIGNUM)
\'将数组信号发生时间转换为K线位置,并记录到单值全局变量系统中,供Perl公式读取,每产生一次新K线时执行一次
READSIG=0
On Error Resume Next
cc = times(SIGNUM).Count
if err.number<>0 then
READSIG = 1
exit function
end if
iGlobal=document.ExtDataNum
for i=iGlobal to 0 step -1
iKeyValue=document.GetExtDataByIndex(i,sKeyName)
if (strComp(left(sKeyName,5),"HH" & right(Formatnumber(1000+SIGNUM,0,0,0,0),3))=0) or (strComp(left(sKeyName,5),"PP" & right(Formatnumber(1000+SIGNUM,0,0,0,0),3))=0) then
call document.RemoveExtData(i)
end if
next
Set History = Formula.ParentGrid.GetHistoryData()
next_sig_pos = 0
For i = times(SIGNUM).Count-1 To 0 step -1
str = Formatnumber(19000000+dates(SIGNUM).GetAt(i),0,0,0,0) & Formatnumber(1000000+times(SIGNUM).GetAt(i),0,0,0,0)
str = mid(str,1,4) & "-" & mid(str,5,2) & "-" & mid(str,7,2) & " " & mid(str,10,2) & ":" & mid(str,12,2) & ":" & mid(str,14,2)
bi = History.GetPosFromDate(str) + 1
Document.SetExtData "PP" & right(Formatnumber(1000+SIGNUM,0,0,0,0),3) & Formatnumber(bi,0,0,0,0),next_sig_pos
Document.SetExtData "HH" & right(Formatnumber(1000+SIGNUM,0,0,0,0),3) & Formatnumber(bi,0,0,0,0),values(SIGNUM).GetAt(i)
next_sig_pos = bi
Next
Document.SetExtData "PP" & right(Formatnumber(1000+SIGNUM,0,0,0,0),3) & "1",next_sig_pos
End Function
Function INIT_SIG(Formula,SigNum,Count)
\'初始化数组,加载公式时或其他必要时间(例如加载新品种时)运行一次
INIT_SIG=0
On Error Resume Next
Set dates(SigNum) = nothing
Set times(SigNum) = nothing
Set values(SigNum) = nothing
if err.number<>0 or SigCount<SigNum+1 then
ReDim Preserve dates(SigNum+1)
ReDim Preserve times(SigNum+1)
ReDim Preserve values(SigNum+1)
ReDim Preserve SigCounts(SigNum+1)
SigCount = SigNum+1
end if
Set dates(SigNum) = CreateObject("Stock.Array")
Set times(SigNum) = CreateObject("Stock.Array")
Set values(SigNum) = CreateObject("Stock.Array")
dates(SigNum).RemoveAll
times(SigNum).RemoveAll
values(SigNum).RemoveAll
SigCounts(SigNum) = Count
End Function
第二步:Perl公式代码修改为以下框架:
///////////////固定的开头,您仅可以修改“保留信号数”以及“策略号”/////////////////////////////////////////////////
GLOBALVARIABLE:d=0,t=0,next_sig_pos=0,保留信号数=20,策略号=0;
mylot:holding,NODRAW;
if BARPOS=1 then
begin
if EXTGBDATA(\'股指合约切换\')=1 then
begin
d:=0;
t:=0;
//EXTGBDATASET(\'股指合约切换\',0);
end;
if d=0 and t=0 then
begin
xxx:=INIT_SIG(策略号,保留信号数);
end
else begin
xxx:=round(READSIG(策略号));
if xxx=1 then
begin
d:=0;
t:=0;
next_sig_pos=0;
xxx:=INIT_SIG(策略号,保留信号数);
end
else
next_sig_pos:=1;
end;
end;
if barpos=next_sig_pos then
begin
myholding:=round(extgbdata(\'HH\' & strright(numtostr(1000+策略号,0),3) & numtostr(barpos,0)))-holding;
next_sig_pos:=round(extgbdata(\'PP\' & strright(numtostr(1000+策略号,0),3) & numtostr(barpos,0)));
if myholding>0 then
begin
pc:=min(abs(min(holding,0)),myholding);
kc:=myholding-pc;
sellshort(pc>0 and holding<0,pc,market);
buy(kc>0 and holding>=0,kc,market);
end
else if myholding<0 then
begin
pc:=min(max(holding,0),abs(myholding));
kc:=abs(myholding)-pc;
sell(pc>0 and holding>0,pc,market);
buyshort(kc>0 and holding<=0,kc,market);
end;
end;
if date()<d or (date()=d and time()<=t) or ISLASTBAR then exit;
//////////////////////////////////////////////////////////////////////////////////////////////////////
//这里本应省略N行代码,这是您原来的策略代码,为了使您马上能测试,我随便写了个简单的策略,请不要照用
issell:=close<open and CALLSTOCK(STKLABEL,vtCLOSE,1,-1)<CALLSTOCK(STKLABEL,vtOpen,1,-1);//2连阴空
isbuy:=close>open and CALLSTOCK(STKLABEL,vtCLOSE,1,-1)>CALLSTOCK(STKLABEL,vtOpen,1,-1);//2连阳多
sell(holding>0 and issell,1,market);
SELLSHORT(holding<0 and isbuy,1,market);
buyshort(holding=0 and issell,-1,market);
buy(holding=0 and isbuy,1,market);
j:=0;
for i:=1 t