Форум » Консультации по программированию » Программирование. » Ответить

Программирование.

Эдуард: Здравствуйте. Подскажите, почему ордер не открывается? input int Slippage=30; input int Magic=156; input double Lot=0.1; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTick() { double TP=0; double cena_ma_1=0; cena_ma_1=iMA(_Symbol,0,10,0,0,0,1); int total=OrdersTotal(); for(int i=total-1; i>=0; i--) if(OrderSelect(i,SELECT_BY_POS)) if(OrderSymbol()==Symbol()) { double openB=OrderOpenPrice(); if(openB>cena_ma_1) { int tiket=OrderSend(_Symbol,OP_BUY,Lot,Ask,Slippage,0,TP,NULL,Magic,0,clrBlue); { Alert("Ордер открылся"); } } } }

Ответов - 46, стр: 1 2 3 4 All

evbut: А на основании чего открывается ордер не понятно? Зачем цикл? Если это доливочный ордер, то имеет смысл использовать массив ордеров с маджиком. Доливочный ордер открывается примерно так: Был открыт ордер по какому-то условию и он был добавлен в массив ордеров советника по данному инструменту с маджиком. К нему, уже при других условиях добавляются ордера как-то так if(UseMAFilter == false || Bid > ma) //MA Filter { tArray[T] = OrderSend(Symbol(), OP_BUY, Lots, ask, slip*PipValue, bid - StopLoss*Point*PipValue, 0, Magic); if(tArray[T]<0) {Alert("OrderSend Error: ", GetLastError());} T++;

Scriptong: Эдуард пишет: Здравствуйте. Подскажите, почему ордер не открывается? Эдуард, Вы здесь намешали мух с котлетами. Цикл, который Вы привели, обычно служит для нахождения ордеров по текущему символу. В этом цикле не должно быть команд торговых операций. Попробуйте запустить этот код онлайн на демо-счете, предварительно открыв хотя бы один ордер с ценой открытия выше МАшки. В итоге получите шквал открытых ордеров Buy. В текущем же виде ордер никогда не будет открыт, т. к. Вы сравниваете цену открытия имеющегося ордера с ценой MA. Если ордера нет или если цена его открытия ниже МА, то новый ордер не будет открыт. Сформулируйте, что именно Вы хотели получить от этого кода.

Эдуард: А так, почему на каждом тике открывает ? input int Slippage=30; input int Magic=156; input double Lot=0.1; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTick() { double TP=0; double ma=0; ma=iMA(_Symbol,0,10,0,0,0,1); if(Open[0]>ma) { int tiket=OrderSend(_Symbol,OP_BUY,Lot,Ask,Slippage,0,TP,NULL,Magic,0,clrBlue); { Alert("Ордер открылся"); } } }


Scriptong: Эдуард пишет: А так, почему на каждом тике открывает ? Потому что Вы именно это и написали в коде: на каждом тике, если цена открытия свечи выше МАшки, то открывать ордер. Чтобы ордер открылся один раз, нужно предварительно произвести проверку, открывались уже ордера на текущей свече или нет. То есть циклом из первого Вашего поста собрать информацию, потом проанализировать ее и только затем выполнять код, приведенный во втором посте.

Эдуард: Не открывает... input int Slippage=30; input int Magic=156; input double Lot=0.1; input double TakeProfit=200; double TP=0; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTick() { TP=NormalizeDouble(Ask+TakeProfit*_Point,_Digits); TP=NormalizeDouble(Bid-TakeProfit*_Point,_Digits); double ma=0; ma=iMA(_Symbol,0,10,0,0,0,1); int total=OrdersTotal(); for(int i=total-1; i>=0; i--) if(OrderSelect(i,SELECT_BY_POS)) if(OrderSymbol()==Symbol()) { if(OrderType()==OP_BUY && OrderMagicNumber()==Magic) if(Open[0]>ma) { int tiket=OrderSend(_Symbol,OP_BUY,Lot,Ask,Slippage,0,TP,NULL,Magic,0,clrBlue); { Alert("Ордер открылся"); } } } }

Scriptong: Эдуард пишет: Не открывает... Давайте так: что именно нужно?

Эдуард: Scriptong пишет: Когда свеча закрывается выше мувинга - Бай. Когда ниже Селл. Хотелось бы понять, что не так. Код писать не надо, он мне не нужен в принципе.

Scriptong: Эдуард пишет: Когда свеча закрывается выше мувинга - Бай. В частностях у Вас все верно. А вот собрано - неверно. Так, условие открытия написано верно: double ma = iMA(...); if (Open[0] > ma) { // Открыть Buy } if (Open[0] < ma) { // Открыть Sell } Эдуард пишет: Хотелось бы понять, что не так. Не так то, что перед открытием необходимо проверить наличие уже открытых ордеров на текущей свече. Иначе Вы на каждом тике будете открывать новый ордер. Для определения времени последнего открытого ордера используйте код наподобие такого: datetime GetLastOpenOrderTime() { datetime lastOpenOrderTime = 0; for (int i = OrdersTotal() - 1; i >= 0; i--) { if (!OrderSelect(i, SELECT_BY_POS)) continue; if (OrderSymbol() != Symbol()) continue; if (OrderType() != OP_BUY && OrderType() != OP_SELL) continue; if (OrderMagicNumber() != i_magicNumber) continue; lastOpenOrderTime = (datetime)MathMax(lastOpenOrderTime, OrderOpenTime()); } return lastOpenOrderTime; } Поэтому перед открытие нового ордера проверяйте время открытия последнего ордера путем сравнения времени открытия свечи и результата, который вернула функция GetLastOpenOrderTime(). datetime lastTime = GetLastOpenOrderTime(); if (lastTime >= Time[0]) { // Новый ордер открывать нельзя, т. к. на этой свече уже был открыт ордер } Эдуард пишет: Код писать не надо, он мне не нужен в принципе. Тогда непонятно, зачем сюда пишете... Здесь ведь именно коды и обсуждаются.

Эдуард: Буду разбираться. Спасибо.

Эдуард: Почему выдает ошибку ? void OnTick() { int tiket=0; if(OP_BUY==0) tiket=OrderSend(_Symbol,OP_BUY,0.1,Ask,10,0,0,NULL,123,0,clrBlue); if(tiket>=0)return(true); else return(false); if(OP_SELL==0) tiket=OrderSend(_Symbol,OP_SELL,0.1,Bid,10,0,0,NULL,123,0,clrRed); if( tiket>=0)return(true); else return(false); }

Scriptong: Эдуард пишет: Почему выдает ошибку ? Имеется в виду ошибка компиляции? Если да, то компилятор указывает на то, что функция OnTick имеет тип void (т. е. без типа), а в теле функции четыре функции return возвращают значение. Нужно убрать возврат значения.

Эдуард: Когда надо делать перебор ордеров ? 1. Когда открываем ордера. 2. Закрываем. 3. Модифицируем. Когда еще ?

Scriptong: Эдуард пишет: Когда надо делать перебор ордеров ? Один раз в начале обработки события Tick или любого другого события. Собираем свои ордера в массив, а потом уже работаем с этим массивом. После выполнения любой торговой операции, если она успешна, необходимо вернуться к месту входа в функцию обработки события. Таким образом, сбор информации будет проведен еще один раз. И так до тех пор, пока не будет в очереди торговых операций, либо любая выполненная торговая операция приведет к ошибке. В случае ошибки (опять же - нужно обработать саму ошибку) следует закончить обработку события и ждать следующего события.

Эдуард: Подскажите на примере части кода. Какое условие прописать, чтобы ордера на одном уровне открывались так: Бай/Селл, то есть чередовались. if(Tipordera(Magik)==1 && Ask>=LastPrice+step*_Point && LastPrice>0 && (Magik)) { tiket=OrderSend(_Symbol,OP_BUY,Lot,Ask,Slippage,0,0,"",Magik,0,clrBlue); LastPrice=Ask; }

Scriptong: Эдуард пишет: Подскажите на примере части кода. Какое условие прописать, чтобы ордера на одном уровне открывались так: Бай/Селл, то есть чередовались. Не существует какого-то условия, чтобы его написал - и получил желаемое. Чаще всего, как и в этом случае, требуется составление целого алгоритма. Насколько я понял задачу, требуется: 1. После открытия первого ордера, например, Buy, ожидаем его закрытия по стопу, профиту или по рынку (принудительное закрытие). 2. По закрытию ордера ожидаем возврата цены к уровню открытия Buy и открываем Sell. 3. Ожидание закрытия Sell. 4. Ожидание возврата цены к уровню открытия Sell и открытие Buy. Такой алгоритм нужен? Даже если он, то это несколько сотен строк кода. Ну и в самом алгоритме еще такой момент не предусмотрен: а что, если цена не вернется к начальному уровню открытия?

Эдуард: Такой алгоритм нужен? Даже если он, то это несколько сотен строк кода. Ну и в самом алгоритме еще такой момент не предусмотрен: а что, если цена не вернется к начальному уровню открытия? Имеются ввиду ордера, которые находятся в рынке. Если цена идет вверх и должен открыться Бай, но на этом уровне уже есть Бай, то не должен открывать - сейчас открывает. Вот я и спрашиваю, какое дополнительное условие прописать в коде открытия ордеров. чтобы на одном уровне ордера чередовались. Сформулируйте логику словами - я сам напишу.

Scriptong: Эдуард пишет: Вот я и спрашиваю, какое дополнительное условие прописать в коде открытия ордеров. чтобы на одном уровне ордера чередовались. Сформулируйте логику словами - я сам напишу. Еще раз: не существует такого условия, это целый алгоритм. В идеале требуется: 1. Найти все ордера, открытые экспертом и записать их в массив. 2. Обработать полученный массив и выяснить, где нужно установить/открыть ордер, а где - нет. Обычно для этой цели я произвожу нумерацию ордеров, чтобы можно было отличать их друг от друга. Номер ордера кодирую в поле MagicNumber ордера. Например, если идентификатор ордеров эксперта 345, то в поле MagicNumber записываю 345 * 100 + 1 = 34501. Такая запись означает, что ордер открыт экспертом с идентификатором 345. Номер ордера в серии - 1. Работа с ордерами, если стратегия сеточная, это достаточно сложная вещь.

Эдуард: Надо сделать перебор ордеров, запомнить уровень, запомнить тип последнего ордера и если при открытии текущего ордера типы совпадают, то не открывать ордер того же типа - так ?

Эдуард: Подскажите пожалуйста, может есть другой способ открывать ордера на уровнях? bool OrderDist(int type) { bool dist=false; RefreshRates(); for (int j=0; j<ArrayRange(massiv_o,0); j++) { if(NormalizeDouble(massiv_o[j], _Digits)>0 && (MathAbs(Bid-NormalizeDouble(massiv_o[j], _Digits))/_Point)<=10) { dist=true; break; } } for(int i=0; i<OrdersTotal(); i++) { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) && OrderMagicNumber()==Magik) if(OrderSymbol()==_Symbol) if(((MathAbs(Bid-OrderOpenPrice())/_Point)<=step/2) && Tipordera(Magik)==type) dist=false; } return(dist); }

Scriptong: Эдуард пишет: Подскажите пожалуйста, может есть другой способ открывать ордера на уровнях? По кускам кода никто ничего не сможет сказать. Так, в этом коде непонятно, что есть massiv_o (как он объявлен и как и чем заполняется), что такое функция Tipordera, что такое переменная step? То есть Вы, находясь в своем контексте рассуждений, задаете вопрос, на который невозможно ответить, не зная этого самого контекста. Также непонятно, почему задается вопрос о необходимости открытия ордера, но ведется работа с уже открытыми ордерами?

Эдуард: По кускам кода никто ничего не сможет сказать. Так, в этом коде непонятно, что есть massiv_o (как он объявлен и как и чем заполняется), что такое функция Tipordera, что такое переменная step? То есть Вы, находясь в своем контексте рассуждений, задаете вопрос, на который невозможно ответить, не зная этого самого контекста. Также непонятно, почему задается вопрос о необходимости открытия ордера, но ведется работа с уже открытыми ордерами? for (int j=0; j<ArrayRange(massiv_o,0); j++)// объявлен глобально определяет количество цен ордеров в массиве, строит виртуально сетку на расстоянии шага (step), после открытия первого ордера. if(NormalizeDouble(massiv_o[j], _Digits)>0 && (MathAbs(Bid-NormalizeDouble(massiv_o[j], _Digits))/_Point)<=10)// 10 это в пунктах погрешность вверх/вниз, когда можно выставить ордер. Тип ордера, он и есть тип ордера if(OrderType()==OP_BUY) tipordera=0; if(OrderType()==OP_SELL) tipordera=1; Вопрос в том, можно ли это сделать проще и надежней ?

Scriptong: Эдуард пишет: for (int j=0; j<ArrayRange(massiv_o,0); j++)// объявлен глобально определяет количество цен ордеров в массиве, строит виртуально сетку на расстоянии шага (step), после открытия первого ордера. Если известен шаг сетки и отправная точка, то для чего массив? Ведь цена любого уровня рассчитывается путем решения простого линейного уравнения... В любом случае нужно видеть, как массив заполняется. Там вполне может быть ошибка. Эдуард пишет: Тип ордера, он и есть тип ордера if(OrderType()==OP_BUY) tipordera=0; if(OrderType()==OP_SELL) tipordera=1; Зачем, если OP_BUY это и есть 0, а OP_SELL - 1? Эдуард пишет: Вопрос в том, можно ли это сделать проще и надежней ? Проще уже некуда. Тем более, что используемый алгоритм явно слишком примитивен для решения поставленной задачи далеко не низкого уровня (средний или даже чуть выше среднего). А вот надежнее - конечно. Чтобы решить задачу, пора ли открывать новый ордер по сетке, нужно: 1. Перебрать все открытые ордера из списка рабочих и сохранить свои ордера в массив. Попутно сформировать максимальные и минимальные цены открытых ордеров. Возможно, еще придется вычислять бреши в ордерах. 2. Вычислить цену открытия следующего ордера на основании максимальной и минимальной цен текущих ордеров. 3. Проверить, нужно ли теперь открывать ордер (попадает ли он в нужный диапазон цен)? Таким образом, пп. 2 и 3 никакого отношения к имеющимся ордерам уже не имеют. А в приведенном Вами коде - имеют.

Evgeny: Добрый вечер! Помогите разобраться с трейлингом. 1. Открывается ордер к примеру на покупку и выше с шагом step открывается отложенный ордер Butstop: //--- ордер на покупку { if (RSI_2<55 && RSI_1>55 && BuyCount == 0 && SellCount == 0) { OrderSend(Symbol(),OP_BUY,0.02,Ask,3,0,0,"",1,0,CLR_NONE); } } //--- отложенный ордер if (BuyCount > 0 && BuyStopCount==0) { OrderSend(Symbol(),OP_BUYSTOP,0.02,Ask+Step*(1+BuyStopCount)*Point,3,0,0,"",1,0,CLR_NONE); } 2. Идет трейлинг ордера buy: for (n=0; n<=total; n++) { OrderSelect(OrderTicket(),SELECT_BY_POS,MODE_TRADES); { if(OrderTicket()!=0 && OrderType()==OP_BUY && Bid>OrderStopLoss()+SL*Point && BuyCount == 1 && SellCount == 0) OrderModify(OrderTicket(),OrderOpenPrice(),Bid-SL*Point,0,0,CLR_NONE); else if(OrderTicket()!=0 && OrderType()==OP_SELL && Ask<OrderStopLoss()-SL*Point && BuyCount == 0 && SellCount == 1) { OrderModify(OrderTicket(),OrderOpenPrice(),Ask+SL*Point,0,0,CLR_NONE); } } } 3. Закрывается половина ордера при выполнении условия //--- Закрытие половины позиции for (n=0; n<=total; n++) { OrderSelect(OrderTicket(),SELECT_BY_POS,MODE_TRADES); { if(OrderTicket()!=0 && OrderType()==OP_BUY && OrderLots()==0.02 && Bid>OrderOpenPrice() && SellCount==0 && BuyCount==1 && OrderMagicNumber()==1 && RSI_1>70 && RSI_0<70) OrderClose(OrderTicket(),0.01,Bid,3,CLR_NONE); else if(OrderTicket()!=0 && OrderType()==OP_SELL && OrderLots()==0.02 && BuyCount==0 && SellCount==1 && OrderMagicNumber()==1 && RSI_1<30 && RSI_0>30) { OrderClose(OrderTicket(),0.01,Ask,3,CLR_NONE); } } } И далее остающаяся половина открытого ордера на покупку с лотом 0.01 не тралится. Когда убираешь открытый ордер BuyStop, то трейлинг работает. Как сделать, чтобы трейлинг работал после закрытия половины позиции при открытом отложенном ордере BuyStop?

Scriptong: Ошибки во втором и третьем блоках. Ошибки грубые - неправильное использование функции OrderSelect(). Эта функция выбирает ордер по тикету (первый случай) или по индексу в списке (второй случай). В первом случае ей нужно передать индекс строки в списке рабочих ордеров или истории счета, при этом указав вторым параметром SELECT_BY_POS. Во втором случае ей нужно передать уникальный идентификатор ордера (тикет) и вторым параметром указать SELECT_BY_TICKET. Здесь же видим, что делается попытка передачи тикета (OrderTicket()) и при этом указывается второй параметр SELECT_BY_POS. Уже явное несоответствие. Далее обращаю внимание на тот факт, что функция OrderTicket() возвращает тикет выбранного ордера. Таким образом, функция никак не может быть аргументом при вызове функции OrderSelect(), которая выполняет этот выбор. Исходя из того, что в обоих блоках используется цикл перебора ордеров (предположительно по списку рабочих ордеров), следовало бы строку: OrderSelect(OrderTicket(),SELECT_BY_POS,MODE_TRADES); заменить на такие строки: if (!OrderSelect(n, SELECT_BY_POS)) continue; Здесь в случае указания индекса строки третий параметр можно не указывать, т. к. он по умолчанию равен MODE_TRADES.

Evgeny: Спасибо Игорь!

allisbob: Здравствуйте. Прошу подсказать как реализовать сравнение депо до открытия начальной сделки с текущим балансом эквити. Сова мартинит после убытка и интересует не разница AccountEquity() и AccounBallance(), а разница AccountEquity() и того первого значения AccountBalance() в самом начале серии "догона"(до входа в рынок с начальным лотом). Понятно, что здесь не обойтись без массивов, потому прошу подсказать направление, а лучше с примерами кода, если не затруднит. Спасибо

Scriptong: allisbob пишет: Прошу подсказать как реализовать сравнение депо до открытия начальной сделки с текущим балансом эквити. Сова мартинит после убытка и интересует не разница AccountEquity() и AccounBallance(), а разница AccountEquity() и того первого значения AccountBalance() в самом начале серии "догона"(до входа в рынок с начальным лотом) На мой взгляд, принципиально неверное решение. Ведь необходимо учитывать, что на одном счете может работать одновременно несколько подобных экспертов. Поэтому текущий баланс или эквити не даст достоверной информации. Единственно верным решением будет отслеживание экспертом собственных сделок в истории счета или в списке рабочих ордеров, если используется открытие встречных/доливочных ордеров.

allisbob: ... Подскажите, по-возможности, что не так. Вот, в сове хочу добавить умножитель лота при срабатывании SL. "реализовал" так: int slippage=10; int start() { ... string txt; static int n; if (Orders>OrdersTotal()) txt=I(); { if (txt=="SL" || txt!="TP") {n++; LOT=Lot[n]; if (n>=10) {n=0; LOT=Lot1;}} if (txt=="TP") {n=0; LOT=Lot1;} } Orders=OrdersTotal(); ... return(0); } и функция: string I() { string txt=NULL; int a=OrdersHistoryTotal()-1; if(OrderSelect(a,SELECT_BY_POS,MODE_HISTORY)==true && OrderSymbol()==Symbol() && OrderMagicNumber()==ID) { if (MathAbs(OrderStopLoss()-OrderClosePrice())<=_Point*slippage) txt="SL"; if (MathAbs(OrderTakeProfit()-OrderClosePrice())<=_Point*slippage) txt="TP"; } return(txt); } Поставленную задачу это выполняет лишь частично. При закрытии руками или по "SL" происхOдит увеличение последующих лотов, но после закрытия по "TP" лот не сбрасывается до Lot1 а дальше растет... Что предпринять? Благодарю заранее.

Scriptong: allisbob пишет: но после закрытия по "TP" лот не сбрасывается до Lot1 а дальше растет По приведенным обрывкам кода сложно сказать, что именно не так. По идее, должно работать, если TakeProfit установлен у ордеров. С другой стороны объем по этому коду должен повышаться на каждом новом тике. Ведь условие: if (txt=="SL" || txt!="TP") сработает и тогда, когда не было закрытия ордера (переменная txt будет содержать пустую строку). Также нужно заметить, что блок, в котором находится эта строка, не принадлежит условию: if (Orders>OrdersTotal()) т. е. блок просто сам по себе. С таким же успехом можно убрать эти фигурные скобки - ничего не изменится. Хотя, конечно, решение задачи подвержено многим "если". К примеру, функция I() будет работать правильно только в тестере. А вот онлайн она может обработать ордер, который просто последний в списке. Ведь сортировать список пользователь может как угодно: по времени открытия, закрытия, по объему и т. д. Также почему то решено, что проскальзывание у стопа и профита обязательно должно лежать в пределах проскальзывания, задаваемого пользователем. Видимо, в этих мелочах и кроется проблема. Для поиска последнего закрытого ордера лучше всего сканировать весь список истории счета и находить в нем наибольшее время закрытия: int GetLastCloseOrderTicket() { datetime dtLastTime = 0; int nLastTicket = -1; for (int i = OrdersHistoryTotal() - 1; i >= 0; i--) { if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue; if (OrderSymbol() != Symbol()) continue; if (m_nMagicNumber != OrderMagicNumber()) continue; if (OrderCloseTime() > dtLastOrderTime) { dtLastTime = OrderCloseTime; nLastTicket = i; } } return nLastTicket; } Далее по полученному тикету определяем причину закрытия: enum ENUM_CLOSE_REASON { CLOSE_REASON_ERROR, // Ошибка определения причины закрытия CLOSE_REASON_MARKET, // Ордер закрыт "по рынку" - не по SL и не по TP CLOSE_REASON_TP, // Ордер закрыт по достижении Take Profit CLOSE_REASON_SL // Ордер закрыт по достижении Stop Loss }; ENUM_CLOSE_REASON GetCloseReason(int nTicket) { if (!OrderSelect(nTicket, SELECT_BY_TICKET) || OrderCloseTime() == 0) return CLOSE_REASON_ERROR; if (OrderType() != OP_BUY && OrderType() != OP_SELL) return CLOSE_REASON_ERROR; // Ордер Buy if (OrderType() == OP_BUY) { if (OrderTakeProfit() > 0.0 && OrderClosePrice() - OrderTakeProfit() > -DBL_EPSILON) return CLOSE_REASON_TP; if (OrderStopLoss() - OrderClosePrice() > -DBL_EPSILON) return CLOSE_REASON_SL; return CLOSE_REASON_MARKET; } // Ордер Sell if (OrderTakeProfit() - OrderClosePrice() > -DBL_EPSILON) return CLOSE_REASON_TP; if (OrderStopLoss() > 0.0 && OrderClosePrice() - OrderStopLoss() > -DBL_EPSILON) return CLOSE_REASON_SL; return CLOSE_REASON_MARKET; } Пример использования: static int nOrdersInHistory = 0; if (nOrdersInHistory != OrdersHistoryTotal()) { ENUM_CLOSE_REASON eCloseReason = GetCloseReason(GetLastCloseOrderTicket()); if (eCloseReason == CLOSE_REASON_SL) { // увеличение объема } if (eCloseReason == CLOSE_REASON_TP) { // возврат к начальному объему } } nOrdersInHistory = OrdersHistoryTotal();

allisbob: Большое спасибо Вам, Игорь, за объяснение. Правда, у меня целый код совы не намного больше приведенного примера Теперь хотел бы уточнения: что присваивается переменной dtLastOrderTime? int GetLastCloseOrderTicket() { datetime dtLastTime = 0; int nLastTicket = -1; for (int i = OrdersHistoryTotal() - 1; i >= 0; i--) { if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue; if (OrderSymbol() != Symbol()) continue; if (m_nMagicNumber != OrderMagicNumber()) continue; if (OrderCloseTime() > dtLastOrderTime) { dtLastTime = OrderCloseTime(); nLastTicket = i; } } return nLastTicket; }

Scriptong: allisbob пишет: что присваивается переменной dtLastOrderTime? Прошу прощения, опечатка. Это переменная dtLastTime.

bro: Скажите, как рассчитать СЛ и ТП по ADX / double adx(int bar) { return(iADX(Symbol(),0,ADX_Period,PRICE_CLOSE,MODE_MAIN,bar)); }

Scriptong: bro пишет: Скажите, как рассчитать СЛ и ТП по ADX / Чтобы привести какой-то код, нужно сначала определиться с тем, каким именно образом хочется рассчитывать SL и TP. То есть для начала метод нужно придумать и описать. Тогда и до кода можно дойти. Пока же Вы привели только код, который получает значение главной линии ADX.

bro: Scriptong пишет: Допустим главная линия ADX показывает 47.7708 Берем 47, для пятизнака будет 470 пунктов.

Scriptong: bro пишет: Допустим главная линия ADX показывает 47.7708 Берем 47, для пятизнака будет 470 пунктов. Ну тогда так. В настроечных параметрах: input uint i_uKoef = 10; // Коэффициент умножения пунктов enum ENUM_TRADE_SIGNAL { TRADE_SIGNAL_NONE, // Нет торгового сигнала TRADE_SIGNAL_BUY, // Торговый сигнал Buy TRADE_SIGNAL_SELL // Торговый сигнал Sell }; В функции расчета торгового сигнала: ENUM_TRADE_SIGNAL GetTradeSignal() { if (<условия для открытия Buy>) return TRADE_SIGNAL_BUY; if (<условия для открытия Sell>) return TRADE_SIGNAL_SELL; return TRADE_SIGNAL_NONE; } При открытии ордера: ENUM_TRADE_SIGNAL eSignal = GetTradeSignal(); if (eSignal == TRADE_SIGNAL_NONE) return; double fADXValue = MothRound(iADX(Symbol(),0,ADX_Period,PRICE_CLOSE,MODE_MAIN,bar)); if (eSignal == TRADE_SIGNAL_BUY) OrderSend(Symbol(), OP_BUY, fLots, uSlippage, Ask, Ask - fADXValue * i_uKoef, Ask + fADXValue * i_uKoef); if (eSignal == TRADE_SIGNAL_SELL) OrderSend(Symbol(), OP_SELL, fLots, uSlippage, Bid, Bid + fADXValue * i_uKoef, Bid - fADXValue * i_uKoef); Это грубо, конечно. Ведь перед открытием ордера нужно произвести огромное количество проверок.

bro: Здравствуйте. Интересует вопрос: можно ли на нулевом баре гарантированно открывать ордера. Допустим если уже есть Бай, то при состоянии "индикатор ниже уровня" гарантированно откроется противоположный ордер. Если так можно сделать то почему в этом коде не получается ? if(NewBar()==true) { cluch_buy=false; cluch_sell=false; } //double ma=iMA(NULL,0,Ma_Period,0,MODE_SMMA,PRICE_MEDIAN,0); //double ma1=iMA(NULL,0,Ma_Period,0,MODE_SMMA,PRICE_MEDIAN,1); double rsi1=iRSI(Symbol(),0,RSI1,PRICE_CLOSE,0); double rsi2=iRSI(Symbol(),0,RSI1,PRICE_CLOSE,1); //double rsi3=iRSI(Symbol(),0,RSI2,PRICE_CLOSE,0); //double rsi4=iRSI(Symbol(),0,RSI2,PRICE_CLOSE,1); if(rsi1>s1 && rsi2<s1) if(cluch_buy==false) { ticket=OrderSend(Symbol(),OP_BUY,Lot,Ask,slipp,0,0,"My order",Magic,0,clrBlue); if(ticket<0) { Print("OrderSend завершилась с ошибкой #",GetLastError()); } else Print("Функция OrderSend успешно выполнена"); cluch_buy=true; cluch_sell=false; } if(rsi1<s1 && rsi2>s1) if(cluch_sell==false) { ticket=OrderSend(Symbol(),OP_SELL,Lot,Bid,slipp,0,0,"My order",Magic,0,clrRed); if(ticket<0) { Print("OrderSend завершилась с ошибкой #",GetLastError()); } else Print("Функция OrderSend успешно выполнена"); cluch_sell=true; cluch_buy=false; } }

Scriptong: bro пишет: Здравствуйте. Интересует вопрос: можно ли на нулевом баре гарантированно открывать ордера. Допустим если уже есть Бай, то при состоянии "индикатор ниже уровня" гарантированно откроется противоположный ордер. Если так можно сделать то почему в этом коде не получается ? Чтобы ответить на этот вопрос, нужно видеть весь код. А здесь лишь кусок кода. В нем по поводу вопроса все нормально. Разве что заметьте, что существует функция NewBar(), которая по содержанию должна срабатывать только один раз на бар. А это влечет за собой отсутствие сброса флага cluch_buy.

bro: Scriptong пишет: Чтобы ответить на этот вопрос, нужно видеть весь код. А здесь лишь кусок кода. В нем по поводу вопроса все нормально. Разве что заметьте, что существует функция NewBar(), которая по содержанию должна срабатывать только один раз на бар. А это влечет за собой отсутствие сброса флага cluch_buy. Да проверка на баре не походит. Код исполняется внутри бара. Что с чем сравнивать для корректной работы приведенной части кода ?

Scriptong: bro пишет: Да проверка на баре не походит. Код исполняется внутри бара. Что с чем сравнивать для корректной работы приведенной части кода ? К сожалению, не могу сказать. Нужно видеть всю логику. Иначе буду лишь гадать.

bro: Здравствуйте. Как прописать в коде, чтобы закрытие, открытие ордера происходило не на новом(0) баре, а на первом ? Например есть открытый ордер Бай, нарисовалась медвежья свеча и в момент, по факту закрытия этой(а не открытия новой) свечи, закрываем ордер. Время, не должно иметь значения. Закрытие текущего бара, не должно сопоставляться с открытием нового. Пусть, даже это не грамотно и убыточно, с точки зрения программирования, или торговли. Можно пример кода ?

Scriptong: bro пишет: Здравствуйте. Как прописать в коде, чтобы закрытие, открытие ордера происходило не на новом(0) баре, а на первом ? Например есть открытый ордер Бай, нарисовалась медвежья свеча и в момент, по факту закрытия этой(а не открытия новой) свечи, закрываем ордер. Время, не должно иметь значения. Закрытие текущего бара, не должно сопоставляться с открытием нового. Пусть, даже это не грамотно и убыточно, с точки зрения программирования, или торговли. Если нужно, чтобы по окончании свечи закрывался ордер, открытый на ней, то так: // Выбрать ордер (по тикету или по индексу) ... // ~-------------- if (OrderOpenTime() >= iOpen(NULL, 0, 0)) return; // или continue, если все это в цикле if (OrderType() == OP_BUY && iOpen(NULL, 0, 1) > iClose(NULL, 0, 1)) { // закрыть ордер } if (OrderType() == OP_SELL && iOpen(NULL, 0, 1) < iClose(NULL, 0, 1)) { // закрыть ордер }

bro: Scriptong пишет: Если нужно, чтобы по окончании свечи закрывался ордер, открытый на ней, то так: Нет, не на ней, на другой свече.

Scriptong: bro пишет: Нет, не на ней, на другой свече. Значит, увеличьте индексы во всех функциях iOpen и iClose на столько баров, сколько требуется.

Evgeny: Доброго времени, Игорь! Подобный вопрос наверное раз в сотый Вам задают... Открывается ордер при выполнении условий... например { if (RSI12_2>50 && RSI12_1<50) { OrderSend(Symbol(),OP_SELL,1.0,Bid,3,Bid+SL*Point,0,"",1,0,CLR_NONE); } } Это происходит на часовом таймфрейме.... Ордер, к примеру, через 10 минут закрывается по стопу, т.е. внутри часового бара. Сразу открывается новый, потому что условие для открытия ордера выполняется пока не закончится час. Снова закрывается с убытком и снова открывается новый... Что добавить в код, чтобы открывался в течение бара (часа) только один ордер. Если он закроется с убытком, то новый бы не открывался? Может функция sleep? Подскажите пожалуйста.

Scriptong: Evgeny пишет: Ордер, к примеру, через 10 минут закрывается по стопу, т.е. внутри часового бара. Сразу открывается новый, потому что условие для открытия ордера выполняется пока не закончится час. Снова закрывается с убытком и снова открывается новый... Что добавить в код, чтобы открывался в течение бара (часа) только один ордер. Если он закроется с убытком, то новый бы не открывался? Если планируется открывать только один ордер на свече, то перед открытием ордера нужно проверить, открывался ли ордер на этой свече. Для этого необходимо обратиться к истории счета и найти там ордер эксперта, открытый позднее заданного времени: bool IsOrderOpenedLaterThanSpecifiedTime(datetime dtTime) { for (int i = OrdersHistoryTotal() - 1; i >= 0; --i) { if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue; if (OrderSymbol() != Symbol()) continue; if (OrderOpenTime() >= dtTime) return true; } return false; } Использование: if (!IsOrderOpenedLaterThanSpecifiedTime(iTime(NULL, 0, 0))) { // Можно открывать ордер }

Evgeny: Scriptong пишет: Для этого необходимо обратиться к истории счета и найти там ордер эксперта, открытый позднее заданного времени Спасибо!



полная версия страницы