352 lines
32 KiB
Plaintext
352 lines
32 KiB
Plaintext
//+------------------------------------------------------------------+
|
||
//| OpenSellStopOrder.mq5 |
|
||
//| Copyright © 2017, Nikolay Kositsin |
|
||
//| Khabarovsk, farria@mail.redcom.ru |
|
||
//+------------------------------------------------------------------+
|
||
#property copyright "Copyright © 2017, Nikolay Kositsin"
|
||
#property link "farria@mail.redcom.ru"
|
||
//---- номер версии скрипта
|
||
#property version "1.00"
|
||
//---- показывать входные параметры
|
||
#property script_show_inputs
|
||
//+----------------------------------------------+
|
||
//| ВХОДНЫЕ ПАРАМЕТРЫ СКРИПТА |
|
||
//+----------------------------------------------+
|
||
input double MM=0.1; // Money Management
|
||
input int DEVIATION=10; // Отклонение цены
|
||
input uint LEVEL=100; // Расстояние до ордера в пунктах
|
||
input uint STOPLOSS=300; // Стоплосс в пунктах от текущей цены
|
||
input uint TAKEPROFIT=800; // Тейкпрофит в пунктах от текущей цены
|
||
input uint RTOTAL=4; // Число повторов при неудачных попытках размещения ордера
|
||
input uint SLEEPTIME=1; // Время паузы между повторами в секундах
|
||
//+------------------------------------------------------------------+
|
||
//| start function |
|
||
//+------------------------------------------------------------------+
|
||
void OnStart()
|
||
{
|
||
//----
|
||
for(uint count=0; count<=RTOTAL && !IsStopped(); count++)
|
||
{
|
||
uint result=SellLimitOrderOpen(Symbol(),MM,DEVIATION,LEVEL,STOPLOSS,TAKEPROFIT);
|
||
if(ResultRetcodeCheck(result)) break;
|
||
else Sleep(SLEEPTIME*1000);
|
||
}
|
||
//----
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| Открываем Sell ордер. |
|
||
//+------------------------------------------------------------------+
|
||
uint SellLimitOrderOpen
|
||
(
|
||
const string symbol,
|
||
double Money_Management,
|
||
uint deviation,
|
||
uint level,
|
||
uint StopLoss,
|
||
uint Takeprofit
|
||
)
|
||
//SellPositionOpen(symbol, Money_Management, deviation, StopLoss, Takeprofit);
|
||
//+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
||
{
|
||
//----
|
||
double volume=SellLotCount(symbol,Money_Management);
|
||
if(volume<=0)
|
||
{
|
||
Print(__FUNCTION__,"(): Неверный объём для структуры торгового запроса");
|
||
return(TRADE_RETCODE_INVALID_VOLUME);
|
||
}
|
||
//---- Объявление структур торгового запроса и результата торгового запроса
|
||
MqlTradeRequest request;
|
||
MqlTradeCheckResult check;
|
||
MqlTradeResult result;
|
||
|
||
//---- обнуление структур
|
||
ZeroMemory(request);
|
||
ZeroMemory(result);
|
||
ZeroMemory(check);
|
||
//----
|
||
int digit=int(SymbolInfoInteger(symbol,SYMBOL_DIGITS));
|
||
double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
|
||
double price=SymbolInfoDouble(symbol, SYMBOL_BID);
|
||
if(!digit || !point || !price) return(TRADE_RETCODE_ERROR);
|
||
price-=level*point;
|
||
|
||
//---- Инициализация структуры торгового запроса MqlTradeRequest для открывания SELL ордера
|
||
request.type = ORDER_TYPE_SELL_STOP;
|
||
request.price = price;
|
||
request.action = TRADE_ACTION_PENDING;
|
||
request.symbol = symbol;
|
||
request.volume = volume;
|
||
//----
|
||
if(StopLoss)
|
||
{
|
||
//---- Определение расстояния до стоплосса в единицах ценового графика
|
||
if(!StopCorrect(symbol,StopLoss)) return(TRADE_RETCODE_ERROR);
|
||
double dStopLoss=StopLoss*point;
|
||
request.sl=NormalizeDouble(request.price+dStopLoss,digit);
|
||
}
|
||
else request.sl=0.0;
|
||
|
||
if(Takeprofit)
|
||
{
|
||
//---- Определение расстояния до тейкпрофита единицах ценового графика
|
||
if(!StopCorrect(symbol,Takeprofit)) return(TRADE_RETCODE_ERROR);
|
||
double dTakeprofit=Takeprofit*point;
|
||
request.tp=NormalizeDouble(request.price-dTakeprofit,digit);
|
||
}
|
||
else request.tp=0.0;
|
||
//----
|
||
request.deviation=deviation;
|
||
request.type_filling=ORDER_FILLING_FOK;
|
||
|
||
//---- Проверка торгового запроса на корректность
|
||
if(!OrderCheck(request,check))
|
||
{
|
||
Print(__FUNCTION__,"(): OrderCheck(): ",ResultRetcodeDescription(check.retcode));
|
||
return(TRADE_RETCODE_INVALID);
|
||
}
|
||
|
||
string word="";
|
||
StringConcatenate(word,__FUNCTION__,"(): <<< Выставляем Sell Stop ордер по ",symbol,"! >>>");
|
||
Print(word);
|
||
|
||
word=__FUNCTION__+"(): OrderSend(): ";
|
||
|
||
//---- Открываем SELL ордер и делаем проверку результата торгового запроса
|
||
if(!OrderSend(request,result) || result.retcode!=TRADE_RETCODE_DONE)
|
||
{
|
||
Print(word,"<<< Не удалось выставить Sell Stop ордер по ",symbol,"!!! >>>");
|
||
Print(word,ResultRetcodeDescription(result.retcode));
|
||
PlaySound("timeout.wav");
|
||
return(result.retcode);
|
||
}
|
||
else
|
||
if(result.retcode==TRADE_RETCODE_DONE)
|
||
{
|
||
Print(word,"<<< Sell Stop ордер по ",symbol," выставлен! >>>");
|
||
PlaySound("ok.wav");
|
||
}
|
||
else
|
||
{
|
||
Print(word,"<<< Не удалось выставить Sell Stop ордер по ",symbol,"!!! >>>");
|
||
PlaySound("timeout.wav");
|
||
return(TRADE_RETCODE_ERROR);
|
||
}
|
||
//----
|
||
return(TRADE_RETCODE_DONE);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| Расчёт размера лота для открывания лонга |
|
||
//+------------------------------------------------------------------+
|
||
double SellLotCount
|
||
(
|
||
string symbol,
|
||
double Money_Management
|
||
)
|
||
// (string symbol, double Money_Management)
|
||
//+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
||
{
|
||
//----
|
||
double margin,Lot;
|
||
|
||
//---- Расчёт лота от баланса средств на счёте
|
||
margin=AccountInfoDouble(ACCOUNT_BALANCE)*Money_Management;
|
||
if(!margin) return(-1);
|
||
|
||
Lot=GetLotForOpeningPos(symbol,POSITION_TYPE_SELL,margin);
|
||
|
||
//---- нормирование величины лота до ближайшего стандартного значения
|
||
if(!LotCorrect(symbol,Lot,POSITION_TYPE_SELL)) return(-1);
|
||
//----
|
||
return(Lot);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| коррекция размера отложенного ордера до допустимого значения |
|
||
//+------------------------------------------------------------------+
|
||
bool StopCorrect(string symbol,int &Stop)
|
||
{
|
||
//----
|
||
long Extrem_Stop;
|
||
if(!SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL,Extrem_Stop)) return(false);
|
||
if(Stop<Extrem_Stop) Stop=int(Extrem_Stop);
|
||
//----
|
||
return(true);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| LotCorrect() function |
|
||
//+------------------------------------------------------------------+
|
||
bool LotCorrect
|
||
(
|
||
string symbol,
|
||
double &Lot,
|
||
ENUM_POSITION_TYPE trade_operation
|
||
)
|
||
//LotCorrect(string symbol, double& Lot, ENUM_POSITION_TYPE trade_operation)
|
||
//+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
||
{
|
||
|
||
double LOTSTEP=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
|
||
double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
|
||
double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
|
||
if(!LOTSTEP || !MaxLot || !MinLot) return(0);
|
||
|
||
//---- нормирование величины лота до ближайшего стандартного значения
|
||
Lot=LOTSTEP*MathFloor(Lot/LOTSTEP);
|
||
|
||
//---- проверка лота на минимальное допустимое значение
|
||
if(Lot<MinLot) Lot=MinLot;
|
||
//---- проверка лота на максимальное допустимое значение
|
||
if(Lot>MaxLot) Lot=MaxLot;
|
||
|
||
//---- проверка средств на достаточность
|
||
if(!LotFreeMarginCorrect(symbol,Lot,trade_operation))return(false);
|
||
//----
|
||
return(true);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| LotFreeMarginCorrect() function |
|
||
//+------------------------------------------------------------------+
|
||
bool LotFreeMarginCorrect
|
||
(
|
||
string symbol,
|
||
double &Lot,
|
||
ENUM_POSITION_TYPE trade_operation
|
||
)
|
||
//(string symbol, double& Lot, ENUM_POSITION_TYPE trade_operation)
|
||
//+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
|
||
{
|
||
//----
|
||
//---- проверка средств на достаточность
|
||
double freemargin=AccountInfoDouble(ACCOUNT_FREEMARGIN);
|
||
if(freemargin<=0) return(false);
|
||
double LOTSTEP=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
|
||
double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
|
||
if(!LOTSTEP || !MinLot) return(0);
|
||
double maxLot=GetLotForOpeningPos(symbol,trade_operation,freemargin);
|
||
//---- нормирование величины лота до ближайшего стандартного значения
|
||
maxLot=LOTSTEP*MathFloor(maxLot/LOTSTEP);
|
||
if(maxLot<MinLot) return(false);
|
||
if(Lot>maxLot) Lot=maxLot;
|
||
//----
|
||
return(true);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| расчёт размер лота для открывания ордера с маржой lot_margin |
|
||
//+------------------------------------------------------------------+
|
||
double GetLotForOpeningPos(string symbol,ENUM_POSITION_TYPE direction,double lot_margin)
|
||
{
|
||
//----
|
||
double price=0.0,n_margin;
|
||
if(direction==POSITION_TYPE_SELL) price=SymbolInfoDouble(symbol,SYMBOL_ASK);
|
||
if(direction==POSITION_TYPE_SELL) price=SymbolInfoDouble(symbol,SYMBOL_BID);
|
||
if(!price) return(NULL);
|
||
|
||
if(!OrderCalcMargin(ENUM_ORDER_TYPE(direction),symbol,1,price,n_margin) || !n_margin) return(0);
|
||
double lot=lot_margin/n_margin;
|
||
|
||
//---- получение торговых констант
|
||
double LOTSTEP=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
|
||
double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
|
||
double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
|
||
if(!LOTSTEP || !MaxLot || !MinLot) return(0);
|
||
|
||
//---- нормирование величины лота до ближайшего стандартного значения
|
||
lot=LOTSTEP*MathFloor(lot/LOTSTEP);
|
||
|
||
//---- проверка лота на минимальное допустимое значение
|
||
if(lot<MinLot) lot=0;
|
||
//---- проверка лота на максимальное допустимое значение
|
||
if(lot>MaxLot) lot=MaxLot;
|
||
//----
|
||
return(lot);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| возврат стрингового результата торговой операции по его коду |
|
||
//+------------------------------------------------------------------+
|
||
string ResultRetcodeDescription(int retcode)
|
||
{
|
||
string str;
|
||
//----
|
||
switch(retcode)
|
||
{
|
||
case TRADE_RETCODE_REQUOTE: str="Реквота"; break;
|
||
case TRADE_RETCODE_REJECT: str="Запрос отвергнут"; break;
|
||
case TRADE_RETCODE_CANCEL: str="Запрос отменен трейдером"; break;
|
||
case TRADE_RETCODE_PLACED: str="Ордер размещен"; break;
|
||
case TRADE_RETCODE_DONE: str="Заявка выполнена"; break;
|
||
case TRADE_RETCODE_DONE_PARTIAL: str="Заявка выполнена частично"; break;
|
||
case TRADE_RETCODE_ERROR: str="Ошибка обработки запроса"; break;
|
||
case TRADE_RETCODE_TIMEOUT: str="Запрос отменен по истечению времени";break;
|
||
case TRADE_RETCODE_INVALID: str="Неправильный запрос"; break;
|
||
case TRADE_RETCODE_INVALID_VOLUME: str="Неправильный объем в запросе"; break;
|
||
case TRADE_RETCODE_INVALID_PRICE: str="Неправильная цена в запросе"; break;
|
||
case TRADE_RETCODE_INVALID_STOPS: str="Неправильные стопы в запросе"; break;
|
||
case TRADE_RETCODE_TRADE_DISABLED: str="Торговля запрещена"; break;
|
||
case TRADE_RETCODE_MARKET_CLOSED: str="Рынок закрыт"; break;
|
||
case TRADE_RETCODE_NO_MONEY: str="Нет достаточных денежных средств для выполнения запроса"; break;
|
||
case TRADE_RETCODE_PRICE_CHANGED: str="Цены изменились"; break;
|
||
case TRADE_RETCODE_PRICE_OFF: str="Отсутствуют котировки для обработки запроса"; break;
|
||
case TRADE_RETCODE_INVALID_EXPIRATION: str="Неверная дата истечения ордера в запросе"; break;
|
||
case TRADE_RETCODE_ORDER_CHANGED: str="Состояние ордера изменилось"; break;
|
||
case TRADE_RETCODE_TOO_MANY_REQUESTS: str="Слишком частые запросы"; break;
|
||
case TRADE_RETCODE_NO_CHANGES: str="В запросе нет изменений"; break;
|
||
case TRADE_RETCODE_SERVER_DISABLES_AT: str="Автотрейдинг запрещен сервером"; break;
|
||
case TRADE_RETCODE_CLIENT_DISABLES_AT: str="Автотрейдинг запрещен клиентским терминалом"; break;
|
||
case TRADE_RETCODE_LOCKED: str="Запрос заблокирован для обработки"; break;
|
||
case TRADE_RETCODE_FROZEN: str="Ордер или позиция заморожены"; break;
|
||
case TRADE_RETCODE_INVALID_FILL: str="Указан неподдерживаемый тип исполнения ордера по остатку "; break;
|
||
case TRADE_RETCODE_CONNECTION: str="Нет соединения с торговым сервером"; break;
|
||
case TRADE_RETCODE_ONLY_REAL: str="Операция разрешена только для реальных счетов"; break;
|
||
case TRADE_RETCODE_LIMIT_ORDERS: str="Достигнут лимит на количество отложенных ордеров"; break;
|
||
case TRADE_RETCODE_LIMIT_VOLUME: str="Достигнут лимит на объем ордеров и позиций для данного символа"; break;
|
||
default: str="Неизвестный результат";
|
||
}
|
||
//----
|
||
return(str);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| возврат результата торговой операции для повтора сделки |
|
||
//+------------------------------------------------------------------+
|
||
bool ResultRetcodeCheck(int retcode)
|
||
{
|
||
string str;
|
||
//----
|
||
switch(retcode)
|
||
{
|
||
case TRADE_RETCODE_REQUOTE: /*Реквота*/ return(false); break;
|
||
case TRADE_RETCODE_REJECT: /*Запрос отвергнут*/ return(false); break;
|
||
case TRADE_RETCODE_CANCEL: /*Запрос отменен трейдером*/ return(true); break;
|
||
case TRADE_RETCODE_PLACED: /*Ордер размещен*/ return(true); break;
|
||
case TRADE_RETCODE_DONE: /*Заявка выполнена*/ return(true); break;
|
||
case TRADE_RETCODE_DONE_PARTIAL: /*Заявка выполнена частично*/ return(true); break;
|
||
case TRADE_RETCODE_ERROR: /*Ошибка обработки запроса*/ return(false); break;
|
||
case TRADE_RETCODE_TIMEOUT: /*Запрос отменен по истечению времени*/ return(false); break;
|
||
case TRADE_RETCODE_INVALID: /*Неправильный запрос*/ return(true); break;
|
||
case TRADE_RETCODE_INVALID_VOLUME: /*Неправильный объем в запросе*/ return(true); break;
|
||
case TRADE_RETCODE_INVALID_PRICE: /*Неправильная цена в запросе*/ return(true); break;
|
||
case TRADE_RETCODE_INVALID_STOPS: /*Неправильные стопы в запросе*/ return(true); break;
|
||
case TRADE_RETCODE_TRADE_DISABLED: /*Торговля запрещена*/ return(true); break;
|
||
case TRADE_RETCODE_MARKET_CLOSED: /*Рынок закрыт*/ return(true); break;
|
||
case TRADE_RETCODE_NO_MONEY: /*Нет достаточных денежных средств для выполнения запроса*/ return(true); break;
|
||
case TRADE_RETCODE_PRICE_CHANGED: /*Цены изменились*/ return(false); break;
|
||
case TRADE_RETCODE_PRICE_OFF: /*Отсутствуют котировки для обработки запроса*/ return(false); break;
|
||
case TRADE_RETCODE_INVALID_EXPIRATION: /*Неверная дата истечения ордера в запросе*/ return(true); break;
|
||
case TRADE_RETCODE_ORDER_CHANGED: /*Состояние ордера изменилось*/ return(true); break;
|
||
case TRADE_RETCODE_TOO_MANY_REQUESTS: /*Слишком частые запросы*/ return(false); break;
|
||
case TRADE_RETCODE_NO_CHANGES: /*В запросе нет изменений*/ return(false); break;
|
||
case TRADE_RETCODE_SERVER_DISABLES_AT: /*Автотрейдинг запрещен сервером*/ return(true); break;
|
||
case TRADE_RETCODE_CLIENT_DISABLES_AT: /*Автотрейдинг запрещен клиентским терминалом*/ return(true); break;
|
||
case TRADE_RETCODE_LOCKED: /*Запрос заблокирован для обработки*/ return(true); break;
|
||
case TRADE_RETCODE_FROZEN: /*Ордер или позиция заморожены*/ return(false); break;
|
||
case TRADE_RETCODE_INVALID_FILL: /*Указан неподдерживаемый тип исполнения ордера по остатку */ return(true); break;
|
||
case TRADE_RETCODE_CONNECTION: /*Нет соединения с торговым сервером*/ break;
|
||
case TRADE_RETCODE_ONLY_REAL: /*Операция разрешена только для реальных счетов*/ return(true); break;
|
||
case TRADE_RETCODE_LIMIT_ORDERS: /*Достигнут лимит на количество отложенных ордеров*/ return(true); break;
|
||
case TRADE_RETCODE_LIMIT_VOLUME: /*Достигнут лимит на объем ордеров и позиций для данного символа*/ return(true); break;
|
||
default: /*Неизвестный результат*/ return(false);
|
||
}
|
||
//----
|
||
return(true);
|
||
}
|
||
//+------------------------------------------------------------------+
|