Предлагаю советник для ручной торговли в тестере MetaTrader4. Одновременно может быть открыта только одна позиция.
Советник позволяет:
— открывать и закрывать вручную сделки в тестере,
— выставлять stop loss (SL) и take profit (TP),
— закрывать сделку, не дожидаясь срабатывания SL или TP,
— переносить SL в безубыток.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Периодически посещают идеи по поводу торговли, которые хочется прогнать в тестере, не создавая для этого отдельного советника. Порой, после окончания торгового дня, появляется желание прогнать этот день еще раз в тестере, и посмотреть, также бы я торговала или как-то иначе. Отрыла бы ордер в этом же месте, как и на реале, или уже по-другому рассудила бы.
Так как у меня одновременно открыт только один ордер. И все мои стратегии сводятся к тому, что для меня в приоритете вход и выход, а не количество, то я для тестера создала небольшой советник.
Советник работает только в тестере. Рекомендую запускать на небольшой скорости. Если в тестере использовать «все тики», то скорость 31 медленная, а 32 — слишком большая, поэтому я часто запускаю советник на «контрольных точках» и со скоростью 31.
При запуске советника сверху справа появляются две текстовые метки:
BUY и
SELL.
Обе метки выделены. Если убрать выделение с BUY (два раза кликнуть мышкой), то произойдет покупка, если убрать выделение с SELL — то продажа.
Эти две метки исчезнут и появится метка
CLOSE и две линии на графике.
Если нажать CLOSE, то сделка закроется, и опять на графике будут только метки BUY и SELL.
Две линии — это и есть будущие SL и TP.
Для buy-ордера верхняя линия — TP, нижняя — SL.
Для sell-ордера верхняя линия — SL, нижняя — TP.
Передвигаем линию на нужное расстояние, убираем выделение и SL/TP выставился. Линия останется на месте выставленного SL/TP, чтобы её можно было двигать. Двигаем, убираем выделение — и таким образом переносим SL/TP.
В том числе и переносим SL в безубыток.
Всё очень интуитивно и понятно.
Вот сам советник:EA_inTester_Sell_Buy_btns.rar (23 Kb)
Всем, кому интересна структура кода советника, то читаем дальше.
_______________________________________________________________________________
КОД.
Вспомогательные функции, которые участвуют в создании данного советника.
1. Функция
LabelCreate — создает текстовую метку. (
оригинал функции)
bool LabelCreate(const string name="Label", // имя метки
const int x=0, // координата по оси X
const int y=0, // координата по оси Y
const color clr=clrRed, // цвет
const string text="CLOSE", // текст
const int font_size=16, // размер шрифта
const ENUM_BASE_CORNER corner=CORNER_RIGHT_UPPER,// угол графика для привязки
const string font="Arial", // шрифт
const ENUM_ANCHOR_POINT anchor=ANCHOR_RIGHT_UPPER,// способ привязки
const double angle=0.0, // наклон текста
const bool back=false, // на заднем плане
const bool selection=true, // выделить для перемещений
const bool hidden=true, // скрыт в списке объектов
const long z_order=0, // приоритет на нажатие мышью
const int sub_window=0, // номер подокна
const long chart_ID=0) // ID графика
{
//--- сбросим значение ошибки
ResetLastError();
//--- создадим текстовую метку
if(!ObjectCreate(chart_ID,name,OBJ_LABEL,sub_window,0,0)) {
Print(__FUNCTION__, ": не удалось создать текстовую метку! Код ошибки = ",GetLastError());
return(false);
}
//--- установим координаты метки
ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
//--- установим угол графика, относительно которого будут определяться координаты точки
ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
//--- установим текст
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- установим шрифт текста
ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//--- установим размер шрифта
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//--- установим угол наклона текста
ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
//--- установим способ привязки
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
//--- установим цвет
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- отобразим на переднем (false) или заднем (true) плане
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- включим (true) или отключим (false) режим перемещения метки мышью
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- скроем (true) или отобразим (false) имя графического объекта в списке объектов
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- установим приоритет на получение события нажатия мыши на графике
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- успешное выполнение
return(true);
}
2. Функция
HLineCreate — создает линию тренда. (
оригинал функции)
bool HLineCreate(const string name="HLine", // имя линии
double price=0, // цена линии
const color clr=clrOrange, // цвет линии
const ENUM_LINE_STYLE style=STYLE_DASH, // стиль линии
const int width=1, // толщина линии
const bool back=false, // на заднем плане
const bool selection=true, // выделить для перемещений
const bool hidden=true, // скрыт в списке объектов
const long z_order=0, // приоритет на нажатие мышью
const int sub_window=0, // номер подокна
const long chart_ID=0) // ID графика
{
//--- сбросим значение ошибки
ResetLastError();
//--- создадим горизонтальную линию
if(!ObjectCreate(chart_ID,name,OBJ_HLINE,sub_window,0,price)) {
Print(__FUNCTION__, ": не удалось создать горизонтальную линию! Код ошибки = ",GetLastError());
return(false);
}
//--- установим цвет линии
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- установим стиль отображения линии
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- установим толщину линии
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
//--- отобразим на переднем (false) или заднем (true) плане
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- включим (true) или отключим (false) режим перемещения линии мышью
//--- при создании графического объекта функцией ObjectCreate, по умолчанию объект
//--- нельзя выделить и перемещать. Внутри же этого метода параметр selection
//--- по умолчанию равен true, что позволяет выделять и перемещать этот объект
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- скроем (true) или отобразим (false) имя графического объекта в списке объектов
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- установим приоритет на получение события нажатия мыши на графике
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- успешное выполнение
return(true);
}
3. Функция
CloseOpenPos — закрывает открытую позицию.
void CloseOpenPos () {
int i, k=OrdersTotal(), ot;
for (i=k-1; i>=0; i--) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if (OrderSymbol()==Symb && OrderMagicNumber()==MagicNumber) {
ot = OrderType();
if(ot==0 || ot==1) {
double _price=Ask; if(ot==0) _price=Bid;
if (!OrderClose(OrderTicket(), OrderLots(), _price, Slippage))
Print("Failed to close the order ", OrderTicket(), "!");
}
}
}
}
}
Еще раз повторяюсь, что советник рассчитан только для тестера, поэтому эта функция и последующие решения имеют упрощенный вид.
Глобальные переменные.
//------- global variables ------------------------------------------+
string Symb; // Присвоим символ в init один раз, чтобы каждый раз не обращаться к нему
double Mi_Lv; // Минимальное расстояние до SL и TP
string EA_LINE_UP_SL_TP = "EA_LINE_UP_SL_TP"; // Наименование верхней горизонтальной линии
string EA_LINE_DN_SL_TP = "EA_LINE_DN_SL_TP"; // Наименование нижней горизонтальной линии
string EA_LABEL_BUY = "EA_LABEL_BUY"; // Наименование текстовой метки BUY
string EA_LABEL_SELL = "EA_LABEL_SELL"; // Наименование текстовой метки SELL
string EA_LABEL_CLOSE = "EA_LABEL_CLOSE"; // Наименование текстовой метки CLOSE
int Label_XDISTANCE = 20; // Расстояние Х до текстовых меток
int Label_YDISTANCE = 20; // Расстояние Y до текстовых меток
int Ticket=-1; // Тикет - чтобы к нему обращаться
datetime TimeLast=-1; // Чтобы двигать линии на новой свече, а не на каждом тике
Входящие параметры.
//------- external parameters ---------------------------------------+
extern double Lot = 1; // Lot - размер лота
extern color ColorBuy = clrGreen; // color text BUY - цвет текста BUY
extern color ColorSell = clrRed; // color text SELL - цвет текста SELL
extern color ColorSL_TP = clrGreen; // color lines SL & TP - цвет горизонтальных линий
extern color ColorClose = clrRed; // color text CLOSE - цвет текста CLOSE
extern int FontSize = 16; // text size - размер текста
extern int MinPointsLine = 100; // min points line from Ask/Bid - минимальное расстояние до линии
extern int MaxPointsLine = 2000; // max points line from Ask/Bid - максимальное расстояние до линии
extern int Slippage = 10; // Slippage
extern int MagicNumber = 5557555; // Magic
ОСНОВНАЯ ЛОГИКА.
Проверяем наличие/отсутствие текстовых меток и линий на графике.
1. Позиций нет открытых — должны присутствовать метки BUY и SELL. И не должно быть метки CLOSE и линий.
//--- если OrdersTotal()==0 - то нет открытых/отложенных ордеров на графике - применимо только для тестера
// есть ли метка BUY, когда нет открытых позиций
if(ObjectFind(EA_LABEL_BUY)!=0 && OrdersTotal()==0) {
LabelCreate(EA_LABEL_BUY, Label_XDISTANCE, Label_YDISTANCE, ColorBuy, "BUY", FontSize);
}
// есть ли метка SELL, когда нет открытых позиций
if(ObjectFind(EA_LABEL_SELL)!=0 && OrdersTotal()==0) {
LabelCreate(EA_LABEL_SELL, Label_XDISTANCE, Label_YDISTANCE+FontSize*2, ColorSell, "SELL", FontSize);
}
// есть ли CLOSE, когда нет открытых позиций
if(ObjectFind(EA_LABEL_CLOSE)==0 && OrdersTotal()==0) {
ObjectDelete(0, EA_LABEL_CLOSE);
}
// есть ли верхняя линия, когда нет открытых позиций
if(ObjectFind(EA_LINE_UP_SL_TP)==0 && OrdersTotal()==0) {
ObjectDelete(0, EA_LINE_UP_SL_TP);
}
// есть ли нижняя линия, когда нет открытых позиций
if(ObjectFind(EA_LINE_DN_SL_TP)==0 && OrdersTotal()==0) {
ObjectDelete(0, EA_LINE_DN_SL_TP);
}
2. Есть открытая позиция — должны присутствовать метка CLOSE и две линии. И не должно быть меток BUY и SELL.
//--- если OrdersTotal()>0 - то есть открытые/отложенные ордера на графике - применимо только для тестера
// есть ли метка CLOSE при открытой позиции
if(ObjectFind(EA_LABEL_CLOSE)!=0 && OrdersTotal()>0) {
LabelCreate(EA_LABEL_CLOSE, Label_XDISTANCE, Label_YDISTANCE, ColorClose, "CLOSE", FontSize);
}
// есть ли верхняя линия при открытой позиции
if(ObjectFind(EA_LINE_UP_SL_TP)!=0 && OrdersTotal()>0) {
HLineCreate(EA_LINE_UP_SL_TP, NormalizeDouble(Ask+MinPointsLine*Point, Digits), ColorSL_TP);
}
// есть ли нижняя линия при открытой позиции
if(ObjectFind(EA_LINE_DN_SL_TP)!=0 && OrdersTotal()>0) {
HLineCreate(EA_LINE_DN_SL_TP, NormalizeDouble(Bid-MinPointsLine*Point, Digits), ColorSL_TP);
}
// есть ли метка BUY при открытой позиции
if(ObjectFind(EA_LABEL_BUY)==0 && OrdersTotal()>0) {
ObjectDelete(0, EA_LABEL_BUY);
}
// есть ли метка SELL при открытой позиции
if(ObjectFind(EA_LABEL_SELL)==0 && OrdersTotal()>0) {
ObjectDelete(0, EA_LABEL_SELL);
}
Открываем/закрываем позиции.
3. Если пользователем убрано выделение с BUY или с SELL метки — открываем позицию. Записываем тикет для выставления SL/TP.
if(ObjectFind(EA_LABEL_BUY)==0 && ObjectGetInteger(0, EA_LABEL_BUY, OBJPROP_SELECTED)==0){
Ticket = OrderSend(Symb, OP_BUY, Lot, Ask, Slippage, 0, 0, NULL, MagicNumber);
return;
}
if(ObjectFind(EA_LABEL_SELL)==0 && ObjectGetInteger(0, EA_LABEL_SELL, OBJPROP_SELECTED)==0){
Ticket = OrderSend(Symb, OP_SELL, Lot, Bid, Slippage, 0, 0, NULL, MagicNumber);
return;
}
Если советник на паузе и убрано одновременно выделение с BUY и с SELL меток, то будет открыт только buy ордер.
4. Если пользователем убрано выделение с CLOSE метки — закрываем позицию.
if(ObjectFind(EA_LABEL_CLOSE)==0 && ObjectGetInteger(0, EA_LABEL_CLOSE, OBJPROP_SELECTED)==0){
CloseOpenPos();
return;
}
Выставляем SL/TP.
5. Если с верхней горизонтальной линии пользователем убрано выделение — выставляем SL/TP.
//--- верхняя линия
if(ObjectFind(EA_LINE_UP_SL_TP)==0 && ObjectGetInteger(0, EA_LINE_UP_SL_TP, OBJPROP_SELECTED)==0) {
if(OrdersTotal()>0) {
// меняем SL или TP
double _price = NormalizeDouble(ObjectGetDouble(0, EA_LINE_UP_SL_TP, OBJPROP_PRICE), Digits);
double _upPrice = 0;
if(_price>Ask) {
_upPrice = _price;
if(_price-Ask<Mi_Lv*Point) _upPrice = NormalizeDouble(Ask + Mi_Lv*Point, Digits);
if(OrderType()==OP_BUY && OrderTakeProfit()!=_upPrice) {
if(OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), _upPrice, 0))
ObjectSetDouble(0, EA_LINE_UP_SL_TP, OBJPROP_PRICE, _upPrice);
}
if(OrderType()==OP_SELL && OrderStopLoss()!=_upPrice) {
if(OrderModify(OrderTicket(), OrderOpenPrice(), _upPrice, OrderTakeProfit(), 0))
ObjectSetDouble(0, EA_LINE_UP_SL_TP, OBJPROP_PRICE, _upPrice);
}
} else {
ObjectSetDouble(0, EA_LINE_UP_SL_TP, OBJPROP_PRICE, Ask+Mi_Lv*Point);
}
ObjectSetInteger(0, EA_LINE_UP_SL_TP, OBJPROP_SELECTED, 1);
}
}
6. Если с нижней горизонтальной линии пользователем убрано выделение — выставляем SL/TP.
//--- нижняя линия
if(ObjectFind(EA_LINE_DN_SL_TP)==0 && ObjectGetInteger(0, EA_LINE_DN_SL_TP, OBJPROP_SELECTED)==0) {
if(OrdersTotal()>0) {
// меняем SL или TP
double _price = NormalizeDouble(ObjectGetDouble(0, EA_LINE_DN_SL_TP, OBJPROP_PRICE), Digits);
double _dnPrice = 0;
if(_price<Bid) {
_dnPrice = _price;
if(Bid-_price<Mi_Lv*Point) _dnPrice = NormalizeDouble(Bid - Mi_Lv*Point, Digits);
if(OrderType()==OP_BUY && OrderStopLoss()!=_dnPrice) {
if(OrderModify(OrderTicket(), OrderOpenPrice(), _dnPrice, OrderTakeProfit(), 0))
ObjectSetDouble(0, EA_LINE_DN_SL_TP, OBJPROP_PRICE, _dnPrice);
}
if(OrderType()==OP_SELL && OrderTakeProfit()!=_dnPrice) {
if(OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), _dnPrice, 0))
ObjectSetDouble(0, EA_LINE_DN_SL_TP, OBJPROP_PRICE, _dnPrice);
}
} else {
ObjectSetDouble(0, EA_LINE_DN_SL_TP, OBJPROP_PRICE, Bid-Mi_Lv*Point);
}
ObjectSetInteger(0, EA_LINE_DN_SL_TP, OBJPROP_SELECTED, 1);
}
}
7. Так как не обязательно сразу выставлять SL и TP, а график не стоит на месте, то возникает необходимость в корректировки линий относительно цены. Для этого во входящих переменных и есть два параметра:
min points line from Ask/Bid и
max points line from Ask/Bid.
//--- линии корректируются
if(ObjectFind(EA_LINE_UP_SL_TP)==0 && ObjectGetInteger(0, EA_LINE_UP_SL_TP, OBJPROP_SELECTED)==1 && Ticket!=-1 && OrdersTotal()>0) {
if(OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES) && ((OrderType()==1 && OrderStopLoss()==0) || (OrderType()==0 && OrderTakeProfit()==0))) {
double _price_up = ObjectGetDouble(0, EA_LINE_UP_SL_TP, OBJPROP_PRICE);
if(_price_up<Ask)
ObjectSetDouble(0, EA_LINE_UP_SL_TP, OBJPROP_PRICE, NormalizeDouble(Ask+MinPointsLine*Point, Digits));
if(TimeLast!=Time[0] && _price_up>Ask+MaxPointsLine*Point)
ObjectSetDouble(0, EA_LINE_UP_SL_TP, OBJPROP_PRICE, NormalizeDouble(Ask+MinPointsLine*Point, Digits));
}
}
if(ObjectFind(EA_LINE_DN_SL_TP)==0 && ObjectGetInteger(0, EA_LINE_DN_SL_TP, OBJPROP_SELECTED)==1 && Ticket!=-1 && OrdersTotal()>0) {
if(OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES) && ((OrderType()==1 && OrderTakeProfit()==0) || (OrderType()==0 && OrderStopLoss()==0))) {
double _price_dn = ObjectGetDouble(0, EA_LINE_DN_SL_TP, OBJPROP_PRICE);
if(_price_dn>Bid)
ObjectSetDouble(0, EA_LINE_DN_SL_TP, OBJPROP_PRICE, NormalizeDouble(Bid-MinPointsLine*Point, Digits));
if(TimeLast!=Time[0] && _price_dn<Bid-MaxPointsLine*Point)
ObjectSetDouble(0, EA_LINE_DN_SL_TP, OBJPROP_PRICE, NormalizeDouble(Bid-MinPointsLine*Point, Digits));
}
}
TimeLast=Time[0];
Надеюсь, данный советник будет вам полезен также, как и мне!
P.S. Сам советник в середине статьи. (специально в середине)
P.S. Нужен программист? Пишите в личку — подскажу, какие идеи возьмусь реализовывать и почём.
Также пользователи от 3-го уровня могут обращаться в "
Стол заказов".
Комментарии (23)
45 Bishop Сообщений: 5812 - АЛЬФАХАМЕЦ-Машковод
27 alterego Сообщений: 2088 - Елена
10 cardon Сообщений: 376
Этот делала чисто под свои нужды. И поделилась им.
27 Oxy Автор Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
16 M-mason Сообщений: 99 - Михаил
19 lorik Сообщений: 357 - Лариса
24 SerOv Сообщений: 859 - Сергей
Интересно советник работает — у меня почему то постоянно отодвигает Тейк а не закрывает. ОТ и стоп отодвигает = а как закрыл по какому принципу так и не понял.
24 SerOv Сообщений: 859 - Сергей
Если же линия сама периодически отодвигается, значит стоп не выставлен.
Понятно объяснила? Или с картинками объяснить?
27 Oxy Автор Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
24 SerOv Сообщений: 859 - Сергей
27 Oxy Автор Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
27 Oxy Автор Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
mql.opentraders.ru/32218.html
В конце статьи советник. Редактирован: 27 апреля 2016, 14:21
27 Oxy Автор Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
8 Genri Сообщений: 378
Не ужели правда!?
35 AM2 Сообщений: 16418 - Андрей
Из видео:
«Чистая прибыль порядка 5 600$ или 56% от депо» — за день.
За неделю по идее накапало бы около 280%. Автор пишет про 200% и 20 000$ прибыли.
Да автор мульти миллиардер уже
27 Oxy Автор Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
4 vsv2675 Сообщений: 67 - Fotini
Вопрос: можно ли в тестере устанавливать тестирование советников не по дням, а по часам?
3 Yuriy52 Сообщений: 2
27 Oxy Автор Сообщений: 3430 - ..ιllιlι.lι.ιllι.ιlι..
9 Wizas Сообщений: 146
кликом на кнопке связанной с соответствующей функцией или по экспирации
35 AM2 Сообщений: 16418 - Андрей
Но там отложенный ордер не удаляется prntscr.com/mtr9zp
может быть из за того, что после этой отложки были выставлены еще ордера?
9 Wizas Сообщений: 146
0 Boss56 Сообщений: 1
Зарегистрируйтесь или авторизуйтесь, чтобы оставить комментарий