Пардон, с выставлением ордера разобрался. Теперь другая беда: передвигаешь стоп, он обратно на место встает. И авто определение направления ордера упростила бы задачу.
Посмотрел более тщательно. Андрей из ТЗ — только выставление ордера.
//+------------------------------------------------------------------+
//| StopLossLine.mq4 |
//+------------------------------------------------------------------+
В советнике есть стопы.
Буду безмерно благодарен если за одно и в этот код включишь функцию выбора расстояние до тейка (не посчитай за наглость)
//+------------------------------------------------------------------+
//| StopLossLine.mq4 |
//+------------------------------------------------------------------+
//#property show_inputs
//--- внешние переменные ---//
extern double RiskSize=10; // Размер риска в валюте депозита
extern bool Use_Lock=false; // false/true - выкл./вкл. использование лока
//extern string NameLine="SL";
extern color TextColor=Red; // Цвет текста на графике
extern int FrontSize=7; // Размер шрифта для текста на графике
extern int Slippage=5; // Максимально допустимый размер проскальзывания (в пунктах)
//--- глобальные переменные ---//
double TickSize, TickValue, Spread, StopLevel, MinLot, MaxLot, LotStep;
int order_type, order_ticket, orders_total;
bool Ans, Activate, FatalError, FreeMarginAlert;
//--- Основная ф-ция скрипта ---//
int start()
{
double SL_Lev, SL_Size, Lot_Size;
// получение рыночной информации
GetMarketInfo();
//if(ObjectFind(NameLine)!=-1) SL_Lev=ObjectGet(NameLine,OBJPROP_PRICE1); else return(0);
SL_Lev=WindowPriceOnDropped();
if(ND(SL_Lev-Bid)>=StopLevel) { // sell
SL_Size=ND(SL_Lev-Bid)/Point;
Lot_Size=GetLot(SL_Size);
TradeSell(Lot_Size);
if(order_ticket!=-1) {
if(!Use_Lock) {
Modify_SL(order_ticket,SL_Lev);
/*if(Ans) ObjDel();*/ }
else {
BuyStop(SL_Lev,Lot_Size);
/*if(order_ticket!=-1) ObjDel();*/ } } }
else if(ND(Ask-SL_Lev)>=StopLevel) { // buy
SL_Size=ND(Ask-SL_Lev)/Point;
Lot_Size=GetLot(SL_Size);
TradeBuy(Lot_Size);
if(order_ticket!=-1) {
if(!Use_Lock) {
Modify_SL(order_ticket,SL_Lev);
/*if(Ans) ObjDel();*/ }
else {
SellStop(SL_Lev,Lot_Size);
/*if(order_ticket!=-1) ObjDel();*/ } } }
else {
Alert("Линия находится слишком близко к текущему значению цены!");
return(0); }
// вывод информации на график
string ObjName="GetLotSize";
if(ObjectFind(ObjName)==-1) {
ObjectCreate(ObjName, OBJ_LABEL, 0, 0, 0);
ObjectSet(ObjName, OBJPROP_CORNER, 0);
ObjectSet(ObjName, OBJPROP_XDISTANCE, 10);
ObjectSet(ObjName, OBJPROP_YDISTANCE, 15); }
ObjectSetText(ObjName, "Размер лота : " + DoubleToStr(Lot_Size, 2), FrontSize, "Courier New", TextColor);
return(0);
}
//--- Ф-ция получение рыночной информации(окружения) --- ---//
void GetMarketInfo() {
TickSize=MarketInfo(Symbol(), MODE_TICKSIZE); // Размер минимального изменения цены
TickValue=MarketInfo(Symbol(), MODE_TICKVALUE); // Стоимость одного пункта
Spread=MarketInfo(Symbol(), MODE_SPREAD); // Текущий спред
StopLevel=MarketInfo(Symbol(), MODE_STOPLEVEL)*Point; // Текущий уровень стопов
MinLot=MarketInfo(Symbol(), MODE_MINLOT); // Минимальный разрешенный объем
MaxLot=MarketInfo(Symbol(), MODE_MAXLOT); // Максимальный разрешенный объем
LotStep=MarketInfo(Symbol(), MODE_LOTSTEP); // Шаг приращения объема
}
//--- Расчет объема сделки с учётом размера стоп-лосса --- ---//
double GetLot(double SL_Size) {
double lot, SL;
if(TickValue==0.0) return(0.0); // Ошибка при получении стоимости тика
if(TickSize==Point) {
SL=SL_Size+Spread; }
else if(TickSize<Point) {
SL=(SL_Size+Spread)*(Point/TickSize); }
else if(TickSize>Point) {
SL=(SL_Size+Spread)*(TickSize/Point); }
lot=RiskSize/SL/TickValue; // Рассчитаем объем
return(NL(lot)); /* Округлим значение до ближайшего */ }
//--- Ф-ция открытия позиции на покупку(по рынку) --- ---//
void TradeBuy(double lot) {
int i;
order_ticket=-1;
RefreshRates(); // Обновим данные
if(AccountFreeMarginCheck(Symbol(), OP_BUY, lot)<=0.0 || GetLastError()==134) {
if(!FreeMarginAlert) {
Alert("Недостаточно средств для отправки приказа. Free Margin = ", DoubleToStr(AccountFreeMargin(),2));
FreeMarginAlert=true; }
return; }
FreeMarginAlert=false;
while(order_ticket<0 && i<5) {
// Отправка торгового запроса
order_ticket=OrderSend(Symbol(),OP_BUY,lot,Ask,Slippage,NULL,NULL,"",NULL,NULL,Blue);
if(order_ticket<0) { if(!Errors(GetLastError())) return; } i++; } /*end of while*/ }
//--- Ф-ция открытия позиции на продажу(по рынку) --- ---//
void TradeSell(double lot) {
int i;
order_ticket=-1;
RefreshRates(); // Обновим данные
if(AccountFreeMarginCheck(Symbol(), OP_SELL, lot)<=0.0 || GetLastError()==134) {
if(!FreeMarginAlert) {
Alert("Недостаточно средств для отправки приказа. Free Margin = ", DoubleToStr(AccountFreeMargin(),2));
FreeMarginAlert=true; }
return; }
FreeMarginAlert=false;
while(order_ticket<0 && i<5) {
// Отправка торгового запроса
order_ticket=OrderSend(Symbol(),OP_SELL,lot,Bid,Slippage,NULL,NULL,"",NULL,NULL,Red);
if(order_ticket<0) { if(!Errors(GetLastError())) return; } i++; } /*end of while*/ }
//--- Ф-ция модификации стоп-лосса --- ---//
void Modify_SL(int OrdTicket, double SL_Lev) {
double op, tp;
int i;
Ans=false;
if(!OrderSelect(OrdTicket,SELECT_BY_TICKET)) return;
op=OrderOpenPrice();
tp=OrderTakeProfit();
i=0;
while(!Ans && i<5) {
//--- Модификация открытой позиции ---//
Ans=OrderModify(OrdTicket,ND(op),ND(SL_Lev),ND(tp),0,Red);
if(!Ans) { if(!Errors(GetLastError())) break; } i++; } /*end of while*/ }
//--- Ф-ция установки BuyStop ордера --- ---//
void BuyStop(double LevInst, double lot) {
int i=0;
order_ticket=-1;
while(order_ticket<0 && i<5) {
// Отправка торгового запроса
order_ticket=OrderSend(Symbol(),OP_BUYSTOP,NL(lot),ND(LevInst),0,NULL,NULL,"",NULL,0,Blue);
if(order_ticket<0) { if(!Errors(GetLastError())) return; } i++; } // end of while
}
//--- Ф-ция установки SellStop ордера --- ---//
void SellStop(double LevInst, double lot) {
int i=0;
order_ticket=-1;
while(order_ticket<0 && i<5) {
// Отправка торгового запроса
order_ticket=OrderSend(Symbol(),OP_SELLSTOP,NL(lot),ND(LevInst),0,NULL,NULL,"",NULL,0,Red);
if(order_ticket<0) { if(!Errors(GetLastError())) return; } i++; } // end of while
}
//--- Ф-ция обработки ошибок при отправке торговых запросов --- ---//
bool Errors(int Error) {
if(Error==0) return(false); // Нет ошибки
switch(Error) {
// Преодолимые ошибки:
case 4: // Торговый сервер занят
Sleep(3000);
RefreshRates(); // Обновим данные
return(true); // Ошибка преодолимая
case 129: // Неправильная цена
case 135: // Цена изменилась
RefreshRates(); // Обновим данные
return(true); // Ошибка преодолимая
case 136: // Нет цен. Ждём новый тик.
while(RefreshRates()==false) // До нового тика
Sleep(1); // Задержка в цикле
return(true); // Ошибка преодолимая
case 137: // Брокер занят
Sleep(3000);
RefreshRates(); // Обновим данные
return(true); // Ошибка преодолимая
case 146: // Подсистема торговли занята
Sleep(500); // Простое решение
RefreshRates(); // Обновим данные
return(true); // Ошибка преодолимая
// Критические ошибки:
case 2 : // Общая ошибка
case 5 : // Старая версия клиентского терминала
case 64: // Счет заблокирован
case 133: // Торговля запрещена
Alert("Критическая ошибка - эксперт остановлен!");
FatalError=true;
return(false); // Критическая ошибка
default: // Другие варианты
return(false); } }
//--- Проверка объема на корректность и округление --- ---//
double NL(double L) {
return(MathRound(MathMin(MathMax(L, MinLot), MaxLot)/LotStep)*LotStep); }
//--- Ф-ция приведения значений к точности одного пункта --- ---//
double ND(double A) {
return( NormalizeDouble(A, Digits) ); }
//--- Ф-ция удаления линии --- ---//
//void ObjDel() {
// if(ObjectFind(NameLine)!=-1) ObjectDelete(NameLine); }
Bluesman