多币种交易程序架构设计-Multi currency transaction program architecture design - MetaTrader 4EA
- 显示:
- 15246
- 等级:
- 已发布:
- 2021.04.17 18:17
- 需要基于此代码的EA交易或指标吗?请在自由职业者服务中订购 进入自由职业者服务
//+------------------------------------------------------------------+
//| muskEAone.mq4 |
//| BillAbiao,QQ:327151901,WX:billabiao |
//| https://one.exness.link/a/sduus6ff |
//+------------------------------------------------------------------+
#property copyright "点击开户:BillAbiao,QQ:327151901,WX:billabiao"
#property link "https://one.exness.link/a/sduus6ff"
#property version "1.00"
#property strict
//------------
string userSymbols2[]={"EURUSD","GBPUSD","GBPCHF"};
//string userSymbols2[]={"EURUSD"};
//string userSymbols2[];
string systemSymbols[];
string debugMsg;
double minEquity,maxEquity;
bool stopFlagRun=false;
//----------
struct CONTROL_DATA{
int index;
string strSymbol;
ENUM_TIMEFRAMES timeFrame;//=PERIOD_H2;
int ExtHandle;
// CTrade ExtTrade;
int magicma;
int switchDo;
int orders_buy,orders_sell;
int orders_pending_buy,orders_pending_sell;
double minOpenPrice_buy,minOpenPrice_sell;
ulong maxOpenPrice_buy_ticket;
ulong minOpenPrice_buy_ticket;
double maxOpenPrice_buy,maxOpenPrice_sell;
double maxPendingOpenPrice_buy,maxPendingOpenPrice_sell;
ulong maxPendingOpenPrice_buy_ticket,maxPendingOpenPrice_sell_ticket;
double minPendingOpenPrice_buy,minPendingOpenPrice_sell;
ulong minPendingOpenPrice_buy_ticket,minPendingOpenPrice_sell_ticket;
double profit_buy,profit_sell;
double volume_buy,volume_sell;
ENUM_ORDER_TYPE signal;
double agvLen;
double minOpenPrice_profitBuy;
double maxOpenPrice_profitBuy;
double maxOpenPrice_volume;
double minOpenPrice_buyVolume;
double maxProfitBuy,minProfitBuy;
datetime lastOpenDateTime;
double maxPendingOpenPrice_volume;
double magicN;
double skip;
ulong stopLevel;//=SymbolInfoInteger(d[index].strSymbol,SYMBOL_SPREAD);
double point;
ulong spread;
double lastAsk;
double ask,bid;
int digits;
};
CONTROL_DATA d[];
#define MAGICMA 03082100
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
initSymbols();
int n=ArraySize(systemSymbols);
ArrayResize(d,n);
for(int i=0;i<n;i++)
{
OnInit_INDEX(i);
}
//---
EventSetTimer(6);
minEquity=0;
maxEquity=0;
return(INIT_SUCCEEDED);
}
void OnInit_INDEX(int index)
{
int k=index;
d[k].index=index;
d[k].strSymbol=systemSymbols[index];
d[k].timeFrame=PERIOD_H1;
d[k].magicma=MAGICMA+index;
d[k].switchDo=1;
d[k].maxProfitBuy=0;
d[k].minProfitBuy=0;
d[k].magicN=5;
d[k].lastAsk=SymbolInfoDouble(d[k].strSymbol,SYMBOL_ASK);
}
void initSymbols()
{
int n=ArraySize(userSymbols2);
ArrayResize(systemSymbols,n);
int i;
for(i=0;i<n;i++)
{
// systemSymbols[i]=userSymbols2[i];
systemSymbols[i]=getSystemSymbol(userSymbols2[i]);
}
return ;
}
string getSystemSymbol(string strSymbol)
{
string ret="";
int n=SymbolsTotal(false);
int i;
string strTemp=strSymbol;
StringToLower(strTemp);
for(i=0;i<n;i++)
{
string name=SymbolName(i,false);
StringToLower( name);
if( strTemp==StringSubstr(name,0,6))
{
ret=SymbolName(i,false);
break;
}
}
return ret;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
EventKillTimer();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
MainRUN( "Tick " );
return ;
/*
debugMsg="";
mainRun();
Comment(debugMsg);
*/
}
void OnTimer()
{
MainRUN( "Timer" );
return ;
}
bool runFlag=false;
void MainRUN( string strWho)
{
if( runFlag) return ;
runFlag=true;
debugMsg=strWho+": ";
mainRun();
runFlag=false;
Comment(debugMsg);
return ;
}
//+------------------------------------------------------------------+
void mainRun()
{
getMainData();
if( stopFlagRun) return ;
int i,n=ArraySize(d);
for( i=0;i<n;i++)
{
subControlSymbol(i);
}
return ;
}
void getMainData()
{
debugMsg+="mainData,";
debugMsg+=StringFormat("date=%s\n", TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS));
double equity=AccountEquity();
if( minEquity==0 || equity<minEquity) minEquity=equity;
if( maxEquity==0 || equity>maxEquity) maxEquity=equity;
debugMsg+=StringFormat("minEquity=%.2f,maxEquity=%.2f,Equity=%.2f\n",minEquity,maxEquity,equity);
if( equity<10)
{
stopFlagRun=true;
}
return ;
}
void subControlSymbol(int index)
{
debugMsg+=StringFormat("%d--> %s\n",index+1, d[index].strSymbol);
control_getdata(index);
switch (d[index].switchDo)
{
case 1:
d[index].switchDo=2;
control_open(index);
break;
case 2:
d[index].switchDo=3;
control_close(index);
break;
case 3:
d[index].switchDo=1;
control_modify(index);
break;
}
//------
debugMsg+="\n";
return ;
}
void control_open(int index)
{
debugMsg+="open\n";
double lots=0.01;
/*
if( d[index].orders_buy==0)
{
double ask=SymbolInfoDouble(d[index].strSymbol,SYMBOL_ASK);
bool res=OrderSend(d[index].strSymbol,OP_BUY,lots,ask,3,0,0,"",d[index].magicma,0,Blue);
return ;
}
if( d[index].orders_sell==0)
{
double bid=SymbolInfoDouble(d[index].strSymbol,SYMBOL_BID);
bool res=OrderSend(d[index].strSymbol,OP_SELL,lots,bid,3,0,0,"",d[index].magicma,0,Red);
return ;
}
*/
if( d[index].ask==d[index].lastAsk){
//debugMsg+="-------------\n";
return ;
}
d[index].lastAsk=d[index].ask;
if( d[index].orders_pending_buy==0 && d[index].orders_buy==0)
{
double ask=SymbolInfoDouble(d[index].strSymbol,SYMBOL_ASK);
double price=ask-d[index].point*(d[index].stopLevel+1);
price=NormalizeDouble(price,d[index].digits);
int res=OrderSend(d[index].strSymbol,OP_BUYLIMIT,lots,price,3,0,0,"",d[index].magicma,0,Blue);
if( res<0 ){
// stopFlagRun=true;
Print("open limit price=",price);
Print("ask=",ask);
}
return ;
}
if( d[index].orders_pending_buy==0) //add pending order
{
double val_1=2*d[index].point*(d[index].stopLevel);
// double val_2=d[index].point*d[index].spread;
double price;//=d[index].minOpenPrice_buy-val_1;//d[index].point*d[index].stopLevel;
double ask=SymbolInfoDouble(d[index].strSymbol,SYMBOL_ASK);
if( ask<d[index].minOpenPrice_buy)
{
price=ask-val_1;
}
else{
price=d[index].minOpenPrice_buy-val_1;
}
//if( ask-price<= val_1*1.5) return ;
lots=countVolumeBuy(index,price);
if( lots<=0) return ;
price=NormalizeDouble(price,d[index].digits);
int res=OrderSend(d[index].strSymbol,OP_BUYLIMIT,lots,price,3,0,0,"",d[index].magicma,0,Blue);
if( res<0 ){
// stopFlagRun=true;
Print("limit price=",price);
Print("ask=",ask);
}
}
return ;
}
double countVolumeBuy(int index, double openPrice)
{
double ret=0;
int i,n=OrdersTotal();
//if( n<=0) return ;
double val=1.5*d[index].point*d[index].stopLevel;
if( val<=0) return ret;
double setPrice=openPrice+val;
double profitAll=0;
for(i=0;i<n;i++)
{
if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
continue;
if( OrderSymbol()!=d[index].strSymbol) continue;
if( OrderMagicNumber()!=d[index].magicma) continue;
profitAll+=(OrderOpenPrice()-setPrice)*OrderLots()*100;
}
ret=MathAbs(profitAll)/(100*val);
double maxLots=SymbolInfoDouble(d[index].strSymbol,SYMBOL_VOLUME_MAX);
if( ret>maxLots) ret=maxLots;
if( ret>0 && ret<0.01) ret=0.01;
ret=NormalizeDouble(ret,2);
return ret;
}
void control_close(int index)
{
debugMsg+="close\n";
if( d[index].orders_buy==0 && d[index].orders_pending_buy>0)
{
double val=d[index].maxPendingOpenPrice_buy+d[index].point*d[index].stopLevel;
if( d[index].bid>val)
{
deleteAllPendingOrders(index,OP_BUYLIMIT);
return ;
}
}
if( d[index].orders_buy>0 )
{
double val=d[index].point*d[index].stopLevel;
if( d[index].bid> d[index].maxOpenPrice_buy+val)
{
closeAllOrders(index, OP_BUY);
deleteAllPendingOrders(index,OP_BUYLIMIT);
return ;
}
double val2=d[index].minOpenPrice_buy+1.5*d[index].stopLevel*d[index].point;
//debugMsg+=StringFormat("val2=%.5f\n",val2);
if( d[index].bid> val2 && d[index].minOpenPrice_profitBuy+ d[index].maxOpenPrice_profitBuy>0)
{
debugMsg+=StringFormat("val2=%.5f\n",val2);
closeSomeOrders(index);
deleteAllPendingOrders(index,OP_BUYLIMIT);
return ;
}
}
return ;
}
void deleteAllPendingOrders(int index,int orderType)
{
//for(;;)
// {
int i,n;
n=OrdersTotal();
if( n<=0) return ;
for(i=0;i<n;i++)
{
if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
continue;
if( OrderSymbol()!=d[index].strSymbol) continue;
if( OrderMagicNumber()!=d[index].magicma) continue;
/*
if(OrderType()==OP_BUY)
{
double bid=SymbolInfoDouble(OrderSymbol(), SYMBOL_BID);
if(!OrderClose(OrderTicket(),OrderLots(),bid,3,Violet))
{
break;
}
}
else if(OrderType()==OP_SELL)
{
double ask=SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK);
if(!OrderClose(OrderTicket(),OrderLots(),ask,3,Violet))
{
break;
}
}*/
if(OrderType()==orderType){
bool ret=OrderDelete(OrderTicket(),Violet);
}
}
// }
}
void closeAllOrders(int index,int orderType)
{
//for(;;)
// {
int i,n;
n=OrdersTotal();
if( n<=0) return ;
for(i=0;i<n;i++)
{
if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
continue;
if( OrderSymbol()!=d[index].strSymbol) continue;
if( OrderMagicNumber()!=d[index].magicma) continue;
if( OrderType()!=orderType) continue;
if(OrderType()==OP_BUY)
{
double bid=SymbolInfoDouble(OrderSymbol(), SYMBOL_BID);
if(!OrderClose(OrderTicket(),OrderLots(),bid,3,Violet))
{
break;
}
}
else if(OrderType()==OP_SELL)
{
double ask=SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK);
if(!OrderClose(OrderTicket(),OrderLots(),ask,3,Violet))
{
break;
}
}
//if(OrderType()==orderType){
// bool ret=OrderDelete(OrderTicket(),Violet);
//}
}
// }
}
void closeSomeOrders(int index)
{
int i,n;
n=OrdersTotal();
if( n<=0) return ;
for(i=0;i<n;i++)
{
if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
continue;
if( OrderSymbol()!=d[index].strSymbol) continue;
if( OrderMagicNumber()!=d[index].magicma) continue;
//if( OrderType()!=orderType) continue;
if(OrderType()==OP_BUY)
{
if( OrderTicket()==d[index].maxOpenPrice_buy_ticket || OrderTicket()==d[index].minOpenPrice_buy_ticket)
{
double bid=SymbolInfoDouble(OrderSymbol(), SYMBOL_BID);
if(!OrderClose(OrderTicket(),OrderLots(),bid,3,Violet))
{
break;
}
}
}
}
}
void control_modify(int index)
{
debugMsg+="modify\n";
}
void control_getdata(int index)
{
debugMsg+="control getdata,";
d[index].spread=SymbolInfoInteger(d[index].strSymbol,SYMBOL_SPREAD);
d[index].point=SymbolInfoDouble(d[index].strSymbol, SYMBOL_POINT);
d[index].stopLevel=SymbolInfoInteger(d[index].strSymbol, SYMBOL_TRADE_STOPS_LEVEL);
debugMsg+=StringFormat("spread=%d, point=%.5f, stopLevel=%d\n",d[index].spread ,d[index].point, d[index].stopLevel) ;
//--
uint dataLen=60;
double allLen=0;
ENUM_TIMEFRAMES timeFrame=PERIOD_D1;
// timeFrame=d[index].timeFrame;
uint i;
for(i=0;i<dataLen;i++)
{
double high=iHigh(d[index].strSymbol,timeFrame,i+1);
double low=iLow(d[index].strSymbol,timeFrame,i+1);
allLen+=MathAbs( high-low);
}
d[index].agvLen= allLen/(dataLen);
d[index].skip=d[index].agvLen/6;
debugMsg+=StringFormat( "agvLen=%.5f, skip=%.5f\n", d[index].agvLen, d[index].skip);
//-------
int buys=0,sells=0;
d[index].orders_pending_buy=0;
d[index].orders_pending_sell=0;
d[index].minOpenPrice_buy=0;
d[index].maxOpenPrice_buy=0;
d[index].minPendingOpenPrice_buy=0;
d[index].maxPendingOpenPrice_buy=0;
d[index].profit_buy=0;
d[index].profit_sell=0;
//---
uint n=OrdersTotal();
for(i=0;i<n;i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderSymbol()==d[index].strSymbol && OrderMagicNumber()==d[index].magicma )
{
double price=OrderOpenPrice();
if(OrderType()==OP_BUY){
buys++;
double buyProfit=OrderProfit()+OrderCommission()+OrderSwap();
if( d[index].minOpenPrice_buy==0 || price<d[index].minOpenPrice_buy)
{
d[index].minOpenPrice_buy=price;
d[index].minOpenPrice_buy_ticket=OrderTicket();
d[index].minOpenPrice_profitBuy=buyProfit;
}
if( d[index].maxOpenPrice_buy==0 || price>d[index].maxOpenPrice_buy)
{
d[index].maxOpenPrice_buy=price;
d[index].maxOpenPrice_buy_ticket=OrderTicket();
d[index].maxOpenPrice_profitBuy=buyProfit;
}
d[index].profit_buy+=OrderProfit()+OrderCommission()+OrderSwap();
}
else if(OrderType()==OP_SELL){
sells++;
d[index].profit_sell+=OrderProfit()+OrderCommission()+OrderSwap();
}
else if(OrderType()==OP_BUYLIMIT){
d[index].orders_pending_buy++;
if( d[index].minPendingOpenPrice_buy==0 || price<d[index].minPendingOpenPrice_buy )
{
d[index].minPendingOpenPrice_buy=price;
}
if( d[index].maxPendingOpenPrice_buy==0 || price>d[index].maxPendingOpenPrice_buy )
{
d[index].maxPendingOpenPrice_buy=price;
}
}
else if(OrderType()==OP_SELLLIMIT){
d[index].orders_pending_sell++;
}
}
}
d[index].orders_buy=buys;
d[index].orders_sell=sells;
debugMsg+=StringFormat( "buys=%d, sells=%d\n", d[index].orders_buy, d[index].orders_sell);
debugMsg+=StringFormat( "pendingbuys=%d, pendingsells=%d\n", d[index].orders_pending_buy, d[index].orders_pending_sell);
debugMsg+=StringFormat( "minOpenPrice=%.5f, maxOpenPrice=%.5f\n", d[index].minOpenPrice_buy, d[index].maxOpenPrice_buy);
debugMsg+=StringFormat( "minPendingOpenPrice=%.5f, maxPendingOpenPrice=%.5f\n", d[index].minPendingOpenPrice_buy, d[index].maxPendingOpenPrice_buy );
//-----------
d[index].bid=SymbolInfoDouble( d[index].strSymbol, SYMBOL_BID);
d[index].ask=SymbolInfoDouble( d[index].strSymbol, SYMBOL_ASK);
debugMsg+=StringFormat( "profit_buy=%.2f, profit_sell=%.2f\n", d[index].profit_buy, d[index].profit_sell);
d[index].digits=(int)SymbolInfoInteger(d[index].strSymbol,SYMBOL_DIGITS);
return ;
}
在服务中心获取要平仓的单子,定时去判断
三條平均移動線交叉顯示 Tri MA Corss三條平均線完全按照高低排列後 可視為趨勢成形 在形態被破壞後 不再繪出影線 在沒有影線的條件下 視為不確定期間
Multi-currency trading in one chart
MT4持仓助手 辅助性EA 订单半自动管理 大量快捷键MT4持仓助手 辅助性EA 订单半自动管理 自动设置止盈止损移动止损 分批平仓 划线模式 横线模式 布林带平仓 定时器追踪止盈止损等 同时有大量快捷键处理下单 改止盈止损 挂单等 省时省力。 使用前请先打印EA快捷键说明文件