MetaTrader编程入门
2008-06-20 15:15:11 来源: 作者:
MetaTrader编程入门教程(0)
----指标文件构成
例1
//+--------------------------------------------------
//双些线后是单行注释,用于注解,自用说明。/*和*/包起来实现多行注释,记录自己的说明介绍,编程使用记录等
//MQL4语言基本服从C语言的规则-----------注意目前MetaEditor处理不好多字节代码,所以不要在代码中使用中文和中文空格-------------+
//每个指标文件只是至少包括三个部分(1)property 和参数,数组声明,(2)初始化函数nit(), (3)主函数start()
//property 是各种说明信息
//最重要必须的是这三种,(1)说明指标将画在价格窗口还是独立的窗口
//(2)有多少个(1~7)储存指标数据的数组,(3)说明对应将画指标的绘画颜色,编号1~7
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- 可设置的参数,可根据需要,由使用者设置
extern int MA_Period=13;
extern int MA_Shift=0;
extern int MA_Method=2;
extern int MA_Price = 6;
/* MA_Method =
MODE_SMA 0 Simple moving average,
MODE_EMA 1 Exponential moving average,
MODE_SMMA 2 Smoothed moving average,
MODE_LWMA 3 Linear weighted moving average.
*/
/* MA_Price =
PRICE_CLOSE 0 Close price.
PRICE_OPEN 1 Open price.
PRICE_HIGH 2 High price.
PRICE_LOW 3 Low price.
PRICE_MEDIAN 4 Median price, (high+low)/2.
PRICE_TYPICAL 5 Typical price, (high+low+close)/3.
PRICE_WEIGHTED 6 Weighted close price, (high+low+close+close)/4.
*/
//数组,储存指标数据
double Buffer0[];
//| 初始化准备函数,装入时调用一次
int init()
{
//-设置编号为0的线的线形等参数, 0~6,对应indicator_color1~7
SetIndexStyle(0,DRAW_LINE);
//---- 设置编号为0的线 与数组的对应关系, 0~6
SetIndexBuffer(0,Buffer0);
return(0);
}
int start() //指标计算主函数,每次计算调用
{
ma();
return(0);
}
//自定义函数,这里只是直接使用库函数实现MA, 若你自己计算,可设计任何指标
void ma()
{
int pos=Bars;
//Bars = Number of bars in the current chart.当前窗口中的蜡烛数
while(pos>=0)
{
Buffer0[pos]=iMA(NULL,0,MA_Period,MA_Shift,MA_Method,MA_Price,pos);
pos--;
}
}
//+--------------------------------------------------
例2
//+--------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 7
#property indicator_color1 Red
#property indicator_color2 Yellow
#property indicator_color3 Blue
#property indicator_color4 Green
#property indicator_color5 Gray
#property indicator_color6 SkyBlue
#property indicator_color7 Tan
extern int MA_Period=13;
extern int MA_Shift=0;
extern int MA_Method=2;
extern int MA_Price = 6;
double Buffer0[];
double Buffer1[];
double Buffer2[];
double Buffer3[];
double Buffer4[];
double Buffer5[];
double Buffer6[];
//----
int init()
{
//-设置编号为0的线的线形等参数, 0~6,对应indicator_color1~7
SetIndexStyle(0,DRAW_LINE);
SetIndexStyle(1,DRAW_LINE);
SetIndexStyle(3,DRAW_LINE);
SetIndexStyle(4,DRAW_LINE);
SetIndexStyle(5,DRAW_LINE);
SetIndexStyle(6,DRAW_LINE);
//---- 设置编号为0的线 与数组的对应关系, 0~6
SetIndexBuffer(0,Buffer0);
SetIndexBuffer(1,Buffer1);
SetIndexBuffer(2,Buffer2);
SetIndexBuffer(3,Buffer3);
SetIndexBuffer(4,Buffer4);
SetIndexBuffer(5,Buffer5);
SetIndexBuffer(6,Buffer6);
return(0);
}
//
int start() //指标计算主函数,每次计算调用
{
ma();
ma1();
return(0);
}
void ma()
{
int pos=Bars;
while(pos>=0)
{
Buffer0[pos]=iMA(NULL,0,MA_Period,MA_Shift,MA_Method,MA_Price,pos);
Buffer1[pos]=iMA(NULL,0,MA_Period*2,MA_Shift,MA_Method,MA_Price,pos);
Buffer2[pos]=iMA(NULL,0,MA_Period*3,MA_Shift,MA_Method,MA_Price,pos);
pos--;
}
}
void ma1()
{
int pos=Bars;
while(pos>=0)
{
Buffer3[pos]=iMA(NULL,0,MA_Period*4,MA_Shift,MA_Method,MA_Price,pos);
Buffer4[pos]=iMA(NULL,0,MA_Period*5,MA_Shift,MA_Method,MA_Price,pos);
Buffer5[pos]=iMA(NULL,0,MA_Period*6,MA_Shift,MA_Method,MA_Price,pos);
Buffer6[pos]=iMA(NULL,0,MA_Period*7,MA_Shift,MA_Method,MA_Price,pos);
pos--;
}
}
MetaTrader编程入门(1)--智能交易系统基础
//+------------------------------------------------------------------+
//| Designed by OKwh, China |
//| Copyright 2006, OKwh |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright 2006, OKwh "
#property link ""
#define MAGICMA 200610011231
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
extern int whichmethod = 1; //1~4 种下单方式
extern double TakeProfit = 100;
extern double StopLoss = 20;
extern double MaximumRisk = 0.3;
extern double TrailingStop =25;
extern int maxOpen = 3; //最多持仓限制
extern int maxLots = 5; //最多单仓限制
extern int bb = 0; //非零就跟踪止赢
extern double MATrendPeriod=26;//使用26均线
int i, p2, xxx,p1, res;
double Lots;
datetime lasttime;
int init() //初始化
{
Lots = 1;
lasttime = NULL;
return(0);
}
int deinit() { return(0); } //反初始化
//| expert start function
int start()
{
CheckForOpen();
if (bb>0) CTP(); //跟踪止赢
return(0);
}
//+------------------------------------------------------------------+
double LotsOptimized() //确定下单量,开仓调用
{
double lot=Lots;
int orders=HistoryTotal(); // history orders total
int losses=0; // number of losses orders without a break
//MarketInfo(Symbol(),MODE_MINLOT);
//MarketInfo(Symbol(),MODE_MAXLOT);
//MarketInfo(Symbol(),MODE_LOTSTEP);
lot=NormalizeDouble(MaximumRisk * AccountBalance()/AccountLeverage(),1);
if(lot<0.1) lot=0.1;
if(lot>maxLots) lot=maxLots;
return(lot);
}
//平仓持有的买单
void CloseBuy()
{
if (OrdersTotal( ) > 0 )
{
for(i=OrdersTotal()-1;i<0;i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderType()==OP_BUY)
{
OrderClose(OrderTicket(),OrderLots(),Bid,3,White);
Sleep(5000);
}
}
}
}
//平仓持有的卖单
void CloseSell()
{
if (OrdersTotal( ) > 0 )
{
for(i=OrdersTotal()-1;i<0;i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderType()==OP_SELL)
{
OrderClose(OrderTicket(),OrderLots(),Ask,3,White);
Sleep(5000);
}
}
}
}
//判断是否买或卖或平仓
int buyorsell() //在这个函数计算设置你的交易信号
{
double MacdCurrent, MacdPrevious, SignalCurrent;
double SignalPrevious, MaCurrent, MaPrevious;
MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);
if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious && MaCurrent>MaPrevious)
return (1); // 买 Ma在上升,Macd在0线上,并且两线上交叉
if(MacdCurrent>0 && MacdCurrentSignalPrevious
&& MaCurrent return (-1); // 卖
return (0); //不交易
}
int nowbuyorsell = 0;
void CheckForOpen()
{
if (Time[0] == lasttime ) return; //每时间周期检查一次
lasttime = Time[0];
nowbuyorsell = buyorsell(); //获取买卖信号
if (nowbuyorsell == 1) //买 先结束已卖的
CloseSell();
if (nowbuyorsell == -1) //卖 先结束已买的
CloseBuy();
if (TimeDayOfWeek(CurTime()) == 1)
{
if (TimeHour(CurTime()) < 3 ) return; //周一早8点前不做
}
if (TimeDayOfWeek(CurTime()) == 5)
{
if (TimeHour(CurTime()) > 19 ) return; //周五晚11点后不做
}
if (OrdersTotal( ) >= maxOpen) return ;
//如果已持有开仓数达到最大,不做
if (nowbuyorsell==0) return; //不交易
TradeOK(); //去下单交易
}
void TradeOK() //去下单交易
{
int error ;
if (nowbuyorsell == 1) //买
{
switch (whichmethod)
{
case 1: res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);break;
case 2: res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,Ask-StopLoss*Point,0,"",MAGICMA,0,Blue); break;
case 3: res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,Ask+TakeProfit*Point,"",MAGICMA,0,Blue);break;
case 4: res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,Ask-StopLoss*Point,Ask+TakeProfit*Point,"",MAGICMA,0,Blue);break;
default : res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);break;
}
if (res <=0)
{
error=GetLastError();
if(error==134)Print("Received 134 Error after OrderSend() !! "); // not enough money
if(error==135) RefreshRates(); // prices have changed
}
Sleep(5000);
return ;
}
if (nowbuyorsell == -1) //卖
{
switch (whichmethod)
{
case 1: res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red); break;
case 2: res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,Bid+StopLoss*Point,0,"",MAGICMA,0,Red); break;
case 3: res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,Bid-TakeProfit*Point,"",MAGICMA,0,Red); break;
case 4: res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,Bid+StopLoss*Point,Bid-TakeProfit*Point,"",MAGICMA,0,Red); break;
default : res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red); break;
}
if (res <=0)
{
error=GetLastError();
if(error==134) Print("Received 134 Error after OrderSend() !! "); // not enough money
if(error==135) RefreshRates(); // prices have changed
}
Sleep(5000);
return ;
}
}
void CTP() //跟踪止赢
{
bool bs = false;
for (int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if (OrderType() == OP_BUY)
{
if ((Bid - OrderOpenPrice()) > (TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT)))
{
if (OrderStopLoss() < Bid - TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT))
{
bs = OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0, Green);
}
}
}
else if (OrderType() == OP_SELL)
{
if ((OrderOpenPrice() - Ask) > (TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT)))
{
if ((OrderStopLoss()) > (Ask + TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT)))
{
bs = OrderModify(OrderTicket(), OrderOpenPrice(),
Ask + TrailingStop * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(),0, Tan);
}
}
}
}
}
MT编程入门教程(2)----指标画哪里?价格窗口还是独立窗口?
其实,都可以,不过是坐标的规格化,使得它们在相近的数据范围,就可以画在一起。
看你自己的习惯。画在价格窗口,方便和价格同时感受。
//+本例展示了如何把MA转换后画到独立窗口,同样也可以把独立窗口的指标改画在价格窗口
//要达到这些目的,需要考虑两个方面 1 估计数据的范围,以确定以什么为单位? 2 确定坐标偏移,也就是确定坐标零点。
//目的就是让你要画的多条线在同样的数值范围,这样才能同时画出,达到参考目的
//比如-1000到+1000和0到+4这样两套数据要变换后才能在同图画出,
//转换方法复习中学数学直角坐标系的缩放和平移部分-------------------------+
// 共画2条线
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Yellow
// Parameter
// MA-Properties
extern double MovingFast = 7;
extern double MovingSlow = 13;
extern double MovingSlow02 = 13;
extern int MaM=2;
extern int MaP=2;
extern int MaM0=3;
extern int MaP0=3;
extern int range1 = 11;
extern int range2 = 4;
int i;
// Buffer
//// 共画2条线,用2个数组存储线数据
double bufferMA1[];
double bufferMA2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//// 设置2条线的顺序编号,画法,对应数组,
SetIndexStyle( 0, DRAW_LINE );
SetIndexBuffer( 0, bufferMA1 );
SetIndexStyle( 1, DRAW_LINE );
SetIndexBuffer( 1, bufferMA2 );
return(0);
}
int deinit() { return(0);}
int start()
{
double Buffer10,Buffer11,Buffer20,Buffer21,Buffer30, Buffer31;
int countedBars = IndicatorCounted();
//---- check for possible errors
if ( countedBars < 0 ) { return(-1); }
if ( countedBars > 0 ) { countedBars--; }
int barsToCount = Bars - countedBars;
for ( int i = barsToCount; i >= 0; i-- )
{
//// 开始计算
Buffer20 = iMA(NULL,0,MovingFast,0,MaM,MaP, i) ;//MovingFast
Buffer30 = iMA(NULL,0,MovingSlow,0,MaM,MaP, i) ;//MovingSlow
Buffer21 = iMA(NULL,0,MovingFast,0,MaM,MaP, i+range1) ;
Buffer31 = iMA(NULL,0,MovingSlow02,0,MaM,MaP, i+range2) ;
//赋值给数组以便画线,使用Point使得坐标以点为单位,保证本指标对不同货币的一致y轴单位和视觉效果
bufferMA1[i] = MathRound((Buffer20-Buffer21)/Point);
bufferMA2[i] = MathRound((Buffer30-Buffer31)/Point);
}
return(0);
}
上面把两个MA的差值画在独立窗口,当然若把差值再加上一个MA,就可以画在价格窗口。
MA及其各种变化是最常用的指标基础。MA一般常用来替代价格本身 再做进一步计算。
如改
#property indicator_chart_window
......
Buffer10 = iMA(NULL,0,MovingFast*6,0,MaM,MaP, i)
bufferMA1 = MathRound(Buffer20-Buffer21)+Buffer10 ;
bufferMA2 = MathRound(Buffer30-Buffer31)+Buffer10 ;
.........
就可以把它们跌加到价格上画了。
你只需修改Buffer10 ,Buffer20, Buffer21 Buffer30, Buffer31为你需要的,在考虑一下数据范围坐标问题,你可以画任意的指标了。
使用timeframes参数可获得其它时间周期的数据。
使用Symbol( ) 可获得当前货币对的名称。
使用Point可获得当前货币对的点值。
MT编程入门教程(3)----设计开发指标和自动交易系统的注意事项(个人观点,仅供参考)
一、 指标的本质和用途:
交易的本质,最基本的交易是一对买卖(有些交易商运行多次部分平仓,有些运行交易间相关联如一个平仓是另一个开仓的条件等),利用交易生存期间的价格变化赢利或亏损,可以看出,一个基本的交易有五个要素(1)仓位大小,(2)建仓价格,(3)平仓价格,(4)开仓时间,(5)平仓时间。基本的交易活动交易围绕这5个要素展开,综合考虑赢利和亏损的可能而进行,其中只有(1)是自己可完全控制的,其它要素决策的依据信息如市场价格、时间演化、其它(政治经济气候需求等)影响的相互复杂作用而不断变化。对于你们这类大多数交易者,所能获得的信息只有两个方面(1)市场本身的价格和时间历史,(2)公开安排的新闻发布,一般均基于此进行交易(当然这里不考虑个人的什么灵感)。这两个方面也就是技术分析和基本面分析的基础。
指标之所以需要是因为市场价格和时间变动是不断变化的过程,动态变化是其基本特征,其中的复杂程度超出了人类的精确认知能力,难以精确的使用自然科学使用的那种基于重现和必然的分析方法。人基本上出于大脑对价格时间图的形象形状的直觉感知进行判断分析的。形象形状的直觉感知方法事实上是大脑对轮廓形状、方向趋势、快慢力度、长短高低、跃变累积等特征的提取能力。鉴于此,所谓指标应需而生,目的就是提炼突出这些特征。基础信息就是相关的时间序列和价格序列,如移动平均指标就是相邻相近某数量价格数值的权重加和平均,其中使用的数值就是价格因素的贡献,价格数值的数目或者说对应的时间坐标就是时间因素,这样用一种数学方法处理选取的价格因素和时间因素得到一个或一系列新的数值,画出图得到新的形象以帮助人获得跟明确清晰的感觉。传统上时间信息被当作简单的等间隔整数序列来使用。只有个别如周期分析较多考虑了时间因素。
无论什么指标,实际都是借助或复杂或简单的数学方法对轮廓形状、方向趋势、快慢力度、长短高低、跃变累积等特征提取。认识到这一点,就再不会为那些激动人心的命名而激动(当然有些人喜欢激动,喜欢灵感,喜欢玄妙,而我自己,无奈由于长期的职业训练,只会用清晰的已知的数理化去表示或近似表示那模糊变动的东西,以实现可操作,丧失了以模糊表达模糊只可意会不可言传的能力了)。
二、指标开发:
借助或复杂或简单的数学方法对轮廓形状、方向趋势、快慢力度、长短高低、跃变累积等特征提取时,人们一般大多从模仿修改已有指标开始。开发中要注意(1)重点要表示那类特征;(2)在单边趋势、突变、振荡三类情况下的表现如何;(3)优点和缺点;(4)什么情况下最有效,什么情况下无效;(5)时间特征如何。
三、交易系统
交易系统要解决很多问题,二不仅是写个公式那么简单,因为它要考虑很多因素。(1)时间周期和货币种类;(2)对各种单边趋势、突变、振荡的适合程度;(3)如何降低失效的损失;(4)如何优化市场成长为活的系统。
编程要考虑(1)判断下单策略;(2)止赢止损跟踪策略;(3)仓位控制;(4)平仓策略;(5)动态调整策略。
事实上,即便是相同指标,不同人使用也是不同的结果。而且成功持续稳定赢利的实际交易往往需要多指标的综合使用和判断。
每个指标和交易系统都有自己的长处和不足,每个交易者还有自己的个性和交易经验和习惯,它们的合适配合,才会增加赢利的可能,否则,任何指标或交易系统都毫无价值。
完全自动的交易系统可能还没有,可能现实中能生存的是指标、交易系统和人的某种组合,以相互补充和动态调整,以适应市场甚至市场的规律也是变化的这个基本点。
鉴于我国外汇交易正逐渐扩展,并且很可能不会是股市那要的发展过程,受朋友邀请,业余指导一个小团队的对外汇交易策略的研究设计工作,筛选出的有效指标将会在eBay和淘宝销售,初步先研发MT的指标,适当时候推出基于互联网的训练程序。我将毫无保留任何有效的技术,因为我明白,那些是工具,即使同样的工具有不同人使用也会产生不同的结果,那种认为给大众公开技术指标交易系统就会让自己失败的说法是好无根据证据的。市场实际是不断变化甚至进化的,任何技术实际是表达表示它的某部分特征而已,而实际交易是人综合处理各种特征的结果。