Пояснение к этому
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Вопросы от начинающих MQL4 MT4 MetaTrader 4
fxsaber, 2017.09.08 13:52
При использовании ChartApplyTemplate требуется обязательная синхронизация, которую в библе делаю так
static bool TemplateApply( const long Chart_ID, const string &Str, const bool Sync = true ) { string TmpStr = Str; const bool SyncFlag = (Sync && Chart_ID && (Chart_ID != ::ChartID()) && !::IsStopped()); if (SyncFlag) { const color ColorStopLevel = (color)::ChartGetInteger(Chart_ID, CHART_COLOR_STOP_LEVEL); if ((bool)(ColorStopLevel >> 24)) ::ChartSetInteger(Chart_ID, CHART_COLOR_STOP_LEVEL, ColorStopLevel & 0xFFFFFF); const int NewColorStopLevel = (int)EXPERT::StringBetween(TmpStr, EXPERT_STOPLEVEL, STRING_END) | (0x01 << 24); TmpStr = Str; EXPERT::StringReplace(TmpStr, EXPERT_STOPLEVEL, STRING_END, EXPERT_STOPLEVEL + (string)NewColorStopLevel + STRING_END); } short Data[]; const bool Res = ::StringToShortArray(TmpStr, Data, 0, ::StringLen(TmpStr)) && ::FileSave(FILENAME, Data) && ::ChartApplyTemplate((ulong)Chart_ID, FILENAME); if (Res && SyncFlag) { long Value; while ((!::IsStopped() && ::ChartGetInteger(Chart_ID, CHART_COLOR_STOP_LEVEL, 0, Value) && (!(bool)((int)Value >> 24)))) ::Sleep(0); ::ChartSetInteger(Chart_ID, CHART_COLOR_STOP_LEVEL, (int)Value & 0xFFFFFF); } return(Res); }
ChartApply не сразу срабатывает. А какие-либо дальнейшие действия можно делать только после срабатывания.
Чтобы понять, что шаблон применился, нужно изменить сам шаблон (в библе изменяется цвет одной характеристики чарта - 4-й байт, отвечающий за прозрачность) и через Sleep дождаться (ChartGetInterger), когда это значение станет свойством чарта. После этого задать ему нормальное значение через ChartSetInteger.
Если же нужно еще и советник запустить на том же чарте, куда кидается скрипт, то нужно открывать новый чарт и на нем через шаблон запускать себя же (скрипт), а оттуда запускать на нужном уже нам чарте советник, закрыв вспомогательный. Это проделывает ExpertLoader_Example.mq5.
может быть полезна при написании различных управляющих панелей чартами/советниками и т.п.
Библиотека работает без DLL - полностью удовлетворяет требованиям Маркета.
Небольшой лайфхак - запуск советников/скриптов на OBJ_CHART-объектах.
Так запущенные советники висят мертво - никак не выполняются. А вот скрипты работают отлично. Поэтому это открывает некоторые возможности.
Например, можно использовать Order-функции из индикаторов на чартах, где уже есть запущенный советник. И при этом никаких новых вспомогательный чартов открывать не требуется.
Компилируем скрипт Scripts\OrderSend.mq5
#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006 #include <GlobalVariables.mqh> // https://www.mql5.com/ru/forum/189649#comment_4854618 struct ORDERSEND { int Type; double Volume; double Price; int SlipPage; double SL; double TP; long Magic; datetime Expiration; color Arrow_Color; }; void OrderSend() { const ORDERSEND Order = _GlobalVariableGet<ORDERSEND>("ORDERSEND"); const string Symb = _GlobalVariableGet<string>("Symbol"); const string comment = _GlobalVariableGet<string>("Comment"); _GlobalVariableSet(__FUNCTION__, OrderSend(Symb, Order.Type, Order.Volume, Order.Price, Order.SlipPage, Order.SL, Order.TP, comment, Order.Magic, Order.Expiration, Order.Arrow_Color)); _GlobalVariableDel("ORDERSEND"); _GlobalVariableDel("Symbol"); _GlobalVariableDel("Comment"); } void OnStart() { OrderSend(); }
И запускаем индикатор, который "умеет торговать"
#include <fxsaber\Expert.mqh> // https://www.mql5.com/ru/code/19003 #include <GlobalVariables.mqh> // https://www.mql5.com/ru/forum/189649#comment_4854618 struct ORDERSEND { int Type; double Volume; double Price; int SlipPage; double SL; double TP; long Magic; datetime Expiration; color Arrow_Color; }; template <typename T> long _GlobalVariableGet2( const string Name, const ulong MaxTime = 1e6 ) { const ulong StartTime = GetMicrosecondCount(); while (!IsStopped() && !GlobalVariableCheck(Name) && (GetMicrosecondCount() - StartTime < MaxTime)) Sleep(0); return(_GlobalVariableGet<T>(Name)); } // OrderSend, который работает даже из индикатора хоть на чарте с советником long OrderSend( string Symb, const int Type, const double dVolume, const double Price, const int SlipPage, const double SL, const double TP, string comment = NULL, const long magic = 0, const datetime dExpiration = 0, color arrow_color = clrNONE ) { MqlParam Params[1]; Params[0].string_value = "Scripts\\OrderSend.ex5"; ORDERSEND Order; Order.Type = Type; Order.Volume = dVolume; Order.Price = Price; Order.SlipPage = SlipPage; Order.SL = SL; Order.TP = TP; Order.Magic = magic; Order.Expiration = dExpiration; Order.Arrow_Color = arrow_color; const long Res = ObjectCreate(0, __FILE__, OBJ_CHART, 0, 0, 0) && _GlobalVariableSet("ORDERSEND", Order) && _GlobalVariableSet("Symbol", Symb) && _GlobalVariableSet("Comment", comment) && EXPERT::Run(ObjectGetInteger(0, __FILE__, OBJPROP_CHART_ID), Params) && ObjectDelete(0, __FILE__) ? _GlobalVariableGet2<long>(__FUNCTION__) : -1; _GlobalVariableDel(__FUNCTION__); return(Res); } void OnInit() { Print(OrderSend(_Symbol, ORDER_TYPE_BUY, 1, SymbolInfoDouble(_Symbol, SYMBOL_ASK), 100, 0, 0, "From Indicator", 9)); } int OnCalculate( const int, const int, const int, const double &[] ) { return(0); }
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Управление советниками через глобальный алгоритм
Totosha16, 2018.02.07 18:57
На текущий момент пытаюсь решить простою задачу, используя вашу библиотеку, которая сводится к следующему: закрыть все советники на всех чартах кроме текущего (того, из которого запущен скрипт ExpertRemove. Можете подсказать как это сделать?
#include <fxsaber\Expert.mqh> // https://www.mql5.com/ru/code/19003 void OnStart() { const long CurrentChart = ChartID(); long Chart = ChartFirst(); while (Chart != -1) { if (Chart != CurrentChart) EXPERT::Remove(Chart); Chart = ChartNext(Chart); } }
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Vladislav Andruschenko, 2018.02.09 10:14
как получить список внешних переменных внутри эксперта? чтобы не перечислять их в массиве повторно? тоесть при установке на график эксперт читает сам себя и смотрит свои внешние настройки.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2018.02.09 12:44
#include <fxsaber\Expert.mqh> // https://www.mql5.com/ru/code/19003 input string Input1 = "Hello World!"; input int Input2 = 123; string GetExpertData( const ulong Chart = 0 ) { string Str = NULL; MqlParam Parameters[]; string Names[]; if (EXPERT::Parameters(Chart, Parameters, Names)) { Str += "\n" + ChartSymbol(Chart) + " " + EnumToString(ChartPeriod(Chart)) + " " + Parameters[0].string_value + "\n"; const int Amount = ArraySize(Names); for (int i = 0; i < Amount; i++) Str += (string)i + ": "+ Names[i] + " = " + Parameters[i + 1].string_value + "\n"; } return(Str); } void OnInit() { Print(GetExpertData()); }
Результат
0: Input1 = Hello World! 1: Input2 = 123
или так
#include <fxsaber\Expert.mqh> // https://www.mql5.com/ru/code/19003 input string Input1 = "Hello World!"; input int Input2 = 123; void OnInit() { MqlParam Parameters[]; string Names[]; if (EXPERT::Parameters(0, Parameters, Names)) ArrayPrint(Parameters); }
Результат
[type] [integer_value] [double_value] [string_value] [0] ... 0 0.00000 "Experts\Test2.ex5" [1] ... 0 0.00000 "Hello World!" [2] ... 123 123.00000 "123"
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2018.02.22 23:53
Проигрывание из индикатора любой длительности звукового файла.
Скрипт Scripts\PlaySound.mq5
#include <GlobalVariables.mqh> // https://www.mql5.com/ru/forum/189649#comment_4854618 void OnStart() { const string SoundName = "SOUND"; if (GlobalVariableCheck(SoundName)) { PlaySound(_GlobalVariableGet<string>(SoundName)); _GlobalVariableDel(SoundName); } }
Индикатор
#property indicator_chart_window #property indicator_buffers 0 #property indicator_plots indicator_buffers #include <fxsaber\Expert.mqh> // https://www.mql5.com/ru/code/19003 #include <GlobalVariables.mqh> // https://www.mql5.com/ru/forum/189649#comment_4854618 class PLAYER { public: const string Name; const long Chart; const long chartID; PLAYER( const long iChart = 0 ) : Name(__FILE__), Chart(iChart ? iChart : ::ChartID()), chartID(::ObjectCreate(this.Chart, this.Name, OBJ_CHART, 0, 0, 0) && ::ObjectSetInteger(this.Chart, this.Name, OBJPROP_XSIZE, 0) && ::ObjectSetInteger(this.Chart, this.Name, OBJPROP_YSIZE, 0) ? ::ObjectGetInteger(this.Chart, this.Name, OBJPROP_CHART_ID) : this.Chart) { } ~PLAYER() { if (this.chartID != this.Chart) ::ObjectDelete(this.Chart, this.Name); } void PlaySound( string FileName, const string ScriptName = "Scripts\\PlaySound.ex5" ) const { static const string SoundName = "SOUND"; if (_GlobalVariableSet(SoundName, FileName)) { MqlParam Params[1]; Params[0].string_value = ScriptName; if (!EXPERT::Run(this.chartID, Params)) _GlobalVariableDel(SoundName); } } }; int OnCalculate( const int rates_total , const int prev_calculated, const int, const double& [] ) { if (!prev_calculated) { const PLAYER Player; Player.PlaySound("email.wav"); } return(rates_total); }
В МТ4, как оказалось, отсутствует намного больше, чем FileSave и FileLoad (которые пишутся в 3 строках каждая):
- Нет CHART_EXPERT_NAME (и нечем заменить, разве что после исправления всех остальных нюансов — тегом name).
- Лобовой FileLoad не подходит, насколько я понимаю, из-за ANSI-кодировки сохраняемого шаблона.
Пришлось написать аналог TemplateToString, читающий файл в текстовом режиме. - STRING_END должен быть пустым, "\r\n" в четверочных шаблонах нет.
- Тэг <expert> в МТ4 используется и для индикаторов, поэтому даже после всех этих правок обнаружить — где индикаторы, а где советник, можно только, положившись на то, что советник указывается последним (а всегда ли это так?). Ну, и добраться до него нужно.
Andrey Khatimlianskii:
Тэг <expert> в МТ4 используется и для индикаторов, поэтому даже после всех этих правок обнаружить — где индикаторы, а где советник, можно только, положившись на то, что советник указывается последним (а всегда ли это так?). Ну, и добраться до него нужно.
Этот исходник может помочь разобраться в вопросе.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Как в индикаторе узнать текущий цвет индикаторной линии?
fxsaber, 2017.05.12 13:45
#property strict #property indicator_chart_window #property indicator_buffers 2 #define PATH "MQL4\\indicators\\" #include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280 string GetIndicatorName( void ) { const string StrName = ::MQLInfoString(MQL_PROGRAM_PATH); const int Pos = ::StringFind(StrName, PATH) + ::StringLen(PATH); return(::StringSubstr(StrName, Pos, ::StringLen(StrName) - Pos - 4)); } void SeekToString( const int handle, const string Str ) { while (!::FileIsEnding(handle)) if (::FileReadString(handle) == Str) break; return; } struct BUFFER_STRUCT { int Shift; int Type; color Color; ENUM_LINE_STYLE Style; int Width; }; const BUFFER_STRUCT GetBufferProperties( const uint Num = 0, const bool FlagSave = true ) { BUFFER_STRUCT Res = {0}; const string FileName = ::WindowExpertName() + ".tpl"; if (FlagSave ? ::ChartSaveTemplate(0, "..\\MQL4\\Files\\" + FileName) : true) { const int handle = ::FileOpen(FileName, ::FILE_READ|::FILE_CSV); if (handle > 0) { ::SeekToString(handle, "name=" + ::GetIndicatorName()); if (Num == 0) ::SeekToString(handle, "</expert>"); else { const string TmpStr = "weight_" + (string)(Num - 1); while (!::FileIsEnding(handle)) if (::StringFind(::FileReadString(handle), TmpStr) == 0) break; } if (!::FileIsEnding(handle)) { static const string Property[] = {"shift", "draw", "color", "style", "weight"}; const string StrNum = "_" + (string)Num + "="; for (int i = 0; i < ::ArraySize(Property); i++) _W(Res)[i * sizeof(int)] = (int)::StringToInteger(::StringSubstr(::FileReadString(handle), ::StringLen(Property[i] + StrNum))); } ::FileClose(handle); } } return(Res); } void OnInit() { string Str = "Colors:"; for (int i = 0; i < indicator_buffers; i++) Str += " " + (string)i + "-" + (string)::GetBufferProperties(i).Color; Alert(Str); } void start() { }
Этот исходник может помочь разобраться в вопросе.
Благодарю! Как всегда, чуть сложнее, чем хотелось бы ;)
У ваших кодов есть одно неоспоримое преимущество — их можно брать, и использовать. Но что-либо подправить в них достаточно сложно, это минус.
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Expert:
Библиотека чтения/записи параметров произвольных советников.
К описанию прикреплены примеры/сценарии ее использования.
ExpertsRemove.mq5
// Снимает запущенные советники со всех чартов
ExpertsReopen.mq5
// Перезапускает работающие советники
ChartsClose.mq5
// Закрывает все чарты, где отсутствуют советники (полезно для VPS)
ExpertLoader_Example.mq5 (в исходнике можно увидеть, как запускается не только советник, но и скрипт (сам себя) под видом советника)
// Запуск советника с заданными входными параметрами
ExpertsChange_Example.mq5
// Перезапускает работающие советники, изменяя входные параметры
Это самые простые в реализации сценарии применения библиотеки. Так же она может быть полезна при написании различных управляющих панелей чартами/советниками и т.п.
Для лучшего понимания работы с библиотекой короткий исходник:
Автор: fxsaber