Здравствуйте!!! Подскажите пожалуйста как написать функцию в советнике , что бы ордера открывались пересекая линию , которую я выставил заранее руками в МТ4!!!
Обучение языку MQL4 под MetaTrader 4📌
От xbms, 13 апреля, 2013 в Уголок Программиста
Коллеги, здравствуйте.
Очень надеюсь, что найдется программист, который подскажет, как справиться с вроде бы готовым решением на странице http://tlap.io/indikator-atr/
В своего скальпера вставил самостоятельно код с функцией, запрещающей торговлю при высокой волатильности
extern bool UseATRFilter = true;
extern int ATRPer = 14;
extern int EnvPer = 240;
input ENUM_MA_METHOD EnvMode = MODE_EMA;
extern double EnvDev = 10;
bool ATRFilter()
{
if(!UseATRFilter) return(true);
double ATR[500];
for(int i=0;i<=499;i++)
{
ATR[i]=iATR(_Symbol,PERIOD_M5,ATRPer,i+1);
}
ArraySetAsSeries(ATR,true);
double ATR1=iATR(_Symbol,PERIOD_M5,ATRPer,1);
double EnvUp=iEnvelopesOnArray(ATR,0,EnvPer,
EnvMode,0,EnvDev,MODE_UPPER,0);
if(ATR1<EnvUp) return(true);
return(false);
}
и получаю ошибку: 'ATRFilter' - function declarations are allowed on global, namespace or class scope only
Я, к сожалению, не программист, а только трейдер, и мучаюсь от своего незнания.
Если можете подсказать, что надо добавить, исправить, буду очень признателен!
- @molot_1 Выставив линию, должен залезть в ее свойство и переименовать ее значение "Имя" в "sell" или "buy". Если торгуешь сеткой то последующим линиям даешь другие имена "sell 2","sell 3","buy 2" и "buy 3". Имя нам нужно чтоб мы знали к какой линии мы будем обращаться.
- Что бы получить цену на которой у нас линия, будь это трендовая или горизонтальная, у нас есть несколько вариантов на выбор:
ObjectGetDouble()
ObjectGet()
ObjectGetValueByShift()
Обращение к линиям идет через имена которые мы определили.
- Осталось сравнить цену линии с текущей ценой бид или с текущими хаем и лоу текущего бара. По результатам открываем, закрываем ордера или ни чего не делаем.
@MakarFX MessageBox не стоит использовать. Пока ты не нажмешь кнопочку ОК в MessageBox программа MQL полностью останавливает работу.
В твоем случаю модификации тейка и лосса вообще будет действовать как УБИЙЦЕЙ твоего счета!!! Причем это будет выглядеть как СУИЦИД!
Изменено 29 января, 2020 пользователем MikR0ReR
@MikR0ReR Вы можете взглянуть на этот код
//+----------------------------------------------------------------------------+
//| i-SignalOfTrade.mq4 |
//| Ким Игорь В. aka KimIV |
//| http://www.kimiv.ru |
//| |
//| 05.12.2007 Сигнализатор выполнения торговых операций. |
//| 13.05.2008 Сигнализация срабатывания отложенного ордера. |
//| 29.12.2008 Исправлена ошибка сигнализации удаления ордера. |
//+----------------------------------------------------------------------------+
#property copyright "Ким Игорь В. aka KimIV"
#property link "http://www.kimiv.ru"
#property indicator_chart_window
//------- Внешние параметры индикатора ----------------------------------------+
extern string _P_WhatOutput = "---------- Что выводить";
extern bool OutAccountNumber = False; // Выводить номер счёта
extern bool OutAccountServer = False; // Выводить имя активного сервера
extern bool OutNameExpert = False; // Выводить имя эксперта
extern bool OutDateTime = False; // Выводить дату и время
extern bool UseTimeLocal = True; // Использовать локальное время
extern bool OutTicket = False; // Выводить тикет
extern bool OutMagic = False; // Выводить магик
extern bool OutComment = False; // Выводить комментарий
extern string _P_WhereOutput = "---------- Куда выводить";
extern bool UseAlert = True; // Использовать диалоговое окно
extern bool UseComment = False; // Выводить комментарий
extern bool UsePrint = False; // Записывать в журнал
extern bool UseSendMail = False; // Посылать электронное письмо
extern bool UseSendPush = False; // Посылать Push-уведомление на мобильные терминалы
extern bool UseSound = False; // Использовать звук
extern string sotFileName = "ok.wav"; // Наименование звукового файла
//------- Глобальные переменные индикатора ------------------------------------+
int sotOTI[]; // тикет OrderTicket()
int sotOTY[]; // тип OrderType()
double sotOOP[]; // цена OrderOpenPrice()
double sotOSL[]; // стоп OrderStopLoss()
double sotOTP[]; // тейк OrderTakeProfit()
bool sotFirstRun=True; // Флаг первого прогона
//+----------------------------------------------------------------------------+
//| |
//| ПРЕДОПРЕДЕЛЁННЫЕ ФУНКЦИИ |
//| |
//+----------------------------------------------------------------------------+
//| Custom indicator initialization function |
//+----------------------------------------------------------------------------+
void init() {
sotFirstRun=True; // Флаг первого прогона
Comment("");
}
//+----------------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+----------------------------------------------------------------------------+
void deinit() { Comment(""); }
//+----------------------------------------------------------------------------+
//| Custom indicator iteration function |
//+----------------------------------------------------------------------------+
void start() {
double p; // Размер пункта в валюте котировки
int d; // Количество цифр после десятичной точки в цене
int i; // Счётчик операций
int in; // Индекс элемента массива операций
int k=OrdersTotal(); // Количество текущих операций
int ot; // Тип операции OrderType()
int oti[]; // Массив новых тикетов
string sh=""; // Строка заголовка почтового сообщения
string st; // Строка тела почтового сообщения
if (sotFirstRun) { MemCurrOP(); sotFirstRun=False; }
if (OutAccountNumber) sh=DoubleToStr(AccountNumber(), 0)+" ";
if (OutAccountServer) sh=sh+AccountServer();
if (StringLen(sh)>0) sh=sh+"\n";
if (OutDateTime) {
if (UseTimeLocal) sh=sh+TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES)+" ";
else sh=sh+TimeToStr(TimeCurrent(), TIME_DATE|TIME_SECONDS)+" ";
}
if (OutNameExpert) sh=sh+WindowExpertName()+" ";
if (StringLen(sh)>0) sh=sh+"\n";
// Открытие/Установка новых, модификация существующих
ArrayResize(oti, k);
for (i=0; i<k; i++) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
oti[i]=OrderTicket();
d=MarketInfo(OrderSymbol(), MODE_DIGITS);
p=MarketInfo(OrderSymbol(), MODE_POINT);
in=ArraySearchInt(sotOTI, oti[i]);
// операция НЕ найдена, значит новая
if (in<0) {
ot=OrderType();
if (ot==OP_BUY || ot==OP_SELL) st="Open ";
if (ot==OP_BUYLIMIT || ot==OP_BUYSTOP
|| ot==OP_SELLLIMIT || ot==OP_SELLSTOP) st="Set ";
if (OutTicket) st=st+DoubleToStr(OrderTicket(), 0)+" ";
st=st+GetNameOP(ot)+" "
+DoubleToStr(OrderLots(), 2)+" "
+OrderSymbol()
+" PR="+DoubleToStr(OrderOpenPrice(), d)
+" SL="+DoubleToStr(OrderStopLoss(), d)
+" TP="+DoubleToStr(OrderTakeProfit(), d)
+"\n"
+IIFs(OutMagic, "Magic="+DoubleToStr(OrderMagicNumber(), 0), "")
+IIFs(OutMagic && OutComment, " ", "")
+IIFs(OutComment, "Comment=\""+OrderComment()+"\"", "")
+IIFs(OutMagic || OutComment, "\n", "");
if (ot==OP_BUY || ot==OP_SELL) {
st=st+"Balance="+DoubleToStr(AccountBalance(), 2)
+" FreeMargin="+DoubleToStr(AccountFreeMargin(), 2);
}
if (StringLen(sh)>0) st=sh+st;
Signal(st);
// операция найдена, значит существовала ранее и возможно изменена
} else {
// срабатывание отложенного ордера
ot=OrderType();
if (ot!=sotOTY[in] && (ot==OP_BUY || ot==OP_SELL)) {
st="Open ";
if (OutTicket) st=st+DoubleToStr(OrderTicket(), 0)+" ";
st=st+GetNameOP(ot)+" by "+GetNameOP(sotOTY[in])+" "
+DoubleToStr(OrderLots(), 2)+" "
+OrderSymbol()
+" PR="+DoubleToStr(OrderOpenPrice(), d)
+" SL="+DoubleToStr(OrderStopLoss(), d)
+" TP="+DoubleToStr(OrderTakeProfit(), d)
+"\n"
+IIFs(OutMagic, "Magic="+DoubleToStr(OrderMagicNumber(), 0), "")
+IIFs(OutMagic && OutComment, " ", "")
+IIFs(OutComment, "Comment=\""+OrderComment()+"\"", "")
+IIFs(OutMagic || OutComment, "\n", "");
if (ot==OP_BUY || ot==OP_SELL) {
st=st+"Balance="+DoubleToStr(AccountBalance(), 2)
+" FreeMargin="+DoubleToStr(AccountFreeMargin(), 2);
}
if (StringLen(sh)>0) st=sh+st;
Signal(st);
}
// модификация ордера или позиции
if ((MathAbs(OrderOpenPrice()-sotOOP[in])>=p)
|| (MathAbs(OrderStopLoss()-sotOSL[in])>=p)
|| (MathAbs(OrderTakeProfit()-sotOTP[in])>=p)) {
st="Modify ";
if (OutTicket) st=st+DoubleToStr(OrderTicket(), 0)+" ";
st=st+GetNameOP(OrderType())+" "
+DoubleToStr(OrderLots(), 2)+" "
+OrderSymbol();
// изменилась цена открытия
if (MathAbs(OrderOpenPrice()-sotOOP[in])>=p) {
st=st+" PR="+DoubleToStr(sotOOP[in], d)+"->"+DoubleToStr(OrderOpenPrice(), d);
}
// изменился уровень стопа
if (MathAbs(OrderStopLoss()-sotOSL[in])>=p) {
st=st+" SL="+DoubleToStr(sotOSL[in], d)+"->"+DoubleToStr(OrderStopLoss(), d);
}
// изменился уровень тейка
if (MathAbs(OrderTakeProfit()-sotOTP[in])>=p) {
st=st+" TP="+DoubleToStr(sotOTP[in], d)+"->"+DoubleToStr(OrderTakeProfit(), d);
}
st=st+IIFs(OutMagic || OutComment, "\n", "")
+IIFs(OutMagic, "Magic="+DoubleToStr(OrderMagicNumber(), 0), "")
+IIFs(OutMagic && OutComment, " ", "")
+IIFs(OutComment, "Comment=\""+OrderComment()+"\"", "")
+IIFs(OutMagic || OutComment, "\n", "");
if (StringLen(sh)>0) st=sh+st;
Signal(st);
}
}
}
}
// Закрытие позиций / Удаление ордеров
k=ArraySize(sotOTI);
for (i=0; i<k; i++) {
if (ArraySearchInt(oti, sotOTI[i])<0) {
ot=sotOTY[i];
if (ot==OP_BUY || ot==OP_SELL) st="Close ";
if (ot==OP_BUYLIMIT || ot==OP_BUYSTOP
|| ot==OP_SELLLIMIT || ot==OP_SELLSTOP) st="Delete ";
if (OutTicket) st=st+DoubleToStr(sotOTI[i], 0)+" ";
if (OrderSelect(sotOTI[i], SELECT_BY_TICKET)) {
d=MarketInfo(OrderSymbol(), MODE_DIGITS);
st=st+GetNameOP(ot)+" "
+DoubleToStr(OrderLots(), 2)+" "
+OrderSymbol()
+" PR="+DoubleToStr(OrderClosePrice(), d)
;
if (ot==OP_BUY || ot==OP_SELL) {
st=st+" Profit="+DoubleToStr(OrderProfit()+OrderSwap(), 2)
+"\n"
+IIFs(OutMagic, "Magic="+DoubleToStr(OrderMagicNumber(), 0), "")
+IIFs(OutMagic && OutComment, " ", "")
+IIFs(OutComment, "Comment=\""+OrderComment()+"\"", "")
+IIFs(OutMagic || OutComment, "\n", "")
+"Balance="+DoubleToStr(AccountBalance(), 2)
+" FreeMargin="+DoubleToStr(AccountFreeMargin(), 2);
}
if (StringLen(sh)>0) st=sh+st;
Signal(st);
}
}
}
MemCurrOP();
}
//+----------------------------------------------------------------------------+
//| |
//| ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ |
//| |
//+----------------------------------------------------------------------------+
//| Выполняет поиск элемента массива по значению |
//| и возвращает индекс найденного элемента или -1 |
//| Параметры: |
//| m - массив элементов |
//| e - значение элемента |
//+----------------------------------------------------------------------------+
int ArraySearchInt(int& m[], int e) {
for (int i=0; i<ArraySize(m); i++) {
if (m[i]==e) return(i);
}
return(-1);
}
//+----------------------------------------------------------------------------+
//| Возвращает наименование торговой операции |
//| Параметры: |
//| op - идентификатор торговой операции |
//+----------------------------------------------------------------------------+
string GetNameOP(int op) {
switch (op) {
case OP_BUY : return("Buy");
case OP_SELL : return("Sell");
case OP_BUYLIMIT : return("BuyLimit");
case OP_SELLLIMIT: return("SellLimit");
case OP_BUYSTOP : return("BuyStop");
case OP_SELLSTOP : return("SellStop");
default : return("Unknown Operation");
}
}
//+----------------------------------------------------------------------------+
//| Возвращает одно из двух значений взависимости от условия. |
//+----------------------------------------------------------------------------+
string IIFs(bool condition, string ifTrue, string ifFalse) {
if (condition) return(ifTrue); else return(ifFalse);
}
//+----------------------------------------------------------------------------+
//| Запоминает текущие операции в массиве. |
//+----------------------------------------------------------------------------+
void MemCurrOP() {
int i, k=OrdersTotal();
ArrayResize(sotOTI, k);
ArrayResize(sotOTY, k);
ArrayResize(sotOOP, k);
ArrayResize(sotOSL, k);
ArrayResize(sotOTP, k);
for (i=0; i<k; i++) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
sotOTI[i]=OrderTicket();
sotOTY[i]=OrderType();
sotOOP[i]=OrderOpenPrice();
sotOSL[i]=OrderStopLoss();
sotOTP[i]=OrderTakeProfit();
}
}
}
//+----------------------------------------------------------------------------+
//| Подача сигнала. |
//| Параметры: |
//| st - строка сообщения |
//+----------------------------------------------------------------------------+
void Signal(string st) {
if (UseAlert) Alert(st);
if (UseComment) Comment(st);
if (UseSendMail) SendMail(WindowExpertName(), st);
if (UseSendPush) SendNotification(st);
if (UsePrint) Print(st);
if (UseSound) PlaySound(sotFileName);
}
//+----------------------------------------------------------------------------+
Если я включаю UseAlert и UseSound, то звук Alert блокирует звук Sound
@MikR0ReR Я так понял надо поставить Sleep
но где? Для меня это китайская грамота
//+----------------------------------------------------------------------------+
//| Подача сигнала. |
//| Параметры: |
//| st - строка сообщения |
//+----------------------------------------------------------------------------+
void Signal(string st) {
if (UseAlert) Alert(st);
if (UseComment) Comment(st);
if (UseSendMail) SendMail(WindowExpertName(), st);
if (UseSendPush) SendNotification(st);
if (UsePrint) Print(st);
if (UseSound) PlaySound(sotFileName);
}1 час назад, MakarFX сказал:Если я включаю UseAlert и UseSound, то звук Alert блокирует звук Sound
А если включить только UseSound, а алерт выключить, будет работать?
51 минуту назад, MakarFX сказал:UseSound будет работать, но не будет окна сообщения
Необъяснимая Ненормативная лексика..., попробуйте поставить if (UseSound) PlaySound(sotFileName); первой строчкой
В 28.01.2020 в 20:19, MikR0ReR сказал:@mischkus Вынесите функцию ATRFilter() за пределы OnTick() в глобальное пространство. Пример:
int OnInit()
{
}OnTick(void)
{
}
bool ATRFilter()
{
}
Ошибки после компиляции нет. Прогоняю тесты, но результат нулевой, что есть этот фильтр, что его нет... То есть вижу, что при всплеске волатильности не убираются лишние трейды.
5 часов назад, mischkus сказал:Ошибки после компиляции нет. Прогоняю тесты, но результат нулевой,
@mischkus Вы вставили функцию, теперь в основном коде программы нужно эту функцию вызвать и в зависимости от её значения true/false нужно запретить или разрешить торговлю.
Т.к. кода советника нет Вы должны сами определить каким образом её использовать.
Типа: если ATRFilter()=true, то делаем то-то, ну, к примеру, покупаем?
Потому что основное - это условия для открытия и закрытия позиции.
И то сейчас одно из условий дает сбой: то работает правильно, то...
2 часа назад, mischkus сказал:Типа: если ATRFilter()=true, то делаем то-то, ну, к примеру, покупаем?
Да, именно так - нужно опрашивать функцию, получать результат и выстраивать торговую логику.
Всем привет!
Помогите пристроить
extern ENUM_BASE_CORNER InpCorner = CORNER_LEFT_UPPER; // Угол привязки индикатора
//--- Clicking on the fifth rectangle
if(id==CHARTEVENT_OBJECT_CLICK)
{
string clickedChartObject=sparam;
if(clickedChartObject==obj_name[5])
{
string name="name_"+IntegerToString(MathRand()+100,0,' ');
y=100;x=5;
ChartXYToTimePrice(0,x,y,window,dt_1,price_1);
ChartXYToTimePrice(0,x+250,y,window,dt_2,price_2);
ChartXYToTimePrice(0,x,y+20,window,dt_3,price_3);
ChannelCreate(0,name,0,dt_1,price_1,dt_2,price_2,dt_3,price_3,1,clrRed,STYLE_SOLID,1,InpBackRect,true,false,false,InpHidden_OBJ,0);
}
}
//+------------------------------------------------------------------+
//| Create an equidistant channel by the given coordinates |
//+------------------------------------------------------------------+
bool ChannelCreate(const long chart_ID=0, // chart's ID
const string name="Channel", // channel name
const int sub_window=0, // subwindow index
datetime time1=0, // first point time
double price1=0, // first point price
datetime time2=0, // second point time
double price2=0, // second point price
datetime time3=0, // third point time
double price3=0, // third point price
const ENUM_BASE_CORNER corner = CORNER_RIGHT_UPPER, // the angle of the graph for the binding
const color clr=clrRed, // channel color
const ENUM_LINE_STYLE style=STYLE_SOLID, // style of channel lines
const int width=1, // width of channel lines
const bool back=false, // in the background
const bool selection=true, // highlight to move
const bool ray_left = false, // extend the line to the left
const bool ray_right=false, // channel's continuation to the right
const bool hidden=true, // hidden in the object list
const long z_order=0) // priority for mouse click
{
//--- reset the error value
ResetLastError();
//--- create a channel by the given coordinates
if(!ObjectCreate(chart_ID,name,OBJ_CHANNEL,sub_window,time1,price1,time2,price2,time3,price3))
{
Print(__FUNCTION__,
": failed to create an equidistant channel! Error code = ",GetLastError());
return(false);
}
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_RAY_RIGHT,ray_right);
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Delete the channel |
//+------------------------------------------------------------------+
bool ChannelDelete(const long chart_ID=0, // chart's ID
const string name="Channel") // channel name
{
//--- reset the error value
ResetLastError();
//--- delete the channel
if(!ObjectDelete(chart_ID,name))
{
Print(__FUNCTION__,
": failed to delete the channel! Error code = ",GetLastError());
return(false);
}
//---
return(true);
}
//---
Я так понял, что ChartXYToTimePrice расчитывает координаты и по умолчанию с левого верхнего углу.
Как бы ChartXYToTimePrice переубедить считать с указанного мной угла?
3 часа назад, MakarFX сказал:Как бы ChartXYToTimePrice переубедить считать с указанного мной угла?
ChartXYToTimePrice Нужно читать! Если не понятно, нужно еще раз прочесть!
Координата X. Начало координат находится в левом верхнем углу главного окна графика.
Координата Y. Начало координат находится в левом верхнем углу главного окна графика.
И ветка для MQ5 находится здесь Обучение языку MQL5 под MetaTrader 5
Изменено 31 января, 2020 пользователем 0ll
Для публикации сообщений создайте учётную запись или авторизуйтесь
Перейти к списку тем