MT4量化交易实战

MT4量化交易实战

1.一些基本概念

  • k线

image-20210825162938145

  • 外汇EA,是外汇智能交易系统的简称(Expert Advisor)。外汇EA是一套用于MT4平台(Metatrader4)的程序化交易系统,可以自动完成外汇交易的操作,无需任何人工的干预。
  • 手数,在外汇货币交易中,“手”是基本操作单位,一手=10万美金。
  • 开仓价是成本价,平仓价是处理单子的价格。
  • 买入是以市价买 挂单是以自己认为的价格买 价格可以一样也可以不一样
  • 多单: 看涨,买入
  • 空单:看跌,抛出
  • 一个完整系统的要素

image-20210823132234834

2.交易中常用的MQL4代码片段

  • Bid是卖价,Ask是买价

1.OrderSend(下单)

int  OrderSend(     返回值,当成功的时候会返回订单号,失败的时候返回-1
   string   symbol, // symbol    交易类型,例如是英镑还是美元。假如多个货币使用同一个ea,可以使用Symbol()来自动获取当前货币类型
   int      cmd,                 // operation    
   double   volume,              // volume   做几手
   double   price,               // price    买的价格
   int      slippage,            // slippage   滑几个点成交
   double   stoploss,            // stop loss   止损
   double   takeprofit,          // take profit   止盈
   string   comment=NULL,        // comment  注释
   int      magic=0,             // magic number  魔术数,相当于id,区分不同的ea 
   datetime expiration=0,        // pending order expiration    过期时间,到达指定时间时,订单还没有成交,就会被撤掉
   color    arrow_color=clrNONE  // color    颜色
   );
  • 第二个参数的含义 cmd

image-20210823143412485

  • slippage 简单点来说就是价格后边的小数点位数。因为小数点的位数是不确定的,所以可以用 Point() 来获取当前货币的小数点位数

image-20210823144127401

2.修改订单

修改订单之前需要先选择一个订单

bool  OrderSelect(           
   int     index,            // index or order ticket   根据索引或者订单号选择订单
   int     select,           // flag 
   int     pool=MODE_TRADES  // mode 
   );
  • 第二个参数

SELECT_BY_POS - index in the order pool 如果是根据索引,就填这个
SELECT_BY_TICKET - index is order ticket. 如果是根据订单号,就填这个

  • 第三个参数

MODE_TRADES 从当前订单中选择
MODE_HISTORY 从历史订单中选择

修改订单

bool  OrderModify( 
   int        ticket,      // ticket   订单号
   double     price,       // price    开仓价
   double     stoploss,    // stop loss  止损
   double     takeprofit,  // take profit   止盈
   datetime   expiration,  // expiration 截止时间
   color      arrow_color  // color  颜色
   );

3.平仓和部分平仓

  • 注意:平仓的时候要从后往前平

平仓

  • 多单和空单
bool  OrderClose( 
   int        ticket,      // ticket  订单号
   double     lots,        // volume   手数
   double     price,       // close price   平仓价
   int        slippage,    // slippage   滑动点数
   color      arrow_color  // color  颜色
   );
  • 挂单
bool  OrderDelete( 
   int        ticket,      // ticket 
   color      arrow_color  // color 
   );

部分平仓

只要修改手数即可。注意:部分平仓之后会生成一个新订单,订单号会改变。

4.文件操作

  1. 删除 #property strict
  2. 添加 #import “kernel32.dll”
  3. 使用 FileOpen 函数
int  FileOpen(    // >0 说明打开成功
   string  file_name,           // File name 文件名
   int     open_flags,          // Combination of flags   文件打开类型和权限相关的操作,如果使用多个,可以用 | 分割
   short   delimiter=';',       // Delimiter    以什么分割,可以是 , * 之类
   uint    codepage=CP_ACP      // Code page 
   );
  • 第二个参数可填类型
FILE_READ        file is opened for reading
FILE_WRITE       file is opened for writing
FILE_BIN         binary read-write mode (no conversion from a string and to a string)
FILE_CSV        
FILE_TXT         
FILE_ANSI       
FILE_UNICODE        
FILE_SHARE_READ         shared reading from several programs
FILE_SHARE_WRITE        shared writing from several programs
FILE_COMMON            
  1. FileWrite函数
uint  FileWrite( 
   int  file_handle,   // File handle    打开文件返回的值
   ...                 // List of recorded parameters   写入的内容
   );
  1. FileRead 有多种类型,如图所示。用法都一样。

image-20210823165950590

string  FileReadString( 
   int  file_handle,     // File handle 
   int  length=0         // Length of the string 
   );
  1. 拷贝文件
//调用kernel32.dll,导入两个方法
int CopyFileW(string a0,string a1,int a2);  //参数含义: 要拷贝文件的路径,存放路径,a2=0
bool CreateDirectoryW(string a0,int a1);   // a1=0
//获取数据文件存放路径
string dataPath = TerminalInfoString(TERMINAL_DATA_PATH)+"\\MAL4\\Files";

5.获取均线价格

double  iMA( 
   string       symbol,           // symbol    产品类型,NULL代表当前产品
   int          timeframe,        // timeframe   产品周期,0代表当前周期
   int          ma_period,        // MA averaging period  均线周期,自己设置的
   int          ma_shift,         // MA shift   偏移
   int          ma_method,        // averaging method  均线类型
   int          applied_price,    // applied price  应用价格
   int          shift             // shift  偏移量
   );

3.趋势交易系统

  • ma.mq4
//+------------------------------------------------------------------+
//|                                                           ma.mq4 |
//|                                                             dzsq |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "dzsq"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict


extern int longMa=20;   //长均线
extern int shortMa=10;  //短均线
extern int callBachMa=30;

extern int stop = 300; //止损
extern int limit = 900; //止盈
extern double lots=1;  //手数
extern double movestop = 500; //移动止损
extern int magic = 12345;

bool isCrossBuy = false; //是否交叉
bool isCrossSell = false;
//是否会调到支撑线
bool isSellCallback = false;
bool isBuyCallback = false;
//是否开仓
bool isBuyOpened=false;
bool isSellOpened=false;

datetime buytime=0;
datetime selltime=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {   
     //向下取整
     //lots = MathFloor(AccountBalance()/10000);
     //获取所有的均线价格,长期,短期,回调
     double longmaPrice1 = iMA(NULL,0,longMa,0,MODE_SMA,PRICE_CLOSE,1);
     double longmaPrice2 = iMA(NULL,0,longMa,0,MODE_SMA,PRICE_CLOSE,2);
     double shortmaPrice1 = iMA(NULL,0,shortMa,0,MODE_SMA,PRICE_CLOSE,1);
     double shortmaPrice2 = iMA(NULL,0,shortMa,0,MODE_SMA,PRICE_CLOSE,2);
     double  callBackPrice = iMA(NULL,0,callBachMa,0,MODE_SMA,PRICE_CLOSE,0);
     
     //均线交叉多头
     if (shortmaPrice1>longmaPrice1 && shortmaPrice2<longmaPrice2){
        isCrossBuy = true;
        isCrossSell = false;
        isSellOpened = false;
        isSellCallback = false;
        closesell(Symbol()+"sell",magic);
     }
     
     //均线交叉空头
     if (shortmaPrice1<longmaPrice1 && shortmaPrice2>longmaPrice2){
        isCrossBuy = false;
        isCrossSell = true;
        isBuyOpened = false;
        isBuyCallback = false;
        closebuy(Symbol()+"buy",magic);
     }
     
     double lowPrice = Low[0];
     double highPrice = High[0];
     double openPrice = Open[0];
     double closePrice = Close[0];
     //符合做多的条件
     if(!isBuyOpened && isCrossBuy && lowPrice < callBackPrice){
         //time[0]  表示当前时间
        if (buytime!=Time[0]){   //解决当前K线重复下单的问题
          if ( buy(lots,stop,limit,Symbol()+"buy",magic)){
            buytime=Time[0];
            isBuyOpened = true;
          }
           
        } 
     }
     //符合做空的条件
     if(!isSellOpened && isCrossSell && highPrice > callBackPrice){
         //time[0]  表示当前时间
        if (selltime!=Time[0]){   //解决当前K线重复下单的问题
           if (sell(lots,stop,limit,Symbol()+"sell",magic)){
           
              selltime=Time[0];
              isSellOpened = true;
              
           }
           
        } 
     }
     yidongzhisun();
  }
  
  //下单函数 针对一个单子
  int buy(double lots,double stop , double limit,string comm,int buymagic){  //手数,止损,止盈,注释,magic
      int ticket=0;   //订单号
      bool zhaodan = false;  //判断有没有重复下单,其实上面已经写过了,这里不写也没关系
      for (int i=0; i < OrdersTotal(); i++){
         
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){
           string zhushi = OrderComment();
           int magicNumber = OrderMagicNumber();
           
           if (OrderSymbol()==Symbol() && OrderType()==OP_BUY && zhushi==comm && magicNumber==buymagic){
             zhaodan = true;
             break;
           }
         }
      }
      if (zhaodan==false){
         if (stop!=0 && limit==0){
            ticket = OrderSend(Symbol(),OP_BUY,lots,Ask,50,Ask-stop*Point,0,comm,buymagic,0,White);
         }
         if (stop==0 &&limit!=0)
             ticket = OrderSend(Symbol(),OP_BUY,lots,Ask,50,0,Ask+limit*Point,comm,buymagic,0,White);
         if (stop==0 &&limit==0)
             ticket = OrderSend(Symbol(),OP_BUY,lots,Ask,50,0,0,comm,buymagic,0,White);
             
         if (stop!=0 &&limit!=0)
             ticket = OrderSend(Symbol(),OP_BUY,lots,Ask,50,Ask-stop*Point,Ask+limit*Point,comm,buymagic,0,White);
         
      }
      
      return (ticket);
      
  }
  
  //下单函数 针对一个单子
  int sell(double lots,double stop , double limit,string comm,int sellmagic){  //手数,止损,止盈,注释,magic
      int ticket=0;   //订单号
      bool zhaodan = false;  //判断有没有重复下单,其实上面已经写过了,这里不写也没关系
      for (int i=0; i < OrdersTotal(); i++){
         
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){
           string zhushi = OrderComment();
           int magicNumber = OrderMagicNumber();
           
           if (OrderSymbol()==Symbol() && OrderType()==OP_SELL && zhushi==comm && magicNumber==sellmagic){
             zhaodan = true;
             break;
           }
         }
      }
      if (zhaodan==false){
         if (stop!=0 && limit==0){
            ticket = OrderSend(Symbol(),OP_SELL,lots,Bid,50,Bid+stop*Point,0,comm,sellmagic,0,White);
         }
         if (stop==0 &&limit!=0)
             ticket = OrderSend(Symbol(),OP_SELL,lots,Bid,50,0,Bid-limit*Point,comm,sellmagic,0,White);
         if (stop==0 &&limit==0)
             ticket = OrderSend(Symbol(),OP_SELL,lots,Bid,50,0,0,comm,sellmagic,0,White);
             
         if (stop!=0 &&limit!=0)
             ticket = OrderSend(Symbol(),OP_SELL,lots,Bid,50,Bid+stop*Point,Bid-limit*Point,comm,sellmagic,0,White);
         
      }
      
      return (ticket);
      
  }
  // 平货币
  void closebuy(string comm,int magic){
     for (int i=OrdersTotal()-1; i >=0; i--){
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){
           
           if (OrderSymbol()==Symbol() && OrderType() == OP_BUY && OrderComment() == comm && OrderMagicNumber() == magic){
             OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),300,Green);  
           }
         }
       }
 
  }
  // 平货币
  void closesell(string comm,int magic){
     for (int i=OrdersTotal()-1; i >=0; i--){
         if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){
           
           if (OrderSymbol()==Symbol() && OrderType()== OP_SELL && OrderComment() == comm && OrderMagicNumber() == magic){
             OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),300,Green);  
           }
         }
       }
 
  }
//设置移动止损
void yidongzhisun(){
  for (int i=0; i<OrdersTotal();i++)
  {
     if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){
           
      if (OrderSymbol()==Symbol() && OrderType() == OP_BUY && OrderMagicNumber() == magic){
      
         if ((Bid-OrderOpenPrice())>=Point*movestop){
         
            if (OrderStopLoss() <(Bid-Point*movestop) || OrderStopLoss()==0){
              OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*movestop,OrderTakeProfit(),0,Green);
            }
         }
      }
      if (OrderSymbol()==Symbol() && OrderType() == OP_SELL && OrderMagicNumber() == magic){
      
         if ((OrderOpenPrice()-Ask)>=Point*movestop){
         
            if (OrderStopLoss() <(Ask + Point*movestop) || OrderStopLoss()==0){
              OrderModify(OrderTicket(),OrderOpenPrice(),Ask + Point*movestop,OrderTakeProfit(),0,Green);
            }
         }
      }
      }
  }
}

//+------------------------------------------------------------------+
  • 11
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值