Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 728
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Здравствуйте. Как то писал советник на MetaTraider 4. Вернее учился писать. Многое не умею и не знаю еще. И решил перенести его на MetaTraider 5 где немного оказалось все по другому. Вообщем брал другой советник. Разбирал его. Копировал код для открытия ставок. Вообщем ошибок вроде нету но работает не так как должно быть. Помогите перенести правильно.
MetaTraider 4:
int err = 0;
double Lot = 0.01; // Лот
double CoofLot = 0;
double Ballance = AccountBalance();
double loss = 100;
bool nap = true; //true - 1
//false - 0
int start()
{
if(OrdersTotal()==0)
{
if(Ballance != AccountBalance())
{
if(AccountBalance() < Ballance )
{
CoofLot++;
Lot = pow(2, CoofLot) * 0.01;
if(nap == true)
{
nap = false;
}
else
{
nap = true;
}
}
if(AccountBalance() > Ballance)
{
Lot = 0.01;
CoofLot = 0;
}
}
Ballance = AccountBalance();
int order;
if(nap == true)
{
order = OrderSend(Symbol(),OP_BUY,Lot,Ask,1*Point,Ask-loss*Point,Ask+loss*Point); // Вверх
}
else
{
order = OrderSend(Symbol(),OP_SELL,Lot,Bid,1*Point,Bid+loss*Point,Bid-loss*Point); // Вниз
}
if(order<0)
{
if (GetLastError()==134)
{
err=1;
Print("NOT ENOGUGHT MONEY!!");
}
return (-1);
}
}
return(0);
}
И вот кое как перенес на MetaTraider 5:
double CoofLot = 0;
double Ballance = ACCOUNT_BALANCE;
double loss = 100;
bool nap = true; //true - 1
//false - 0
void OnTick()
{
MqlTick latest_price; // Будет использоваться для текущих котировок
MqlTradeRequest mrequest; // Будет использоваться для отсылки торговых запросов
MqlTradeResult mresult;
if(OrdersTotal()==0)
{
if(!SymbolInfoTick(_Symbol,latest_price))
{
Alert("Ошибка получения последних котировок - ошибка:",GetLastError(),"!!");
return;
}
if(Ballance != ACCOUNT_BALANCE)
{
if(ACCOUNT_BALANCE < Ballance )
{
CoofLot++;
Lot = pow(2, CoofLot) * 0.01;
if(nap == true)
{
nap = false;
}
else
{
nap = true;
}
}
if(ACCOUNT_BALANCE > Ballance)
{
Lot = 0.01;
CoofLot = 0;
}
}
Ballance = ACCOUNT_BALANCE;
int order;
if(nap == true)
{
mrequest.action = TRADE_ACTION_DEAL; // немедленное исполнение
mrequest.price = NormalizeDouble(latest_price.ask,_Digits); // последняя цена ask
mrequest.sl = NormalizeDouble(latest_price.ask - 100*_Point,_Digits); // Stop Loss
mrequest.tp = NormalizeDouble(latest_price.ask + 100*_Point,_Digits); // Take Profit
mrequest.symbol = _Symbol; // символ
mrequest.volume = Lot; // количество лотов для торговли
mrequest.type = ORDER_TYPE_BUY; // ордер на покупку
mrequest.type_filling = ORDER_FILLING_FOK; // тип исполнения ордера - все или ничего
mrequest.deviation=100; // проскальзывание от текущей цены
//--- отсылаем ордер
order = OrderSend(mrequest,mresult);
}
else
{
mrequest.action = TRADE_ACTION_DEAL; // немедленное исполнение
mrequest.price = NormalizeDouble(latest_price.bid,_Digits); // последняя цена Bid
mrequest.sl = NormalizeDouble(latest_price.bid + 100*_Point,_Digits); // Stop Loss
mrequest.tp = NormalizeDouble(latest_price.bid - 100*_Point,_Digits); // Take Profit
mrequest.symbol = _Symbol; // символ
mrequest.volume = Lot; // количество лотов для торговли
mrequest.type= ORDER_TYPE_SELL; // ордер на продажу
mrequest.type_filling = ORDER_FILLING_FOK; // тип исполнения ордера - все или ничего
mrequest.deviation=100; // проскальзывание от текущей цены
//--- отсылаем ордер
order = OrderSend(mrequest,mresult);
}
}
return;
}
Здравствуйте. Как то писал советник на MetaTraider 4. Вернее учился писать. Многое не умею и не знаю еще. И решил перенести его на MetaTraider 5 где немного оказалось все по другому. Вообщем брал другой советник. Разбирал его. Копировал код для открытия ставок. Вообщем ошибок вроде нету но работает не так как должно быть. Помогите перенести правильно.
Код будет такой (но при этом будьте внимательны - здесь идёт проверка на общее количество позиций на торговом счёте (PositionsTotal):
то есть нет проверки сколько именно позиций по данному символу и данному Magic (к слову сказать, Magic вообще не задан))
//| TestEA.mq5 |
//| Copyright © 2016, Vladimir Karputov |
//| http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2016, Vladimir Karputov"
#property link "http://wmua.ru/slesar/"
#property version "1.00"
//---
double Lot = 0.01;
double CoofLot = 1.0;
double loss = 100.0;
bool nap = true;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
CoofLot = 1.0;
loss = 100.0;
nap = true;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
static double Balance=0.0;
if(Balance==0.0)
Balance=AccountInfoDouble(ACCOUNT_BALANCE);
if(PositionsTotal()==0)
{
MqlTick latest_price; // Будет использоваться для текущих котировок
if(!SymbolInfoTick(_Symbol,latest_price))
{
Alert("Ошибка получения последних котировок - ошибка:",GetLastError(),"!!");
return;
}
if(Balance!=AccountInfoDouble(ACCOUNT_BALANCE))
{
if(AccountInfoDouble(ACCOUNT_BALANCE)<Balance)
{
CoofLot++;
Lot=pow(2,CoofLot)*0.01;
if(nap==true)
{
nap=false;
}
else
{
nap=true;
}
}
if(AccountInfoDouble(ACCOUNT_BALANCE)>Balance)
{
Lot=0.01;
CoofLot=1.0;
}
}
Balance=AccountInfoDouble(ACCOUNT_BALANCE);
MqlTradeRequest mrequest; // Будет использоваться для отсылки торговых запросов
MqlTradeResult mresult;
ZeroMemory(mrequest);
ZeroMemory(mresult);
bool order=false;
if(nap==true)
{
mrequest.action = TRADE_ACTION_DEAL; // немедленное исполнение
mrequest.price = NormalizeDouble(latest_price.ask,_Digits); // последняя цена ask
mrequest.sl = NormalizeDouble(latest_price.bid - 100*_Point,_Digits); // Stop Loss
mrequest.tp = NormalizeDouble(latest_price.bid + 100*_Point,_Digits); // Take Profit
mrequest.symbol = _Symbol; // символ
mrequest.volume = Lot; // количество лотов для торговли
mrequest.type = ORDER_TYPE_BUY; // ордер на покупку
mrequest.type_filling = ORDER_FILLING_FOK; // тип исполнения ордера - все или ничего
mrequest.deviation=100; // проскальзывание от текущей цены
//--- отсылаем ордер
order=OrderSend(mrequest,mresult);
}
else
{
mrequest.action = TRADE_ACTION_DEAL; // немедленное исполнение
mrequest.price = NormalizeDouble(latest_price.bid,_Digits); // последняя цена Bid
mrequest.sl = NormalizeDouble(latest_price.ask + 100*_Point,_Digits); // Stop Loss
mrequest.tp = NormalizeDouble(latest_price.ask - 100*_Point,_Digits); // Take Profit
mrequest.symbol = _Symbol; // символ
mrequest.volume = Lot; // количество лотов для торговли
mrequest.type= ORDER_TYPE_SELL; // ордер на продажу
mrequest.type_filling = ORDER_FILLING_FOK; // тип исполнения ордера - все или ничего
mrequest.deviation=100; // проскальзывание от текущей цены
//--- отсылаем ордер
order=OrderSend(mrequest,mresult);
}
}
return;
}
//+------------------------------------------------------------------+
Также результат операции OrderSend имеет тип bool.
Для хранения баланса я применил статическую переменную
if(Balance==0.0)
Balance=AccountInfoDouble(ACCOUNT_BALANCE);
- то есть переменная "Balance" при последующих заходах в OnTick() не будет пересоздаваться заново, а она будет помнить своё значение с предыдущего тика.
Хотя я бы написал так:
//| TestEA.mq5 |
//| Copyright © 2017, Vladimir Karputov |
//| http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2017, Vladimir Karputov"
#property link "http://wmua.ru/slesar/"
#property version "1.001"
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
CPositionInfo m_position; // trade position object
CTrade m_trade; // trading object
CSymbolInfo m_symbol; // symbol info object
CAccountInfo m_account; // account info wrapper
//---
double Lot = 0.01;
double CoofLot = 1.0;
double Loss = 100.0;
bool nap = true;
//---
ulong m_magic = 15489; // magic number
ulong m_slippage = 10; // slippage
double m_adjusted_point; // point value adjusted for 3 or 5 points
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
m_symbol.Name(Symbol()); // sets symbol name
if(!RefreshRates())
{
Print("Error RefreshRates. Bid=",DoubleToString(m_symbol.Bid(),Digits()),
", Ask=",DoubleToString(m_symbol.Ask(),Digits()));
return(INIT_FAILED);
}
m_symbol.Refresh();
//---
m_trade.SetExpertMagicNumber(m_magic);
//---
m_trade.SetDeviationInPoints(m_slippage);
//--- tuning for 3 or 5 digits
int digits_adjust=1;
if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
digits_adjust=10;
m_adjusted_point=m_symbol.Point()*digits_adjust;
//---
CoofLot = 1.0;
Loss = 100.0;
nap = true;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
static double static_Balance=0.0;
if(static_Balance==0.0)
static_Balance=m_account.Balance();
double balance=m_account.Balance(); // локальная переменная для хранения баланса на время OnTick
//--- считаем позиции по символу и по Magic
int total=0;
for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of open positions
if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
total++;
if(total==0)
{
//--- попытка обновить цены
if(!RefreshRates())
return; // есил не удалось обновить цены - просто выходим
if(static_Balance!=balance)
{
if(balance<static_Balance)
{
CoofLot++;
double lots=pow(2,CoofLot)*0.01; // локальная переменная для временных расчётов лота
//--- проверка корректности лота
Lot=LotCheck(lots);
if(Lot==0.0)
return;
if(nap)
nap=false;
else
nap=true;
}
if(balance>static_Balance)
{
Lot=0.01;
CoofLot=1.0;
}
}
static_Balance=balance;
if(nap==true)
{
double sl=m_symbol.NormalizePrice(m_symbol.Bid() - Loss*m_adjusted_point); // Stop Loss
double tp=m_symbol.NormalizePrice(m_symbol.Bid() + Loss*m_adjusted_point); // Take Profit
if(m_trade.Buy(Lot,NULL,m_symbol.Ask(),sl,tp))
{
if(m_trade.ResultDeal()==0)
Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
else
Print("Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
}
else
Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
}
else
{
double sl=m_symbol.NormalizePrice(m_symbol.Ask()+Loss*m_adjusted_point); // Stop Loss
double tp=m_symbol.NormalizePrice(m_symbol.Ask()-Loss*m_adjusted_point); // Take Profit
if(m_trade.Sell(Lot,NULL,m_symbol.Ask(),sl,tp))
{
if(m_trade.ResultDeal()==0)
Print("Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
else
Print("Sell -> true. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
}
else
Print("Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
}
}
return;
}
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data |
//+------------------------------------------------------------------+
bool RefreshRates()
{
//--- refresh rates
if(!m_symbol.RefreshRates())
return(false);
//--- protection against the return value of "zero"
if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Lot Check |
//+------------------------------------------------------------------+
double LotCheck(double lots)
{
//--- calculate maximum volume
double volume=NormalizeDouble(lots,2);
double stepvol=m_symbol.LotsStep();
if(stepvol>0.0)
volume=stepvol*MathFloor(volume/stepvol);
//---
double minvol=m_symbol.LotsMin();
if(volume<minvol)
volume=0.0;
//---
double maxvol=m_symbol.LotsMax();
if(volume>maxvol)
volume=maxvol;
return(volume);
}
//+------------------------------------------------------------------+
Здесь:
Добавлено:
получился очень интересный результат одиночного прогона в тестере стратегий:
Хотя я бы написал так:
Базовый функционал реализован, но постоянно появляются ошибки типа "Invalid price". Добавил дополнительные проверки на то, чтобы устранить их возможные причины, и соответственно, установку их в заведомо корректные значения, но ошибки никуда не делись. Сам уже не знаю, в каком направлении двигаться. Подскажите, где я сделал ошибку? Исходные коды прилагаю.
Здравствуйте! Решил для самообразования сделать мультивалютный эксперт по стратегии Green-Red Candle на MQL5.
Базовый функционал реализован, но постоянно появляются ошибки типа "Invalid price". Добавил дополнительные проверки на то, чтобы устранить их возможные причины, и соответственно, установку их в заведомо корректные значения, но ошибки никуда не делись. Сам уже не знаю, в каком направлении двигаться. Подскажите, где я сделал ошибку? Исходные коды прилагаю.
Перед совершением торговой операции нужно обновлять цены в объекте торгового класса CSymbolInfo. В моих моно-проектах (в которых только один символ) я использую такую функцию:
//| Refreshes the symbol quotes data |
//+------------------------------------------------------------------+
bool RefreshRates()
{
//--- refresh rates
if(!m_symbol.RefreshRates())
return(false);
//--- protection against the return value of "zero"
if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
return(false);
//---
return(true);
}
и использование - если ну удалось обновить цены, то просто выходим, если удачно обновили цены, то будет торговая операция:
if(!m_symbol.RefreshRates())
return;
if(m_trade.Buy(lots,NULL,m_symbol.Ask(),sl,tp))
{
if(m_trade.ResultDeal()==0)
Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
else
Print("Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription());
}
else
Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
", description of result: ",m_trade.ResultRetcodeDescription(
Подскажите красивое и "лёгкое" решение, чем заменить вот эту конструкцию:
Сейчас стоит такое, но как по мне - слишком "тяжёлое" решение:
if(time<0) return(-1);
datetime Arr[],time1;
CopyTime(symbol,tf,0,1,Arr);
time1=Arr[0];
if(CopyTime(symbol,tf,time,time1,Arr)>0) {
if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
if(time<time1) return(1);
else return(0);
}
else return(-1);
}
Подскажите красивое и "лёгкое" решение, чем заменить вот эту конструкцию:
Сейчас стоит такое, но как по мне - слишком "тяжёлое" решение:
if(time<0) return(-1);
datetime Arr[],time1;
CopyTime(symbol,tf,0,1,Arr);
time1=Arr[0];
if(CopyTime(symbol,tf,time,time1,Arr)>0) {
if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
if(time<time1) return(1);
else return(0);
}
else return(-1);
}
//| Возвращает смещение бара по времени |
//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
int res=-1;
datetime last_bar;
if(SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar)) {
if(time>last_bar) res=0;
else {
const int shift=Bars(symbol_name,timeframe,time,last_bar);
if(shift>0) res=shift-1;
}
}
return(res);
}
//+------------------------------------------------------------------+
Вот не проверял, если честно - всё время не доходит. Проверите, напишите результат пожалуйста.
Подскажите красивое и "лёгкое" решение, чем заменить вот эту конструкцию:
Сейчас стоит такое, но как по мне - слишком "тяжёлое" решение:
if(time<0) return(-1);
datetime Arr[],time1;
CopyTime(symbol,tf,0,1,Arr);
time1=Arr[0];
if(CopyTime(symbol,tf,time,time1,Arr)>0) {
if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
if(time<time1) return(1);
else return(0);
}
else return(-1);
}