Более 3-х лет я мечтал, написать на MQL5 мультивалютный усреднитель и вот сегодня моя мечта осуществилась! Торговать советник будет по всем символам, которые имеются в окне рынка. Предварительно я посмотрел на работы других авторов, но мне захотелось иметь собственную основу. Прототипом послужил мой советник «Hello» на MQL4. Сразу же после создания эксперта он нарисовал мне вот такую красивую картинку за 2 года. Как такое могло получиться сам удивляюсь!
Начал я как всегда со входных переменных:
//--- входные параметры эксперта
input int TakeProfit = 500; // Тейкпрофит
input int StopLoss = 500; // Стоплосс
input int Step = 10; // Шаг между ордерами
input int BuySell = 1; // 0-не торгуем 1-Buy 2-Sell
input int AllSymbols = 1; // 0-символ графика 1-все символы
input int Slip = 50; // Проскальзывание
input double Lot = 0.1; // Количество лотов для торговли
input double MaxLot = 5; // Максимальный торговый объем
input double KLot = 2; // Увеличение лота
input double Profit = 50; // Профит в валюте
input long Magic = 123; // Магик
Функции открытия и закрытия позиций я снял со своего советника «Боллинджер на стероидах» и немного только исправил некоторые моменты.
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OpenBuy(string Symb)
{
double sl=0,tp=0;
// Лучшее предложение на покупку
double Ask=SymbolInfoDouble(Symb,SYMBOL_ASK);
if(StopLoss>0) sl=NormalizeDouble(Ask-StopLoss*_Point,_Digits);
if(TakeProfit>0) tp=NormalizeDouble(Ask+TakeProfit*_Point,_Digits);
//--- готовим запрос
MqlTradeRequest request={0};
request.action = TRADE_ACTION_DEAL; // немедленное исполнение
request.price = NormalizeDouble(Ask,_Digits); // последняя цена ask
request.sl = sl; // Stop Loss
request.tp = tp; // Take Profit
request.symbol=Symb; // символ
request.volume = Lot; // количество лотов для торговли
request.magic = Magic; // Magic Number
request.type = ORDER_TYPE_BUY; // ордер на покупку
request.type_filling = ORDER_FILLING_FOK; // тип исполнения ордера - все или ничего
request.deviation=Slip; // проскальзывание от текущей цены
//--- отправим торговый приказ
MqlTradeResult result={0};
if(OrderSend(request,result))
//--- выведем в лог ответ сервера
Print(__FUNCTION__,":",result.comment);
if(result.retcode==10016) Print(result.bid,result.ask,result.price);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OpenSell(string Symb)
{
double sl=0,tp=0;
// Лучшее предложение на продажу
double Bid=SymbolInfoDouble(Symb,SYMBOL_BID);
if(StopLoss>0) sl=NormalizeDouble(Bid+StopLoss*_Point,_Digits);
if(TakeProfit>0) tp=NormalizeDouble(Bid-TakeProfit*_Point,_Digits);
//--- готовим запрос
MqlTradeRequest request={0};
request.action = TRADE_ACTION_DEAL; // немедленное исполнение
request.price = NormalizeDouble(Bid,_Digits); // последняя цена bid
request.sl = sl; // Stop Loss
request.tp = tp; // Take Profit
request.symbol=Symb; // символ
request.volume = Lot; // количество лотов для торговли
request.magic = Magic; // Magic Number
request.type = ORDER_TYPE_SELL; // ордер на продажу
request.deviation=Slip; // проскальзывание от текущей цены
//--- отправим торговый приказ
MqlTradeResult result={0};
if(OrderSend(request,result))
//--- выведем в лог ответ сервера
Print(__FUNCTION__,":",result.comment);
if(result.retcode==10016) Print(result.bid,result.ask,result.price);
}
//+------------------------------------------------------------------+
//| Закрытие длинной позиции |
//+------------------------------------------------------------------+
void CloseBuy(string Symb)
{
double Bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); // лучшее предложение на продажу
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
{
//--- готовим запрос
MqlTradeRequest request={0};
request.action = TRADE_ACTION_DEAL; // немедленное исполнение
request.price = NormalizeDouble(Bid,_Digits); // последняя цена Bid
request.sl = 0; // Stop Loss
request.tp = 0; // Take Profit
request.symbol = Symb; // символ
request.volume = PositionGetDouble(POSITION_VOLUME);// количество лотов для торговли
request.magic = Magic; // Magic Number
request.type= ORDER_TYPE_SELL; // ордер на продажу
request.type_filling = ORDER_FILLING_FOK; // тип исполнения ордера - все или ничего
request.deviation=Slip; // проскальзывание от текущей цены
//--- отправим торговый приказ
MqlTradeResult result={0};
if(OrderSend(request,result))
//--- выведем в лог ответ сервера
Print(__FUNCTION__,":",result.comment);
if(result.retcode==10016) Print(result.bid,result.ask,result.price);
}
}
//+------------------------------------------------------------------+
//| Закрытие короткой позиции |
//+------------------------------------------------------------------+
void CloseSell(string Symb)
{
double Ask = SymbolInfoDouble(Symb,SYMBOL_ASK); // лучшее предложение на покупку
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
{
//--- готовим запрос
MqlTradeRequest request={0};
request.action = TRADE_ACTION_DEAL; // немедленное исполнение
request.price = NormalizeDouble(Ask,_Digits); // последняя цена ask
request.sl = 0; // Stop Loss
request.tp = 0; // Take Profit
request.symbol = Symb; // символ
request.volume = PositionGetDouble(POSITION_VOLUME); // количество лотов для торговли
request.magic = Magic; // Magic Number
request.type = ORDER_TYPE_BUY; // ордер на покупку
request.type_filling = ORDER_FILLING_FOK; // тип исполнения ордера - все или ничего
request.deviation=5; // проскальзывание от текущей цены
//--- отправим торговый приказ
MqlTradeResult result={0};
if(OrderSend(request,result))
//--- выведем в лог ответ сервера
Print(__FUNCTION__,":",result.comment);
if(result.retcode==10016) Print(result.bid,result.ask,result.price);
}
}
//+------------------------------------------------------------------+
В функции открытия позиций,
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OpenPos()
{
for(int i=SymbolsTotal(true)-1;i>=0;i--)
{
string Symb=SymbolName(i,true);
if(CountTrades(Symb)<1 && BuySell==1)
{
//--- Открываем ордер на покупку
OpenBuy(Symb);
}
//--- Sell
if(CountTrades(Symb)<1 && BuySell==2)
{
//--- Открываем ордер на продажу
OpenSell(Symb);
}
}
}
//+------------------------------------------------------------------+
сначала получаем количество символов в окне рынка
SymbolsTotal(true)
затем пробегаемся по всем символам и если нет открытой позы по инструменту,
CountTrades(Symb)<1
открываем ордер.
//--- Открываем ордер на покупку
OpenBuy(Symb);
Затем по аналогии с советником на MQL4 я стал писать другие функции. Сначала подсчет позиций по символу.
Функция на MQL4:
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CountTrades()
{
int count=0;
for(int i=OrdersTotal()-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
{
if(OrderType()==OP_BUY || OrderType()==OP_SELL)
count++;
}
}
}
return(count);
}
//+------------------------------------------------------------------+
Функция на MQL5:
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CountTrades(string Symb)
{
int count=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(PositionGetSymbol(i)==Symb)
{
if(PositionGetInteger(POSITION_MAGIC)==Magic)
{
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY || PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) count++;
}
}
}
return(count);
}
//+------------------------------------------------------------------+
Осилив правописание на примере одной функции не составило особого труда написать и все остальные:
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double SymbProfit(string Symb)
{
double pr=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(PositionGetSymbol(i)==Symb)
{
if(PositionGetInteger(POSITION_MAGIC)==Magic)
{
pr=+PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
}
}
}
return(pr);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CloseAll(string Symb)
{
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(PositionGetSymbol(i)==Symb)
{
if(PositionGetInteger(POSITION_MAGIC)==Magic)
{
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) CloseBuy(Symb);
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) CloseSell(Symb);;
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
long FindOrderType(string Symb)
{
long oticket,ticketNumber=0,type=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(PositionGetSymbol(i)==Symb)
{
if(PositionGetInteger(POSITION_MAGIC)==Magic)
{
oticket=PositionGetInteger(POSITION_IDENTIFIER);
if(oticket>ticketNumber)
{
ticketNumber=oticket;
type=PositionGetInteger(POSITION_TYPE);
}
}
}
}
return(type);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double FindLastBuyPrice(string Symb)
{
long oticket,ticketNumber=0;
double oprice=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(PositionGetSymbol(i)==Symb)
{
if(PositionGetInteger(POSITION_MAGIC)==Magic)
{
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
{
oticket=PositionGetInteger(POSITION_IDENTIFIER);
if(oticket>ticketNumber)
{
ticketNumber=oticket;
oprice=PositionGetDouble(POSITION_PRICE_OPEN);
}
}
}
}
}
return(oprice);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double FindLastSellPrice(string Symb)
{
long oticket,ticketNumber=0;
double oprice=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
if(PositionGetSymbol(i)==Symb)
{
if(PositionGetInteger(POSITION_MAGIC)==Magic)
{
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
{
oticket=PositionGetInteger(POSITION_IDENTIFIER);
if(oticket>ticketNumber)
{
ticketNumber=oticket;
oprice=PositionGetDouble(POSITION_PRICE_OPEN);
}
}
}
}
}
return(oprice);
}
//+------------------------------------------------------------------+
В процессе написания эксперта я выводил необходимые функции в коммент, чтобы удостовериться в работоспособности функции.
Comment("\n Pos: ",CountTrades("GBPUSD"),
"\n Type: ",FindOrderType("GBPUSD"),
"\n Price: ",FindLastSellPrice("GBPUSD"),
"\n Profit: ",SymbProfit("GBPUSD"),
"\n Symb1: ",SymbolName(0,true),
"\n Symb2: ",SymbolName(1,true),
"\n Symbols: ",SymbolsTotal(true));
Функция открытия усредняющих позиций была также написана по образцу с MQL4.
Функция на MQL4:
if(CountTrades()>0 && CountTrades()<=MaxTrades)
{
int otype=FindOrderType();
if(otype==OP_BUY)
{
price=FindLastBuyPrice();
if((price-Ask)/Point>=Step)
{
ticket=OrderSend(Symbol(),OP_BUY,Lot(),Ask,Slip,0,0,"Buy Order",Magic,0,Blue);
ModifyOrders();
}
}
else if(otype==OP_SELL)
{
price=FindLastSellPrice();
if((Bid-price)/Point>=Step)
{
ticket=OrderSend(Symbol(),OP_SELL,Lot(),Ask,Slip,0,0,"Sell Order",Magic,0,Red);
ModifyOrders();
}
}
}
Функция на MQL5:
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OpenLastPos()
{
for(int i=SymbolsTotal(true)-1;i>=0;i--)
{
string Symb=SymbolName(i,true);
// Лучшее предложение на покупку
double Ask=SymbolInfoDouble(Symb,SYMBOL_ASK);
// Лучшее предложение на продажу
double Bid=SymbolInfoDouble(Symb,SYMBOL_BID);
if(CountTrades(Symb)>0)
{
long otype=FindOrderType(Symb);
if(otype==0)
{
price=FindLastBuyPrice(Symb);
if((price-Ask)/_Point>=Step)
{
OpenBuy(Symb);
}
}
else if(otype==1)
{
price=FindLastSellPrice(Symb);
if((Bid-price)/_Point>=Step)
{
OpenSell(Symb);
}
}
}
}
}
//+------------------------------------------------------------------+
Закрытие позиций по символам когда превышен определенный уровень профита, у меня стоит только для одного символа. Как сделать по всем будет для вас домашним заданием
if(SymbProfit(_Symbol)>Profit) CloseAll(_Symbol);
Советник уже стоит у меня на демо и тестируется со следующими настройками.
П.С. Советник написан как пример разработки стратегии усреднения позиций, скачать можно по ссылке:
www.opentraders.ru/downloads/945/
Комментарии (0)
Зарегистрируйтесь или авторизуйтесь, чтобы оставить комментарий