1) Комбинация Shift + E «намертво» прописана в коде, у меня пока не получилось реализовать ввод горячих клавиш через параметры
2) Не удалось корректно настроить изменение визуального состояния кнопок (нажата/отжата), поэтому отключил это (п****)
3) При перемещении ползунка SL новое значение стопа будет присвоено после отжатия ЛКМ
4) Импорт из винды какой-то там библиотеки:
#import «user32.dll»
int GetAsyncKeyState(int vKey);
нужен только для работы горячих клавиш открытия позиции.
Если вам не нужны горячие клавиши или вас беспокоит предупреждение
«Разрешить импорт dll (потенциально опасно, включать только для проверенных приложений)»
— удалите или закомментируйте эти участки кода:
#import «user32.dll»
int GetAsyncKeyState(int vKey);
#import
#define VK_SHIFT 16
#define VK_LSHIFT 160
#define VK_RSHIFT 161
#define VK_E 69
bool KeyState(int vKey)
{
return((GetAsyncKeyState(vKey) & 0x8000) != 0);
}
...
// Обработка нажатия горячих клавиш (в обработчике событий)
if(id == CHARTEVENT_KEYDOWN)
{
// Проверяем, что нажат Shift + E (код Shift — 16, код E — 69)
if(lparam == 69 && (KeyState(VK_SHIFT) || KeyState(VK_LSHIFT) || KeyState(VK_RSHIFT)))
{
OpenCalculatedPositions();
Print(«Позиции открыты по горячей клавише Shift+E»);
}
}
...
// Тень для метки горячих клавиш (в разделе Create UI)
ObjectCreate(0, «RISK_lblHotkey_shadow», OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, «RISK_lblHotkey_shadow», OBJPROP_XDISTANCE, 121); // Смещение на 1 пиксель
ObjectSetInteger(0, «RISK_lblHotkey_shadow», OBJPROP_YDISTANCE, baseY + 33); // Смещение на 1 пиксель
ObjectSetString(0, «RISK_lblHotkey_shadow», OBJPROP_TEXT, «(Shift + E)»);
ObjectSetInteger(0, «RISK_lblHotkey_shadow», OBJPROP_COLOR, clrBlack);
ObjectSetInteger(0, «RISK_lblHotkey_shadow», OBJPROP_BACK, false);
ObjectSetInteger(0, «RISK_lblHotkey_shadow», OBJPROP_FONTSIZE, 10);
// Метка горячих клавиш
ObjectCreate(0, «RISK_lblHotkey», OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, «RISK_lblHotkey», OBJPROP_XDISTANCE, 120);
ObjectSetInteger(0, «RISK_lblHotkey», OBJPROP_YDISTANCE, baseY + 32);
ObjectSetString(0, «RISK_lblHotkey», OBJPROP_TEXT, «(Shift + E)»);
ObjectSetInteger(0, «RISK_lblHotkey», OBJPROP_COLOR, clrWhite);
ObjectSetInteger(0, «RISK_lblHotkey», OBJPROP_BACK, false);
ObjectSetInteger(0, «RISK_lblHotkey», OBJPROP_FONTSIZE, 10);
5) Не удалось доработать кнопки Set SL, Open Positions и Remove Expert так, чтобы они срабатывали только при полном клике
(то есть чтобы не срабатывали, если ЛКМ зажимается за пределами кнопки и отпускается в её пределах).
Будьте осторожны при перемещении графика. Не отжимайте клик на кнопках, это приведет к их нажатию!
6) Имеет смысл добавить прямоугольник-«ручку» к линии-ползунку SL, чтобы её было проще перетаскивать. Пока что не получилось.
7) Отправка ордеров на открытие позиций реализована через функцию OrderSendAsync(request, result), а не через обычную SendAsync. Особенность OrderSendAsync в том, что ордера на открытие нескольких позиций отправляются практически мгновенно, не дожидаясь ответа торгового сервера между отправкой предыдущего ордера и следующего. Поэтому отслеживание исполнения ордеров через MqlTradeResult не работает. Через OnTradeTransaction() тоже пока не получилось, забил хрен. Обрабатываю новые позиции в OnTrade(), указываю при отправке ордеров на открытие позиций в комментарии к ним заданный RR для правильной корректировки на случай проскальзывания. Вроде ок, все баботает, деду нраица.
8) Сбор данных о максимальном Bid и минимальном Ask я реализовал через MqlRates rates[]. Поэтому трейлинг-стоп начинается только при наступлении следующего минутного бара после открытия позиции. В первую минуту он пока не работает. Возможно, нужно как то сделать, чтобы для текущего, ещё не закрытого сразу после открытия позиции бара, данные собирались с тиковой истории, а остальные через MqlRates rates[], чтобы не засрать память тиками за кучу времени. Мб подумаю потом над этой проблемой, но поскольку мне это сейчас вообще не важно, ибо не торгую на минутках, а с первого раза я пока более правильную реализацию не осилил, ничего не обещаю.