海龟交易法

ATR指标

ATR:这个指标用来衡量价格波动性的平均水平,帮助交易者判断市场波动水平,从而做出更好的交易决策。ATR计算基于一段时间的价格波动情况,通常使用14天的时间周期,计算过程如下:

        1、计算每日的TR值-最高价、最低价、前一天收盘价彼此之间的最大差值。

        TR=max(high-low,abs(high-previous_close),abs(low-previous_close))

        2、计算14天内的平均TR值,初始ATR用14天的TR简单平均值,后续的ATR值用公式:

        ATR=[(前一天的ATR*13)+当天TR值]/14

较高的ATR值意味着价格波动较大,可能需要设置更宽松的止损和止盈水平;而较低的ATR值意味着价格波动较小,可以考虑设置更紧密的止损和止盈水平。ATR的值通常已价格为单位,如果是股票,ATR的值可能以美元表示,如果是外汇,可能以点数表示。

海龟交易法

头寸规模

        海龟交易法的ATR周期设为20日。那么ATR=[(前一天的ATR*19)+当天TR值]/20;

        绝对波动幅度=ATR*合约每一点所代表的价值;

        按照我们所称单位建立头寸=账户资金的%1/绝对波动幅度;

例如:

        ATR=0.0132;账户规模=100000;每一点价值=3000;

        则头寸规模=100000*1%/3000*0.0132=25(向下取整数)

入市

入市规则有两个:

1、20日突破为基础的偏短系统-突破定义为超过前20日的最高价或最低价。

2、55日突破为基础的较简单的长线系统-只要有一个信号显示价格超过了前55日最高价或最低价就建立头寸。

追踪

海龟交易系统不是一有突破信号就全仓介入,而是根据最新市场价格变化进行逐步建仓。海龟在价格突破时只建立一个单位的头寸,在建立头寸后根据前面指令的实际成交价为基础以每突破0.5N的间隔进行加仓。

例如:

        黄金:ATR=2.5 55日突破=310

        增加的第一个单位310.00

        第二个单位310.00+1/2个2.5即311.25

        第三个单位311.25+1/2个2.5即312.50

        第四个单位312.50+1/2个2.5即313.75

  1. 黄金:N=2.5 这里的N表示波动性因子,通常用Average True Range (ATR)来度量市场的波动性。在这个例子中,N=2.5表示市场的波动性因子为2.5。

  2. 55日突破=310 这句话表示市场的价格突破了过去55个交易日的最高价,触发了买入信号。这意味着交易者会建立多头头寸(买入头寸)。

  3. 增加的第一个单位310.00 这是建立头寸的第一个单位,即交易者在价格突破55日最高价后的第一个买入点。头寸的进场价格是310.00。

  4. 第二个单位310.00+1/2个2.5即311.25 这是建立头寸的第二个单位,即交易者在价格上涨了一个波动性因子N后的第二个买入点。头寸的进场价格是311.25。

  5. 第三个单位311.25+1/2个2.5即312.50 这是建立头寸的第三个单位,即交易者在价格再次上涨了一个波动性因子N后的第三个买入点。头寸的进场价格是312.50。

  6. 第四个单位312.50+1/2个2.5即313.75 这是建立头寸的第四个单位,即交易者在价格再次上涨了一个波动性因子N后的第四个买入点。头寸的进场价格是313.75。

这种头寸管理方式可以让交易者在趋势朝有利方向发展时逐步建立头寸,以便在趋势持续时获取更大的利润。同时,也能帮助控制风险,因为如果价格逆转,交易者只会失去已经建立的头寸单位,而不会一次性失去全部头寸。

止损

在你建立头寸之前,你需要预先确定退出的点位。如果市场波动触及你的价位,你就必须每一次毫无例外的退出。在这一立场上摇摆不定最终会导致灾难。

海龟以头寸风险为基础设置止损,任何一笔交易不能出现2%以上的风险,因为价格波动1N表示1%的账户净值,容许风险为2%的最大止损就是价格波动2N,为了保证全部头寸的风险最小,如果另外增加了单位,前面单位的止损需提高0.5N。

第一单位的止损为进场价格减去2倍的N值,第二单位的止损为进场价格减去1.5倍的N值,第三单位的止损为进场价格减去1倍的N值。这样设置止损,可以让交易头寸在价格波动中有一定的空间,同时根据价格的变化逐步调整止损位置,以平衡风险和利润的关系。

假设N=ATR的值,N=4,55日突破价位=100;

初始:

入市价格止损价相差
100922N

第一次加仓:

入市价格止损价相差
100941.5N
102942N

        

第二次加仓:

入市价格止损价相差
100961N
102961.5N
104962N

第三次加仓:

入市价格止损价相差
100980.5N
102981N
104981.5N
106982N

离市

海龟交易法则对于系统一系统二有着不同的离市标准:

系统一

离市对于多头头寸为10日最低价,对于空头头寸为10日最高价。当价格波动与头寸方向相反,即价格涨势中出现多头头寸或价格跌势中出现空头头寸时,如果价格突破了过去10日的最低价(对于多头头寸)或最高价(对于空头头寸),那么所有头寸中的所有单位都会退出市场。

系统二

离市对于多头头寸为20日最低价,对于空头头寸为20日最高价,如果价格波动与头寸背离,如果价格突破了过去20日的最低价(对于多头头寸)或最高价(对于空头头寸),所有头寸中的所有单位都会退出市场。海龟入市时一般不会设置离市止损价,但会在日间盯着价格,一旦价格穿过离市突破价,就开始下离市指令。

MT4代码实现

声明输入变量和全局变量

extern   int miMaxTks   = 4;              // 开仓上限-可以开仓的最大数量,最多四次买入/卖出
extern   int miSlip     = 0;              // 滑点容许-允许的最大滑点值(买/卖的值和实际价格的最大差值)
extern   int miRetry    = 10;             // 失败重试-下单失败的最大重试次数
extern   int miMagic    = 8010;           // 魔术数字-订单的唯一编号
extern   int miS1P1     = 55;             // 长线系统开仓-长线交易系统的周期,确定什么时候开仓
extern   int miS1P2     = 20;             // 长线系统止盈-长线系统的止盈周期,计算止盈点
double   gdAtr = 0;                       // 平均波幅 | N  -用于计算止损和加仓价格
double   gdLot = 0;                       // 交易单位 | Unit  -交易手数
double   gdPValue = 0;                    // 每点价值 | 报价  -账户的净值和盈亏
int      giState = 0;                     // 状态标识         -交易的状态:0-等待、1-开仓、2-满仓持仓
string   msSVals[3] = {"等待突破","突破加仓","满仓持仓"};     //交易状态的描述信息 
int      errState = 0;                    // 简易的错误提示-不同的错误类型
bool     mbErr = false;                   // 错误标记-是否发生了错误
string   msSErrs[2] = {"手数规模达到平台下限","手数规模超过平台上限"};
int      miTkCtn = 0;                     // 交易数统计| 调试用     -已经进行了多少次交易次数
int      miTkNums = 0;                    // 交易单统计| 加仓统计   -已经完成了多少单交易
int      miTkFck  = 0;                    // 交易完毕的突破次数     -交易完毕的次数,即达到止盈或止损条件的交易
bool     mbDiUp = false;                  // 方向向上               -多头头寸,看涨
bool     mbDiDn = false;                  // 方向向下               -空头头寸,看跌
double   gdPrice = 0;                     // 下一次加仓价格,需要加上1/2N的价格
int      miTkLast = 0;                    // 最后一笔开仓的订单号(上一笔订单)
double   SLL;                             //止损价位,当价格达到止损价位时,交易系统会自动平仓,以避免进一步的损失
double   TPP;                             //止盈价位,当价格达到止盈价位时,交易系统会自动平仓,以锁定收益

在init函数中,执行以下代码:

int init()
{
   gdPValue = MarketInfo(Symbol(), MODE_TICKVALUE)/MarketInfo(Symbol(), MODE_TICKSIZE);
   return(0);
}

MarketInfo(Symbol(), MODE_TICKVALUE): 这个函数用于获取当前交易品种每个点的价值。

MarketInfo(Symbol(), MODE_TICKSIZE): 这个函数用于获取当前交易品种的最小价格变动单位。

计算出来的 gdPValue 就是在当前交易品种中,每一个点价格变动对应的账户价值变动金额。这个值在海龟交易系统中用于控制头寸规模和风险,帮助确定头寸的大小和止损点位。

int deinit()
{
	ObjectsDeleteAll(WindowFind(WindowExpertName()),OBJ_LABEL);
	Comment("");
	return(0);
} 
  1. ObjectsDeleteAll(WindowFind(WindowExpertName()), OBJ_LABEL): 这个函数用于删除当前图表中由该EA创建的所有标签对象。WindowFind(WindowExpertName())找到当前EA所在的图表,然后ObjectsDeleteAll删除该图表上所有类型为OBJ_LABEL(标签)的对象。

  2. Comment(""): 这个函数用于在当前图表上添加文本注释。在这里,通过传递空字符串""作为参数,实际上是清除了当前图表上的任何文本注释,相当于将文本注释清空。

总结:deinit函数主要用于在EA停止运行时清理图表上的显示内容,确保不会在图表上留下任何未使用的标签或文本注释。这样可以保持图表整洁,并避免不必要的资源占用。

EA交易程序的入口函数:

int start(){
   
   f_Center();
   f_ShowStatus();
   
   return(0);
}

f_Center函数用来根据当前状态执行相应的交易检测和交易操作:

//根据当前状态执行相应的交易检测和交易操作
int f_Center(){
    f_KLCheck();              //进行开仓数量等基础变量的检测和生成
    switch(giState){
      case 0:                 // 等待状态
      {
         f_TcCheck();         //进行交易单位和平均波幅等检测
         f_VPCheck();         //检查是否出现突破信号
         break;
      }
      case 1:                 // 开仓状态
      {
         f_CLCheck();         // 是否符合退出条件
         f_ATCheck();         // 是否符合加仓条件
         break;
      }
      case 2:                 // 满仓状态
      {
         f_CLCheck();         // 是否符合推出条件
         break;
      }
   }  
   return(0);
}

f_KLCheck函数主要用于根据当前的订单情况更新交易状态和相关参数,并执行相应的操作,包括判断当前趋势、计算平均真实波幅、设置下一次加仓价格等。

// 检查是否被止损|校验系统状态
void f_KLCheck(){   
   //记录当前订单的数量 
	int tiTk = 0;
	//当前开仓价格
	double tdPrc = 0;
   //OrderTotal函数返回待处理的订单的数目
	for(int cnt=0; cnt<OrdersTotal(); cnt++)
	{
	   //函数的参数分别是:账单的下标-订单池中的索引-从交易池中选择订单
		if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))
		{
			Print("OrderSelect返回错误:",GetLastError());
			continue;
		}
      //选中的订单是否是当前交易货币
		if(OrderSymbol()==Symbol())
		{
		   
		   tiTk++;
		   //是否已经有交易头寸
		   if(miTkNums > 0) continue;   
		   
		   if(OrderType() == OP_BUY){
		      mbDiUp = true;
		      mbDiDn = false;
		      
		      if(OrderOpenPrice() > tdPrc){
		         tdPrc = OrderOpenPrice();
		         //当前订单的平均真是波幅,开盘价和止损线的距离的一般
		         gdAtr = (tdPrc - OrderStopLoss())/2;   // 最高价格和止损线的距离始终是2N
		         gdPrice = tdPrc + gdAtr/2;             //下次加仓的价格
		         gdLot = OrderLots();                   //将gdLot设为当前订单的交易手数
		      }
		   }else if(OrderType() == OP_SELL){
		      mbDiDn = true;
		      mbDiUp = false;
		      
		      if(OrderOpenPrice() < tdPrc){
		         tdPrc = OrderOpenPrice();
		         gdAtr = (OrderStopLoss()-tdPrc)/2;
		         gdPrice = tdPrc - gdAtr/2;
		         gdLot = OrderLots();
		      }		      
		   }
		}
	}   
	
	switch(tiTk){
	   case 0:
	   {
	      f_SQuit();
	      break;
	   }
	   default:
	   {
	      
	      if(miTkNums == 0) break;
	      if(tiTk == miMaxTks) giState = 2;      //到达最大交易手数-满仓
	      else giState = 1;                      //开仓
	      
	      miTkNums = tiTk;
	      
	      break;
	   }
	
	}
	
}

下面是提到的退出系统交易函数:

// 退出系统交易状态用清理
void f_SQuit(){      
   if(miTkNums>0) miTkFck++;     //有交易单则增加交易完毕的突破次数
   mbDiDn = false;               //重置方向表示为false,不再持有头寸
   mbDiUp = false;   
   miTkNums = 0;                 //交易单数设为0,表示不再持有任何订单
   giState = 0;                  //系统状态置为0,代表等待,不进行任何交易
}

 f_TcCheck函数用来完成础变量的检测和生成:

// 基础变量的检测和生成
int f_TcCheck(){   
   //获得20日周期的当前交易品种的ATR指标
   gdAtr = iATR(NULL,0,20,0);
   //AccountFreeMargin返回当前账户的自由保证金,/100得到一个手数对应的资金量,再除以ATR*每点价值得到实际的手数
   gdLot = (AccountFreeMargin()/100)/(gdAtr*gdPValue);
   //将手数保留两位小数
   gdLot = NormalizeDouble(gdLot,2);
   //手数规模小于最小或最大手数范围
   if(gdLot < MarketInfo(Symbol(),MODE_MINLOT)){
      mbErr = true;                             //出现错误
      gdLot = MarketInfo(Symbol(),MODE_MINLOT); //手数设置为交易品种的允许的最小值
      errState = 0;                             //表示手数规模达到平台下限
   }else if(gdLot > MarketInfo(Symbol(),MODE_MAXLOT))
   {
      mbErr = true;                             //出现错误
      gdLot = MarketInfo(Symbol(),MODE_MAXLOT); //手数设置为交易品种的允许的最大值
      errState = 1;                             //表示手数规模达到平台上限
   }else{
      mbErr = false;                            //没出现错误
   }
   gdLot = NormalizeDouble(gdLot,2);            //将手数规模保留两位小数
   
   return(0);
}

接下来是等待突破的价格检测:

// 等待突破的价格监测
int f_VPCheck(){  
   // 使用 iHighest() 函数找到 miS1P1 周期内最高价的索引
   int      tiH      = iHighest(NULL,0,MODE_HIGH,miS1P1,1);
   // 使用 iHigh() 函数获取找到的最高价
   double   tdHigh   = iHigh(NULL,0,tiH);
   // 使用 iLowest() 函数找到 miS1P1 周期内最低价的索引
   int      tiL      = iLowest(NULL,0,MODE_HIGH,miS1P1,1);
   // 使用 iLow() 函数获取找到的最低价
   double   tdLow   = iLow(NULL,0,tiL);  
   // 检查当前的Ask(卖出价)是否大于最高价 tdHigh-方向向上
   if(Ask > tdHigh){
      mbDiUp = true;
      mbDiDn = false;
   }
   // 检查当前的Bid(买入价)是否小于最低价 tdLow-方向向下
   if(Bid < tdLow){
      mbDiDn = true;
      mbDiUp = false;
   }
   // 如果方向向上(mbDiUp为true)或方向向下(mbDiDn为true),则调用 f_VPHandle() 函数处理
   if(mbDiDn || mbDiUp){
      f_VPHandle();  
   }
   return(0);
}

f_VPHandle函数用作处理突破的情况,当方向向上/向下后遍满足突破的条件(第一次突破):

void f_VPHandle(){
   giState = 1;   // 设置交易状态为开仓状态
   miTkNums = 0;  // 将交易单统计设置为0,表示当前没有交易头寸
   
   if(mbDiUp){    // 如果方向向上
      f_BuyMe();  // 调用函数执行买入操作
      return;     // 结束函数的执行,避免继续执行下面的代码
   }
   
   if(mbDiDn){    // 如果方向向下
      f_SellMe(); // 调用函数执行卖出操作
      return;     // 结束函数的执行,避免继续执行下面的代码
   }
}

买入和卖出的函数:

// 现价多单
int f_BuyMe(){   

	Alert("<BuyMe>");
	int ctn_i = -1;
	int ti = miRetry;
   while(true){
      // 计算止损价(SLL)为当前Bid减去2倍的平均真实波幅(gdAtr)
      SLL = Bid - 2 * gdAtr;
	   TPP = 0;
	   // 发送市价多单交易请求
      ctn_i=i_OrderSend(Symbol(),OP_BUY,gdLot,Ask,miSlip,SLL,TPP,"M"+StringConcatenate(Period())+"",miMagic,0,Red);
      if(ctn_i>0){
         // 如果成功下单,调用函数 f_TKoped() 处理开仓成功的逻辑
		   f_TKoped();
		   // 将最后一笔开仓的订单号设置为当前交易单的订单号
		   miTkLast = ctn_i;
		   break;
	   }
	   // 如果下单失败,减少重试次数
	   ti--;
	   // 如果重试次数小于等于0,也退出循环
	   if(ti<=0) break;
   }
	// 计算下次加仓的价格为当前Ask加上一半的平均真实波幅(gdAtr/2)
	gdPrice = Ask + (gdAtr/2);
	// 返回交易单号,如果下单成功,则为正整数,否则为-1
	return(ctn_i);
}

// 现价空单
int f_SellMe(){   

	Alert("<SellMe>");
	int ctn_i = -1;
	int ti = miRetry;
   while(true){
      // 计算止损价(SLL)为当前Bid加上2倍的平均真实波幅(gdAtr)
      SLL = Ask + 2 * gdAtr;
	   TPP = 0;
      ctn_i=i_OrderSend(Symbol(),OP_SELL,gdLot,Bid,miSlip,SLL,TPP,"M"+StringConcatenate(Period())+"",miMagic,0,Blue);
      if(ctn_i>0){
		   f_TKoped();
		   miTkLast = ctn_i;
		   break;
	   }
	   ti--;
	   if(ti<=0) break;
   }
	 // 计算下次加仓的价格为当前Bid减去一半的平均真实波幅(gdAtr/2)
	gdPrice = Bid - (gdAtr/2);
	return(ctn_i);
}

再来看看处理开仓成功逻辑的函数:

void f_TKoped(){
   ++miTkCtn;                 // miTkCtn自增1,用于统计交易次数
   ++miTkNums;                // miTkNums自增1,用于统计当前的交易单数(头寸数)
   
   if(miTkNums>=miMaxTks){    // 如果当前交易单数(头寸数)大于等于最大交易手数(miMaxTks)
      giState = 2;            // 将交易状态giState设为2,表示满仓状态
   }
}

接下来是持仓状态下,是否满足退出交易的条件:

// 是否符合退出条件
void f_CLCheck(){    
   bool tbQuit = false;    // 声明一个布尔型变量 tbQuit,用于标记是否需要退出交易
   // 如果当前交易方向是多头(mbDiUp为真)
   if(mbDiUp){
      int      tiL      = iLowest(NULL,0,MODE_HIGH,miS1P2,1);
      double   tdLow   = iLow(NULL,0,tiL); 
      // 如果当前的卖价 Bid 低于监测周期内的最低点 tdLow-满足退出条件
      if(Bid < tdLow){  
         tbQuit = true;
      }   
   }
   // 如果当前交易方向是空头(mbDiDn为真)
   if(mbDiDn){
      int      tiH      = iHighest(NULL,0,MODE_HIGH,miS1P2,1);
      double   tdHigh   = iHigh(NULL,0,tiH);  
       // 如果当前的买价 Ask 高于监测周期内的最高点 tdHigh-满足退出条件
      if(Ask > tdHigh){ 
         tbQuit = true; 
      } 
   }
   // 如果 tbQuit 为真,表示需要退出交易,需要平仓交易
   if(tbQuit){
      f_CloseAllTks();
      f_SQuit();
   } 
}

上面用到了平仓交易的函数:

// 关闭所有订单
void f_CloseAllTks(){   
	Alert("<CloseAllTks>");
	// 从最后一个订单开始遍历所有订单,包括历史订单
	for(int cnt=OrdersTotal();cnt>=0;cnt--)
	{
	   // 如果不能选择该订单,继续遍历下一个订单
		if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)) continue;
		// 检查该订单是否是当前交易货币,并且订单的魔术数字是否与给定的魔术数字相符
		if(OrderSymbol()==Symbol() && OrderMagicNumber()==miMagic)
		{   
		   // 如果订单类型是买单(OP_BUY)
		   if(OrderType() == OP_BUY){
		      // 使用 while 循环来确保买单成功平仓
		      while(!OrderClose(OrderTicket(),OrderLots(),Bid,miSlip));
		   }
		   // 如果订单类型是卖单(OP_SELL)
		   if(OrderType() == OP_SELL){
		      // 使用 while 循环来确保卖单成功平仓
		      while(!OrderClose(OrderTicket(),OrderLots(),Ask,miSlip));
		   }
		   
		}
   }
}

检查完是否满足开仓状态下的退出条件后,检查是否满足加仓条件:

// 加仓检测
void f_ATCheck(){    
   // 如果当前趋势是多头趋势
   if(mbDiUp){
      // 如果当前的卖价(Ask)高于下一次加仓的价格(gdPrice)
      if(Ask > gdPrice){
         // 调用函数 f_FixTkSLL() 来修改止损价
         f_FixTkSLL();
         // 调用函数 f_BuyMe() 来执行加仓的买单操作
         f_BuyMe();
      }
      return;
   }
   // 如果当前趋势是空头趋势
   if(mbDiDn){
      // 如果当前的买价(Bid)低于下一次加仓的价格(gdPrice)
      if(Bid < gdPrice){
         // 调用函数 f_FixTkSLL() 来修改止损价
         f_FixTkSLL();
         // 调用函数 f_SellMe() 来执行加仓的卖单操作
         f_SellMe();
      }
      return;
   }
}

下面是修改止损的函数:

// 修正订单止损|上推
void f_FixTkSLL(){      
	Alert("<FixTkSLL>");
	for(int cnt=OrdersTotal();cnt>=0;cnt--)
	{  
	   // 选中订单,根据索引 cnt,以 MODE_TRADES 模式查询订单
		if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)) continue;
		// 判断选中的订单是否为当前交易货币对(Symbol())且魔术数字(MagicNumber)与 miMagic 相符
		if(OrderSymbol()==Symbol() && OrderMagicNumber()==miMagic)
		{  
		   // 如果订单类型为买单(OP_BUY)
		   if(OrderType() == OP_BUY){    
		      // 通过 OrderModify 函数来修改订单的止损价(Stop Loss Level)
		      // 将止损价上推一个平均真实波幅的距离(gdAtr/2)
		      // 传入的参数依次为:订单号(OrderTicket())、开仓价格(OrderOpenPrice())、止损价(OrderStopLoss() + gdAtr/2)、止盈价(OrderTakeProfit())、对应的参数(0)、颜色(Blue)
		      // while 循环保证直到订单修改成功才继续执行后续代码
		      while(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss() + gdAtr/2,OrderTakeProfit(),0,Blue));
		   }
		   // 如果订单类型为卖单(OP_SELL)
		   if(OrderType() == OP_SELL){
		      // 通过 OrderModify 函数来修改订单的止损价(Stop Loss Level)
		      // 将止损价下推一个平均真实波幅的距离(gdAtr/2)
		      // 传入的参数依次为:订单号(OrderTicket())、开仓价格(OrderOpenPrice())、止损价(OrderStopLoss() - gdAtr/2)、止盈价(OrderTakeProfit())、对应的参数(0)、颜色(Blue)
		      // while 循环保证直到订单修改成功才继续执行后续代码
		      while(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss() - gdAtr/2,OrderTakeProfit(),0,Blue));
		   }
		   
		}
   }   
}

还有一种也就是满仓条件下,是否满足退出条件,也就是上面的f_CLCheck函数。

最后是我们的下订单的函数:

// 下订单
int  i_OrderSend(string symbol,int cmd,double volume,double price,int slippage,double stoploss,double takeprofit,string comment,int magic,datetime expiration,color arrow_color)
{
	int t_tid=0;
	Alert("下单:"+symbol+DoubleToStr(price)+ "|Lot:" + DoubleToStr(volume,2) + "|SL:"+DoubleToStr(stoploss)+"|TP:"+DoubleToStr(takeprofit));
	while(true)
	{
		t_tid=OrderSend(symbol,cmd,volume,price,slippage,stoploss,takeprofit,comment,magic,expiration,arrow_color);  
		//-------------------------------------------------------------------- 7 --
		if(t_tid>0) // 交易成功
		{
			Alert("下单成功..");
			break;                                 // 退出循环
		}
		//-------------------------------------------------------------------- 8 --
		int Error=GetLastError();                 // 失败
		switch(Error)                             
		{
			case 135:Alert("报价已经改变,请重试..");
			RefreshRates();                        // 更新数据
			continue;                              // 下一次迭代
			case 136:Alert("没有报价,请等待更新..");
			while(RefreshRates()==false)           // 等待新的报价
			Sleep(1);                              // 延时一秒
			continue;                              // 下一次迭代
			case 146:Alert("交易系统繁忙,请重试..");
			Sleep(500);                            
			RefreshRates();                        // 更新数据
			continue;                              // 下一次迭代
		}

		switch(Error) 
		{
			case 2 : Alert("通用错误.");
			break;                              
			case 5 : Alert("客户端版本过低.");
			break;                              
			case 64: Alert("账号被屏蔽.");
			break;                              
			case 133:Alert("禁止交易");
			break;                              
			default:
			Alert("发生错误",Error);// Other alternatives   
			break;
		}
		break;
	}
	return(t_tid);

为了方便我们了解交易中的数据,在我们的MT窗口左上角,我们展示平均波幅、可用资金等数据信息。

i_DisPlayInfo函数展示一个文本信息,参数从左到右分别是:标签对象的名称-标签对象的文本内容-标签对象的原点-X坐标偏移-Y坐标偏移-标签文本大小-标签文本样式-标签文本的颜色

void i_DisPlayInfo(string LableName, string LableDoc, int Corner, int LableX, int LableY, int DocSize, string DocStyle, color DocColor)
{
    // 如果 Corner 参数为 -1,表示不显示标签,直接返回
    if (Corner == -1)
        return;

    // 创建标签对象,并指定对象的类型为 OBJ_LABEL(标签)
    ObjectCreate(LableName, OBJ_LABEL, 0, 0, 0);
    
    // 设置标签对象的文本内容、文本大小、文本样式和文本颜色
    ObjectSetText(LableName, LableDoc, DocSize, DocStyle, DocColor);
    
    // 设定标签对象的坐标原点,可选值为:0-左上角,1-右上角,2-左下角,3-右下角,-1-不显示标签
    ObjectSet(LableName, OBJPROP_CORNER, Corner);
    
    // 设置标签对象的 X 坐标偏移
    ObjectSet(LableName, OBJPROP_XDISTANCE, LableX);
    
    // 设置标签对象的 Y 坐标偏移
    ObjectSet(LableName, OBJPROP_YDISTANCE, LableY);
}

上面的函数是一个属性信息,完整的属性信息如下:

void f_ShowStatus(){ 
   i_DisPlayInfo("LableSplit","----------海龟系统-----------",0,15,15,10,"黑体",SteelBlue);
   i_DisPlayInfo("LableLot","交易单位::"+DoubleToStr(gdLot,2),0,15,30,10,"黑体",SteelBlue);
   i_DisPlayInfo("LableN","平均波幅::"+DoubleToStr(gdAtr),0,15,48,10,"黑体",SteelBlue);

	i_DisPlayInfo("Acc87lance","账面资金::"+DoubleToStr(AccountBalance(),2),0,15,66,10,"黑体",SteelBlue);
	i_DisPlayInfo("LableC5rice6","净值资金::"+DoubleToStr(AccountEquity(),2),0,15,84,10,"黑体",SteelBlue);
	i_DisPlayInfo("Labl456rice6","保证资金::"+DoubleToStr(AccountMargin(),2),0,15,102,10,"黑体",SteelBlue);
	i_DisPlayInfo("Labl4hcjce6","可用资金::"+DoubleToStr(AccountFreeMargin(),2),0,15,120,10,"黑体",SteelBlue);
	i_DisPlayInfo("Labl4hcjde6","账面盈亏::"+DoubleToStr(AccountProfit(),2),0,15,138,10,"黑体",SteelBlue);
	i_DisPlayInfo("Labl4hcjde7","交易统计::"+DoubleToStr(miTkNums,0)+"/" + DoubleToStr(miTkCtn,0)+">>" + DoubleToStr(miTkFck,0),0,15,156,10,"黑体",SteelBlue);
	i_DisPlayInfo("Labl4hcjde8","系统状态::"+msSVals[giState],0,15,174,10,"黑体",SteelBlue);
	if(mbErr){
	   i_DisPlayInfo("Labl4hcjde9","警示信息::"+msSErrs[errState],0,15,192,10,"黑体",Red);
	} 
}

以上就是海龟交易法MT4实现的全部内容了。如果有错误恳请指针,万分感谢!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值