이에 대한 설명
트레이딩, 자동매매 시스템 및 트레이딩 전략 테스트에 관한 포럼
MQL4 MT4 메타트레이더 4 초보자가 자주 묻는 질문
fxsaber, 2017.09.08 13:52
차트 적용 템플릿을 사용할 때 다음과 같이 필수 동기화가 필요합니다.
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); }
차트 적용은 즉시 트리거되지 않습니다. 그리고 추가 작업은 트리거된 후에만 수행할 수 있습니다.
템플릿이 적용되었음을 이해하려면 템플릿 자체를 변경하고(성경에서 차트의 한 특성인 투명도를 담당하는 4바이트의 색상이 변경됨) 이 값이 차트의 속성이 될 때까지 잠자기(ChartGetInterger)를 기다려야 합니다. 그런 다음 ChartSetInteger를 통해 정상 값을 설정합니다.
스크립트가 실행되는 동일한 차트에서 Expert Advisor를 실행해야 하는 경우 새 차트를 열고 템플릿을 통해 동일한 (스크립트)를 실행해야 하며, 거기에서 보조 차트를 닫은 후 필요한 차트에서 Expert Advisor를 실행해야 합니다. 이 작업은 ExpertLoader_Example.mq5가 수행합니다.
может быть полезна при написании различных управляющих панелей чартами/советниками и т.п.
라이브러리는 DLL 없이 실행되므로 마켓 요구 사항을 완벽하게 충족합니다.
약간의 해킹 - OBJ_CHART 객체에서 EA/스크립트 실행.
그래서 실행된 Expert Advisors는 어떤 방식으로도 실행되지 않습니다. 그러나 스크립트는 완벽하게 잘 작동합니다. 따라서 이것은 몇 가지 가능성을 열어줍니다.
예를 들어, 이미 실행중인 전문가 조언자가있는 차트의 지표에서 주문 함수를 사용할 수 있습니다. 그리고 새로운 보조 차트를 열 필요가 없습니다.
스크립트 Scripts\OrderSend.mq5를 컴파일합니다.
#include <MT4Orders.mqh> // https://www.mql5.com/ko/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/ko/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)); } // 전문가 어드바이저가 있는 차트에서도 인디케이터에서 작동하는 주문 보내기 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); }
트레이딩, 자동매매 시스템 및 트레이딩 전략 테스트 포럼
토토샤16, 2018.02.07 18:57
현재 라이브러리를 사용하여 다음과 같이 요약되는 간단한 문제를 해결하려고합니다. 현재 차트 (ExpertRemove 스크립트가 실행되는 차트)를 제외한 모든 차트에서 모든 Expert Advisor를 닫습니다. 어떻게 해야 하는지 알려주실 수 있나요?
#include <fxsaber\Expert.mqh> // https://www.mql5.com/ko/code/19003 void OnStart() { const long CurrentChart = ChartID(); long Chart = ChartFirst(); while (Chart != -1) { if (Chart != CurrentChart) EXPERT::Remove(Chart); Chart = ChartNext(Chart); } }
트레이딩, 자동매매 시스템 및 트레이딩 전략 테스트 포럼
블라디슬라프 안드루셴코, 2018.02.09 10:14 AM
전문가 조언자 내부에서 외부 변수 목록을 가져 오는 방법은 무엇입니까? 배열에 반복적으로 나열 할 필요가 없도록? 즉, 차트에 설정할 때 전문가 조언자가 스스로 읽고 외부 설정을 살펴 봅니다.
트레이딩, 자동매매 시스템 및 트레이딩 전략 테스트에 관한 포럼.
fxsaber, 2018.02.09 12:44 오후.
#include <fxsaber\Expert.mqh> // https://www.mql5.com/ko/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/ko/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
인디케이터에서 원하는 기간의 사운드 파일 재생.
스크립트\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/ko/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에는 FileSave 및 FileLoad(각각 3줄로 작성됨)보다 훨씬 더 많은 것이 누락되어 있습니다:
- 차트 전문가 이름이 없습니다 (다른 모든 뉘앙스를 수정 한 후 이름표를 제외하고는 대체 할 것이 없습니다).
- 제가 알기로는 저장된 템플릿의 ANSI 인코딩 때문에 정면 파일로드는 적합하지 않습니다.
텍스트 모드에서 파일을 읽는 TemplateToString의 아날로그를 작성해야했습니다. - 문자열_끝은 비어 있어야 하며, 쿼드러플 템플릿에는 "\r\n"이 없어야 합니다.
- MT4의 <전문가> 태그는 지표에도 사용되므로 이러한 모든 편집 후에도 EA가 마지막으로 지정되었다는 사실에 의존해야만 지표의 위치와 EA의 위치를 찾을 수 있습니다 (항상 그렇습니까?). 글쎄, 그리고 당신은 그것에 도달해야합니다.
Andrey Khatimlianskii:
MT4의 <전문가> 태그는 지표에도 사용되므로 이러한 모든 편집 후에도 전문가 자문가가 마지막에 지정되어 있다는 사실에 의존하여 지표의 위치와 전문가 자문가의 위치를 찾을 수 있습니다 (항상 그렇습니까?). 글쎄, 그리고 당신은 그것에 도달해야합니다.
이 소스 코드는 질문을 이해하는 데 도움이 될 수 있습니다.
트레이딩, 자동매매 시스템 및 트레이딩 전략 테스트에 관한 포럼.
보조지표에서 보조지표 선의 현재 색상을 어떻게 알 수 있나요?
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/ko/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() { }
이 자료는 문제를 이해하는 데 도움이 될 수 있습니다.
감사합니다! 항상 그렇듯이 생각보다 조금 더 복잡하네요 ;)
코드는 가져와서 사용할 수 있다는 한 가지 확실한 장점이 있습니다. 그러나 코드를 수정하기가 매우 어렵다는 단점이 있습니다.
전문가:
임의의 EA의 읽기/쓰기 매개변수 라이브러리.
Author: fxsaber