Explicación
Foro sobre trading, sistemas automatizados de trading y prueba de estrategias de trading
Preguntas de los principiantes MQL4 MT4 MetaTrader 4
fxsaber, 2017.09.08 13:52
Cuando se utiliza ChartApplyTemplate, se requiere una sincronización obligatoria, que hago en la biblia así
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 no se activa inmediatamente. Y cualquier otra acción se puede hacer sólo después de la activación.
Para entender que la plantilla se ha aplicado, es necesario cambiar la plantilla en sí (el color de una característica del gráfico se cambia en la biblia - el 4 º byte, responsable de la transparencia) y esperar a través de Sleep (ChartGetInterger), cuando este valor se convierte en una propiedad del gráfico. Después de eso, establecer su valor normal a través de ChartSetInteger.
Si necesitamos ejecutar un Asesor Experto en el mismo gráfico donde se lanza el script, entonces necesitamos abrir un nuevo gráfico y ejecutar el mismo (script) en él a través de la plantilla, y desde ahí ejecutar el Asesor Experto en el gráfico que necesitamos, habiendo cerrado el auxiliar. Esto lo hace ExpertLoader_Example.mq5.
может быть полезна при написании различных управляющих панелей чартами/советниками и т.п.
La biblioteca funciona sin DLL: satisface plenamente los requisitos del mercado.
Un pequeño hack - ejecutar EAs/scripts en OBJ_CHART-objetos.
Así que los Asesores Expertos lanzados cuelgan muertos - no se ejecutan de ninguna manera. Pero los scripts funcionan perfectamente bien. Por lo tanto, esto abre algunas posibilidades.
Por ejemplo, puede utilizar las funciones de orden de los indicadores en los gráficos, donde ya hay un Asesor Experto en ejecución. Y no es necesario abrir nuevos gráficos auxiliares.
Compile el script Scripts\OrderSend.mq5
#include <MT4Orders.mqh> // https://www.mql5.com/es/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(); }
Y ejecute el indicador, que "puede operar".
#include <fxsaber\Expert.mqh> // https://www.mql5.com/es/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 = 1 e6 ) { const ulong StartTime = GetMicrosecondCount(); while (!IsStopped() && !GlobalVariableCheck(Name) && (GetMicrosecondCount() - StartTime < MaxTime)) Sleep(0); return(_GlobalVariableGet<T>(Name)); } // OrderSend, que funciona incluso desde el indicador incluso en un gráfico con un Asesor Experto 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); }
Foro sobre negociación, sistemas automatizados de negociación y prueba de estrategias de negociación
Gestión de Asesores Expertos a través de un algoritmo global
Totosha16, 2018.02.07 18:57
En estos momentos estoy intentando resolver un problema sencillo utilizando vuestra librería, que se reduce a lo siguiente: cerrar todos los Expert Advisors en todos los gráficos excepto en el actual (aquel desde el que se ejecuta el script ExpertRemove. ¿Puede decirme cómo hacerlo?
#include <fxsaber\Expert.mqh> // https://www.mql5.com/es/code/19003 void OnStart() { const long CurrentChart = ChartID(); long Chart = ChartFirst(); while (Chart != -1) { if (Chart != CurrentChart) EXPERT::Remove(Chart); Chart = ChartNext(Chart); } }
Foro sobre negociación, sistemas automatizados de negociación y prueba de estrategias de negociación
Vladislav Andruschenko, 2018.02.09 10:14 AM
¿Cómo obtener la lista de variables externas dentro del Asesor Experto? para no tener que enumerarlas en la matriz repetidamente? es decir, al configurarlo en un gráfico, el Asesor Experto se lee a sí mismo y mira su configuración externa.
Foro sobre trading, sistemas automatizados de trading y testeo de estrategias de trading.
fxsaber, 2018.02.09 12:44 pm.
#include <fxsaber\Expert.mqh> // https://www.mql5.com/es/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()); }
Resultado
0: Input1 = Hello World! 1: Input2 = 123
o así
#include <fxsaber\Expert.mqh> // https://www.mql5.com/es/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); }
Resultado
[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"
Foro sobre negociación, sistemas automatizados de negociación y prueba de estrategias de negociación
fxsaber, 2018.02.22 23:53
Reproducir un archivo de sonido de cualquier duración desde el indicador.
Scripts\PlaySound.mq5 script.
#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); } }
Indicador
#property indicator_chart_window #property indicator_buffers 0 #property indicator_plots indicator_buffers #include <fxsaber\Expert.mqh> // https://www.mql5.com/es/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); }
MT4, como se vio después, le falta mucho más que FileSave y FileLoad (que están escritos en 3 líneas cada uno):
- No CHART_EXPERT_NAME (y nada para reemplazarlo con, excepto después de arreglar todos los otros matices - la etiqueta de nombre).
- Frontal FileLoad no es adecuado, según tengo entendido, debido a la codificación ANSI de la plantilla guardada.
Tuve que escribir un análogo de TemplateToString, leyendo el archivo en modo texto. - STRING_END debe estar vacío, no hay "\r\n" en las plantillas cuádruples.
- La etiqueta <expert> en MT4 también se utiliza para los indicadores, por lo que incluso después de todas estas ediciones, se puede saber dónde están los indicadores y dónde está el EA sólo confiando en el hecho de que el EA se especifica en último lugar (¿y es siempre así?). Bueno, y hay que llegar a ella.
Andrey Khatimlianskii:
La etiqueta <expert> en MT4 también se utiliza para los indicadores, por lo que incluso después de todas estas ediciones, sólo se puede saber dónde están los indicadores y dónde está el Asesor Experto confiando en el hecho de que el Asesor Experto se especifica en último lugar (¿y es siempre así?). Bueno, y hay que llegar a él.
Este código fuente puede ayudar a entender la pregunta.
Foro sobre trading, sistemas automatizados de trading y testeo de estrategias de trading.
Cómo averiguar el color actual de la línea del indicador en un indicador?
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/es/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() { }
Esta fuente puede ayudar a comprender la cuestión.
Gracias. Como siempre, un poco más complicado de lo que me gustaría ;)
Tus códigos tienen una ventaja innegable: se pueden coger y utilizar. Pero es bastante difícil retocar algo en ellos, eso es una desventaja.
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Expert:
Autor: fxsaber