2017/5/7
MT5入门到精通之十七(动态链接库,使用windows系统自带函数功能或用于加密)
一.安装dll开发工具 visual studio 2017 (enterprise)
注意要选择如下组件安装
2.创建如下类型的dll项目
3.开始写代码
3.1注意编译成64位的(MT5是64位的),已经将需要使用的函数在如下文件公共出来
3.2,将生成好的dll文件放入mt5中
3.3 调试正常
4.替换EA里面的 满足多单开单函数
4.1 mt5函数
bool satifyOpenBuy()
{
bool result=false;
if(h4_rates[0].low<h4_bollLow[0] && m30_fast[0]>m30_slow[0] && m30_kdj_main[0]>m30_kdj_signal[0] && m30_kdj_main[1]<m30_kdj_signal[1])
{
result=true;
}
return result;
}
4.2替换后c++函数(注意序列化不支持,需要dll函数里面自己处理)
#include <vector>
using namespace std;
//2.入栈出栈
#pragma pack(push,1)
struct MqlRates
{
__int64 time; // 周期开始时间
double open; // 开盘价
double high; // 周期最高价
double low; // 周期最低价
double close; // 收盘价
unsigned __int64 tick_volume; // 订单交易量
int spread; // 点差
unsigned __int64 real_volume; // 交易量
};
#pragma pack(pop)
//bool satifyOpenBuy(MqlRates &h4_rates[], double &h4_bollLow[], double &m30_fast[], double &m30_slow[], double &m30_kdj_main[], double &m30_kdj_signal[], int arrSize);
extern "C" BOOL PASCAL EXPORT satifyOpenBuy(MqlRates *h4_rates, double *h4_bollLow, double *m30_fast, double *m30_slow, double *m30_kdj_main, double *m30_kdj_signal, int arrSize)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
vector<MqlRates> v_h4_rates(h4_rates, h4_rates + arrSize);
reverse(v_h4_rates.begin(), v_h4_rates.end());
vector<double> v_h4_bollLow(h4_bollLow, h4_bollLow + arrSize);
reverse(v_h4_bollLow.begin(), v_h4_bollLow.end());
vector<double> v_m30_fast(m30_fast, m30_fast + arrSize);
reverse(v_m30_fast.begin(), v_m30_fast.end());
vector<double> v_m30_slow(m30_slow, m30_slow + arrSize);
reverse(v_m30_slow.begin(), v_m30_slow.end());
vector<double> v_m30_kdj_main(m30_kdj_main, m30_kdj_main + arrSize);
reverse(v_m30_kdj_main.begin(), v_m30_kdj_main.end());
vector<double> v_m30_kdj_signal(m30_kdj_signal, m30_kdj_signal + arrSize);
reverse(v_m30_kdj_signal.begin(), v_m30_kdj_signal.end());
BOOL a = FALSE;
if (v_h4_rates[0].low<v_h4_bollLow[0] && v_m30_fast[0]>v_m30_slow[0] && v_m30_kdj_main[0] > v_m30_kdj_signal[0] && v_m30_kdj_main[1] < v_m30_kdj_signal[1])
{
a = TRUE;
}
else
{
a = FALSE;
}
return(a);
}
4.3 别忘了将函数公开出来
5.完整代码如下 (注意序列化不支持,需要dll函数里面自己处理)
5.1//testMT5Dll.def
; testMT5Dll.def : 声明 DLL 的模块参数。
LIBRARY
EXPORTS
; 此处可以是显式导出
add
getString
arrDeal
satifyOpenBuy
5.2// testMT5Dll.cpp
// testMT5Dll.cpp : 定义 DLL 的初始化例程。
//
#include "stdafx.h"
#include "testMT5Dll.h"
#include <vector>
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//2.入栈出栈
#pragma pack(push,1)
struct MqlRates
{
__int64 time; // 周期开始时间
double open; // 开盘价
double high; // 周期最高价
double low; // 周期最低价
double close; // 收盘价
unsigned __int64 tick_volume; // 订单交易量
int spread; // 点差
unsigned __int64 real_volume; // 交易量
};
#pragma pack(pop)
//
//TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的,
// 则从此 DLL 导出的任何调入
// MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到
// 该函数的最前面。
//
// 例如:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // 此处为普通函数体
// }
//
// 此宏先于任何 MFC 调用
// 出现在每个函数中十分重要。 这意味着
// 它必须作为函数中的第一个语句
// 出现,甚至先于所有对象变量声明,
// 这是因为它们的构造函数可能生成 MFC
// DLL 调用。
//
// 有关其他详细信息,
// 请参阅 MFC 技术说明 33 和 58。
//
// CtestMT5DllApp
BEGIN_MESSAGE_MAP(CtestMT5DllApp, CWinApp)
END_MESSAGE_MAP()
// CtestMT5DllApp 构造
CtestMT5DllApp::CtestMT5DllApp()
{
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的一个 CtestMT5DllApp 对象
CtestMT5DllApp theApp;
// CtestMT5DllApp 初始化
BOOL CtestMT5DllApp::InitInstance()
{
CWinApp::InitInstance();
return TRUE;
}
//double add(double a,double b);
extern "C" double PASCAL EXPORT add(double a, double b)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// 此处为普通函数体
return a + b;
}
//string getString(string str);
extern "C" WCHAR* PASCAL EXPORT getString(WCHAR* str)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return(str);
}
//double arrDeal(double &aArr[],int arrSize,int &bArr[],int bArrSize,string &cArr[],int cArrSize);
extern "C" double PASCAL EXPORT arrDeal(double *aArr, int aArrSize, int *bArr, int bArrSize, WCHAR* *cArr, int cArrSize)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
//1.倒叙
vector<double> v_aArr(aArr, aArr + aArrSize);
reverse(v_aArr.begin(), v_aArr.end());
double aSum = 0;
for (int i = 0;i<aArrSize;i++)
{
aSum = aSum + aArr[i];
}
double bSum = 0;
for (int i = 0;i<bArrSize;i++)
{
bSum = bSum + bArr[i];
}
for (int i = 0;i<cArrSize;i++)
{
}
return(v_aArr[0]);
}
//bool satifyOpenBuy(MqlRates &h4_rates[], double &h4_bollLow[], double &m30_fast[], double &m30_slow[], double &m30_kdj_main[], double &m30_kdj_signal[], int arrSize);
extern "C" BOOL PASCAL EXPORT satifyOpenBuy(MqlRates *h4_rates, double *h4_bollLow, double *m30_fast, double *m30_slow, double *m30_kdj_main, double *m30_kdj_signal, int arrSize)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
vector<MqlRates> v_h4_rates(h4_rates, h4_rates + arrSize);
reverse(v_h4_rates.begin(), v_h4_rates.end());
vector<double> v_h4_bollLow(h4_bollLow, h4_bollLow + arrSize);
reverse(v_h4_bollLow.begin(), v_h4_bollLow.end());
vector<double> v_m30_fast(m30_fast, m30_fast + arrSize);
reverse(v_m30_fast.begin(), v_m30_fast.end());
vector<double> v_m30_slow(m30_slow, m30_slow + arrSize);
reverse(v_m30_slow.begin(), v_m30_slow.end());
vector<double> v_m30_kdj_main(m30_kdj_main, m30_kdj_main + arrSize);
reverse(v_m30_kdj_main.begin(), v_m30_kdj_main.end());
vector<double> v_m30_kdj_signal(m30_kdj_signal, m30_kdj_signal + arrSize);
reverse(v_m30_kdj_signal.begin(), v_m30_kdj_signal.end());
BOOL a = FALSE;
if (v_h4_rates[0].low<v_h4_bollLow[0] && v_m30_fast[0]>v_m30_slow[0] && v_m30_kdj_main[0] > v_m30_kdj_signal[0] && v_m30_kdj_main[1] < v_m30_kdj_signal[1])
{
a = TRUE;
}
else
{
a = FALSE;
}
return(a);
}
5.3 替换后EA代码testDllEA.mq5
//+------------------------------------------------------------------+
//| testDllEA.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#import "testMT5Dll.dll"
double add(double a,double b);
string getString(string str);
double arrDeal(double &aArr[],int arrSize,int &bArr[],int bArrSize,string &cArr[],int cArrSize);
bool satifyOpenBuy(MqlRates &h4_rates[], double &h4_bollLow[], double &m30_fast[], double &m30_slow[], double &m30_kdj_main[], double &m30_kdj_signal[], int arrSize);
#import
#include <wz\Trade.mqh>
#include <wz\Kline.mqh>
input int magic=170501;
input double lots=0.1;//开单量
input int slPoint=200;//止损点数
input int tpPoint=200;//止盈点数
input int fast_period=5;//小均线周期
input int slow_period=10;//大均线周期
input int boll_period=20;//布林带周期
input double boll_deviations=2;//布林带偏差
input int kdj_kPeriod=5;//KDJ K period
input int kdj_dPeriod=3;//KDJ D period
input int kdj_jPeriod=3;//KDJ J period
Trade td;//交易对象
Kline kl;//行情对象
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//为了函数间可以访问数组,声明生全局变量(注意指标里面都做过倒序处理)
//1.定义获取指标数据的数组
//数据索引最大是1,所有只需要获取2个值即可
int count=2;
double m30_fast[];
double m30_slow[];
double h4_fast[];
double h4_slow[];
double m30_bollUp[],m30_bollLow[],m30_bollMid[];
double h4_bollUp[],h4_bollLow[],h4_bollMid[];
double m30_kdj_main[],m30_kdj_signal[];
double h4_kdj_main[],h4_kdj_signal[];
MqlRates m30_rates[];
MqlRates h4_rates[];
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnTick()
{
//2.获取指标值
kl.MA(m30_fast,count,Symbol(),PERIOD_M30,fast_period,0,MODE_SMA,PRICE_CLOSE);
kl.MA(m30_slow,count,Symbol(),PERIOD_M30,slow_period,0,MODE_SMA,PRICE_CLOSE);
kl.MA(h4_fast,count,Symbol(),PERIOD_H4,fast_period,0,MODE_SMA,PRICE_CLOSE);
kl.MA(h4_slow,count,Symbol(),PERIOD_H4,slow_period,0,MODE_SMA,PRICE_CLOSE);
kl.Bands(m30_bollUp,m30_bollLow,m30_bollMid,count,Symbol(),PERIOD_M30,boll_period,0,boll_deviations,PRICE_CLOSE);
kl.Bands(h4_bollUp,h4_bollLow,h4_bollMid,count,Symbol(),PERIOD_H4,boll_period,0,boll_deviations,PRICE_CLOSE);
kl.Stochastic(m30_kdj_main,m30_kdj_signal,count,Symbol(),PERIOD_M30,kdj_kPeriod,kdj_dPeriod,kdj_jPeriod,MODE_SMA,STO_LOWHIGH);
kl.Stochastic(h4_kdj_main,h4_kdj_signal,count,Symbol(),PERIOD_H4,kdj_kPeriod,kdj_dPeriod,kdj_jPeriod,MODE_SMA,STO_LOWHIGH);
kl.getRates(m30_rates,count,Symbol(),PERIOD_M30);
kl.getRates(h4_rates,count,Symbol(),PERIOD_H4);
//3.条件判断进行开仓和平仓
/*if(satifyOpenBuy())
{
td.buyPlus(Symbol(),lots,slPoint,tpPoint,Symbol()+"buy",magic);
}*/
//3.1 用dll函数实现satifyOpenBuy
if(satifyOpenBuy(h4_rates,h4_bollLow,m30_fast,m30_slow,m30_kdj_main,m30_kdj_signal,count)==true)
{
td.buyPlus(Symbol(),lots,slPoint,tpPoint,Symbol()+"buy",magic);
}
/*if(satifyCloseBuy())
{
td.closeAllBuy(Symbol(),magic);
}
if(satifyOpenSell())
{
td.sellPlus(Symbol(),lots,slPoint,tpPoint,Symbol()+"sell",magic);
}
if(satifyCloseSell())
{
td.closeAllSell(Symbol(),magic);
}*/
}
//+------------------------------------------------------------------+
bool satifyOpenBuy()
{
bool result=false;
if(h4_rates[0].low<h4_bollLow[0] && m30_fast[0]>m30_slow[0] && m30_kdj_main[0]>m30_kdj_signal[0] && m30_kdj_main[1]<m30_kdj_signal[1])
{
result=true;
}
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool satifyCloseBuy()
{
bool result=false;
if(m30_kdj_main[0]<m30_kdj_signal[0] && m30_kdj_main[1]>m30_kdj_signal[1])
{
result=true;
}
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool satifyOpenSell()
{
bool result=false;
if(h4_rates[0].high>h4_bollUp[0] && m30_fast[0]<m30_slow[0] && m30_kdj_main[0]<m30_kdj_signal[0] && m30_kdj_main[1]>m30_kdj_signal[1])
{
result=true;
}
return result;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool satifyCloseSell()
{
bool result=false;
if(m30_kdj_main[0]>m30_kdj_signal[0] && m30_kdj_main[1]<m30_kdj_signal[1])
{
result=true;
}
return result;
}
//+------------------------------------------------------------------+
如果您发现本文对你有所帮助,如果您认为其他人也可能受益,请把它分享出去。