Отправлено: 13.10.16 15:32. Заголовок: А на основании чего ..
А на основании чего открывается ордер не понятно? Зачем цикл? Если это доливочный ордер, то имеет смысл использовать массив ордеров с маджиком. Доливочный ордер открывается примерно так: Был открыт ордер по какому-то условию и он был добавлен в массив ордеров советника по данному инструменту с маджиком. К нему, уже при других условиях добавляются ордера как-то так
Отправлено: 13.10.16 16:33. Заголовок: Эдуард пишет: Здрав..
Эдуард пишет:
цитата:
Здравствуйте. Подскажите, почему ордер не открывается?
Эдуард, Вы здесь намешали мух с котлетами. Цикл, который Вы привели, обычно служит для нахождения ордеров по текущему символу. В этом цикле не должно быть команд торговых операций. Попробуйте запустить этот код онлайн на демо-счете, предварительно открыв хотя бы один ордер с ценой открытия выше МАшки. В итоге получите шквал открытых ордеров Buy.
В текущем же виде ордер никогда не будет открыт, т. к. Вы сравниваете цену открытия имеющегося ордера с ценой MA. Если ордера нет или если цена его открытия ниже МА, то новый ордер не будет открыт. Сформулируйте, что именно Вы хотели получить от этого кода.
Отправлено: 13.10.16 17:56. Заголовок: Эдуард пишет: А так..
Эдуард пишет:
цитата:
А так, почему на каждом тике открывает ?
Потому что Вы именно это и написали в коде: на каждом тике, если цена открытия свечи выше МАшки, то открывать ордер. Чтобы ордер открылся один раз, нужно предварительно произвести проверку, открывались уже ордера на текущей свече или нет. То есть циклом из первого Вашего поста собрать информацию, потом проанализировать ее и только затем выполнять код, приведенный во втором посте.
Отправлено: 13.10.16 19:57. Заголовок: Эдуард пишет: Когда..
Эдуард пишет:
цитата:
Когда свеча закрывается выше мувинга - Бай.
В частностях у Вас все верно. А вот собрано - неверно. Так, условие открытия написано верно:
цитата:
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;
Поэтому перед открытие нового ордера проверяйте время открытия последнего ордера путем сравнения времени открытия свечи и результата, который вернула функция GetLastOpenOrderTime().
цитата:
datetime lastTime = GetLastOpenOrderTime(); if (lastTime >= Time[0]) { // Новый ордер открывать нельзя, т. к. на этой свече уже был открыт ордер }
Эдуард пишет:
цитата:
Код писать не надо, он мне не нужен в принципе.
Тогда непонятно, зачем сюда пишете... Здесь ведь именно коды и обсуждаются.
Отправлено: 17.10.16 14:48. Заголовок: Эдуард пишет: Почем..
Эдуард пишет:
цитата:
Почему выдает ошибку ?
Имеется в виду ошибка компиляции? Если да, то компилятор указывает на то, что функция OnTick имеет тип void (т. е. без типа), а в теле функции четыре функции return возвращают значение. Нужно убрать возврат значения.
Отправлено: 17.10.16 14:51. Заголовок: Эдуард пишет: Когда..
Эдуард пишет:
цитата:
Когда надо делать перебор ордеров ?
Один раз в начале обработки события Tick или любого другого события. Собираем свои ордера в массив, а потом уже работаем с этим массивом. После выполнения любой торговой операции, если она успешна, необходимо вернуться к месту входа в функцию обработки события. Таким образом, сбор информации будет проведен еще один раз. И так до тех пор, пока не будет в очереди торговых операций, либо любая выполненная торговая операция приведет к ошибке. В случае ошибки (опять же - нужно обработать саму ошибку) следует закончить обработку события и ждать следующего события.
Отправлено: 25.10.16 09:00. Заголовок: Эдуард пишет: Подск..
Эдуард пишет:
цитата:
Подскажите на примере части кода. Какое условие прописать, чтобы ордера на одном уровне открывались так: Бай/Селл, то есть чередовались.
Не существует какого-то условия, чтобы его написал - и получил желаемое. Чаще всего, как и в этом случае, требуется составление целого алгоритма. Насколько я понял задачу, требуется:
1. После открытия первого ордера, например, Buy, ожидаем его закрытия по стопу, профиту или по рынку (принудительное закрытие). 2. По закрытию ордера ожидаем возврата цены к уровню открытия Buy и открываем Sell. 3. Ожидание закрытия Sell. 4. Ожидание возврата цены к уровню открытия Sell и открытие Buy.
Такой алгоритм нужен? Даже если он, то это несколько сотен строк кода. Ну и в самом алгоритме еще такой момент не предусмотрен: а что, если цена не вернется к начальному уровню открытия?
Сообщение: 886
Настроение: нормальное
Зарегистрирован: 20.10.14
Откуда: Россия
Репутация:
0
Отправлено: 25.10.16 09:34. Заголовок: Такой алгоритм нужен..
цитата:
Такой алгоритм нужен? Даже если он, то это несколько сотен строк кода. Ну и в самом алгоритме еще такой момент не предусмотрен: а что, если цена не вернется к начальному уровню открытия?
Имеются ввиду ордера, которые находятся в рынке. Если цена идет вверх и должен открыться Бай, но на этом уровне уже есть Бай, то не должен открывать - сейчас открывает. Вот я и спрашиваю, какое дополнительное условие прописать в коде открытия ордеров. чтобы на одном уровне ордера чередовались. Сформулируйте логику словами - я сам напишу.
Отправлено: 25.10.16 16:19. Заголовок: Эдуард пишет: Вот я..
Эдуард пишет:
цитата:
Вот я и спрашиваю, какое дополнительное условие прописать в коде открытия ордеров. чтобы на одном уровне ордера чередовались. Сформулируйте логику словами - я сам напишу.
Еще раз: не существует такого условия, это целый алгоритм. В идеале требуется:
1. Найти все ордера, открытые экспертом и записать их в массив. 2. Обработать полученный массив и выяснить, где нужно установить/открыть ордер, а где - нет.
Обычно для этой цели я произвожу нумерацию ордеров, чтобы можно было отличать их друг от друга. Номер ордера кодирую в поле MagicNumber ордера. Например, если идентификатор ордеров эксперта 345, то в поле MagicNumber записываю 345 * 100 + 1 = 34501. Такая запись означает, что ордер открыт экспертом с идентификатором 345. Номер ордера в серии - 1. Работа с ордерами, если стратегия сеточная, это достаточно сложная вещь.
Сообщение: 887
Настроение: нормальное
Зарегистрирован: 20.10.14
Откуда: Россия
Репутация:
0
Отправлено: 25.10.16 10:17. Заголовок: Надо сделать перебор..
Надо сделать перебор ордеров, запомнить уровень, запомнить тип последнего ордера и если при открытии текущего ордера типы совпадают, то не открывать ордер того же типа - так ?
Отправлено: 06.11.16 17:18. Заголовок: Эдуард пишет: Подск..
Эдуард пишет:
цитата:
Подскажите пожалуйста, может есть другой способ открывать ордера на уровнях?
По кускам кода никто ничего не сможет сказать. Так, в этом коде непонятно, что есть massiv_o (как он объявлен и как и чем заполняется), что такое функция Tipordera, что такое переменная step? То есть Вы, находясь в своем контексте рассуждений, задаете вопрос, на который невозможно ответить, не зная этого самого контекста.
Также непонятно, почему задается вопрос о необходимости открытия ордера, но ведется работа с уже открытыми ордерами?
Сообщение: 889
Настроение: нормальное
Зарегистрирован: 20.10.14
Откуда: Россия
Репутация:
0
Отправлено: 06.11.16 21:20. Заголовок: По кускам кода никто..
цитата:
По кускам кода никто ничего не сможет сказать. Так, в этом коде непонятно, что есть 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;
Вопрос в том, можно ли это сделать проще и надежней ?
Отправлено: 07.11.16 15:27. Заголовок: Эдуард пишет: for (..
Эдуард пишет:
цитата:
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 никакого отношения к имеющимся ордерам уже не имеют. А в приведенном Вами коде - имеют.
И далее остающаяся половина открытого ордера на покупку с лотом 0.01 не тралится. Когда убираешь открытый ордер BuyStop, то трейлинг работает. Как сделать, чтобы трейлинг работал после закрытия половины позиции при открытом отложенном ордере BuyStop?
Отправлено: 13.06.17 20:33. Заголовок: Ошибки во втором и т..
Ошибки во втором и третьем блоках. Ошибки грубые - неправильное использование функции OrderSelect(). Эта функция выбирает ордер по тикету (первый случай) или по индексу в списке (второй случай). В первом случае ей нужно передать индекс строки в списке рабочих ордеров или истории счета, при этом указав вторым параметром SELECT_BY_POS. Во втором случае ей нужно передать уникальный идентификатор ордера (тикет) и вторым параметром указать SELECT_BY_TICKET. Здесь же видим, что делается попытка передачи тикета (OrderTicket()) и при этом указывается второй параметр SELECT_BY_POS. Уже явное несоответствие. Далее обращаю внимание на тот факт, что функция OrderTicket() возвращает тикет выбранного ордера. Таким образом, функция никак не может быть аргументом при вызове функции OrderSelect(), которая выполняет этот выбор. Исходя из того, что в обоих блоках используется цикл перебора ордеров (предположительно по списку рабочих ордеров), следовало бы строку:
Здравствуйте. Прошу подсказать как реализовать сравнение депо до открытия начальной сделки с текущим балансом эквити. Сова мартинит после убытка и интересует не разница AccountEquity() и AccounBallance(), а разница AccountEquity() и того первого значения AccountBalance() в самом начале серии "догона"(до входа в рынок с начальным лотом). Понятно, что здесь не обойтись без массивов, потому прошу подсказать направление, а лучше с примерами кода, если не затруднит.
Прошу подсказать как реализовать сравнение депо до открытия начальной сделки с текущим балансом эквити. Сова мартинит после убытка и интересует не разница AccountEquity() и AccounBallance(), а разница AccountEquity() и того первого значения AccountBalance() в самом начале серии "догона"(до входа в рынок с начальным лотом)
На мой взгляд, принципиально неверное решение. Ведь необходимо учитывать, что на одном счете может работать одновременно несколько подобных экспертов. Поэтому текущий баланс или эквити не даст достоверной информации. Единственно верным решением будет отслеживание экспертом собственных сделок в истории счета или в списке рабочих ордеров, если используется открытие встречных/доливочных ордеров.
... Подскажите, по-возможности, что не так. Вот, в сове хочу добавить умножитель лота при срабатывании 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 а дальше растет... Что предпринять? Благодарю заранее.
Отправлено: 07.07.17 09:41. Заголовок: allisbob пишет: но ..
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;
Далее по полученному тикету определяем причину закрытия:
цитата:
enum ENUM_CLOSE_REASON { CLOSE_REASON_ERROR, // Ошибка определения причины закрытия CLOSE_REASON_MARKET, // Ордер закрыт "по рынку" - не по SL и не по TP CLOSE_REASON_TP, // Ордер закрыт по достижении Take Profit CLOSE_REASON_SL // Ордер закрыт по достижении Stop Loss };
Отправлено: 09.07.17 16:05. Заголовок: Большое спасибо Вам,..
Большое спасибо Вам, Игорь, за объяснение. Правда, у меня целый код совы не намного больше приведенного примера
Теперь хотел бы уточнения: что присваивается переменной 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;
Чтобы привести какой-то код, нужно сначала определиться с тем, каким именно образом хочется рассчитывать SL и TP. То есть для начала метод нужно придумать и описать. Тогда и до кода можно дойти. Пока же Вы привели только код, который получает значение главной линии ADX.
Здравствуйте. Интересует вопрос: можно ли на нулевом баре гарантированно открывать ордера. Допустим если уже есть Бай, то при состоянии "индикатор ниже уровня" гарантированно откроется противоположный ордер. Если так можно сделать то почему в этом коде не получается ?
Здравствуйте. Интересует вопрос: можно ли на нулевом баре гарантированно открывать ордера. Допустим если уже есть Бай, то при состоянии "индикатор ниже уровня" гарантированно откроется противоположный ордер. Если так можно сделать то почему в этом коде не получается ?
Чтобы ответить на этот вопрос, нужно видеть весь код. А здесь лишь кусок кода. В нем по поводу вопроса все нормально. Разве что заметьте, что существует функция NewBar(), которая по содержанию должна срабатывать только один раз на бар. А это влечет за собой отсутствие сброса флага cluch_buy.
Чтобы ответить на этот вопрос, нужно видеть весь код. А здесь лишь кусок кода. В нем по поводу вопроса все нормально. Разве что заметьте, что существует функция NewBar(), которая по содержанию должна срабатывать только один раз на бар. А это влечет за собой отсутствие сброса флага cluch_buy.
Да проверка на баре не походит. Код исполняется внутри бара. Что с чем сравнивать для корректной работы приведенной части кода ?
Отправлено: 05.09.17 11:21. Заголовок: Здравствуйте. Как пр..
Здравствуйте. Как прописать в коде, чтобы закрытие, открытие ордера происходило не на новом(0) баре, а на первом ?
Например есть открытый ордер Бай, нарисовалась медвежья свеча и в момент, по факту закрытия этой(а не открытия новой) свечи, закрываем ордер. Время, не должно иметь значения. Закрытие текущего бара, не должно сопоставляться с открытием нового. Пусть, даже это не грамотно и убыточно, с точки зрения программирования, или торговли.
Здравствуйте. Как прописать в коде, чтобы закрытие, открытие ордера происходило не на новом(0) баре, а на первом ?
Например есть открытый ордер Бай, нарисовалась медвежья свеча и в момент, по факту закрытия этой(а не открытия новой) свечи, закрываем ордер. Время, не должно иметь значения. Закрытие текущего бара, не должно сопоставляться с открытием нового. Пусть, даже это не грамотно и убыточно, с точки зрения программирования, или торговли.
Если нужно, чтобы по окончании свечи закрывался ордер, открытый на ней, то так:
цитата:
// Выбрать ордер (по тикету или по индексу) ... // ~-------------- if (OrderOpenTime() >= iOpen(NULL, 0, 0)) return; // или continue, если все это в цикле
Отправлено: 27.09.18 20:10. Заголовок: Помогите с кодом
Доброго времени, Игорь!
Подобный вопрос наверное раз в сотый Вам задают...
Открывается ордер при выполнении условий... например
{ 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? Подскажите пожалуйста.
Ордер, к примеру, через 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))) { // Можно открывать ордер }
Все даты в формате GMT
2 час. Хитов сегодня: 2
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет