20 Commits

Author SHA1 Message Date
Hiroaki86 d72f688785 EAのinput初期値を変更 2026-06-14 22:28:29 +09:00
Hiroaki86 2c4709a6ab Refactor MQL5 EA logic and sync documentation 2026-06-14 22:16:37 +09:00
HiroK f65b4abc21 Merge pull request #5 from HirorihirorihK/codex/20260607_separate_ea
Codex/20260607 separate ea
2026-06-14 22:13:33 +09:00
Hiroaki86 52067c1973 Harden HIT entry and manager state handling 2026-06-14 22:02:17 +09:00
Hiroaki86 7b11d44d66 Refactor EA codebase and update project docs 2026-06-13 23:22:06 +09:00
Hiroaki86 f9012e19e2 Expand API-derived TP distances 2026-06-13 11:58:49 +09:00
Hiroaki86 4de3d24dcd Add range breakout guard for reverse limit orders 2026-06-13 11:27:10 +09:00
Hiroaki86 2532d416fa EAを注文用とパネル管理用に分離 2026-06-07 22:24:58 +09:00
Hiroaki86 b7789d4572 Split HIT EA into entry and position manager 2026-06-07 22:06:30 +09:00
HiroK f49769dc1e Merge pull request #4 from HirorihirorihK/codex/20260606_gpt_model_change
Codex/20260606 gpt model change
2026-06-06 20:47:43 +09:00
Hiroaki86 e3fb298b82 Update GPT settings for gpt-5.5 2026-06-06 20:46:28 +09:00
Hiroaki86 cc17fe2e04 Remove obsolete refactor artifacts and update specs 2026-06-06 14:45:43 +09:00
Hiroaki86 bdecd2d074 Add ver5 compatibility for shared headers 2026-06-06 14:44:28 +09:00
HiroK 35dc842839 Merge pull request #3 from HirorihirorihK/codex/20260606_refactor
Restore entry response schema version constant
2026-06-06 14:18:13 +09:00
Hiroaki86 286804ece3 Restore entry response schema version constant 2026-06-06 14:16:31 +09:00
HiroK 14cc991ab3 Merge pull request #2 from HirorihirorihK/codex/20260530_api
Codex/20260530 api
2026-06-04 20:12:20 +09:00
Hiroaki86 13eaa74309 Add safe-stop diagnostics to H1 entry logs 2026-06-04 19:56:13 +09:00
Hiroaki86 33cfc2597c Harden pending cancellation and startup state handling 2026-05-31 17:17:54 +09:00
Hiroaki86 bbc8ea1a80 Adopt structured outputs for GPT entry generation 2026-05-30 22:01:57 +09:00
HiroK 652da68675 Merge pull request #1 from HirorihirorihK/codex/20260529
Codex/20260529
2026-05-30 21:32:15 +09:00
115 changed files with 12305 additions and 16219 deletions
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_6F166A751A950DA3
#define MQL_AUTO_FORWARDS_INCLUDED_6F166A751A950DA3
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/AccountInfo/AccountInfoSample.mq5
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_19FA7EF3A5C17005
#define MQL_AUTO_FORWARDS_INCLUDED_19FA7EF3A5C17005
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/ArrayDouble/ArrayDoubleSample.mq5
#endif
@@ -0,0 +1,15 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_3910007FE5A4066C
#define MQL_AUTO_FORWARDS_INCLUDED_3910007FE5A4066C
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/BitonicSort.mq5
#line 24 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/BitonicSort.mq5"
resource as string cl_program void QuickSortAscending(float &array[], int first, int last);
#line 72 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/BitonicSort.mq5"
bool QuickSort_CPU(float &data_array[], ulong &time_cpu);
#line 88 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/BitonicSort.mq5"
bool BitonicSort_GPU(COpenCL &OpenCL, float &data_array[], ulong &time_gpu);
#line 149 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/BitonicSort.mq5"
bool PrepareDataArray(long global_memory_size, float &data[], int &data_count);
#endif
@@ -0,0 +1,15 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_9CA2F4117B4FA02E
#define MQL_AUTO_FORWARDS_INCLUDED_9CA2F4117B4FA02E
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/BitonicSort.mq5
#line 24 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/BitonicSort.mq5"
resource as string cl_program void QuickSortAscending(double &array[], int first, int last);
#line 72 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/BitonicSort.mq5"
bool QuickSort_CPU(double &data_array[], ulong &time_cpu);
#line 88 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/BitonicSort.mq5"
bool BitonicSort_GPU(COpenCL &OpenCL, double &data_array[], ulong &time_gpu);
#line 155 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/BitonicSort.mq5"
bool PrepareDataArray(long global_memory_size, double &data[], int &data_count);
#endif
@@ -0,0 +1,9 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_84FF22BB352A811E
#define MQL_AUTO_FORWARDS_INCLUDED_84FF22BB352A811E
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/Canvas/CanvasSample.mq5
#line 207 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/Canvas/CanvasSample.mq5"
uint RandomRGB(void);
#endif
@@ -0,0 +1,15 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_B3A29339D5503F77
#define MQL_AUTO_FORWARDS_INCLUDED_B3A29339D5503F77
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Comment_Test.mq5
#line 24 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Comment_Test.mq5"
define PANEL_BODY bool EnsureRectLabel(const string name);
#line 29 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Comment_Test.mq5"
bool EnsureLabel(const string name);
#line 35 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Comment_Test.mq5"
void CreateInfoPanel();
#line 92 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Comment_Test.mq5"
void SetPanelText(const string title, const string body);
#endif
@@ -0,0 +1,27 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_179D8076AE6D13CF
#define MQL_AUTO_FORWARDS_INCLUDED_179D8076AE6D13CF
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5
#line 1349 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
int OnInitEvent();
#line 1375 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
void OnDeinitEvent(const int reason);
#line 1391 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
define MASK_RIGHT_MIDDLE 16 void CommonChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
#line 1506 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
void CreatePendingSetLine(color clr, double line_price);
#line 1521 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
void MovePendingSetLine(double line_price);
#line 1530 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
void DeletePendingSetLine();
#line 1539 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
void RecalculateValues(int position, double price_ref);
#line 1598 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
bool CheckLots();
#line 1616 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
void OpenBuyPendingOrder(double order_price);
#line 1654 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/Debug_Entry_Panel.mq5"
void OpenSellPendingOrder(double order_price);
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_161E94623585B981
#define MQL_AUTO_FORWARDS_INCLUDED_161E94623585B981
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/FFT.mq5
#line 28 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/FFT.mq5"
define FFT_DIRECTION 1 void fft(const int N, float &x_real[], float &x_imag[], float &X_real[], float &X_imag[]);
#line 40 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/FFT.mq5"
void ifft(const int N, float &x_real[], float &x_imag[], float &X_real[], float &X_imag[]);
#line 62 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/FFT.mq5"
void fft_rec(const int N, const int offset, const int delta, float &x_real[], float &x_imag[], float &X_real[], float &X_imag[], float &XX_real[], float &XX_imag[]);
#line 104 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/FFT.mq5"
bool FFT_CPU(int direction, int power, float &data_real[], float &data_imag[], ulong &time_cpu);
#line 131 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/FFT.mq5"
bool ExecutionWait(COpenCL& OpenCL, int kernel_index);
#line 155 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/FFT.mq5"
bool FFT_GPU(int direction, int power, float &data_real[], float &data_imag[], ulong &time_gpu);
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_2B43903CEDDD8F57
#define MQL_AUTO_FORWARDS_INCLUDED_2B43903CEDDD8F57
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/FFT.mq5
#line 28 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/FFT.mq5"
define FFT_DIRECTION 1 void fft(const int N, double &x_real[], double &x_imag[], double &X_real[], double &X_imag[]);
#line 40 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/FFT.mq5"
void ifft(const int N, double &x_real[], double &x_imag[], double &X_real[], double &X_imag[]);
#line 62 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/FFT.mq5"
void fft_rec(const int N, const int offset, const int delta, double &x_real[], double &x_imag[], double &X_real[], double &X_imag[], double &XX_real[], double &XX_imag[]);
#line 104 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/FFT.mq5"
bool FFT_CPU(int direction, int power, double &data_real[], double &data_imag[], ulong &time_cpu);
#line 131 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/FFT.mq5"
bool ExecutionWait(COpenCL& OpenCL, int kernel_index);
#line 155 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/FFT.mq5"
bool FFT_GPU(int direction, int power, double &data_real[], double &data_imag[], ulong &time_gpu);
#endif
@@ -0,0 +1,45 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_0D006635EECD9565
#define MQL_AUTO_FORWARDS_INCLUDED_0D006635EECD9565
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5
#line 390 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
void CreateDoneFile(const string name);
#line 405 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
void DeleteDoneFile(const string name);
#line 415 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool CheckDoneFile(const string name);
#line 423 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count);
#line 469 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
void RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[]);
#line 517 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
void ExecuteBatchTrend();
#line 529 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
void ExecuteBatchEntry();
#line 542 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool RecordOHLCAndExecuteBatch_Trend(EAState &state);
#line 561 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool RecordOHLCAndExecuteBatch_Entry(EAState &state);
#line 581 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool GetTrendState(EAState &state);
#line 599 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
void LoadTrendState(int &trend_state);
#line 621 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool GetTargetPrices(EAState &state);
#line 659 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
void LoadTargetPrices(double &target_prices[]);
#line 702 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool SendOrder(int orderType, double price, double tp, double sl);
#line 774 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
#line 787 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
string RequestComment(int orderType);
#line 799 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool CancelExpiredOrders();
#line 851 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
bool CloseExpiredPositions();
#line 926 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA.mq5"
int GetBarShiftByTime(datetime time, ENUM_TIMEFRAMES tf, int default_shift);
#endif
@@ -0,0 +1,95 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_9E7CFFCE7624C343
#define MQL_AUTO_FORWARDS_INCLUDED_9E7CFFCE7624C343
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5
#line 168 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool GetTickContext(TickContext &ctx);
#line 192 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void ManageExpiredTrades();
#line 211 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void ProcessTrendUpdate(EAState &state);
#line 238 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool IsTrendResultReady();
#line 251 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void RefreshTrendState(EAState &state);
#line 266 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void ProcessEntryUpdate(EAState &state);
#line 297 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
string BuildStatusMessage(TickContext &ctx);
#line 333 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void UpdateStatusComment(TickContext &ctx);
#line 347 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool IsSpreadAllowed(TickContext &ctx);
#line 360 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool IsEntryResultReady();
#line 373 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void RefreshTargetPrices(EAState &state);
#line 389 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void ProcessEntryDecisionIfNeeded(EAState &state, TickContext &ctx);
#line 413 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool ShouldRunEntryDecision(EAState &state);
#line 429 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool ValidateEntryPreconditions(EAState &state);
#line 472 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
int SendAllowedEntryOrders(EAState &state, TickContext &ctx);
#line 509 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx);
#line 553 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
string EntryTypeName(const int orderType);
#line 580 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
double CurrentPriceForOrderType(const int orderType, TickContext &ctx);
#line 601 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool IsTargetPriceOrderConditionMatched(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 633 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void UpdateEntryRetryState(EAState &state, const int sent_success);
#line 662 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void CreateDoneFile(const string name);
#line 682 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void DeleteDoneFile(const string name);
#line 698 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool CheckDoneFile(const string name);
#line 720 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count);
#line 774 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[]);
#line 829 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool ExecuteBatchTrend();
#line 859 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool ExecuteBatchEntry();
#line 889 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool RecordOHLCAndExecuteBatch_Trend(EAState &state);
#line 922 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool RecordOHLCAndExecuteBatch_Entry(EAState &state);
#line 956 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool GetTrendState(EAState &state);
#line 981 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void LoadTrendState(int &trend_state);
#line 1015 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool GetTargetPrices(EAState &state);
#line 1060 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
void LoadTargetPrices(double &target_prices[]);
#line 1113 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool SendOrder(int orderType, double price, double tp, double sl);
#line 1191 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
#line 1210 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
string RequestComment(int orderType);
#line 1229 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool IsOrderTypeAllowedByTrend(const int orderType, const int trend_state);
#line 1251 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool HasValidTargetPrices(const double en, const double tp, const double sl);
#line 1264 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
int CountMyPendingOrders();
#line 1297 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
int CountMyPositions();
#line 1327 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
int CountMyUsed();
#line 1343 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool CancelExpiredOrders();
#line 1402 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
bool CloseExpiredPositions();
#line 1487 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor.mq5"
int GetBarShiftByTime(datetime time, ENUM_TIMEFRAMES tf, int default_shift);
#endif
@@ -0,0 +1,129 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_4914830B59E597AA
#define MQL_AUTO_FORWARDS_INCLUDED_4914830B59E597AA
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5
#line 245 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool GetTickContext(TickContext &ctx);
#line 269 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void ManageExpiredTrades();
#line 288 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void ProcessTrendUpdate(EAState &state);
#line 315 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsTrendResultReady();
#line 328 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void RefreshTrendState(EAState &state);
#line 343 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void ProcessEntryUpdate(EAState &state);
#line 374 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
string BuildStatusMessage(TickContext &ctx);
#line 410 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void UpdateStatusComment(TickContext &ctx);
#line 424 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsSpreadAllowed(TickContext &ctx);
#line 437 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsEntryResultReady();
#line 450 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void RefreshTargetPrices(EAState &state);
#line 466 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void ProcessEntryDecisionIfNeeded(EAState &state, TickContext &ctx);
#line 490 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool ShouldRunEntryDecision(EAState &state);
#line 506 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool ValidateEntryPreconditions(EAState &state);
#line 549 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
int SendAllowedEntryOrders(EAState &state, TickContext &ctx);
#line 586 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx);
#line 633 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
string EntryTypeName(const int orderType);
#line 660 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
double CurrentPriceForOrderType(const int orderType, TickContext &ctx);
#line 681 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsTargetPriceOrderConditionMatched(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 715 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool MeetsTradeDistanceRules(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 765 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void UpdateEntryRetryState(EAState &state, const int sent_success);
#line 794 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void CreateDoneFile(const string name);
#line 814 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void DeleteDoneFile(const string name);
#line 830 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool CheckDoneFile(const string name);
#line 843 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void CreateRunningFile(const string name, const uint process_id);
#line 864 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void DeleteRunningFile(const string name);
#line 879 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
datetime LoadRunningStartedAt(const string name);
#line 905 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
uint LoadRunningProcessId(const string name);
#line 938 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsRunningFileTimedOut(const string name);
#line 950 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void ResetExternalProcessState(ExternalProcessState &process);
#line 966 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool AttachRunningProcess(const string running_file, const string label, ExternalProcessState &process);
#line 994 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool UpdateExternalProcessStatus(ExternalProcessState &process, const string label);
#line 1030 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsExternalProcessTimedOut(ExternalProcessState &process, const string running_file);
#line 1044 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool StartBatchProcess(const string bat_file, const string running_file, const string label, ExternalProcessState &process);
#line 1100 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void PrepareDoneFileOnInit(const string done_file, const string running_file, const string label);
#line 1133 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsProcessResultReady(const string done_file, const string running_file, const string result_file, const string label, ExternalProcessState &process);
#line 1179 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsProcessStartAllowed(const string done_file, const string running_file, const string label, ExternalProcessState &process);
#line 1234 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void RecoverTimedOutPythonProcesses();
#line 1262 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool RecoverTimedOutProcess(const string done_file, const string running_file, const string label, ExternalProcessState &process);
#line 1325 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count);
#line 1380 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[]);
#line 1436 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool ExecuteBatchTrend();
#line 1455 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool ExecuteBatchEntry();
#line 1474 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool RecordOHLCAndExecuteBatch_Trend(EAState &state);
#line 1508 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool RecordOHLCAndExecuteBatch_Entry(EAState &state);
#line 1543 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool GetTrendState(EAState &state);
#line 1568 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void LoadTrendState(int &trend_state);
#line 1602 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool GetTargetPrices(EAState &state);
#line 1647 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void LoadTargetPrices(double &target_prices[]);
#line 1700 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool SendOrder(int orderType, double price, double tp, double sl);
#line 1779 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
#line 1797 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
void ApplyPendingOrderExpiration(MqlTradeRequest &request);
#line 1836 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
string RequestComment(int orderType);
#line 1855 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool IsOrderTypeAllowedByTrend(const int orderType, const int trend_state);
#line 1877 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool HasValidTargetPrices(const double en, const double tp, const double sl);
#line 1890 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
int CountMyPendingOrders();
#line 1923 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
int CountMyPositions();
#line 1953 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
int CountMyUsed();
#line 1969 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool CancelExpiredOrders();
#line 2028 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
bool CloseExpiredPositions();
#line 2113 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver2.mq5"
int GetBarShiftByTime(datetime time, ENUM_TIMEFRAMES tf, int default_shift);
#endif
@@ -0,0 +1,141 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_9D52C52B2EF1E2BC
#define MQL_AUTO_FORWARDS_INCLUDED_9D52C52B2EF1E2BC
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5
#line 267 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool GetTickContext(TickContext &ctx);
#line 291 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void ManageExpiredTrades();
#line 310 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void ProcessTrendUpdate(EAState &state);
#line 337 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsTrendResultReady();
#line 350 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void RefreshTrendState(EAState &state);
#line 365 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void ProcessEntryUpdate(EAState &state);
#line 396 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void ProcessM15EntryTimingUpdate();
#line 426 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
string BuildStatusMessage(TickContext &ctx);
#line 462 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void UpdateStatusComment(TickContext &ctx);
#line 476 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
string MarketStateName(const int market_state);
#line 508 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsSpreadAllowed(TickContext &ctx);
#line 521 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsEntryResultReady();
#line 534 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void RefreshTargetPrices(EAState &state);
#line 550 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void ProcessEntryDecisionIfNeeded(EAState &state, TickContext &ctx);
#line 575 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool ShouldRunEntryDecision(EAState &state);
#line 591 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool ValidateEntryPreconditions(EAState &state);
#line 641 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsTargetCandidateExpired(EAState &state);
#line 663 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
int SendAllowedEntryOrders(EAState &state, TickContext &ctx);
#line 701 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx);
#line 754 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
string EntryTypeName(const int orderType);
#line 781 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
double CurrentPriceForOrderType(const int orderType, TickContext &ctx);
#line 802 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsTargetPriceOrderConditionMatched(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 837 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsM15EntryTimingConfirmed(const int orderType, TickContext &ctx, const double en);
#line 880 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
double AverageM15Range(const MqlRates &rates[], const int count);
#line 914 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsM15SignalAligned(const int orderType, const MqlRates &prev_bar, const MqlRates &last_bar, const double en, const double entry_zone);
#line 959 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
double SafeBarRange(const MqlRates &bar);
#line 981 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool MeetsTradeDistanceRules(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 1031 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void UpdateEntryRetryState(EAState &state, const int sent_success);
#line 1061 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void CreateDoneFile(const string name);
#line 1081 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void DeleteDoneFile(const string name);
#line 1097 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool CheckDoneFile(const string name);
#line 1110 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void CreateRunningFile(const string name, const uint process_id);
#line 1131 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void DeleteRunningFile(const string name);
#line 1146 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
datetime LoadRunningStartedAt(const string name);
#line 1172 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
uint LoadRunningProcessId(const string name);
#line 1205 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsRunningFileTimedOut(const string name);
#line 1217 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void ResetExternalProcessState(ExternalProcessState &process);
#line 1233 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool AttachRunningProcess(const string running_file, const string label, ExternalProcessState &process);
#line 1261 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool UpdateExternalProcessStatus(ExternalProcessState &process, const string label);
#line 1297 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsExternalProcessTimedOut(ExternalProcessState &process, const string running_file);
#line 1311 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool StartBatchProcess(const string bat_file, const string running_file, const string label, ExternalProcessState &process);
#line 1367 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void PrepareDoneFileOnInit(const string done_file, const string running_file, const string label);
#line 1400 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsProcessResultReady(const string done_file, const string running_file, const string result_file, const string label, ExternalProcessState &process);
#line 1446 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsProcessStartAllowed(const string done_file, const string running_file, const string label, ExternalProcessState &process);
#line 1501 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void RecoverTimedOutPythonProcesses();
#line 1530 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool RecoverTimedOutProcess(const string done_file, const string running_file, const string label, ExternalProcessState &process);
#line 1593 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count);
#line 1648 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[]);
#line 1704 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool ExecuteBatchTrend();
#line 1723 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool ExecuteBatchEntry();
#line 1742 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool RecordOHLCAndExecuteBatch_Trend(EAState &state);
#line 1776 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool RecordOHLCAndExecuteBatch_Entry(EAState &state);
#line 1811 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool GetTrendState(EAState &state);
#line 1836 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void LoadTrendState(int &trend_state);
#line 1870 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool GetTargetPrices(EAState &state);
#line 1916 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void LoadTargetPrices(double &target_prices[]);
#line 1969 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool SendOrder(int orderType, double price, double tp, double sl);
#line 2048 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
#line 2066 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
void ApplyPendingOrderExpiration(MqlTradeRequest &request);
#line 2105 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
string RequestComment(int orderType);
#line 2124 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool IsOrderTypeAllowedByTrend(const int orderType, const int trend_state);
#line 2157 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool HasValidTargetPrices(const double en, const double tp, const double sl);
#line 2170 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
int CountMyPendingOrders();
#line 2203 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
int CountMyPositions();
#line 2233 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
int CountMyUsed();
#line 2249 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool CancelExpiredOrders();
#line 2308 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver3.mq5"
bool CloseExpiredPositions();
#endif
@@ -0,0 +1,145 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_9E59DBEED0735B14
#define MQL_AUTO_FORWARDS_INCLUDED_9E59DBEED0735B14
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5
#line 267 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool GetTickContext(TickContext &ctx);
#line 291 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void ManageExpiredTrades();
#line 310 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void ProcessTrendUpdate(EAState &state);
#line 337 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsTrendResultReady();
#line 350 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void RefreshTrendState(EAState &state);
#line 365 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void ProcessEntryUpdate(EAState &state);
#line 396 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void ProcessM15EntryTimingUpdate();
#line 426 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
string BuildStatusMessage(TickContext &ctx);
#line 462 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void UpdateStatusComment(TickContext &ctx);
#line 476 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
string MarketStateName(const int market_state);
#line 508 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsSpreadAllowed(TickContext &ctx);
#line 521 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsEntryResultReady();
#line 534 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void RefreshTargetPrices(EAState &state);
#line 550 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void ProcessEntryDecisionIfNeeded(EAState &state, TickContext &ctx);
#line 575 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool ShouldRunEntryDecision(EAState &state);
#line 591 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool ValidateEntryPreconditions(EAState &state);
#line 641 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsTargetCandidateExpired(EAState &state);
#line 663 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
int SendAllowedEntryOrders(EAState &state, TickContext &ctx);
#line 701 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx);
#line 754 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
string EntryTypeName(const int orderType);
#line 781 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
double CurrentPriceForOrderType(const int orderType, TickContext &ctx);
#line 802 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsTargetPriceOrderConditionMatched(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 837 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsM15EntryTimingConfirmed(const int orderType, TickContext &ctx, const double en);
#line 882 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsTrendStopOrderType(const int orderType);
#line 897 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
double AverageM15Range(const MqlRates &rates[], const int count);
#line 931 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsM15SignalAligned(const int orderType, const MqlRates &prev_bar, const MqlRates &last_bar, const double en, const double entry_zone);
#line 976 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
double SafeBarRange(const MqlRates &bar);
#line 998 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool MeetsTradeDistanceRules(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 1048 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void UpdateEntryRetryState(EAState &state, const int sent_success);
#line 1078 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void CreateDoneFile(const string name);
#line 1098 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void DeleteDoneFile(const string name);
#line 1114 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool CheckDoneFile(const string name);
#line 1127 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void CreateRunningFile(const string name, const uint process_id);
#line 1148 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void DeleteRunningFile(const string name);
#line 1163 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
datetime LoadRunningStartedAt(const string name);
#line 1189 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
uint LoadRunningProcessId(const string name);
#line 1222 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsRunningFileTimedOut(const string name);
#line 1234 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void ResetExternalProcessState(ExternalProcessState &process);
#line 1250 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool AttachRunningProcess(const string running_file, const string label, ExternalProcessState &process);
#line 1278 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool UpdateExternalProcessStatus(ExternalProcessState &process, const string label);
#line 1314 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsExternalProcessTimedOut(ExternalProcessState &process, const string running_file);
#line 1328 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool StartBatchProcess(const string bat_file, const string running_file, const string label, ExternalProcessState &process);
#line 1384 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void PrepareDoneFileOnInit(const string done_file, const string running_file, const string label);
#line 1417 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsProcessResultReady(const string done_file, const string running_file, const string result_file, const string label, ExternalProcessState &process);
#line 1463 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsProcessStartAllowed(const string done_file, const string running_file, const string label, ExternalProcessState &process);
#line 1518 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void RecoverTimedOutPythonProcesses();
#line 1547 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool RecoverTimedOutProcess(const string done_file, const string running_file, const string label, ExternalProcessState &process);
#line 1610 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count);
#line 1665 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[]);
#line 1721 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool ExecuteBatchTrend();
#line 1740 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool ExecuteBatchEntry();
#line 1759 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool RecordOHLCAndExecuteBatch_Trend(EAState &state);
#line 1793 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool RecordOHLCAndExecuteBatch_Entry(EAState &state);
#line 1828 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool GetTrendState(EAState &state);
#line 1853 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void LoadTrendState(int &trend_state);
#line 1887 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool GetTargetPrices(EAState &state);
#line 1933 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void LoadTargetPrices(double &target_prices[]);
#line 1986 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool SendOrder(int orderType, double price, double tp, double sl);
#line 2065 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
#line 2083 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
void ApplyPendingOrderExpiration(MqlTradeRequest &request);
#line 2122 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
string RequestComment(int orderType);
#line 2141 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool IsOrderTypeAllowedByTrend(const int orderType, const int trend_state);
#line 2174 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool HasValidTargetPrices(const double en, const double tp, const double sl);
#line 2187 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
int CountMyPendingOrders();
#line 2220 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
int CountMyPositions();
#line 2250 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
int CountMyUsed();
#line 2266 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool CancelExpiredOrders();
#line 2325 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
bool CloseExpiredPositions();
#line 2410 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/python_for_ea/work/HIT-EA_refactor_ver3_restore.mq5"
int GetBarShiftByTime(datetime time, ENUM_TIMEFRAMES tf, int default_shift);
#endif
@@ -0,0 +1,141 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_CA569FC9DF595747
#define MQL_AUTO_FORWARDS_INCLUDED_CA569FC9DF595747
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5
#line 267 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool GetTickContext(TickContext &ctx);
#line 291 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void ManageExpiredTrades();
#line 310 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void ProcessTrendUpdate(EAState &state);
#line 337 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsTrendResultReady();
#line 350 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void RefreshTrendState(EAState &state);
#line 365 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void ProcessEntryUpdate(EAState &state);
#line 396 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void ProcessM15EntryTimingUpdate();
#line 426 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
string BuildStatusMessage(TickContext &ctx);
#line 462 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void UpdateStatusComment(TickContext &ctx);
#line 476 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
string MarketStateName(const int market_state);
#line 508 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsSpreadAllowed(TickContext &ctx);
#line 521 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsEntryResultReady();
#line 534 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void RefreshTargetPrices(EAState &state);
#line 550 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void ProcessEntryDecisionIfNeeded(EAState &state, TickContext &ctx);
#line 575 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool ShouldRunEntryDecision(EAState &state);
#line 591 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool ValidateEntryPreconditions(EAState &state);
#line 641 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsTargetCandidateExpired(EAState &state);
#line 663 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
int SendAllowedEntryOrders(EAState &state, TickContext &ctx);
#line 701 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx);
#line 754 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
string EntryTypeName(const int orderType);
#line 781 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
double CurrentPriceForOrderType(const int orderType, TickContext &ctx);
#line 802 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsTargetPriceOrderConditionMatched(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 837 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsM15EntryTimingConfirmed(const int orderType, TickContext &ctx, const double en);
#line 880 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
double AverageM15Range(const MqlRates &rates[], const int count);
#line 914 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsM15SignalAligned(const int orderType, const MqlRates &prev_bar, const MqlRates &last_bar, const double en, const double entry_zone);
#line 959 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
double SafeBarRange(const MqlRates &bar);
#line 981 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool MeetsTradeDistanceRules(const int orderType, TickContext &ctx, const double en, const double tp, const double sl);
#line 1031 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void UpdateEntryRetryState(EAState &state, const int sent_success);
#line 1061 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void CreateDoneFile(const string name);
#line 1081 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void DeleteDoneFile(const string name);
#line 1097 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool CheckDoneFile(const string name);
#line 1110 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void CreateRunningFile(const string name, const uint process_id);
#line 1131 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void DeleteRunningFile(const string name);
#line 1146 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
datetime LoadRunningStartedAt(const string name);
#line 1172 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
uint LoadRunningProcessId(const string name);
#line 1205 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsRunningFileTimedOut(const string name);
#line 1217 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void ResetExternalProcessState(ExternalProcessState &process);
#line 1233 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool AttachRunningProcess(const string running_file, const string label, ExternalProcessState &process);
#line 1261 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool UpdateExternalProcessStatus(ExternalProcessState &process, const string label);
#line 1297 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsExternalProcessTimedOut(ExternalProcessState &process, const string running_file);
#line 1311 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool StartBatchProcess(const string bat_file, const string running_file, const string label, ExternalProcessState &process);
#line 1367 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void PrepareDoneFileOnInit(const string done_file, const string running_file, const string label);
#line 1400 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsProcessResultReady(const string done_file, const string running_file, const string result_file, const string label, ExternalProcessState &process);
#line 1446 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsProcessStartAllowed(const string done_file, const string running_file, const string label, ExternalProcessState &process);
#line 1501 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void RecoverTimedOutPythonProcesses();
#line 1530 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool RecoverTimedOutProcess(const string done_file, const string running_file, const string label, ExternalProcessState &process);
#line 1593 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count);
#line 1648 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[]);
#line 1704 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool ExecuteBatchTrend();
#line 1723 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool ExecuteBatchEntry();
#line 1742 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool RecordOHLCAndExecuteBatch_Trend(EAState &state);
#line 1776 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool RecordOHLCAndExecuteBatch_Entry(EAState &state);
#line 1811 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool GetTrendState(EAState &state);
#line 1836 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void LoadTrendState(int &trend_state);
#line 1870 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool GetTargetPrices(EAState &state);
#line 1916 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void LoadTargetPrices(double &target_prices[]);
#line 1969 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool SendOrder(int orderType, double price, double tp, double sl);
#line 2048 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
#line 2066 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
void ApplyPendingOrderExpiration(MqlTradeRequest &request);
#line 2105 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
string RequestComment(int orderType);
#line 2124 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool IsOrderTypeAllowedByTrend(const int orderType, const int trend_state);
#line 2157 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool HasValidTargetPrices(const double en, const double tp, const double sl);
#line 2170 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
int CountMyPendingOrders();
#line 2203 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
int CountMyPositions();
#line 2233 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
int CountMyUsed();
#line 2249 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool CancelExpiredOrders();
#line 2308 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver4.mq5"
bool CloseExpiredPositions();
#endif
@@ -0,0 +1,17 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_2B1E831B48ED62C8
#define MQL_AUTO_FORWARDS_INCLUDED_2B1E831B48ED62C8
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver5.mq5
#line 344 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver5.mq5"
string SLTPBoolText(const bool value);
#line 349 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver5.mq5"
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings);
#line 374 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver5.mq5"
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings, const bool print_summary);
#line 420 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver5.mq5"
bool InitializeSLTPManager();
#line 444 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver5.mq5"
void ManageSLTPPositions();
#endif
@@ -0,0 +1,35 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_0606879F41E1B67C
#define MQL_AUTO_FORWARDS_INCLUDED_0606879F41E1B67C
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5
#line 269 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
string MQL5RootPath();
#line 280 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
string PythonAppDir();
#line 291 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
string PythonBatchPath(const string filename);
#line 302 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
bool IsSafeFileTokenChar(const int ch);
#line 316 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
string SanitizeFileToken(const string value);
#line 341 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
string BuildMT5FilePrefix();
#line 352 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
string PrefixedMT5FileName(const string base_name);
#line 366 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
void ConfigurePythonGatewayFileNames();
#line 389 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
void ConfigurePythonGatewayPaths();
#line 509 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
string SLTPBoolText(const bool value);
#line 514 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings);
#line 539 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings, const bool print_summary);
#line 585 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
bool InitializeSLTPManager();
#line 609 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/HIT-EA_refactor_ver6.mq5"
void ManageSLTPPositions();
#endif
@@ -0,0 +1,35 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_A28FB657951C5DDB
#define MQL_AUTO_FORWARDS_INCLUDED_A28FB657951C5DDB
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5
#line 250 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
string MQL5RootPath();
#line 261 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
string PythonAppDir();
#line 272 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
string PythonBatchPath(const string filename);
#line 283 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
bool IsSafeFileTokenChar(const int ch);
#line 297 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
string SanitizeFileToken(const string value);
#line 322 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
string BuildMT5FilePrefix();
#line 333 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
string PrefixedMT5FileName(const string base_name);
#line 347 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
void ConfigurePythonGatewayFileNames();
#line 370 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
void ConfigurePythonGatewayPaths();
#line 487 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
string SLTPBoolText(const bool value);
#line 492 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings);
#line 517 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings, const bool print_summary);
#line 563 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
bool InitializeSLTPManager();
#line 587 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/HIT-EA_refactor_ver6.mq5"
void ManageSLTPPositions();
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_91C16B255C7E9289
#define MQL_AUTO_FORWARDS_INCLUDED_91C16B255C7E9289
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/Canvas/Charts/HistogramChartSample.mq5
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_59D6116AA23C57CE
#define MQL_AUTO_FORWARDS_INCLUDED_59D6116AA23C57CE
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/Canvas/Charts/LineChartSample.mq5
#endif
@@ -0,0 +1,11 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_2E7990E38B74D88C
#define MQL_AUTO_FORWARDS_INCLUDED_2E7990E38B74D88C
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/MatrixMult.mq5
#line 16 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/MatrixMult.mq5"
define BLOCK_SIZE 10 bool MatrixMult_CPU(const float &matrix_a[], const float &matrix_b[], float &matrix_c[], const int rows_a, const int cols_a, const int cols_b, ulong &time_cpu);
#line 44 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/MatrixMult.mq5"
bool MatrixMult_GPU(const float &matrix_a[], const float &matrix_b[], float &matrix1_c[], float &matrix2_c[], const int rows_a, const int cols_a, const int cols_b, const int size_a, const int size_b, const int size_c, ulong &time1_gpu, ulong &time2_gpu);
#endif
@@ -0,0 +1,11 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_8863193ADB2FB42C
#define MQL_AUTO_FORWARDS_INCLUDED_8863193ADB2FB42C
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/MatrixMult.mq5
#line 16 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/MatrixMult.mq5"
define BLOCK_SIZE 10 bool MatrixMult_CPU(const double &matrix_a[], const double &matrix_b[], double &matrix_c[], const int rows_a, const int cols_a, const int cols_b, ulong &time_cpu);
#line 44 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/MatrixMult.mq5"
bool MatrixMult_GPU(const double &matrix_a[], const double &matrix_b[], double &matrix1_c[], double &matrix2_c[], const int rows_a, const int cols_a, const int cols_b, const int size_a, const int size_b, const int size_c, ulong &time1_gpu, ulong &time2_gpu);
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_341E64FA398F3C31
#define MQL_AUTO_FORWARDS_INCLUDED_341E64FA398F3C31
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/ObjectChart/ObjChartSample.mq5
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_C003532A3D198092
#define MQL_AUTO_FORWARDS_INCLUDED_C003532A3D198092
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OrderInfo/OrderInfoSample.mq5
#endif
@@ -0,0 +1,9 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_354D95DCD3828EA3
#define MQL_AUTO_FORWARDS_INCLUDED_354D95DCD3828EA3
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/Canvas/Charts/PieChartSample.mq5
#line 93 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/Canvas/Charts/PieChartSample.mq5"
uint RandomRGB(void);
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_73CBA22BCFB6FEDB
#define MQL_AUTO_FORWARDS_INCLUDED_73CBA22BCFB6FEDB
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/PositionInfo/PositionInfoSample.mq5
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_BB733E31A9114819
#define MQL_AUTO_FORWARDS_INCLUDED_BB733E31A9114819
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/Remnant 3D/Remnant 3D.mq5
#endif
@@ -0,0 +1,75 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_44EA2BBDE109222B
#define MQL_AUTO_FORWARDS_INCLUDED_44EA2BBDE109222B
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5
#line 229 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ManageSltp();
#line 239 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
bool CheckStopDistance(const ENUM_POSITION_TYPE type, const double new_sl);
#line 262 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
bool CheckTakeProfitDistance(const ENUM_POSITION_TYPE type, const double new_tp);
#line 285 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ManageStops(const ENUM_POSITION_TYPE side_filter);
#line 351 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void AdjustTakeProfit(const double pips_adjust, const ENUM_POSITION_TYPE side_filter);
#line 397 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ApplyFixedSLTP(const ENUM_POSITION_TYPE side_filter);
#line 448 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
bool CollectSideInfo(const ENUM_POSITION_TYPE side, double &avg_price, ulong &tickets[]);
#line 479 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ManageBuyBE(const bool show_line);
#line 497 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ManageSellBE(const bool show_line);
#line 515 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ExecuteSideBreakEven(const ENUM_POSITION_TYPE side, const double avg_price, ulong &tickets[]);
#line 532 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void UpdateSideStopLoss(const double line_price, ulong &tickets[], const ENUM_POSITION_TYPE side);
#line 563 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ApplyFixedSL(ulong &tickets[], const ENUM_POSITION_TYPE side, const double pips_from_open);
#line 595 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
bool CreatePanel();
#line 650 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void CreateLabel(CLabel &label, const string name, const int x, const int y, const string text);
#line 668 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void CreateEdit(CEdit &edit, const string name, const int x, const int y);
#line 685 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void CreateButton(CButton &button, const string name, const int x, const int y, const int width, const int height, const string text, const color background, const color border, const color text_color);
#line 708 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void SetInitialValues();
#line 720 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void UpdateInputValues();
#line 732 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ApplyPanelValues();
#line 753 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void ToggleInputLock();
#line 777 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void SetInputsReadOnly(const bool read_only);
#line 789 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
bool ReadPanelDouble(CEdit &edit, const string label, const double min_value, const double max_value, const double fallback, double &out_value);
#line 811 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void UpdateToggleButton(CButton &button, const bool state);
#line 829 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void UpdateSideLine(const ENUM_POSITION_TYPE side, const bool show_line, const bool has_position, const double avg_price);
#line 852 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void DrawLineAndText(const string base, const double price, const color line_color, const string text);
#line 883 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void DeleteBreakEvenLine(const string base);
#line 889 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
bool PositionMatches(const ulong ticket);
#line 904 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
int CountPositions(const ENUM_POSITION_TYPE side_filter);
#line 920 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
bool TryModifyPosition(const ulong ticket, const double new_sl, const double new_tp, const string reason);
#line 944 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
bool IsBetterStop(const ENUM_POSITION_TYPE type, const double current_sl, const double candidate_sl);
#line 961 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void Push(ulong &items[], const ulong value);
#line 968 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
double NormalizePrice(const double price);
#line 975 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
double PipSize(const string symbol);
#line 994 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/SLTP_Panel.mq5"
void DisplayPanelStatus();
#endif
@@ -0,0 +1,139 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_FC92D045A9101619
#define MQL_AUTO_FORWARDS_INCLUDED_FC92D045A9101619
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5
#line 545 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool EnsureSTHandle(const int slot, const ENUM_TIMEFRAMES tf);
#line 581 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
int InitHandles();
#line 621 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void UpdateAllSTHandles();
#line 630 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool IsTradingTime();
#line 667 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void HandleTradingTimeTransition();
#line 704 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void CreateDoneFlagFile(string fileName);
#line 726 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void DeleteDoneFlagFile(string fileName);
#line 740 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool CheckDoneFlagFile(string fileName);
#line 751 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void ResetPredictionFiles(const bool reset_last_time);
#line 786 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool IsSpreadOK(const double limit_points);
#line 803 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
TradeSide DecideEntrySide();
#line 844 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void ExecuteEntry(const TradeSide side);
#line 920 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool IsOutOfRange(const string symbol, const ENUM_TIMEFRAMES tf, const int periods, const double max_range);
#line 963 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool IsOutOfRangeShort(const string symbol, const ENUM_TIMEFRAMES tf, const int periods, const double max_range);
#line 1002 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
double AdjustPoint(string Currency);
#line 1032 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void DisplayEAValues();
#line 1064 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool CheckStopDistance(ENUM_POSITION_TYPE type, double price_now, double new_sl);
#line 1094 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void ManageStops(const ENUM_STOPF_FILTER side_filter);
#line 1276 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void HighVolatilityLimit();
#line 1487 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
inline int SecToBars(long seconds);
#line 1502 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool RunPythonBatch(const string bat_path, const int wait_sec);
#line 1538 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void PredictFlg();
#line 1643 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool LoadPredictionOutcome(string file_name);
#line 1735 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void ResetAfterTimeout();
#line 1764 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void WriteIndicatorsToFile(string symbol, int timeframe, int count, string filename);
#line 2148 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void CheckPositions();
#line 2188 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
int CountPositions(const ENUM_POSITION_TYPE type, const uint magic);
#line 2219 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool PlaceEntryOrder(const TradeSide side, const int current_position, datetime &last_order_time, double limit_price);
#line 2334 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool SendOrder(const TradeSide side, double limit_price, double sl, double tp);
#line 2416 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool CloseTimedPositions(const ENUM_POSITION_TYPE dir, const ENUM_ORDER_TYPE opos);
#line 2477 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
#line 2504 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void AdjustTakeProfit(const double pips_adjust, const ENUM_POSITION_TYPE side_filter);
#line 2585 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
int EntryTrend(int &out_flag, double &out_st_now, double &out_hull_now, double &currentOpen, double &currentAsk);
#line 2658 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool SuperTrendDirection(int &out_trend_flag, double &out_value, int buffer_num);
#line 2695 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool SuperTrendDirection2nd(int &out_trend_flag, double &out_value, int buffer_num);
#line 2734 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool DevBandFilter(double &devbndValue);
#line 2769 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool ProcessPairChange(int &st_prev_flg, int &st_flg);
#line 2858 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void SetInitialValues();
#line 2876 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void UpdateInputValues();
#line 3092 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void CreatePanel();
#line 3719 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void Push(ulong &a[], const ulong v);
#line 3735 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void DrawLineAndText(const string base, double price, color clr, const string txt, double offset, int shift_bars, bool del);
#line 3787 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool CollectSideInfo(const string sym, ulong magic, ENUM_POSITION_TYPE side, double &avg, ulong &tickets[]);
#line 3819 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void DrawSideBreakEvenLine(const string sym, double avg, double buf, ENUM_POSITION_TYPE side);
#line 3841 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void UpdateSideLine(ENUM_POSITION_TYPE side, bool show_line, bool has_pos, double avg_price);
#line 3867 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void UpdateSideStopLoss(const string sym, const double line_price, ulong &tickets[], const ENUM_POSITION_TYPE side);
#line 3932 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void ExecuteSideBreakEven(const ENUM_POSITION_TYPE side, const double avg_price, ulong &tickets[]);
#line 3956 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void ManageBuyBE(const bool show_line);
#line 3993 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void ManageSellBE(const bool show_line);
#line 4029 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void ApplyFixedSL(ulong &tickets[], const ENUM_POSITION_TYPE side, const double pips_from_open);
#line 4082 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool CreateRangeLine(const string name, const double price, const color clr);
#line 4100 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void EnsureRangeLines();
#line 4119 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void DeleteRangeLines();
#line 4128 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool GetRangePrices(double &upper, double &lower);
#line 4145 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
TradeSide HorizonLineRangeCheck();
#line 4179 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
string TrainBatPath();
#line 4217 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
string PredictBatPath();
#line 4611 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void CreateToggleButton(const bool state);
#line 4636 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void RefreshButtonAppearance(const bool state);
#line 4650 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void DebugCheck(bool buycheck);
#line 4710 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool CheckDevBandFilter(double &devbndValue);
#line 4745 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
bool CheckPlaceEntryOrder(const TradeSide side);
#line 4812 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void CheckExecuteEntry(const TradeSide side);
#line 4912 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void CheckEntryTrend();
#line 4926 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void CheckSuperTrend(int buffer_num);
#line 4944 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_153540.mq5"
void CheckSuperTrendSecond(int buffer_num);
#endif
@@ -0,0 +1,139 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_6D58833B3F6D6F70
#define MQL_AUTO_FORWARDS_INCLUDED_6D58833B3F6D6F70
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5
#line 545 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool EnsureSTHandle(const int slot, const ENUM_TIMEFRAMES tf);
#line 581 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
int InitHandles();
#line 621 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void UpdateAllSTHandles();
#line 630 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool IsTradingTime();
#line 667 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void HandleTradingTimeTransition();
#line 704 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void CreateDoneFlagFile(string fileName);
#line 726 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void DeleteDoneFlagFile(string fileName);
#line 740 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool CheckDoneFlagFile(string fileName);
#line 751 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void ResetPredictionFiles(const bool reset_last_time);
#line 786 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool IsSpreadOK(const double limit_points);
#line 803 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
TradeSide DecideEntrySide();
#line 844 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void ExecuteEntry(const TradeSide side);
#line 920 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool IsOutOfRange(const string symbol, const ENUM_TIMEFRAMES tf, const int periods, const double max_range);
#line 963 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool IsOutOfRangeShort(const string symbol, const ENUM_TIMEFRAMES tf, const int periods, const double max_range);
#line 1002 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
double AdjustPoint(string Currency);
#line 1032 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void DisplayEAValues();
#line 1064 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool CheckStopDistance(ENUM_POSITION_TYPE type, double price_now, double new_sl);
#line 1094 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void ManageStops(const ENUM_STOPF_FILTER side_filter);
#line 1276 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void HighVolatilityLimit();
#line 1487 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
inline int SecToBars(long seconds);
#line 1502 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool RunPythonBatch(const string bat_path, const int wait_sec);
#line 1538 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void PredictFlg();
#line 1643 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool LoadPredictionOutcome(string file_name);
#line 1735 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void ResetAfterTimeout();
#line 1764 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void WriteIndicatorsToFile(string symbol, int timeframe, int count, string filename);
#line 2148 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void CheckPositions();
#line 2188 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
int CountPositions(const ENUM_POSITION_TYPE type, const uint magic);
#line 2219 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool PlaceEntryOrder(const TradeSide side, const int current_position, datetime &last_order_time, double limit_price);
#line 2334 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool SendOrder(const TradeSide side, double limit_price, double sl, double tp);
#line 2416 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool CloseTimedPositions(const ENUM_POSITION_TYPE dir, const ENUM_ORDER_TYPE opos);
#line 2477 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
#line 2504 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void AdjustTakeProfit(const double pips_adjust, const ENUM_POSITION_TYPE side_filter);
#line 2585 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
int EntryTrend(int &out_flag, double &out_st_now, double &out_hull_now, double &currentOpen, double &currentAsk);
#line 2658 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool SuperTrendDirection(int &out_trend_flag, double &out_value, int buffer_num);
#line 2695 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool SuperTrendDirection2nd(int &out_trend_flag, double &out_value, int buffer_num);
#line 2734 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool DevBandFilter(double &devbndValue);
#line 2769 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool ProcessPairChange(int &st_prev_flg, int &st_flg);
#line 2858 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void SetInitialValues();
#line 2876 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void UpdateInputValues();
#line 3092 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void CreatePanel();
#line 3719 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void Push(ulong &a[], const ulong v);
#line 3735 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void DrawLineAndText(const string base, double price, color clr, const string txt, double offset, int shift_bars, bool del);
#line 3787 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool CollectSideInfo(const string sym, ulong magic, ENUM_POSITION_TYPE side, double &avg, ulong &tickets[]);
#line 3819 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void DrawSideBreakEvenLine(const string sym, double avg, double buf, ENUM_POSITION_TYPE side);
#line 3841 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void UpdateSideLine(ENUM_POSITION_TYPE side, bool show_line, bool has_pos, double avg_price);
#line 3867 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void UpdateSideStopLoss(const string sym, const double line_price, ulong &tickets[], const ENUM_POSITION_TYPE side);
#line 3932 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void ExecuteSideBreakEven(const ENUM_POSITION_TYPE side, const double avg_price, ulong &tickets[]);
#line 3956 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void ManageBuyBE(const bool show_line);
#line 3993 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void ManageSellBE(const bool show_line);
#line 4029 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void ApplyFixedSL(ulong &tickets[], const ENUM_POSITION_TYPE side, const double pips_from_open);
#line 4082 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool CreateRangeLine(const string name, const double price, const color clr);
#line 4100 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void EnsureRangeLines();
#line 4119 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void DeleteRangeLines();
#line 4128 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool GetRangePrices(double &upper, double &lower);
#line 4145 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
TradeSide HorizonLineRangeCheck();
#line 4179 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
string TrainBatPath();
#line 4217 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
string PredictBatPath();
#line 4611 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void CreateToggleButton(const bool state);
#line 4636 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void RefreshButtonAppearance(const bool state);
#line 4650 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void DebugCheck(bool buycheck);
#line 4710 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool CheckDevBandFilter(double &devbndValue);
#line 4745 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
bool CheckPlaceEntryOrder(const TradeSide side);
#line 4812 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void CheckExecuteEntry(const TradeSide side);
#line 4912 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void CheckEntryTrend();
#line 4926 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void CheckSuperTrend(int buffer_num);
#line 4944 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/.cache/SLTP_Panel_original_20260503_171108.mq5"
void CheckSuperTrendSecond(int buffer_num);
#endif
@@ -0,0 +1,13 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_2803837B848A49C7
#define MQL_AUTO_FORWARDS_INCLUDED_2803837B848A49C7
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Seascape/Seascape.mq5
#line 17 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Seascape/Seascape.mq5"
bool ModelInitialize(int &cl_ctx, int &cl_prg, int &cl_krn, int &cl_mem);
#line 76 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Seascape/Seascape.mq5"
bool ModelResize(const int cl_ctx, const int cl_krn, int &cl_mem);
#line 108 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Seascape/Seascape.mq5"
void ModelShutdown(int cl_ctx, int cl_prg, int cl_krn, int cl_mem);
#endif
@@ -0,0 +1,11 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_5ACB5DC3B62295AE
#define MQL_AUTO_FORWARDS_INCLUDED_5ACB5DC3B62295AE
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/ObjectSphere/SphereSample.mq5
#line 32 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/ObjectSphere/SphereSample.mq5"
int Init(void);
#line 55 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/ObjectSphere/SphereSample.mq5"
void Deinit(void);
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_913F84D0A480706B
#define MQL_AUTO_FORWARDS_INCLUDED_913F84D0A480706B
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/SuperTrend_Custom.mq5
#endif
@@ -0,0 +1,9 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_0091820D9801137D
#define MQL_AUTO_FORWARDS_INCLUDED_0091820D9801137D
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/SuperTrend_CustomWithOffset.mq5
#line 91 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/SuperTrend_CustomWithOffset.mq5"
double PipPoint(string Currency);
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_A2FA19F2F2B00979
#define MQL_AUTO_FORWARDS_INCLUDED_A2FA19F2F2B00979
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/SuperTrend_Custom_20251203.mq5
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_B7AE972329AA640F
#define MQL_AUTO_FORWARDS_INCLUDED_B7AE972329AA640F
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/SymbolInfo/SymbolInfoSample.mq5
#endif
@@ -0,0 +1,65 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_76E6C7C5F947CA70
#define MQL_AUTO_FORWARDS_INCLUDED_76E6C7C5F947CA70
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5
#line 11 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
include <Generic\HashSet.mqh> bool TestAddRange_AsArrayList(const int count, const int add_length);
#line 51 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestAddRange_AsArray(const int count, const int add_length);
#line 90 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestAddRange_AsNULL(const int count);
#line 121 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestAddRange(const string test_name);
#line 143 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestBinarySearch_Validations(const int count);
#line 177 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestBinarySearch_WithoutDuplicates(const int count);
#line 201 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestBinarySearch_WithDuplicates(const int count);
#line 227 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestBinarySearch(const string test_name);
#line 249 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestIndexOf_NonExistingValues(const int count);
#line 268 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestIndexOf_OrderIsCorrect(const int count);
#line 300 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestIndexOf_Common(const int count);
#line 336 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestIndexOf_OutOfRange(const int count);
#line 361 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestIndexOf(const string test_name);
#line 387 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestMisc_BasicInsert(const int count);
#line 449 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestMisc_InsertRange(const int count);
#line 526 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestMisc_Contains(const int count);
#line 545 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestMisc_Remove(const int count);
#line 568 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestMisc_Clear(const int count);
#line 594 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestMisc(const string test_name);
#line 624 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestRemove_Range(const int count);
#line 680 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestRemove_Invalid(const int count);
#line 747 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestRemove(const string test_name);
#line 765 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestReverse_Range(const int count);
#line 829 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestReverse_Invalid(const int count);
#line 893 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestReverse(const string test_name);
#line 911 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestSort_WithDuplicates(const int count);
#line 941 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestSort_Invalid(const int count);
#line 976 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
bool TestSort(const string test_name);
#line 994 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestArrayList.mq5"
void TestArrayList(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,9 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_7E6865B26226F42F
#define MQL_AUTO_FORWARDS_INCLUDED_7E6865B26226F42F
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Alglib/TestClasses.mq5
#line 708 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Alglib/TestClasses.mq5"
string GetElapsed(ulong microseconds);
#endif
@@ -0,0 +1,47 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_5FE06143237DE253
#define MQL_AUTO_FORWARDS_INCLUDED_5FE06143237DE253
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5
#line 34 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
include <Math\Fuzzy\SugenoFuzzySystem.mqh> bool Test_NormalCombinationMembershipFunction();
#line 67 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_GeneralizedBellShapedMembershipFunction();
#line 91 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_SigmoidalMembershipFunction();
#line 114 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_ProductTwoSigmoidalMembershipFunctions();
#line 140 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_TrapezoidMembershipFunction();
#line 173 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_NormalMembershipFunction();
#line 196 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_TriangularMembershipFunction();
#line 232 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_ConstantMembershipFunction();
#line 254 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_P_S_Z_ShapedMembershipFunction();
#line 277 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_Bisector();
#line 295 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_Centroid();
#line 322 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_Defuzzification();
#line 374 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_TipingProblem();
#line 439 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool Test_TypicalFuzzyControlSystem();
#line 511 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
void AddSugenoFuzzyRule(CSugenoFuzzySystem *fs, CFuzzyVariable *fv1, CFuzzyVariable *fv2, CSugenoVariable *sv, const string value1, const string value2, const string result);
#line 527 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool TestMembersipFunctions(const string test_name);
#line 573 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool TestDefuzzificationMethods(const string test_name);
#line 595 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
bool TestFuzzySystems(const string test_name);
#line 613 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
void TestFuzzy(int &tests_performed, int &tests_passed);
#line 643 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Fuzzy/TestFuzzy.mq5"
void UnitTests(const string package_name);
#endif
@@ -0,0 +1,17 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_BE102765F52275B6
#define MQL_AUTO_FORWARDS_INCLUDED_BE102765F52275B6
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashMap.mq5
#line 11 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashMap.mq5"
include <Generic\HashMap.mqh> bool TestMisc_Constructor(const int count);
#line 43 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashMap.mq5"
bool TestMisc_Contains(const int count);
#line 86 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashMap.mq5"
bool TestMisc_Remove(const int count);
#line 137 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashMap.mq5"
bool TestMisc(const string test_name);
#line 159 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashMap.mq5"
void TestHashMap(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,15 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_93CEB4A9784F8D93
#define MQL_AUTO_FORWARDS_INCLUDED_93CEB4A9784F8D93
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashSet.mq5
#line 11 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashSet.mq5"
include <Generic\HashSet.mqh> bool TestMisc_Constructor(const int count);
#line 42 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashSet.mq5"
bool TestMisc_TrimExpress(const int count);
#line 102 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashSet.mq5"
bool TestMisc(const string test_name);
#line 120 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestHashSet.mq5"
void TestHashSet(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_1F0599A026B84EF4
#define MQL_AUTO_FORWARDS_INCLUDED_1F0599A026B84EF4
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Alglib/TestInterfaces.mq5
#endif
@@ -0,0 +1,49 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_F0EAFCB070990DCB
#define MQL_AUTO_FORWARDS_INCLUDED_F0EAFCB070990DCB
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5
#line 11 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
include <Generic\ArrayList.mqh> bool TestAddAfter_Node(const int count);
#line 213 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddAfter_Node_Negative(const int count);
#line 256 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddAfter(const string test_name);
#line 275 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddBefore_Node(const int count);
#line 482 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddBefore_Node_Negative(const int count);
#line 525 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddBefore(const string test_name);
#line 544 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddFirst_Node(const int count);
#line 678 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddFirst_Node_Negative(const int count);
#line 733 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddFirst(const string test_name);
#line 751 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddLast_Node(const int count);
#line 872 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddLast_Node_Negative(const int count);
#line 927 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestAddLast(const string test_name);
#line 945 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestConstructor_Complex(const int count);
#line 980 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestConstructor(const string test_name);
#line 994 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestMisc_Find(const int count);
#line 1160 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestMisc_FindLast(const int count);
#line 1326 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestMisc_RemoveNode(const int count);
#line 1646 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestMisc_RemoveFirst(const int count);
#line 1770 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestMisc_RemoveLast(const int count);
#line 1899 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
bool TestMisc(const string test_name);
#line 1929 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestLinkedList.mq5"
void TestLinkedList(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,25 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_9FBBF7ABE49E50A5
#define MQL_AUTO_FORWARDS_INCLUDED_9FBBF7ABE49E50A5
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5
#line 11 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
include <Generic\ArrayList.mqh> bool TestConstructor_Valid(const int count);
#line 49 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
bool TestConstructor_Invalid(const int count);
#line 65 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
bool TestConstructor(const string test_name);
#line 83 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
bool TestMisc_Dequeue(const int count);
#line 105 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
bool TestMisc_Peek(const int count);
#line 126 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
bool TestMisc_Complex(const int count);
#line 160 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
bool TestMisc_TrimExcess(const int count);
#line 198 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
bool TestMisc(const string test_name);
#line 224 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestQueue.mq5"
void TestQueue(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,31 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_285A3D310E563F12
#define MQL_AUTO_FORWARDS_INCLUDED_285A3D310E563F12
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5
#line 12 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
include <Generic\HashSet.mqh> bool TestMisc_Constructor(const int count);
#line 48 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestMisc_Contains(const int count);
#line 80 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestMisc_Add(const int count);
#line 106 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestMisc(const string test_name);
#line 128 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestFind_Max(const int count);
#line 153 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestFind_Min(const int count);
#line 178 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestFind(const string test_name);
#line 196 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestRemove_Node(const int count);
#line 242 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestRemove_Max(const int count);
#line 270 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestRemove_Min(const int count);
#line 298 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
bool TestRemove(const string test_name);
#line 320 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestRedBlackTree.mq5"
void TestRedBlackTree(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,17 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_F0CDE49CD36EE893
#define MQL_AUTO_FORWARDS_INCLUDED_F0CDE49CD36EE893
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedMap.mq5
#line 11 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedMap.mq5"
include <Generic\SortedMap.mqh> bool TestMisc_Constructor(const int count);
#line 43 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedMap.mq5"
bool TestMisc_Contains(const int count);
#line 86 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedMap.mq5"
bool TestMisc_Ordering(const int count);
#line 138 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedMap.mq5"
bool TestMisc(const string test_name);
#line 160 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedMap.mq5"
void TestSortedMap(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,15 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_667F905F7001A8C2
#define MQL_AUTO_FORWARDS_INCLUDED_667F905F7001A8C2
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedSet.mq5
#line 11 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedSet.mq5"
include <Generic\SortedSet.mqh> bool TestMisc_Constructor(const int count);
#line 54 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedSet.mq5"
bool TestMisc_GetViewBetween(const int count);
#line 102 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedSet.mq5"
bool TestMisc(const string test_name);
#line 120 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestSortedSet.mq5"
void TestSortedSet(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,25 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_5271212BCF47E690
#define MQL_AUTO_FORWARDS_INCLUDED_5271212BCF47E690
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5
#line 11 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
include <Generic\ArrayList.mqh> bool TestConstructor_Valid(const int count);
#line 49 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
bool TestConstructor_Invalid(const int count);
#line 65 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
bool TestConstructor(const string test_name);
#line 83 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
bool TestMisc_Pop(const int count);
#line 105 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
bool TestMisc_Peek(const int count);
#line 126 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
bool TestMisc_Complex(const int count);
#line 160 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
bool TestMisc_TrimExcess(const int count);
#line 198 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
bool TestMisc(const string test_name);
#line 224 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Generic/TestStack.mq5"
void TestStack(int &tests_performed, int &tests_passed);
#endif
@@ -0,0 +1,57 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_C52E756923511659
#define MQL_AUTO_FORWARDS_INCLUDED_C52E756923511659
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5
#line 690 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
int GetCorrectDigits(const double delta);
#line 721 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestBinomialDistribution(string test_name, const double n, const double probability, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 905 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestBetaDistribution(string test_name, const double a, const double b, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 1089 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestGammaDistribution(string test_name, const double a, const double b, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 1273 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestCauchyDistribution(string test_name, const double a, const double b, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 1451 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestExponentialDistribution(string test_name, const double mu, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 1635 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestUnifromDistribution(string test_name, const double a, const double b, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 1819 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestGeometricDistribution(string test_name, const double p, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 2003 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestHypergeometricDistribution(string test_name, const double m, const double k, const double n, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 2187 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestLogisticDistribution(string test_name, const double mu, const double sigma, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 2371 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestWeibullDistribution(string test_name, const double a, const double b, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 2555 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestPoissonDistribution(string test_name, const double lambda, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 2739 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestFDistribution(string test_name, const double nu1, const double nu2, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 2924 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestChiSquareDistribution(string test_name, const double nu, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 3108 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestNoncentralChiSquareDistribution(string test_name, const double nu, const double sigma, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 3293 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestNoncentralFDistribution(string test_name, const double nu1, const double nu2, const double sigma, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 3478 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestNoncentralBetaDistribution(string test_name, const double a, const double b, const double lambda, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 3663 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestNegativeBinomialDistribution(string test_name, const double r, const double p, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 3847 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestTDistribution(string test_name, const double nu, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 4031 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestNoncentralTDistribution(string test_name, const double nu, const double delta, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 4215 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestNormalDistribution(string test_name, const double mu, const double sigma, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 4400 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
bool TestLognormalDistribution(string test_name, const double mu, const double sigma, const double &x_values[], const double &pdf_values[], const double &cdf_values[], precision_info &precision);
#line 4584 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
void ShowPrecisionInfo(const string distribution, precision_info &precision);
#line 4596 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
void TestDistributions(int &tests_performed, int &tests_passed);
#line 4837 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStat.mq5"
void UnitTests(const string package_name);
#endif
@@ -0,0 +1,55 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_A4CE858F6174B574
#define MQL_AUTO_FORWARDS_INCLUDED_A4CE858F6174B574
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5
#line 71 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
define AverageCount 1000 void ShowBenchmarkInfo(const string test_info, benchmark_info &benchmark);
#line 85 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
void CalculateStatisticalProperties(benchmark_info &benchmark, double &pdf_times[], double &cdf_times[], double &quantile_times[], double &random_times[]);
#line 121 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkBinomial(benchmark_info &benchmark_binomial, int &tests_performed, int &tests_passed);
#line 184 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkBeta(benchmark_info &benchmark_beta, int &tests_performed, int &tests_passed);
#line 249 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkGamma(benchmark_info &benchmark_gamma, int &tests_performed, int &tests_passed);
#line 314 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkCauchy(benchmark_info &benchmark_cauchy, int &tests_performed, int &tests_passed);
#line 379 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkExponential(benchmark_info &benchmark_exponential, int &tests_performed, int &tests_passed);
#line 443 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkUniform(benchmark_info &benchmark_uniform, int &tests_performed, int &tests_passed);
#line 508 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkGeometric(benchmark_info &benchmark_geometric, int &tests_performed, int &tests_passed);
#line 572 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkHypergeometric(benchmark_info &benchmark_hypergeometric, int &tests_performed, int &tests_passed);
#line 638 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkLogistic(benchmark_info &benchmark_logistic, int &tests_performed, int &tests_passed);
#line 703 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkWeibull(benchmark_info &benchmark_weibull, int &tests_performed, int &tests_passed);
#line 768 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkPoisson(benchmark_info &benchmark_poisson, int &tests_performed, int &tests_passed);
#line 832 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkF(benchmark_info &benchmark_f, int &tests_performed, int &tests_passed);
#line 897 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkChiSquare(benchmark_info &benchmark_chisquare, int &tests_performed, int &tests_passed);
#line 961 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkNoncentralChiSquare(benchmark_info &benchmark_noncentral_chisquare, int &tests_performed, int &tests_passed);
#line 1026 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkNoncentralF(benchmark_info &benchmark_noncentral_f, int &tests_performed, int &tests_passed);
#line 1092 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkNoncentralBeta(benchmark_info &benchmark_noncentral_beta, int &tests_performed, int &tests_passed);
#line 1158 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkNegativeBinomial(benchmark_info &benchmark_negative_binomial, int &tests_performed, int &tests_passed);
#line 1223 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkT(benchmark_info &benchmark_t, int &tests_performed, int &tests_passed);
#line 1287 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkNoncentralT(benchmark_info &benchmark_noncentral_t, int &tests_performed, int &tests_passed);
#line 1353 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkNormal(benchmark_info &benchmark_normal, int &tests_performed, int &tests_passed);
#line 1420 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
bool CalculateBenchmarkLognormal(benchmark_info &benchmark_lognormal, int &tests_performed, int &tests_passed);
#line 1487 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatBenchmark.mq5"
void CalculateBenchmarks(string package_name);
#endif
@@ -0,0 +1,11 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_BFB129A2D4624852
#define MQL_AUTO_FORWARDS_INCLUDED_BFB129A2D4624852
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatPrecision.mq5
#line 80 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatPrecision.mq5"
int GetCorrectDigits(const double delta);
#line 101 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/UnitTests/Stat/TestStatPrecision.mq5"
void TestPrecision(const string comment, const double pdf, const double cdf, const double pdf_calculated, const double cdf_calculated);
#endif
@@ -0,0 +1,13 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_C4D984B7A8F9E5BD
#define MQL_AUTO_FORWARDS_INCLUDED_C4D984B7A8F9E5BD
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/TradingPanel.mq5
#line 219 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/TradingPanel.mq5"
bool IsTradingTime();
#line 256 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/TradingPanel.mq5"
void HandleTradingTimeTransition();
#line 292 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Files/temp/TradingPanel.mq5"
void DisplayEAValues();
#endif
@@ -0,0 +1,13 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_F6A6A516F36ED9AC
#define MQL_AUTO_FORWARDS_INCLUDED_F6A6A516F36ED9AC
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/TradingPanel.mq5
#line 219 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/TradingPanel.mq5"
bool IsTradingTime();
#line 256 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/TradingPanel.mq5"
void HandleTradingTimeTransition();
#line 292 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Experts/MyProject/TradingPanel.mq5"
void DisplayEAValues();
#endif
@@ -0,0 +1,15 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_FE5807CDA84A867B
#define MQL_AUTO_FORWARDS_INCLUDED_FE5807CDA84A867B
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/Wavelet.mq5
#line 294 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/Wavelet.mq5"
double Weirstrass(double x, double a, double b);
#line 311 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/Wavelet.mq5"
void PrepareModelData(double &price_data[], const int datacount);
#line 326 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/Wavelet.mq5"
void PreparePriceData(const string symbol, ENUM_TIMEFRAMES timeframe, double &price_data[], const int datacount);
#line 334 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Double/Wavelet.mq5"
void PrepareMomentumData(double &price_data[], double &momentum_data[], const int momentum_period);
#endif
@@ -0,0 +1,15 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_FFD23185C8FA7332
#define MQL_AUTO_FORWARDS_INCLUDED_FFD23185C8FA7332
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/Wavelet.mq5
#line 288 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/Wavelet.mq5"
float Weirstrass(float x, float a, float b);
#line 305 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/Wavelet.mq5"
void PrepareModelData(float &price_data[], const int datacount);
#line 320 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/Wavelet.mq5"
void PreparePriceData(const string symbol, ENUM_TIMEFRAMES timeframe, float &price_data[], const int datacount);
#line 336 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Scripts/Examples/OpenCL/Float/Wavelet.mq5"
void PrepareMomentumData(float &price_data[], float &momentum_data[], const int momentum_period);
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_66C47364059C2765
#define MQL_AUTO_FORWARDS_INCLUDED_66C47364059C2765
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/MyProject/eATR.mq5
#endif
@@ -0,0 +1,7 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_C83C4339A8613F40
#define MQL_AUTO_FORWARDS_INCLUDED_C83C4339A8613F40
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/eSuperTrend.mq5
#endif
@@ -0,0 +1,9 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_1FA3998C331B62BF
#define MQL_AUTO_FORWARDS_INCLUDED_1FA3998C331B62BF
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/eSuperTrendWithOffset.mq5
#line 89 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/eSuperTrendWithOffset.mq5"
double PipPoint(string Currency);
#endif
@@ -0,0 +1,9 @@
#ifndef MQL_AUTO_FORWARDS_INCLUDED_CCD19995C6662ABE
#define MQL_AUTO_FORWARDS_INCLUDED_CCD19995C6662ABE
// Auto-generated by MQL Clangd. Do not edit — regenerated by "MQL: Create Configuration".
// Forward declarations for top-level functions in c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/eSuperTrendWithOffset2.mq5
#line 101 "c:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Indicators/eSuperTrendWithOffset2.mq5"
double PipPoint(string Currency);
#endif
+20
View File
@@ -23,5 +23,25 @@
"editor.tabSize": 3,
"C_Cpp.default.forcedInclude": [
"c:\\Users\\new\\.vscode\\extensions\\l-i-v.mql-tools-2.2.0\\data\\mql5_en.mqh"
],
"clangd.fallbackFlags": [
"-xc++",
"-std=c++17",
"-D__MQL__",
"-D__MQL5__",
"-includec:/Users/new/.cursor/extensions/ngsoftware.mql-clangd-1.1.55-universal/files/mql_clangd_compat.h",
"-fms-extensions",
"-fms-compatibility",
"-ferror-limit=0",
"-Wno-invalid-token-paste",
"-Wno-unused-value",
"-Wno-unknown-pragmas",
"-Wno-writable-strings",
"-Xclang",
"-Wno-invalid-pp-directive",
"-Wno-unknown-directives",
"-Wno-language-extension-token",
"-Ic:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5",
"-Ic:/Users/new/AppData/Roaming/MetaQuotes/Terminal/5BDB0B60344C088C2FA5CA35699BAAFD/MQL5/Include"
]
}
-935
View File
@@ -1,935 +0,0 @@
//+------------------------------------------------------------------+
//| HIT_EA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.00"
//+------------------------------------------------------------------+
//| バッチファイル実行用の設定
//+------------------------------------------------------------------+
#import "Shell32.dll"
int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
#import
// バッチファイルのパス
string get_trend_reply_bat = "C:\\ea_py\\get_trend_reply.bat"; // H4: trend
string get_entry_reply_bat = "C:\\ea_py\\get_entry_reply.bat"; // H1: entry
// プロセス完了ファイルの設定
string done_trend_file = "process_done_trend.txt";
string done_entry_file = "process_done_entry.txt";
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| インプットの設定
//+------------------------------------------------------------------+
//--- 入力パラメータ
input double lot_size = 0.01; // ロット数
input double spread_limit = 20; // 許容スプレッド(point)
input int magic_number = 10001; // マジックナンバー
input int initial_order = 0; // 起動時の注文(0:なし, 1:あり)
ulong slippage = 10; // スリッページ
//--- 主要な定数・設定
#define POSITION_LIMIT 48
#define ENTRY_H1_LIMIT 1 // H1本数(=1時間)
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
#define HISTORY_BARS 72
// ANALYZE_TIMEFRAME は削除(H4/H1 両方使うため定数ではなく直接指定)
#define TARGET_SIZE 13
#define DEFAULT_TARGET_PRICE 0.0
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| EAの状態をまとめる構造体
//+------------------------------------------------------------------+
struct EAState
{
int trend_state; // ★追加:トレンドを格納する変数
int res_chk; // GPTの回答が正しく取得できたか
double en_price[5]; // エントリー基準価格
double tp_price[5]; // 利益確定価格
double sl_price[5]; // ロスカット基準価格
bool load_trend_flg; // ★変更:トレンドを更新するタイミングか
bool load_target_flg; // ★変更:ターゲット価格を更新するタイミングか
int chk_cnt; // エントリー判定の試行回数
datetime last_trend_update; // ★追加:前回トレンドを更新した時刻
datetime last_target_update; // ★変更:前回ターゲット価格を更新した時刻
datetime last_chk;
};
EAState g_ea; // EA全体の状態をここで管理
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 必要な関数プロトタイプ宣言
//| プロセス完了ファイル("process_done.txt")関連
//+------------------------------------------------------------------+
// "process_done.txt"を作成する関数
void CreateDoneFile(const string name);
// "process_done.txt"を削除する関数
void DeleteDoneFile(const string name);
// "process_done.txt"の存在を確認し、存在する場合はtrueを返す関数
bool CheckDoneFile(const string name);
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 必要な関数プロトタイプ宣言
//| OHLCデータの取得からターゲット価格の取得まで
//+------------------------------------------------------------------+
//| 最新のOHLCデータを取得する関数
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count);
//| "ohlc.csv"を出力する関数
void RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[]);
//| バッチファイル(Pythonスクリプト)を実行する関数
void ExecuteBatchTrend();
void ExecuteBatchEntry();
// | "ohlc.csv"を出力後、バッチファイルの実行する関数
bool RecordOHLCAndExecuteBatch_Trend(EAState &state);
bool RecordOHLCAndExecuteBatch_Entry(EAState &state);
//| ターゲット価格を取得する関数
bool GetTargetPrices(EAState &state);
//| "target_prices.txt"を読み込む関数
void LoadTargetPrices(double &target_prices[]);
//| "xxx"を読み込む関数
bool GetTrendState(EAState &state);
void LoadTrendState(int &trend_state);
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 必要な関数プロトタイプ宣言
//| エントリー注文関連
//+------------------------------------------------------------------+
//| エントリー注文を送信する関数 (1:buy-stop, 2:buy-limit, 3:sell-stop, 4:sell-limit)
bool SendOrder(int orderType, double price, double tp, double sl);
//| 注文の執行ポリシーを取得する関数
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol);
//| 注文コメント(ローカル時刻)を生成する関数(先頭に orderType を付与)
string RequestComment(int orderType);
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 必要な関数プロトタイプ宣言
//| 時間制限処理関連
//+------------------------------------------------------------------+
//| 時間が経過したエントリー注文をキャンセルする関数
bool CancelExpiredOrders();
//| 時間が経過したポジションをクローズする関数
bool CloseExpiredPositions();
//| 指定された時間に最も近いバーのインデックスを返す関数
// int GetBarIndexByTime(datetime time, int default_index = 0);
int GetBarShiftByTime(datetime time, ENUM_TIMEFRAMES tf, int default_shift = -1);
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
void OnInit()
// プロセス完了ファイル("process_done.txt)"を作成
{
CreateDoneFile(done_trend_file);
CreateDoneFile(done_entry_file);
}
//+------------------------------------------------------------------+
//| ティック毎の処理
//+------------------------------------------------------------------+
void OnTick()
{
static int init_order_flg = initial_order;
// ─────────────────────────────────────────────
// (1) H4更新検知:トレンド用
// ─────────────────────────────────────────────
int current_bars_H4 = iBars(NULL, PERIOD_H4);
static int pre_bars_H4 = current_bars_H4;
int bars_H4_change = current_bars_H4 - pre_bars_H4;
if(bars_H4_change > 0 || init_order_flg == 1)
{
RecordOHLCAndExecuteBatch_Trend(g_ea);
}
pre_bars_H4 = current_bars_H4;
// trend done待ち(なければ以降をスキップ)
if(!CheckDoneFile(done_trend_file))
return;
// トレンド取得
GetTrendState(g_ea);
// ─────────────────────────────────────────────
// (2) H1更新検知:エントリー用
// ─────────────────────────────────────────────
static bool bars_H1_check = false;
int current_bars_H1 = iBars(NULL, PERIOD_H1);
static int pre_bars_H1 = current_bars_H1;
int bars_H1_change = current_bars_H1 - pre_bars_H1;
if(bars_H1_change > 0 || init_order_flg == 1)
{
init_order_flg = 0;
bars_H1_check = true;
g_ea.chk_cnt = 0;
g_ea.last_chk = 0;
RecordOHLCAndExecuteBatch_Entry(g_ea);
}
pre_bars_H1 = current_bars_H1;
// ── ティック情報・コメント表示 ──
MqlTick last_tick;
if(!SymbolInfoTick(_Symbol, last_tick))
{
return;
}
double Ask = last_tick.ask;
double Bid = last_tick.bid;
double Spread = MathRound((Ask - Bid) / Point()) * Point();
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
string message = StringFormat(
" \nAsk: %." + IntegerToString(digits) + "f"
"\nBid: %." + IntegerToString(digits) + "f"
"\nSpread: %." + IntegerToString(digits) + "f"
"\n\nLast Trend Update:\n %s"
"\n\nTrend State: %.0f" // ★追加
"\n\nLast Target Update:\n %s"
"\n\n[T1 Buy Stop ] en: %." + IntegerToString(digits) + "f tp: %." + IntegerToString(digits) + "f sl: %." + IntegerToString(digits) + "f"
"\n[T2 Buy Limit] en: %." + IntegerToString(digits) + "f tp: %." + IntegerToString(digits) + "f sl: %." + IntegerToString(digits) + "f"
"\n[T3 Sell Stop] en: %." + IntegerToString(digits) + "f tp: %." + IntegerToString(digits) + "f sl: %." + IntegerToString(digits) + "f"
"\n[T4 SellLimit] en: %." + IntegerToString(digits) + "f tp: %." + IntegerToString(digits) + "f sl: %." + IntegerToString(digits) + "f\n",
Ask, Bid, Spread,
TimeToString(g_ea.last_trend_update, TIME_DATE | TIME_MINUTES),
g_ea.trend_state, // ★追加
TimeToString(g_ea.last_target_update, TIME_DATE | TIME_MINUTES),
g_ea.en_price[1], g_ea.tp_price[1], g_ea.sl_price[1],
g_ea.en_price[2], g_ea.tp_price[2], g_ea.sl_price[2],
g_ea.en_price[3], g_ea.tp_price[3], g_ea.sl_price[3],
g_ea.en_price[4], g_ea.tp_price[4], g_ea.sl_price[4]
);
Comment(message);
// スプレッド制限
if(Spread > spread_limit * Point())
return;
// entry done待ち
if(!CheckDoneFile(done_entry_file))
return;
// ターゲット取得
GetTargetPrices(g_ea);
// 期限切れ注文キャンセル・ポジクローズ
if(OrdersTotal() > 0)
CancelExpiredOrders();
if(PositionsTotal() > 0)
CloseExpiredPositions();
// ─────────────────────────────────────────────
// エントリー条件判定&注文送信(H1更新タイミングで1回)
// ─────────────────────────────────────────────
// if(bars_H4_check && TimeCurrent() - g_ea.last_chk >= 60)
// {
// bars_H4_check = false;
// g_ea.last_chk = TimeCurrent();
if(bars_H1_check && TimeCurrent() - g_ea.last_chk >= 60)
{
bars_H1_check = false;
g_ea.last_chk = TimeCurrent();
if(g_ea.res_chk == 0)
{
Print("[Entry Skip] res_chk=0 (range). No entry orders are sent.");
g_ea.chk_cnt = 0;
}
else
{
int used = OrdersTotal() + PositionsTotal();
if(used >= POSITION_LIMIT)
{
Print("Position limit exceeded: used=", used, " limit=", POSITION_LIMIT);
}
else
{
int sent_success = 0; // ★ 送信成功数(= SendOrder true の回数)
// ★ 1..4 を順に判定して、条件OKなら送る
for(int t=1; t<=4; t++)
{
// ポジション上限チェック(途中で到達したら打ち切り)
used = OrdersTotal() + PositionsTotal();
if(used >= POSITION_LIMIT)
{
Print("Position limit reached while sending. used=", used, " limit=", POSITION_LIMIT);
break;
}
string entry_type;
double cur_price; // ログ用(Ask/Bid
if(t==1)
{
entry_type="Buy Stop";
cur_price=Ask;
}
else
if(t==2)
{
entry_type="Buy Limit";
cur_price=Ask;
}
else
if(t==3)
{
entry_type="Sell Stop";
cur_price=Bid;
}
else
{
entry_type="Sell Limit"; // t==4
cur_price=Bid;
}
double en = g_ea.en_price[t];
double tp = g_ea.tp_price[t];
double sl = g_ea.sl_price[t];
bool ok=false;
if(t==1)
ok = (Ask < en && tp > en && sl < en); // buy-stop
else
if(t==2)
ok = (Ask > en && tp > en && sl < en); // buy-limit
else
if(t==3)
ok = (Bid > en && tp < en && sl > en); // sell-stop
else
ok = (Bid < en && tp < en && sl > en); // sell-limit
if(ok)
{
Print("[", entry_type, " Order Try at ", cur_price, "] en=", en, " tp=", tp, " sl=", sl);
if(SendOrder(t, en, tp, sl))
{
sent_success++;
Print("[", entry_type, " Order Sent] ticket ok. en=", en, " tp=", tp, " sl=", sl);
}
else
{
Print("[", entry_type, " Order Failed] en=", en, " tp=", tp, " sl=", sl);
}
}
else
{
Print("[No ", entry_type, "] cur=", cur_price, " en=", en, " tp=", tp, " sl=", sl);
}
}
if(sent_success > 0)
{
g_ea.chk_cnt = 0; // 1件でも通ったら終了
}
else
{
g_ea.chk_cnt += 1;
Print("[Retry] no order sent. chk_cnt=", g_ea.chk_cnt, "/10");
if(g_ea.chk_cnt < 10)
{
// bars_H4_check = true; // 60秒後に再度このブロックに入る
bars_H1_check = true; // ★ GPT-EAの bars_H4_check → bars_H1_check に変更
}
else
{
Print("[Retry End] reached max tries. reset chk_cnt.");
g_ea.chk_cnt = 0;
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| "process_done.txt"を作成する関数
//+------------------------------------------------------------------+
void CreateDoneFile(const string name)
{
if(!FileIsExist(name))
{
int h = FileOpen(name, FILE_WRITE|FILE_TXT);
if(h != INVALID_HANDLE)
FileClose(h);
else
Print("Failed to create file: ", name, " err=", GetLastError());
}
}
//+------------------------------------------------------------------+
//| "process_done.txt"を削除する関数
//+------------------------------------------------------------------+
void DeleteDoneFile(const string name)
{
if(FileIsExist(name))
FileDelete(name);
}
//+------------------------------------------------------------------+
//| "process_done.txt"の存在を確認し、存在する場合はtrueを返す関数
//+------------------------------------------------------------------+
bool CheckDoneFile(const string name)
{
return FileIsExist(name);
}
//+------------------------------------------------------------------+
//| 最新のOHLCデータを取得する関数
//+------------------------------------------------------------------+
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count)
{
ArrayResize(times, 0);
ArrayResize(open_prices, 0);
ArrayResize(high_prices, 0);
ArrayResize(low_prices, 0);
ArrayResize(close_prices, 0);
if(bars_count < 2)
return false;
// 時間データを取得
if(CopyTime(_Symbol, tf, 0, bars_count, times) <= 0)
{
Print(__FUNCTION__, ": Failed to copy time data (bars=", bars_count, ") err=", GetLastError());
return false;
}
// OHLCデータを取得
MqlRates rates[];
if(CopyRates(_Symbol, tf, 0, bars_count, rates) <= 0)
{
Print(__FUNCTION__, ": Failed to copy rates data (bars=", bars_count, ") err=", GetLastError());
return false;
}
// 必要なデータを配列に格納
for(int i = 0; i < ArraySize(rates); i++)
{
ArrayResize(open_prices, i + 1);
ArrayResize(high_prices, i + 1);
ArrayResize(low_prices, i + 1);
ArrayResize(close_prices, i + 1);
open_prices[i] = rates[i].open;
high_prices[i] = rates[i].high;
low_prices[i] = rates[i].low;
close_prices[i] = rates[i].close;
}
return true;
}
//+------------------------------------------------------------------+
//| "ohlc.csv"を出力する関数
//+------------------------------------------------------------------+
void RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[])
{
// 出力先ファイル名
// string filename = "ohlc.csv";
// ファイルを "書き込みモード" でオープン (テキスト/ANSI)
int fileHandle = FileOpen(filename, FILE_WRITE | FILE_TXT | FILE_ANSI);
// ファイルが開けたかチェック
if(fileHandle == INVALID_HANDLE)
{
Print(__FUNCTION__, " : Failed to open file: ", GetLastError());
return;
}
// 配列サイズを取得 (times, open, high, low, close の要素数は同じ前提)
int size = ArraySize(times);
// ヘッダー行を追加
FileWrite(fileHandle, "Time,Open,High,Low,Close");
// 小数点の桁数を取得
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
// フォーマット文字列を動的に生成
string formatString = StringFormat("%%s,%%.%df,%%.%df,%%.%df,%%.%df", digits, digits, digits, digits);
// 1行ずつ "時刻, Open, High, Low, Close" の形式で書き込み
for(int i = 0; i < size; i++)
{
// 時間をフォーマット
string timeStr = TimeToString(times[i], TIME_DATE | TIME_MINUTES);
// 1行分の文字列を生成 (小数点以下の桁数を `digits` に調整)
string line = StringFormat(formatString,
timeStr, open_prices[i], high_prices[i], low_prices[i], close_prices[i]);
// ファイルに書き込み (改行付き)
FileWrite(fileHandle, line);
}
// 書き込み終了後、ファイルを閉じる
FileClose(fileHandle);
}
//+------------------------------------------------------------------+
//| バッチファイル(Pythonスクリプト)を実行する関数
//+------------------------------------------------------------------+
void ExecuteBatchTrend()
{
if(CheckDoneFile(done_trend_file))
{
DeleteDoneFile(done_trend_file);
ShellExecuteW(0, "open", get_trend_reply_bat, "", "", 1);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ExecuteBatchEntry()
{
if(CheckDoneFile(done_entry_file))
{
DeleteDoneFile(done_entry_file);
ShellExecuteW(0, "open", get_entry_reply_bat, "", "", 1);
}
}
//+------------------------------------------------------------------+
//| "ohlc.csv"を出力後、バッチファイルの実行する関数
//+------------------------------------------------------------------+
bool RecordOHLCAndExecuteBatch_Trend(EAState &state)
{
datetime times[];
double open_prices[], high_prices[], low_prices[], close_prices[];
if(!GetLatestOHLC(times, open_prices, high_prices, low_prices, close_prices,
PERIOD_H4, HISTORY_BARS))
{ Print("GetLatestOHLC(H4) failed."); return false; }
RecordOHLC("ohlc_H4.csv", times, open_prices, high_prices, low_prices, close_prices);
ExecuteBatchTrend();
state.load_trend_flg = true;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool RecordOHLCAndExecuteBatch_Entry(EAState &state)
{
datetime times[];
double open_prices[], high_prices[], low_prices[], close_prices[];
if(!GetLatestOHLC(times, open_prices, high_prices, low_prices, close_prices,
PERIOD_H1, HISTORY_BARS))
{ Print("GetLatestOHLC(H1) failed."); return false; }
RecordOHLC("ohlc_H1.csv", times, open_prices, high_prices, low_prices, close_prices);
ExecuteBatchEntry();
state.load_target_flg = true;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool GetTrendState(EAState &state)
{
bool ProcessDone = CheckDoneFile(done_trend_file);
if(ProcessDone && g_ea.load_trend_flg)
{
int trend_state;
LoadTrendState(trend_state);
state.trend_state = trend_state;
Print("trend_state: ", state.trend_state);
g_ea.load_trend_flg = false;
g_ea.last_trend_update = TimeLocal();
}
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void LoadTrendState(int &trend_state)
{
string filename = "trend_state.txt";
if(FileIsExist(filename))
{
int filehandle = FileOpen(filename, FILE_READ | FILE_TXT);
if(filehandle != INVALID_HANDLE)
{
string line = FileReadString(filehandle);
trend_state = (int)StringToInteger(line);
FileClose(filehandle);
}
else
{ Print("Failed to open trend_state.txt"); trend_state = 0; }
}
else
{ Print("trend_state.txt not found"); trend_state = 0; }
}
//+------------------------------------------------------------------+
//| ターゲット価格を取得する関数
//+------------------------------------------------------------------+
bool GetTargetPrices(EAState &state)
{
bool ProcessDone = CheckDoneFile(done_entry_file); // ←変更
if(ProcessDone && g_ea.load_target_flg) // ←変更
{
double target_prices[];
LoadTargetPrices(target_prices);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
// 先頭は res_chk
state.res_chk = (int)target_prices[0];
// ★ 1..4 の (en,tp,sl) を読む:合計12個
for(int t=1; t<=4; t++)
{
int base = 1 + (t-1)*3; // 1,4,7,10
state.en_price[t] = NormalizeDouble(target_prices[base + 0], digits);
state.tp_price[t] = NormalizeDouble(target_prices[base + 1], digits);
state.sl_price[t] = NormalizeDouble(target_prices[base + 2], digits);
}
// ログ(任意)
Print("target_prices: res=", state.res_chk,
" | T1 en=", state.en_price[1], " tp=", state.tp_price[1], " sl=", state.sl_price[1],
" | T2 en=", state.en_price[2], " tp=", state.tp_price[2], " sl=", state.sl_price[2],
" | T3 en=", state.en_price[3], " tp=", state.tp_price[3], " sl=", state.sl_price[3],
" | T4 en=", state.en_price[4], " tp=", state.tp_price[4], " sl=", state.sl_price[4]);
g_ea.load_target_flg = false; // ←変更
g_ea.last_target_update = TimeLocal(); // ←変更
}
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| "target_prices.txt"を読み込む関数
//+------------------------------------------------------------------+
void LoadTargetPrices(double &target_prices[])
{
ArrayResize(target_prices, TARGET_SIZE);
string filename = "target_prices.txt";
if(FileIsExist(filename))
{
int filehandle = FileOpen(filename, FILE_READ | FILE_TXT);
if(filehandle != INVALID_HANDLE)
{
int i = 0;
while(!FileIsEnding(filehandle) && i < TARGET_SIZE)
{
string line = FileReadString(filehandle);
target_prices[i] = StringToDouble(line);
i++;
}
FileClose(filehandle);
}
else
{
Print("Failed to open file. Error code: ", GetLastError());
for(int i = 0; i < TARGET_SIZE; i++)
{
target_prices[i] = DEFAULT_TARGET_PRICE;
}
}
}
else
{
Print("File does not exist: ", filename);
for(int i = 0; i < TARGET_SIZE; i++)
{
target_prices[i] = DEFAULT_TARGET_PRICE;
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| エントリー注文を送信する関数 (1:buy-stop, 2:buy-limit, 3:sell-stop, 4:sell-limit)
//+------------------------------------------------------------------+
bool SendOrder(int orderType, double price, double tp, double sl)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.magic = magic_number;
request.symbol = _Symbol;
request.volume = lot_size;
request.deviation = slippage;
request.type_filling = GetOrderFillingPolicy(_Symbol);
request.price = NormalizeDouble(price, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
request.tp = NormalizeDouble(tp, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
request.sl = NormalizeDouble(sl, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
request.comment = RequestComment(orderType);
string orderTypeStr = "";
// 指値または逆指値注文
request.action = TRADE_ACTION_PENDING;
switch(orderType)
{
case 1: // 順張り買い (buy-stop)
request.type = ORDER_TYPE_BUY_STOP;
orderTypeStr = "buy-stop";
break;
case 2: // 逆張り買い (buy-limit)
request.type = ORDER_TYPE_BUY_LIMIT;
orderTypeStr = "buy-limit";
break;
case 3: // 順張り売り (sell-stop)
request.type = ORDER_TYPE_SELL_STOP;
orderTypeStr = "sell-stop";
break;
case 4: // 逆張り売り (sell-limit)
request.type = ORDER_TYPE_SELL_LIMIT;
orderTypeStr = "sell-limit";
break;
default: // 不正なorderType
Print(__FUNCTION__, ": invalid orderType=", orderType);
return false;
}
// 注文送信
if(!OrderSend(request, result))
{
Print(__FUNCTION__, ": OrderSend failed. err=", GetLastError());
return false;
}
// 注文成功確認
if(result.retcode == TRADE_RETCODE_PLACED ||
result.retcode == TRADE_RETCODE_DONE ||
result.retcode == TRADE_RETCODE_DONE_PARTIAL)
{
Print(request.comment + " - " + orderTypeStr + " order success (ticket=", result.order, ")");
return true;
}
else
{
Print(__FUNCTION__, ": OrderSend retcode=", result.retcode);
return false;
}
}
//+------------------------------------------------------------------+
//| 注文の執行ポリシーを取得する関数
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol)
{
long fill_mode = SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);
if((fill_mode & SYMBOL_FILLING_IOC) != 0)
return ORDER_FILLING_IOC;
if((fill_mode & SYMBOL_FILLING_FOK) != 0)
return ORDER_FILLING_FOK;
return ORDER_FILLING_RETURN;
}
//+------------------------------------------------------------------+
//| 注文コメント(ローカル時刻)を生成する関数(先頭に orderType を付与)
//+------------------------------------------------------------------+
string RequestComment(int orderType)
{
datetime localTime = TimeLocal();
string timeStr = TimeToString(localTime, TIME_DATE|TIME_MINUTES);
// 先頭に 1,2,3,4 を付ける(例: "1 | PC Time: 2026.02.14 19:05"
return IntegerToString(orderType) + " | PC Time: " + timeStr;
}
//+------------------------------------------------------------------+
//| 時間が経過したエントリー注文をキャンセルする関数
//+------------------------------------------------------------------+
bool CancelExpiredOrders()
{
bool result = false;
// 未決済注文の数を取得
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(OrderSelect(ticket)) // 注文を選択
{
if(OrderGetString(ORDER_SYMBOL) != _Symbol)
continue;
if(OrderGetInteger(ORDER_MAGIC) != magic_number)
continue;
datetime open_time = (datetime)OrderGetInteger(ORDER_TIME_SETUP);
int open_shift = GetBarShiftByTime(open_time, PERIOD_H1, -1); // H1
if(open_shift < 0)
continue; // 時刻解決できないなら触らない
if(open_shift >= ENTRY_H1_LIMIT) // H1本数(=1本 ≒ 1時間)
{
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
request.action=TRADE_ACTION_REMOVE; // 取引操作タイプ
request.order = ticket; // 注文チケット
if(!OrderSend(request, trade_result)) // 削除リクエスト送信
{
Print("Failed to delete order. Ticket: ", ticket, " Error: ", GetLastError());
}
else
{
if(trade_result.retcode == TRADE_RETCODE_DONE)
{
Print("Order canceled successfully due to a time limit. Ticket: ", ticket);
result = true; // 削除成功フラグ
}
else
{
Print("Order cancellation failed. Ticket: ", ticket, " Retcode: ", trade_result.retcode);
}
}
}
}
}
return result;
}
//+------------------------------------------------------------------+
//| 時間が経過したポジションをクローズする関数
//+------------------------------------------------------------------+
bool CloseExpiredPositions()
{
bool result = false;
// ポジションを逆順でループ
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string position_symbol = PositionGetSymbol(i);
if(position_symbol!="")
{
// Magic Number とシンボルでフィルタリング
if(position_symbol != _Symbol)
continue;
if(PositionGetInteger(POSITION_MAGIC) == magic_number)
{
// ポジションのエントリー時刻を取得
datetime entry_time = (datetime)PositionGetInteger(POSITION_TIME);
int entry_shift = GetBarShiftByTime(entry_time, PERIOD_H1, -1);
if(entry_shift < 0)
continue;
if(entry_shift >= CLOSE_H1_LIMIT) // H1本数(=12本 ≒ 12時間)
{
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
// ポジションタイプに応じてリクエストを設定
int position_type = (int)PositionGetInteger(POSITION_TYPE);
request.action = TRADE_ACTION_DEAL;
request.position = PositionGetInteger(POSITION_TICKET); // ポジションのチケット番号
request.symbol = position_symbol; // シンボル
request.volume = PositionGetDouble(POSITION_VOLUME); // ポジションサイズ
request.price = (position_type == POSITION_TYPE_BUY)
? SymbolInfoDouble(position_symbol, SYMBOL_BID) // BUYの場合はBIDでクローズ
: SymbolInfoDouble(position_symbol, SYMBOL_ASK); // SELLの場合はASKでクローズ
request.deviation = slippage;
request.type = (position_type == POSITION_TYPE_BUY)
? ORDER_TYPE_SELL // BUYポジションをSELLでクローズ
: ORDER_TYPE_BUY; // SELLポジションをBUYでクローズ
request.type_filling = GetOrderFillingPolicy(position_symbol); // 注文執行ポリシー
request.magic = magic_number;
// 注文送信
if(!OrderSend(request, trade_result))
{
Print("Failed to close position. Ticket: ", request.position, " Error: ", GetLastError());
continue;
}
// 結果の確認
if(trade_result.retcode == TRADE_RETCODE_DONE || trade_result.retcode == TRADE_RETCODE_DONE_PARTIAL)
{
Print("Position closed successfully due to a time limit. Ticket: ", request.position);
result = true; // 少なくとも1つ成功した場合
}
else
{
Print("Failed to close position. Ticket: ", request.position, " Retcode: ", trade_result.retcode);
}
}
}
}
else
{
Print("Failed to select position at index ", i, ". Error: ", GetLastError());
}
}
return result;
}
//+------------------------------------------------------------------+
//| 指定された時間に最も近いバーのインデックスを返す関数
//+------------------------------------------------------------------+
int GetBarShiftByTime(datetime time, ENUM_TIMEFRAMES tf, int default_shift = -1)
{
if(time <= 0)
return default_shift;
int shift = iBarShift(_Symbol, tf, time, false); // 近傍バーで解決する
if(shift < 0)
return default_shift;
return shift;
}
//+------------------------------------------------------------------+
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-441
View File
@@ -1,441 +0,0 @@
//+------------------------------------------------------------------+
//| HIT_EA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.01"
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Panel/SLTPManagerPanel.mqh>
//+------------------------------------------------------------------+
//| バッチファイル実行用の設定
//+------------------------------------------------------------------+
// Windowsプロセス起動・終了確認用
#define CREATE_NO_WINDOW 0x08000000
#define PROCESS_QUERY_LIMITED_INFORMATION 0x00001000
#define SYNCHRONIZE 0x00100000
#define WAIT_OBJECT_0 0
#define WAIT_TIMEOUT 258
#define STILL_ACTIVE 259
struct STARTUPINFO_W
{
uint cb;
string lpReserved;
string lpDesktop;
string lpTitle;
uint dwX;
uint dwY;
uint dwXSize;
uint dwYSize;
uint dwXCountChars;
uint dwYCountChars;
uint dwFillAttribute;
uint dwFlags;
ushort wShowWindow;
ushort cbReserved2;
long lpReserved2;
long hStdInput;
long hStdOutput;
long hStdError;
};
struct PROCESS_INFORMATION
{
long hProcess;
long hThread;
uint dwProcessId;
uint dwThreadId;
};
#import "kernel32.dll"
int CreateProcessW(string lpApplicationName, string lpCommandLine, long lpProcessAttributes, long lpThreadAttributes, int bInheritHandles, uint dwCreationFlags, long lpEnvironment, string lpCurrentDirectory, STARTUPINFO_W &lpStartupInfo, PROCESS_INFORMATION &lpProcessInformation);
int WaitForSingleObject(long hHandle, uint dwMilliseconds);
int GetExitCodeProcess(long hProcess, uint &lpExitCode);
int CloseHandle(long hObject);
long OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
#import
// バッチファイルのパス
string get_trend_reply_bat = "C:\\ea_py\\bat\\get_trend_reply.bat"; // H4: trend
string get_entry_reply_bat = "C:\\ea_py\\bat\\get_entry_reply.bat"; // H1: entry
// プロセス完了ファイルの設定
string done_trend_file = "process_done_trend.txt";
string done_entry_file = "process_done_entry.txt";
// Python出力ファイル
string trend_state_file = "trend_state.txt";
string target_prices_file = "target_prices.txt";
// Python実行中を判定するための管理ファイル
string running_trend_file = "process_running_trend.txt";
string running_entry_file = "process_running_entry.txt";
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| インプットの設定
//+------------------------------------------------------------------+
//--- 入力パラメータ
input double lot_size = 0.01; // ロット数
input double spread_limit = 60; // 許容スプレッド(point)
input int magic_number = 10001; // マジックナンバー
input int initial_order = 0; // 起動時の注文(0:なし, 1:あり)
input bool use_m15_entry_filter = true; // M15確定足で発注タイミングを確認
input double m15_entry_zone_atr_multiplier = 1.50; // M15平均レンジ何本分まで候補価格への接近を許可
input bool use_m15_imbalance_confirmation = true; // T1/T3でM15初動確認を追加
input int m15_imbalance_avg_body_period = 20; // M15平均実体計算期間
input double m15_imbalance_sensitivity = 2.0; // M15初動検知感度
input double m15_imbalance_min_avg_body_points = 1.0; // 平均実体の最小値(point)
input bool use_m15_imbalance_debug_log = false; // M15初動確認ログ
input int input_entry_max_candidate_age_minutes = 45; // H1候補価格を新規発注に使う最大経過分数
input bool input_sltp_manager_enabled = false; // UI連動SLTP管理を有効化
input bool input_sltp_show_panel = true; // SLTP操作パネルを表示
input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化
input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips
input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips
input bool input_sltp_use_elapsed_breakeven = false; // 保有時間BEを有効化
input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間
input double input_sltp_elapsed_breakeven_buffer_pips = 3.0; // 保有時間BE固定バッファpips
input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化
input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips
input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips
input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips
input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips
input bool input_sltp_use_tp_progress_stop = false; // TP進捗SLを有効化
input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率
input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率
input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化
ulong slippage = 10; // スリッページ
//--- 主要な定数・設定
#define POSITION_LIMIT 48
#define ENTRY_H1_LIMIT 1 // H1本数(=1時間)
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
#define HISTORY_BARS 72
#define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す
#define M15_CONFIRM_BARS 30
#define M15_MIN_ENTRY_ZONE_POINTS 10
#define M15_MIN_BODY_RATIO 0.25
#define M15_REJECTION_WICK_RATIO 0.35
#define ENTRY_RETRY_SECONDS 60
#define ENTRY_RETRY_LIMIT 10
// ANALYZE_TIMEFRAME は削除(H4/H1 両方使うため定数ではなく直接指定)
#define TARGET_SIZE 13
#define DEFAULT_TARGET_PRICE 0.0
#define PYTHON_TIMEOUT_SECONDS 600 // Python完了待ちの上限(秒)
#define MARKET_LOW_VOL_RANGE 0
#define MARKET_HIGH_VOL_RANGE 1
#define MARKET_LOW_VOL_UP 2
#define MARKET_HIGH_VOL_UP 3
#define MARKET_LOW_VOL_DOWN 4
#define MARKET_HIGH_VOL_DOWN 5
#define MARKET_TECHNICAL_ERROR_STOP 6
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| EAの状態をまとめる構造体
//+------------------------------------------------------------------+
struct EAState
{
int trend_state; // H4 market_state0..5、6は技術エラー停止)を格納する変数
int res_chk; // GPTの回答が正しく取得できたか
double en_price[5]; // エントリー基準価格
double tp_price[5]; // 利益確定価格
double sl_price[5]; // ロスカット基準価格
bool load_trend_flg; // ★変更:トレンドを更新するタイミングか
bool load_target_flg; // ★変更:ターゲット価格を更新するタイミングか
int chk_cnt; // エントリー判定の試行回数
datetime last_trend_update; // ★追加:前回トレンドを更新した時刻
datetime last_target_update; // ★変更:前回ターゲット価格を更新した時刻
datetime target_loaded_at; // H1候補価格をEAへ読み込んだサーバー時刻
datetime last_chk;
};
EAState g_ea; // EA全体の状態をここで管理
// initial_order 用の初回処理フラグ
// H4トレンド処理とH1エントリー処理で別々に管理し、初回起動時の再実行ループを防ぐ。
bool g_init_trend_pending = false;
bool g_init_entry_pending = false;
// H4/H1のバー更新状態
int g_pre_bars_H4 = 0;
int g_pre_bars_H1 = 0;
int g_pre_bars_M15 = 0;
bool g_bars_H1_check = false;
bool g_bars_M15_check = false;
// ティックごとの価格情報
struct TickContext
{
double ask;
double bid;
double spread;
double spread_points;
int digits;
};
// 外部Pythonプロセスの状態
struct ExternalProcessState
{
long handle;
uint process_id;
bool active;
bool exit_code_ready;
uint exit_code;
datetime started_at;
};
ExternalProcessState g_trend_process;
ExternalProcessState g_entry_process;
CSLTPManager g_sltp_manager;
CSLTPManagerPanel g_sltp_panel;
SLTPManagerPanelSettings g_sltp_settings;
bool g_sltp_settings_valid = false;
bool g_sltp_panel_created = false;
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
/**
* @brief EA起動時の初期化処理を行います。
*
* Python連携用のdone/runningファイル状態を確認し、`initial_order` が有効な場合は
* H4トレンド判定とH1エントリー価格生成をそれぞれ初回実行対象にします。
* H4/H1の初回フラグを分けることで、起動直後にH4処理だけが繰り返される状態を防ぎます。
*/
int OnInit()
// プロセス完了ファイルと実行中ファイルの状態を初期化
{
PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend");
PrepareDoneFileOnInit(done_entry_file, running_entry_file, "entry");
// initial_order=1 の場合でも、H4/H1を別々に1回だけ初回実行する。
g_init_trend_pending = (initial_order == 1);
g_init_entry_pending = (initial_order == 1);
if(!InitializeSLTPManager())
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| 終了時の処理
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ResetExternalProcessState(g_trend_process);
ResetExternalProcessState(g_entry_process);
if(g_sltp_panel_created)
g_sltp_panel.Destroy(reason);
// Clear chart status text left by Comment() when the EA is removed.
Comment("");
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| ティック毎の処理
//+------------------------------------------------------------------+
/**
* @brief ティック受信ごとにEA全体の処理を制御します。
*
* 処理順序は、ティック情報取得、期限切れ注文/ポジション管理、H4トレンド更新、
* H1エントリー価格更新、M15エントリータイミング更新、ステータス表示、新規注文判定の順です。
* 時間制限処理はPython完了待ちやスプレッド判定より前に実行します。
*/
void OnTick()
{
TickContext ctx;
if(!GetTickContext(ctx))
return;
// 期限切れ注文・ポジションは、Python待ちやスプレッド制限に関係なく先に処理する。
ManageExpiredTrades();
// Existing-position protection stays active even while Python results are pending.
ManageSLTPPositions();
// 外部Pythonがdoneを返さない場合に、一定時間で待機状態を解除して再実行対象にする。
RecoverTimedOutPythonProcesses();
// H4新バーまたは初回起動時に、トレンド判定用Pythonを起動する。
ProcessTrendUpdate(g_ea);
// トレンド判定が完了していない場合、新規注文側の処理だけをスキップする。
if(!IsTrendResultReady())
return;
RefreshTrendState(g_ea);
// H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。
ProcessEntryUpdate(g_ea);
// M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。
ProcessM15EntryTimingUpdate();
UpdateStatusComment(ctx);
// ここから下は新規注文に関する処理。
if(!IsSpreadAllowed(ctx))
return;
if(!IsEntryResultReady())
return;
RefreshTargetPrices(g_ea);
ProcessEntryDecisionIfNeeded(g_ea, ctx);
}
//+------------------------------------------------------------------+
//| SLTP manager panel and settings bridge
//+------------------------------------------------------------------+
string SLTPBoolText(const bool value)
{
return value ? "ON" : "OFF";
}
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
{
settings.manager_enabled = input_sltp_manager_enabled;
settings.use_breakeven = input_sltp_use_breakeven;
settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips;
settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips;
settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven;
settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours;
settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips;
settings.use_active_trailing = input_sltp_use_active_trailing;
settings.active_breakeven_pips = input_sltp_active_breakeven_pips;
settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips;
settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips;
settings.active_step_move_pips = input_sltp_active_step_move_pips;
settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop;
settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent;
settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent;
settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit;
}
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
const bool print_summary)
{
g_sltp_settings_valid = false;
g_sltp_manager.SetMagicNumber((ulong)magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(slippage);
g_sltp_manager.SetBreakevenSettings(settings.use_breakeven,
settings.breakeven_trigger_pips,
settings.breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven,
settings.elapsed_breakeven_hours,
settings.elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing,
settings.active_breakeven_pips,
settings.active_stop_loss_offset_pips,
settings.active_step_trigger_pips,
settings.active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop,
settings.tp_progress_trigger_percent,
settings.tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit);
if(!g_sltp_manager.ValidateSettings())
{
Print("HIT SLTP settings rejected. Manager is disabled until valid settings are applied.");
return false;
}
g_sltp_settings = settings;
g_sltp_settings_valid = true;
if(print_summary)
{
Print("HIT SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled),
" BE=", SLTPBoolText(settings.use_breakeven),
" ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven),
" ActiveTrail=", SLTPBoolText(settings.use_active_trailing),
" TPProgress=", SLTPBoolText(settings.use_tp_progress_stop),
" HighVol=", SLTPBoolText(settings.use_high_volatility_limit));
}
return true;
}
bool InitializeSLTPManager()
{
SLTPManagerPanelSettings initial_settings;
LoadSLTPInputSettings(initial_settings);
if(!ApplySLTPSettings(initial_settings, true))
return false;
g_sltp_panel.Init(g_sltp_settings);
if(input_sltp_show_panel)
{
if(!g_sltp_panel.CreatePanel())
{
Print("HIT SLTP panel is unavailable. EA continues with input-based SLTP settings.");
return true;
}
g_sltp_panel.SetInitialValues();
g_sltp_panel_created = true;
}
return true;
}
void ManageSLTPPositions()
{
if(!g_sltp_settings_valid)
return;
if(!g_sltp_settings.manager_enabled)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(!g_sltp_panel_created)
return;
SLTPManagerPanelSettings candidate_settings = g_sltp_settings;
if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings))
{
if(!ApplySLTPSettings(candidate_settings, true))
Print("HIT SLTP panel apply failed. Please review panel values.");
}
}
// Function implementations are kept in project headers so the EA entry points stay compact.
#include <MyLib/Common/HITRuntimeController.mqh>
#include <MyLib/Signals/HITEntrySignal.mqh>
#include <MyLib/Common/HITExternalProcess.mqh>
#include <MyLib/Signals/HITPythonSignalGateway.mqh>
#include <MyLib/Trading/HITTradeManager.mqh>
@@ -1,440 +0,0 @@
//+------------------------------------------------------------------+
//| HIT_EA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.01"
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Panel/SLTPManagerPanel.mqh>
//+------------------------------------------------------------------+
//| バッチファイル実行用の設定
//+------------------------------------------------------------------+
// Windowsプロセス起動・終了確認用
#define CREATE_NO_WINDOW 0x08000000
#define PROCESS_QUERY_LIMITED_INFORMATION 0x00001000
#define SYNCHRONIZE 0x00100000
#define WAIT_OBJECT_0 0
#define WAIT_TIMEOUT 258
#define STILL_ACTIVE 259
struct STARTUPINFO_W
{
uint cb;
string lpReserved;
string lpDesktop;
string lpTitle;
uint dwX;
uint dwY;
uint dwXSize;
uint dwYSize;
uint dwXCountChars;
uint dwYCountChars;
uint dwFillAttribute;
uint dwFlags;
ushort wShowWindow;
ushort cbReserved2;
long lpReserved2;
long hStdInput;
long hStdOutput;
long hStdError;
};
struct PROCESS_INFORMATION
{
long hProcess;
long hThread;
uint dwProcessId;
uint dwThreadId;
};
#import "kernel32.dll"
int CreateProcessW(string lpApplicationName, string lpCommandLine, long lpProcessAttributes, long lpThreadAttributes, int bInheritHandles, uint dwCreationFlags, long lpEnvironment, string lpCurrentDirectory, STARTUPINFO_W &lpStartupInfo, PROCESS_INFORMATION &lpProcessInformation);
int WaitForSingleObject(long hHandle, uint dwMilliseconds);
int GetExitCodeProcess(long hProcess, uint &lpExitCode);
int CloseHandle(long hObject);
long OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
#import
// バッチファイルのパス
string get_trend_reply_bat = "C:\\ea_py\\bat\\get_trend_reply.bat"; // H4: trend
string get_entry_reply_bat = "C:\\ea_py\\bat\\get_entry_reply.bat"; // H1: entry
// プロセス完了ファイルの設定
string done_trend_file = "process_done_trend.txt";
string done_entry_file = "process_done_entry.txt";
// Python出力ファイル
string trend_state_file = "trend_state.txt";
string target_prices_file = "target_prices.txt";
// Python実行中を判定するための管理ファイル
string running_trend_file = "process_running_trend.txt";
string running_entry_file = "process_running_entry.txt";
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| インプットの設定
//+------------------------------------------------------------------+
//--- 入力パラメータ
input double lot_size = 0.01; // ロット数
input double spread_limit = 60; // 許容スプレッド(point)
input int magic_number = 10001; // マジックナンバー
input int initial_order = 0; // 起動時の注文(0:なし, 1:あり)
input bool use_m15_entry_filter = true; // M15確定足で発注タイミングを確認
input double m15_entry_zone_atr_multiplier = 1.50; // M15平均レンジ何本分まで候補価格への接近を許可
input bool use_m15_imbalance_confirmation = true; // T1/T3でM15初動確認を追加
input int m15_imbalance_avg_body_period = 20; // M15平均実体計算期間
input double m15_imbalance_sensitivity = 2.0; // M15初動検知感度
input double m15_imbalance_min_avg_body_points = 1.0; // 平均実体の最小値(point)
input bool use_m15_imbalance_debug_log = false; // M15初動確認ログ
input bool input_sltp_manager_enabled = false; // UI連動SLTP管理を有効化
input bool input_sltp_show_panel = true; // SLTP操作パネルを表示
input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化
input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips
input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips
input bool input_sltp_use_elapsed_breakeven = false; // 保有時間BEを有効化
input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間
input double input_sltp_elapsed_breakeven_buffer_pips = 3.0; // 保有時間BE固定バッファpips
input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化
input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips
input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips
input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips
input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips
input bool input_sltp_use_tp_progress_stop = false; // TP進捗SLを有効化
input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率
input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率
input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化
ulong slippage = 10; // スリッページ
//--- 主要な定数・設定
#define POSITION_LIMIT 48
#define ENTRY_H1_LIMIT 1 // H1本数(=1時間)
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
#define HISTORY_BARS 72
#define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す
#define M15_CONFIRM_BARS 30
#define M15_MIN_ENTRY_ZONE_POINTS 10
#define M15_MIN_BODY_RATIO 0.25
#define M15_REJECTION_WICK_RATIO 0.35
#define ENTRY_RETRY_SECONDS 60
#define ENTRY_RETRY_LIMIT 10
// ANALYZE_TIMEFRAME は削除(H4/H1 両方使うため定数ではなく直接指定)
#define TARGET_SIZE 13
#define DEFAULT_TARGET_PRICE 0.0
#define PYTHON_TIMEOUT_SECONDS 600 // Python完了待ちの上限(秒)
#define MARKET_LOW_VOL_RANGE 0
#define MARKET_HIGH_VOL_RANGE 1
#define MARKET_LOW_VOL_UP 2
#define MARKET_HIGH_VOL_UP 3
#define MARKET_LOW_VOL_DOWN 4
#define MARKET_HIGH_VOL_DOWN 5
#define MARKET_TECHNICAL_ERROR_STOP 6
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| EAの状態をまとめる構造体
//+------------------------------------------------------------------+
struct EAState
{
int trend_state; // H4 market_state0..5、6は技術エラー停止)を格納する変数
int res_chk; // GPTの回答が正しく取得できたか
double en_price[5]; // エントリー基準価格
double tp_price[5]; // 利益確定価格
double sl_price[5]; // ロスカット基準価格
bool load_trend_flg; // ★変更:トレンドを更新するタイミングか
bool load_target_flg; // ★変更:ターゲット価格を更新するタイミングか
int chk_cnt; // エントリー判定の試行回数
datetime last_trend_update; // ★追加:前回トレンドを更新した時刻
datetime last_target_update; // ★変更:前回ターゲット価格を更新した時刻
datetime target_loaded_at; // H1候補価格をEAへ読み込んだサーバー時刻
datetime last_chk;
};
EAState g_ea; // EA全体の状態をここで管理
// initial_order 用の初回処理フラグ
// H4トレンド処理とH1エントリー処理で別々に管理し、初回起動時の再実行ループを防ぐ。
bool g_init_trend_pending = false;
bool g_init_entry_pending = false;
// H4/H1のバー更新状態
int g_pre_bars_H4 = 0;
int g_pre_bars_H1 = 0;
int g_pre_bars_M15 = 0;
bool g_bars_H1_check = false;
bool g_bars_M15_check = false;
// ティックごとの価格情報
struct TickContext
{
double ask;
double bid;
double spread;
double spread_points;
int digits;
};
// 外部Pythonプロセスの状態
struct ExternalProcessState
{
long handle;
uint process_id;
bool active;
bool exit_code_ready;
uint exit_code;
datetime started_at;
};
ExternalProcessState g_trend_process;
ExternalProcessState g_entry_process;
CSLTPManager g_sltp_manager;
CSLTPManagerPanel g_sltp_panel;
SLTPManagerPanelSettings g_sltp_settings;
bool g_sltp_settings_valid = false;
bool g_sltp_panel_created = false;
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
/**
* @brief EA起動時の初期化処理を行います。
*
* Python連携用のdone/runningファイル状態を確認し、`initial_order` が有効な場合は
* H4トレンド判定とH1エントリー価格生成をそれぞれ初回実行対象にします。
* H4/H1の初回フラグを分けることで、起動直後にH4処理だけが繰り返される状態を防ぎます。
*/
int OnInit()
// プロセス完了ファイルと実行中ファイルの状態を初期化
{
PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend");
PrepareDoneFileOnInit(done_entry_file, running_entry_file, "entry");
// initial_order=1 の場合でも、H4/H1を別々に1回だけ初回実行する。
g_init_trend_pending = (initial_order == 1);
g_init_entry_pending = (initial_order == 1);
if(!InitializeSLTPManager())
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| 終了時の処理
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ResetExternalProcessState(g_trend_process);
ResetExternalProcessState(g_entry_process);
if(g_sltp_panel_created)
g_sltp_panel.Destroy(reason);
// Clear chart status text left by Comment() when the EA is removed.
Comment("");
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| ティック毎の処理
//+------------------------------------------------------------------+
/**
* @brief ティック受信ごとにEA全体の処理を制御します。
*
* 処理順序は、ティック情報取得、期限切れ注文/ポジション管理、H4トレンド更新、
* H1エントリー価格更新、M15エントリータイミング更新、ステータス表示、新規注文判定の順です。
* 時間制限処理はPython完了待ちやスプレッド判定より前に実行します。
*/
void OnTick()
{
TickContext ctx;
if(!GetTickContext(ctx))
return;
// 期限切れ注文・ポジションは、Python待ちやスプレッド制限に関係なく先に処理する。
ManageExpiredTrades();
// Existing-position protection stays active even while Python results are pending.
ManageSLTPPositions();
// 外部Pythonがdoneを返さない場合に、一定時間で待機状態を解除して再実行対象にする。
RecoverTimedOutPythonProcesses();
// H4新バーまたは初回起動時に、トレンド判定用Pythonを起動する。
ProcessTrendUpdate(g_ea);
// トレンド判定が完了していない場合、新規注文側の処理だけをスキップする。
if(!IsTrendResultReady())
return;
RefreshTrendState(g_ea);
// H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。
ProcessEntryUpdate(g_ea);
// M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。
ProcessM15EntryTimingUpdate();
UpdateStatusComment(ctx);
// ここから下は新規注文に関する処理。
if(!IsSpreadAllowed(ctx))
return;
if(!IsEntryResultReady())
return;
RefreshTargetPrices(g_ea);
ProcessEntryDecisionIfNeeded(g_ea, ctx);
}
//+------------------------------------------------------------------+
//| SLTP manager panel and settings bridge
//+------------------------------------------------------------------+
string SLTPBoolText(const bool value)
{
return value ? "ON" : "OFF";
}
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
{
settings.manager_enabled = input_sltp_manager_enabled;
settings.use_breakeven = input_sltp_use_breakeven;
settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips;
settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips;
settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven;
settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours;
settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips;
settings.use_active_trailing = input_sltp_use_active_trailing;
settings.active_breakeven_pips = input_sltp_active_breakeven_pips;
settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips;
settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips;
settings.active_step_move_pips = input_sltp_active_step_move_pips;
settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop;
settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent;
settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent;
settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit;
}
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
const bool print_summary)
{
g_sltp_settings_valid = false;
g_sltp_manager.SetMagicNumber((ulong)magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(slippage);
g_sltp_manager.SetBreakevenSettings(settings.use_breakeven,
settings.breakeven_trigger_pips,
settings.breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven,
settings.elapsed_breakeven_hours,
settings.elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing,
settings.active_breakeven_pips,
settings.active_stop_loss_offset_pips,
settings.active_step_trigger_pips,
settings.active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop,
settings.tp_progress_trigger_percent,
settings.tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit);
if(!g_sltp_manager.ValidateSettings())
{
Print("HIT SLTP settings rejected. Manager is disabled until valid settings are applied.");
return false;
}
g_sltp_settings = settings;
g_sltp_settings_valid = true;
if(print_summary)
{
Print("HIT SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled),
" BE=", SLTPBoolText(settings.use_breakeven),
" ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven),
" ActiveTrail=", SLTPBoolText(settings.use_active_trailing),
" TPProgress=", SLTPBoolText(settings.use_tp_progress_stop),
" HighVol=", SLTPBoolText(settings.use_high_volatility_limit));
}
return true;
}
bool InitializeSLTPManager()
{
SLTPManagerPanelSettings initial_settings;
LoadSLTPInputSettings(initial_settings);
if(!ApplySLTPSettings(initial_settings, true))
return false;
g_sltp_panel.Init(g_sltp_settings);
if(input_sltp_show_panel)
{
if(!g_sltp_panel.CreatePanel())
{
Print("HIT SLTP panel is unavailable. EA continues with input-based SLTP settings.");
return true;
}
g_sltp_panel.SetInitialValues();
g_sltp_panel_created = true;
}
return true;
}
void ManageSLTPPositions()
{
if(!g_sltp_settings_valid)
return;
if(!g_sltp_settings.manager_enabled)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(!g_sltp_panel_created)
return;
SLTPManagerPanelSettings candidate_settings = g_sltp_settings;
if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings))
{
if(!ApplySLTPSettings(candidate_settings, true))
Print("HIT SLTP panel apply failed. Please review panel values.");
}
}
// Function implementations are kept in project headers so the EA entry points stay compact.
#include <MyLib/Common/HITRuntimeController.mqh>
#include <MyLib/Signals/HITEntrySignal.mqh>
#include <MyLib/Common/HITExternalProcess.mqh>
#include <MyLib/Signals/HITPythonSignalGateway.mqh>
#include <MyLib/Trading/HITTradeManager.mqh>
@@ -1,441 +0,0 @@
//+------------------------------------------------------------------+
//| HIT_EA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.01"
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Panel/SLTPManagerPanel.mqh>
//+------------------------------------------------------------------+
//| バッチファイル実行用の設定
//+------------------------------------------------------------------+
// Windowsプロセス起動・終了確認用
#define CREATE_NO_WINDOW 0x08000000
#define PROCESS_QUERY_LIMITED_INFORMATION 0x00001000
#define SYNCHRONIZE 0x00100000
#define WAIT_OBJECT_0 0
#define WAIT_TIMEOUT 258
#define STILL_ACTIVE 259
struct STARTUPINFO_W
{
uint cb;
string lpReserved;
string lpDesktop;
string lpTitle;
uint dwX;
uint dwY;
uint dwXSize;
uint dwYSize;
uint dwXCountChars;
uint dwYCountChars;
uint dwFillAttribute;
uint dwFlags;
ushort wShowWindow;
ushort cbReserved2;
long lpReserved2;
long hStdInput;
long hStdOutput;
long hStdError;
};
struct PROCESS_INFORMATION
{
long hProcess;
long hThread;
uint dwProcessId;
uint dwThreadId;
};
#import "kernel32.dll"
int CreateProcessW(string lpApplicationName, string lpCommandLine, long lpProcessAttributes, long lpThreadAttributes, int bInheritHandles, uint dwCreationFlags, long lpEnvironment, string lpCurrentDirectory, STARTUPINFO_W &lpStartupInfo, PROCESS_INFORMATION &lpProcessInformation);
int WaitForSingleObject(long hHandle, uint dwMilliseconds);
int GetExitCodeProcess(long hProcess, uint &lpExitCode);
int CloseHandle(long hObject);
long OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
#import
// バッチファイルのパス
string get_trend_reply_bat = "C:\\ea_py\\bat\\get_trend_reply.bat"; // H4: trend
string get_entry_reply_bat = "C:\\ea_py\\bat\\get_entry_reply.bat"; // H1: entry
// プロセス完了ファイルの設定
string done_trend_file = "process_done_trend.txt";
string done_entry_file = "process_done_entry.txt";
// Python出力ファイル
string trend_state_file = "trend_state.txt";
string target_prices_file = "target_prices.txt";
// Python実行中を判定するための管理ファイル
string running_trend_file = "process_running_trend.txt";
string running_entry_file = "process_running_entry.txt";
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| インプットの設定
//+------------------------------------------------------------------+
//--- 入力パラメータ
input double lot_size = 0.01; // ロット数
input double spread_limit = 60; // 許容スプレッド(point)
input int magic_number = 10001; // マジックナンバー
input int initial_order = 0; // 起動時の注文(0:なし, 1:あり)
input bool use_m15_entry_filter = true; // M15確定足で発注タイミングを確認
input double m15_entry_zone_atr_multiplier = 1.50; // M15平均レンジ何本分まで候補価格への接近を許可
input bool use_m15_imbalance_confirmation = true; // T1/T3でM15初動確認を追加
input int m15_imbalance_avg_body_period = 20; // M15平均実体計算期間
input double m15_imbalance_sensitivity = 2.0; // M15初動検知感度
input double m15_imbalance_min_avg_body_points = 1.0; // 平均実体の最小値(point)
input bool use_m15_imbalance_debug_log = false; // M15初動確認ログ
input int input_entry_max_candidate_age_minutes = 45; // H1候補価格を新規発注に使う最大経過分数
input bool input_sltp_manager_enabled = false; // UI連動SLTP管理を有効化
input bool input_sltp_show_panel = true; // SLTP操作パネルを表示
input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化
input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips
input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips
input bool input_sltp_use_elapsed_breakeven = false; // 保有時間BEを有効化
input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間
input double input_sltp_elapsed_breakeven_buffer_pips = 3.0; // 保有時間BE固定バッファpips
input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化
input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips
input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips
input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips
input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips
input bool input_sltp_use_tp_progress_stop = false; // TP進捗SLを有効化
input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率
input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率
input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化
ulong slippage = 10; // スリッページ
//--- 主要な定数・設定
#define POSITION_LIMIT 48
#define ENTRY_H1_LIMIT 1 // H1本数(=1時間)
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
#define HISTORY_BARS 72
#define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す
#define M15_CONFIRM_BARS 30
#define M15_MIN_ENTRY_ZONE_POINTS 10
#define M15_MIN_BODY_RATIO 0.25
#define M15_REJECTION_WICK_RATIO 0.35
#define ENTRY_RETRY_SECONDS 60
#define ENTRY_RETRY_LIMIT 10
// ANALYZE_TIMEFRAME は削除(H4/H1 両方使うため定数ではなく直接指定)
#define TARGET_SIZE 13
#define DEFAULT_TARGET_PRICE 0.0
#define PYTHON_TIMEOUT_SECONDS 600 // Python完了待ちの上限(秒)
#define MARKET_LOW_VOL_RANGE 0
#define MARKET_HIGH_VOL_RANGE 1
#define MARKET_LOW_VOL_UP 2
#define MARKET_HIGH_VOL_UP 3
#define MARKET_LOW_VOL_DOWN 4
#define MARKET_HIGH_VOL_DOWN 5
#define MARKET_TECHNICAL_ERROR_STOP 6
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| EAの状態をまとめる構造体
//+------------------------------------------------------------------+
struct EAState
{
int trend_state; // H4 market_state0..5、6は技術エラー停止)を格納する変数
int res_chk; // GPTの回答が正しく取得できたか
double en_price[5]; // エントリー基準価格
double tp_price[5]; // 利益確定価格
double sl_price[5]; // ロスカット基準価格
bool load_trend_flg; // ★変更:トレンドを更新するタイミングか
bool load_target_flg; // ★変更:ターゲット価格を更新するタイミングか
int chk_cnt; // エントリー判定の試行回数
datetime last_trend_update; // ★追加:前回トレンドを更新した時刻
datetime last_target_update; // ★変更:前回ターゲット価格を更新した時刻
datetime target_loaded_at; // H1候補価格をEAへ読み込んだサーバー時刻
datetime last_chk;
};
EAState g_ea; // EA全体の状態をここで管理
// initial_order 用の初回処理フラグ
// H4トレンド処理とH1エントリー処理で別々に管理し、初回起動時の再実行ループを防ぐ。
bool g_init_trend_pending = false;
bool g_init_entry_pending = false;
// H4/H1のバー更新状態
int g_pre_bars_H4 = 0;
int g_pre_bars_H1 = 0;
int g_pre_bars_M15 = 0;
bool g_bars_H1_check = false;
bool g_bars_M15_check = false;
// ティックごとの価格情報
struct TickContext
{
double ask;
double bid;
double spread;
double spread_points;
int digits;
};
// 外部Pythonプロセスの状態
struct ExternalProcessState
{
long handle;
uint process_id;
bool active;
bool exit_code_ready;
uint exit_code;
datetime started_at;
};
ExternalProcessState g_trend_process;
ExternalProcessState g_entry_process;
CSLTPManager g_sltp_manager;
CSLTPManagerPanel g_sltp_panel;
SLTPManagerPanelSettings g_sltp_settings;
bool g_sltp_settings_valid = false;
bool g_sltp_panel_created = false;
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
/**
* @brief EA起動時の初期化処理を行います。
*
* Python連携用のdone/runningファイル状態を確認し、`initial_order` が有効な場合は
* H4トレンド判定とH1エントリー価格生成をそれぞれ初回実行対象にします。
* H4/H1の初回フラグを分けることで、起動直後にH4処理だけが繰り返される状態を防ぎます。
*/
int OnInit()
// プロセス完了ファイルと実行中ファイルの状態を初期化
{
PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend");
PrepareDoneFileOnInit(done_entry_file, running_entry_file, "entry");
// initial_order=1 の場合でも、H4/H1を別々に1回だけ初回実行する。
g_init_trend_pending = (initial_order == 1);
g_init_entry_pending = (initial_order == 1);
if(!InitializeSLTPManager())
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| 終了時の処理
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ResetExternalProcessState(g_trend_process);
ResetExternalProcessState(g_entry_process);
if(g_sltp_panel_created)
g_sltp_panel.Destroy(reason);
// Clear chart status text left by Comment() when the EA is removed.
Comment("");
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| ティック毎の処理
//+------------------------------------------------------------------+
/**
* @brief ティック受信ごとにEA全体の処理を制御します。
*
* 処理順序は、ティック情報取得、期限切れ注文/ポジション管理、H4トレンド更新、
* H1エントリー価格更新、M15エントリータイミング更新、ステータス表示、新規注文判定の順です。
* 時間制限処理はPython完了待ちやスプレッド判定より前に実行します。
*/
void OnTick()
{
TickContext ctx;
if(!GetTickContext(ctx))
return;
// 期限切れ注文・ポジションは、Python待ちやスプレッド制限に関係なく先に処理する。
ManageExpiredTrades();
// Existing-position protection stays active even while Python results are pending.
ManageSLTPPositions();
// 外部Pythonがdoneを返さない場合に、一定時間で待機状態を解除して再実行対象にする。
RecoverTimedOutPythonProcesses();
// H4新バーまたは初回起動時に、トレンド判定用Pythonを起動する。
ProcessTrendUpdate(g_ea);
// トレンド判定が完了していない場合、新規注文側の処理だけをスキップする。
if(!IsTrendResultReady())
return;
RefreshTrendState(g_ea);
// H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。
ProcessEntryUpdate(g_ea);
// M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。
ProcessM15EntryTimingUpdate();
UpdateStatusComment(ctx);
// ここから下は新規注文に関する処理。
if(!IsSpreadAllowed(ctx))
return;
if(!IsEntryResultReady())
return;
RefreshTargetPrices(g_ea);
ProcessEntryDecisionIfNeeded(g_ea, ctx);
}
//+------------------------------------------------------------------+
//| SLTP manager panel and settings bridge
//+------------------------------------------------------------------+
string SLTPBoolText(const bool value)
{
return value ? "ON" : "OFF";
}
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
{
settings.manager_enabled = input_sltp_manager_enabled;
settings.use_breakeven = input_sltp_use_breakeven;
settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips;
settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips;
settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven;
settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours;
settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips;
settings.use_active_trailing = input_sltp_use_active_trailing;
settings.active_breakeven_pips = input_sltp_active_breakeven_pips;
settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips;
settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips;
settings.active_step_move_pips = input_sltp_active_step_move_pips;
settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop;
settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent;
settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent;
settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit;
}
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
const bool print_summary)
{
g_sltp_settings_valid = false;
g_sltp_manager.SetMagicNumber((ulong)magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(slippage);
g_sltp_manager.SetBreakevenSettings(settings.use_breakeven,
settings.breakeven_trigger_pips,
settings.breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven,
settings.elapsed_breakeven_hours,
settings.elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing,
settings.active_breakeven_pips,
settings.active_stop_loss_offset_pips,
settings.active_step_trigger_pips,
settings.active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop,
settings.tp_progress_trigger_percent,
settings.tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit);
if(!g_sltp_manager.ValidateSettings())
{
Print("HIT SLTP settings rejected. Manager is disabled until valid settings are applied.");
return false;
}
g_sltp_settings = settings;
g_sltp_settings_valid = true;
if(print_summary)
{
Print("HIT SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled),
" BE=", SLTPBoolText(settings.use_breakeven),
" ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven),
" ActiveTrail=", SLTPBoolText(settings.use_active_trailing),
" TPProgress=", SLTPBoolText(settings.use_tp_progress_stop),
" HighVol=", SLTPBoolText(settings.use_high_volatility_limit));
}
return true;
}
bool InitializeSLTPManager()
{
SLTPManagerPanelSettings initial_settings;
LoadSLTPInputSettings(initial_settings);
if(!ApplySLTPSettings(initial_settings, true))
return false;
g_sltp_panel.Init(g_sltp_settings);
if(input_sltp_show_panel)
{
if(!g_sltp_panel.CreatePanel())
{
Print("HIT SLTP panel is unavailable. EA continues with input-based SLTP settings.");
return true;
}
g_sltp_panel.SetInitialValues();
g_sltp_panel_created = true;
}
return true;
}
void ManageSLTPPositions()
{
if(!g_sltp_settings_valid)
return;
if(!g_sltp_settings.manager_enabled)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(!g_sltp_panel_created)
return;
SLTPManagerPanelSettings candidate_settings = g_sltp_settings;
if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings))
{
if(!ApplySLTPSettings(candidate_settings, true))
Print("HIT SLTP panel apply failed. Please review panel values.");
}
}
// Function implementations are kept in project headers so the EA entry points stay compact.
#include <MyLib/Common/HITRuntimeController.mqh>
#include <MyLib/Signals/HITEntrySignal.mqh>
#include <MyLib/Common/HITExternalProcess.mqh>
#include <MyLib/Signals/HITPythonSignalGateway.mqh>
#include <MyLib/Trading/HITTradeManager.mqh>
@@ -1,441 +0,0 @@
//+------------------------------------------------------------------+
//| HIT_EA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.01"
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Panel/SLTPManagerPanel.mqh>
//+------------------------------------------------------------------+
//| バッチファイル実行用の設定
//+------------------------------------------------------------------+
// Windowsプロセス起動・終了確認用
#define CREATE_NO_WINDOW 0x08000000
#define PROCESS_QUERY_LIMITED_INFORMATION 0x00001000
#define SYNCHRONIZE 0x00100000
#define WAIT_OBJECT_0 0
#define WAIT_TIMEOUT 258
#define STILL_ACTIVE 259
struct STARTUPINFO_W
{
uint cb;
string lpReserved;
string lpDesktop;
string lpTitle;
uint dwX;
uint dwY;
uint dwXSize;
uint dwYSize;
uint dwXCountChars;
uint dwYCountChars;
uint dwFillAttribute;
uint dwFlags;
ushort wShowWindow;
ushort cbReserved2;
long lpReserved2;
long hStdInput;
long hStdOutput;
long hStdError;
};
struct PROCESS_INFORMATION
{
long hProcess;
long hThread;
uint dwProcessId;
uint dwThreadId;
};
#import "kernel32.dll"
int CreateProcessW(string lpApplicationName, string lpCommandLine, long lpProcessAttributes, long lpThreadAttributes, int bInheritHandles, uint dwCreationFlags, long lpEnvironment, string lpCurrentDirectory, STARTUPINFO_W &lpStartupInfo, PROCESS_INFORMATION &lpProcessInformation);
int WaitForSingleObject(long hHandle, uint dwMilliseconds);
int GetExitCodeProcess(long hProcess, uint &lpExitCode);
int CloseHandle(long hObject);
long OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
#import
// バッチファイルのパス
string get_trend_reply_bat = "C:\\ea_py\\bat\\get_trend_reply.bat"; // H4: trend
string get_entry_reply_bat = "C:\\ea_py\\bat\\get_entry_reply.bat"; // H1: entry
// プロセス完了ファイルの設定
string done_trend_file = "process_done_trend.txt";
string done_entry_file = "process_done_entry.txt";
// Python出力ファイル
string trend_state_file = "trend_state.txt";
string target_prices_file = "target_prices.txt";
// Python実行中を判定するための管理ファイル
string running_trend_file = "process_running_trend.txt";
string running_entry_file = "process_running_entry.txt";
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| インプットの設定
//+------------------------------------------------------------------+
//--- 入力パラメータ
input double lot_size = 0.01; // ロット数
input double spread_limit = 60; // 許容スプレッド(point)
input int magic_number = 10001; // マジックナンバー
input int initial_order = 0; // 起動時の注文(0:なし, 1:あり)
input bool use_m15_entry_filter = true; // M15確定足で発注タイミングを確認
input double m15_entry_zone_atr_multiplier = 1.50; // M15平均レンジ何本分まで候補価格への接近を許可
input bool use_m15_imbalance_confirmation = true; // T1/T3でM15初動確認を追加
input int m15_imbalance_avg_body_period = 20; // M15平均実体計算期間
input double m15_imbalance_sensitivity = 2.0; // M15初動検知感度
input double m15_imbalance_min_avg_body_points = 1.0; // 平均実体の最小値(point)
input bool use_m15_imbalance_debug_log = false; // M15初動確認ログ
input int input_entry_max_candidate_age_minutes = 45; // H1候補価格を新規発注に使う最大経過分数
input bool input_sltp_manager_enabled = false; // UI連動SLTP管理を有効化
input bool input_sltp_show_panel = true; // SLTP操作パネルを表示
input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化
input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips
input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips
input bool input_sltp_use_elapsed_breakeven = false; // 保有時間BEを有効化
input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間
input double input_sltp_elapsed_breakeven_buffer_pips = 3.0; // 保有時間BE固定バッファpips
input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化
input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips
input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips
input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips
input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips
input bool input_sltp_use_tp_progress_stop = false; // TP進捗SLを有効化
input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率
input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率
input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化
ulong slippage = 10; // スリッページ
//--- 主要な定数・設定
#define POSITION_LIMIT 48
#define ENTRY_H1_LIMIT 1 // H1本数(=1時間)
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
#define HISTORY_BARS 72
#define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す
#define M15_CONFIRM_BARS 30
#define M15_MIN_ENTRY_ZONE_POINTS 10
#define M15_MIN_BODY_RATIO 0.25
#define M15_REJECTION_WICK_RATIO 0.35
#define ENTRY_RETRY_SECONDS 60
#define ENTRY_RETRY_LIMIT 10
// ANALYZE_TIMEFRAME は削除(H4/H1 両方使うため定数ではなく直接指定)
#define TARGET_SIZE 13
#define DEFAULT_TARGET_PRICE 0.0
#define PYTHON_TIMEOUT_SECONDS 600 // Python完了待ちの上限(秒)
#define MARKET_LOW_VOL_RANGE 0
#define MARKET_HIGH_VOL_RANGE 1
#define MARKET_LOW_VOL_UP 2
#define MARKET_HIGH_VOL_UP 3
#define MARKET_LOW_VOL_DOWN 4
#define MARKET_HIGH_VOL_DOWN 5
#define MARKET_TECHNICAL_ERROR_STOP 6
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| EAの状態をまとめる構造体
//+------------------------------------------------------------------+
struct EAState
{
int trend_state; // H4 market_state0..5、6は技術エラー停止)を格納する変数
int res_chk; // GPTの回答が正しく取得できたか
double en_price[5]; // エントリー基準価格
double tp_price[5]; // 利益確定価格
double sl_price[5]; // ロスカット基準価格
bool load_trend_flg; // ★変更:トレンドを更新するタイミングか
bool load_target_flg; // ★変更:ターゲット価格を更新するタイミングか
int chk_cnt; // エントリー判定の試行回数
datetime last_trend_update; // ★追加:前回トレンドを更新した時刻
datetime last_target_update; // ★変更:前回ターゲット価格を更新した時刻
datetime target_loaded_at; // H1候補価格をEAへ読み込んだサーバー時刻
datetime last_chk;
};
EAState g_ea; // EA全体の状態をここで管理
// initial_order 用の初回処理フラグ
// H4トレンド処理とH1エントリー処理で別々に管理し、初回起動時の再実行ループを防ぐ。
bool g_init_trend_pending = false;
bool g_init_entry_pending = false;
// H4/H1のバー更新状態
int g_pre_bars_H4 = 0;
int g_pre_bars_H1 = 0;
int g_pre_bars_M15 = 0;
bool g_bars_H1_check = false;
bool g_bars_M15_check = false;
// ティックごとの価格情報
struct TickContext
{
double ask;
double bid;
double spread;
double spread_points;
int digits;
};
// 外部Pythonプロセスの状態
struct ExternalProcessState
{
long handle;
uint process_id;
bool active;
bool exit_code_ready;
uint exit_code;
datetime started_at;
};
ExternalProcessState g_trend_process;
ExternalProcessState g_entry_process;
CSLTPManager g_sltp_manager;
CSLTPManagerPanel g_sltp_panel;
SLTPManagerPanelSettings g_sltp_settings;
bool g_sltp_settings_valid = false;
bool g_sltp_panel_created = false;
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
/**
* @brief EA起動時の初期化処理を行います。
*
* Python連携用のdone/runningファイル状態を確認し、`initial_order` が有効な場合は
* H4トレンド判定とH1エントリー価格生成をそれぞれ初回実行対象にします。
* H4/H1の初回フラグを分けることで、起動直後にH4処理だけが繰り返される状態を防ぎます。
*/
int OnInit()
// プロセス完了ファイルと実行中ファイルの状態を初期化
{
PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend");
PrepareDoneFileOnInit(done_entry_file, running_entry_file, "entry");
// initial_order=1 の場合でも、H4/H1を別々に1回だけ初回実行する。
g_init_trend_pending = (initial_order == 1);
g_init_entry_pending = (initial_order == 1);
if(!InitializeSLTPManager())
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| 終了時の処理
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ResetExternalProcessState(g_trend_process);
ResetExternalProcessState(g_entry_process);
if(g_sltp_panel_created)
g_sltp_panel.Destroy(reason);
// Clear chart status text left by Comment() when the EA is removed.
Comment("");
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| ティック毎の処理
//+------------------------------------------------------------------+
/**
* @brief ティック受信ごとにEA全体の処理を制御します。
*
* 処理順序は、ティック情報取得、期限切れ注文/ポジション管理、H4トレンド更新、
* H1エントリー価格更新、M15エントリータイミング更新、ステータス表示、新規注文判定の順です。
* 時間制限処理はPython完了待ちやスプレッド判定より前に実行します。
*/
void OnTick()
{
TickContext ctx;
if(!GetTickContext(ctx))
return;
// 期限切れ注文・ポジションは、Python待ちやスプレッド制限に関係なく先に処理する。
ManageExpiredTrades();
// Existing-position protection stays active even while Python results are pending.
ManageSLTPPositions();
// 外部Pythonがdoneを返さない場合に、一定時間で待機状態を解除して再実行対象にする。
RecoverTimedOutPythonProcesses();
// H4新バーまたは初回起動時に、トレンド判定用Pythonを起動する。
ProcessTrendUpdate(g_ea);
// トレンド判定が完了していない場合、新規注文側の処理だけをスキップする。
if(!IsTrendResultReady())
return;
RefreshTrendState(g_ea);
// H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。
ProcessEntryUpdate(g_ea);
// M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。
ProcessM15EntryTimingUpdate();
UpdateStatusComment(ctx);
// ここから下は新規注文に関する処理。
if(!IsSpreadAllowed(ctx))
return;
if(!IsEntryResultReady())
return;
RefreshTargetPrices(g_ea);
ProcessEntryDecisionIfNeeded(g_ea, ctx);
}
//+------------------------------------------------------------------+
//| SLTP manager panel and settings bridge
//+------------------------------------------------------------------+
string SLTPBoolText(const bool value)
{
return value ? "ON" : "OFF";
}
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
{
settings.manager_enabled = input_sltp_manager_enabled;
settings.use_breakeven = input_sltp_use_breakeven;
settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips;
settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips;
settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven;
settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours;
settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips;
settings.use_active_trailing = input_sltp_use_active_trailing;
settings.active_breakeven_pips = input_sltp_active_breakeven_pips;
settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips;
settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips;
settings.active_step_move_pips = input_sltp_active_step_move_pips;
settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop;
settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent;
settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent;
settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit;
}
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
const bool print_summary)
{
g_sltp_settings_valid = false;
g_sltp_manager.SetMagicNumber((ulong)magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(slippage);
g_sltp_manager.SetBreakevenSettings(settings.use_breakeven,
settings.breakeven_trigger_pips,
settings.breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven,
settings.elapsed_breakeven_hours,
settings.elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing,
settings.active_breakeven_pips,
settings.active_stop_loss_offset_pips,
settings.active_step_trigger_pips,
settings.active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop,
settings.tp_progress_trigger_percent,
settings.tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit);
if(!g_sltp_manager.ValidateSettings())
{
Print("HIT SLTP settings rejected. Manager is disabled until valid settings are applied.");
return false;
}
g_sltp_settings = settings;
g_sltp_settings_valid = true;
if(print_summary)
{
Print("HIT SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled),
" BE=", SLTPBoolText(settings.use_breakeven),
" ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven),
" ActiveTrail=", SLTPBoolText(settings.use_active_trailing),
" TPProgress=", SLTPBoolText(settings.use_tp_progress_stop),
" HighVol=", SLTPBoolText(settings.use_high_volatility_limit));
}
return true;
}
bool InitializeSLTPManager()
{
SLTPManagerPanelSettings initial_settings;
LoadSLTPInputSettings(initial_settings);
if(!ApplySLTPSettings(initial_settings, true))
return false;
g_sltp_panel.Init(g_sltp_settings);
if(input_sltp_show_panel)
{
if(!g_sltp_panel.CreatePanel())
{
Print("HIT SLTP panel is unavailable. EA continues with input-based SLTP settings.");
return true;
}
g_sltp_panel.SetInitialValues();
g_sltp_panel_created = true;
}
return true;
}
void ManageSLTPPositions()
{
if(!g_sltp_settings_valid)
return;
if(!g_sltp_settings.manager_enabled)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(!g_sltp_panel_created)
return;
SLTPManagerPanelSettings candidate_settings = g_sltp_settings;
if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings))
{
if(!ApplySLTPSettings(candidate_settings, true))
Print("HIT SLTP panel apply failed. Please review panel values.");
}
}
// Function implementations are kept in project headers so the EA entry points stay compact.
#include <MyLib/Common/HITRuntimeController.mqh>
#include <MyLib/Signals/HITEntrySignal.mqh>
#include <MyLib/Common/HITExternalProcess.mqh>
#include <MyLib/Signals/HITPythonSignalGateway.mqh>
#include <MyLib/Trading/HITTradeManager.mqh>
@@ -1,462 +0,0 @@
//+------------------------------------------------------------------+
//| HIT_EA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.01"
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Panel/SLTPManagerPanel.mqh>
//+------------------------------------------------------------------+
//| バッチファイル実行用の設定
//+------------------------------------------------------------------+
// Windowsプロセス起動・終了確認用
#define CREATE_NO_WINDOW 0x08000000
#define PROCESS_QUERY_LIMITED_INFORMATION 0x00001000
#define SYNCHRONIZE 0x00100000
#define WAIT_OBJECT_0 0
#define WAIT_TIMEOUT 258
#define STILL_ACTIVE 259
struct STARTUPINFO_W
{
uint cb;
string lpReserved;
string lpDesktop;
string lpTitle;
uint dwX;
uint dwY;
uint dwXSize;
uint dwYSize;
uint dwXCountChars;
uint dwYCountChars;
uint dwFillAttribute;
uint dwFlags;
ushort wShowWindow;
ushort cbReserved2;
long lpReserved2;
long hStdInput;
long hStdOutput;
long hStdError;
};
struct PROCESS_INFORMATION
{
long hProcess;
long hThread;
uint dwProcessId;
uint dwThreadId;
};
#import "kernel32.dll"
int CreateProcessW(string lpApplicationName, string lpCommandLine, long lpProcessAttributes, long lpThreadAttributes, int bInheritHandles, uint dwCreationFlags, long lpEnvironment, string lpCurrentDirectory, STARTUPINFO_W &lpStartupInfo, PROCESS_INFORMATION &lpProcessInformation);
int WaitForSingleObject(long hHandle, uint dwMilliseconds);
int GetExitCodeProcess(long hProcess, uint &lpExitCode);
int CloseHandle(long hObject);
long OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
#import
// バッチファイルのパス
string get_trend_reply_bat = "C:\\ea_py\\bat\\get_trend_reply.bat"; // H4: trend
string get_entry_reply_bat = "C:\\ea_py\\bat\\get_entry_reply.bat"; // H1: entry
// プロセス完了ファイルの設定
string done_trend_file = "process_done_trend.txt";
string done_entry_file = "process_done_entry.txt";
// Python出力ファイル
string trend_state_file = "trend_state.txt";
string target_prices_file = "target_prices.txt";
string target_zones_file = "target_zones.txt";
// Python実行中を判定するための管理ファイル
string running_trend_file = "process_running_trend.txt";
string running_entry_file = "process_running_entry.txt";
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| インプットの設定
//+------------------------------------------------------------------+
enum SplitLotMode
{
SPLIT_LOT_TOTAL = 0, // 総ロットをN分割
SPLIT_LOT_FIXED = 1 // 1注文あたり固定ロット
};
//--- 入力パラメータ
input double lot_size = 0.01; // ロット数
input double spread_limit = 60; // 許容スプレッド(point)
input int magic_number = 10001; // マジックナンバー
input int initial_order = 0; // 起動時の注文(0:なし, 1:あり)
input int input_position_limit = 10; // 自EAの未約定注文+ポジション上限
input bool use_split_entry_zone = false; // H1予測ゾーンで分割エントリーする
input int split_entry_count = 3; // 分割エントリー本数(1..10)
input SplitLotMode split_lot_mode = SPLIT_LOT_TOTAL; // 分割ロット配分モード
input double split_total_lot_size = 0.09; // 総量分割モードの合計ロット
input double split_fixed_lot_size = 0.01; // 固定ロットモードの1注文ロット
input bool cancel_old_split_pending_on_new_zone = true; // 新ゾーン読込時に旧分割pendingを取消
input bool use_m15_entry_filter = true; // M15確定足で発注タイミングを確認
input double m15_entry_zone_atr_multiplier = 1.50; // M15平均レンジ何本分まで候補価格への接近を許可
input bool use_m15_imbalance_confirmation = true; // T1/T3でM15初動確認を追加
input int m15_imbalance_avg_body_period = 20; // M15平均実体計算期間
input double m15_imbalance_sensitivity = 2.0; // M15初動検知感度
input double m15_imbalance_min_avg_body_points = 1.0; // 平均実体の最小値(point)
input bool use_m15_imbalance_debug_log = false; // M15初動確認ログ
input int input_entry_max_candidate_age_minutes = 45; // H1候補価格を新規発注に使う最大経過分数
input bool input_sltp_manager_enabled = false; // UI連動SLTP管理を有効化
input bool input_sltp_show_panel = true; // SLTP操作パネルを表示
input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化
input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips
input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips
input bool input_sltp_use_elapsed_breakeven = false; // 保有時間BEを有効化
input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間
input double input_sltp_elapsed_breakeven_buffer_pips = 3.0; // 保有時間BE固定バッファpips
input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化
input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips
input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips
input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips
input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips
input bool input_sltp_use_tp_progress_stop = false; // TP進捗SLを有効化
input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率
input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率
input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化
ulong slippage = 10; // スリッページ
//--- 主要な定数・設定
#define POSITION_LIMIT 48
#define ENTRY_H1_LIMIT 1 // H1本数(=1時間)
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
#define HISTORY_BARS 72
#define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す
#define M15_CONFIRM_BARS 30
#define M15_MIN_ENTRY_ZONE_POINTS 10
#define M15_MIN_BODY_RATIO 0.25
#define M15_REJECTION_WICK_RATIO 0.35
#define ENTRY_RETRY_SECONDS 60
#define ENTRY_RETRY_LIMIT 10
// ANALYZE_TIMEFRAME は削除(H4/H1 両方使うため定数ではなく直接指定)
#define TARGET_SIZE 13
#define TARGET_ZONE_SCHEMA_VERSION 2
#define DEFAULT_TARGET_PRICE 0.0
#define PYTHON_TIMEOUT_SECONDS 600 // Python完了待ちの上限(秒)
#define MARKET_LOW_VOL_RANGE 0
#define MARKET_HIGH_VOL_RANGE 1
#define MARKET_LOW_VOL_UP 2
#define MARKET_HIGH_VOL_UP 3
#define MARKET_LOW_VOL_DOWN 4
#define MARKET_HIGH_VOL_DOWN 5
#define MARKET_TECHNICAL_ERROR_STOP 6
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| EAの状態をまとめる構造体
//+------------------------------------------------------------------+
struct EAState
{
int trend_state; // H4 market_state0..5、6は技術エラー停止)を格納する変数
int res_chk; // GPTの回答が正しく取得できたか
double en_price[5]; // エントリー基準価格
double tp_price[5]; // 利益確定価格
double sl_price[5]; // ロスカット基準価格
int zone_res_chk; // 予測ゾーンが正しく取得できたか
string zone_candidate_id; // H1確定足由来の候補ID
double zone_low[5]; // 分割エントリー用ゾーン下限
double zone_high[5]; // 分割エントリー用ゾーン上限
double zone_tp[5]; // 分割エントリー用TP
double zone_sl[5]; // 分割エントリー用SL
bool load_trend_flg; // ★変更:トレンドを更新するタイミングか
bool load_target_flg; // ★変更:ターゲット価格を更新するタイミングか
int chk_cnt; // エントリー判定の試行回数
datetime last_trend_update; // ★追加:前回トレンドを更新した時刻
datetime last_target_update; // ★変更:前回ターゲット価格を更新した時刻
datetime target_loaded_at; // H1候補価格をEAへ読み込んだサーバー時刻
datetime last_chk;
};
EAState g_ea; // EA全体の状態をここで管理
// initial_order 用の初回処理フラグ
// H4トレンド処理とH1エントリー処理で別々に管理し、初回起動時の再実行ループを防ぐ。
bool g_init_trend_pending = false;
bool g_init_entry_pending = false;
// H4/H1のバー更新状態
int g_pre_bars_H4 = 0;
int g_pre_bars_H1 = 0;
int g_pre_bars_M15 = 0;
bool g_bars_H1_check = false;
bool g_bars_M15_check = false;
// ティックごとの価格情報
struct TickContext
{
double ask;
double bid;
double spread;
double spread_points;
int digits;
};
// 外部Pythonプロセスの状態
struct ExternalProcessState
{
long handle;
uint process_id;
bool active;
bool exit_code_ready;
uint exit_code;
datetime started_at;
};
ExternalProcessState g_trend_process;
ExternalProcessState g_entry_process;
CSLTPManager g_sltp_manager;
CSLTPManagerPanel g_sltp_panel;
SLTPManagerPanelSettings g_sltp_settings;
bool g_sltp_settings_valid = false;
bool g_sltp_panel_created = false;
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
/**
* @brief EA起動時の初期化処理を行います。
*
* Python連携用のdone/runningファイル状態を確認し、`initial_order` が有効な場合は
* H4トレンド判定とH1エントリー価格生成をそれぞれ初回実行対象にします。
* H4/H1の初回フラグを分けることで、起動直後にH4処理だけが繰り返される状態を防ぎます。
*/
int OnInit()
// プロセス完了ファイルと実行中ファイルの状態を初期化
{
PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend");
PrepareDoneFileOnInit(done_entry_file, running_entry_file, "entry");
// initial_order=1 の場合でも、H4/H1を別々に1回だけ初回実行する。
g_init_trend_pending = (initial_order == 1);
g_init_entry_pending = (initial_order == 1);
if(!InitializeSLTPManager())
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| 終了時の処理
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ResetExternalProcessState(g_trend_process);
ResetExternalProcessState(g_entry_process);
if(g_sltp_panel_created)
g_sltp_panel.Destroy(reason);
// Clear chart status text left by Comment() when the EA is removed.
Comment("");
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| ティック毎の処理
//+------------------------------------------------------------------+
/**
* @brief ティック受信ごとにEA全体の処理を制御します。
*
* 処理順序は、ティック情報取得、期限切れ注文/ポジション管理、H4トレンド更新、
* H1エントリー価格更新、M15エントリータイミング更新、ステータス表示、新規注文判定の順です。
* 時間制限処理はPython完了待ちやスプレッド判定より前に実行します。
*/
void OnTick()
{
TickContext ctx;
if(!GetTickContext(ctx))
return;
// 期限切れ注文・ポジションは、Python待ちやスプレッド制限に関係なく先に処理する。
ManageExpiredTrades();
// Existing-position protection stays active even while Python results are pending.
ManageSLTPPositions();
// 外部Pythonがdoneを返さない場合に、一定時間で待機状態を解除して再実行対象にする。
RecoverTimedOutPythonProcesses();
// H4新バーまたは初回起動時に、トレンド判定用Pythonを起動する。
ProcessTrendUpdate(g_ea);
// トレンド判定が完了していない場合、新規注文側の処理だけをスキップする。
if(!IsTrendResultReady())
return;
RefreshTrendState(g_ea);
// H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。
ProcessEntryUpdate(g_ea);
// M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。
ProcessM15EntryTimingUpdate();
UpdateStatusComment(ctx);
// ここから下は新規注文に関する処理。
if(!IsSpreadAllowed(ctx))
return;
if(!IsEntryResultReady())
return;
RefreshTargetPrices(g_ea);
ProcessEntryDecisionIfNeeded(g_ea, ctx);
}
//+------------------------------------------------------------------+
//| SLTP manager panel and settings bridge
//+------------------------------------------------------------------+
string SLTPBoolText(const bool value)
{
return value ? "ON" : "OFF";
}
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
{
settings.manager_enabled = input_sltp_manager_enabled;
settings.use_breakeven = input_sltp_use_breakeven;
settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips;
settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips;
settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven;
settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours;
settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips;
settings.use_active_trailing = input_sltp_use_active_trailing;
settings.active_breakeven_pips = input_sltp_active_breakeven_pips;
settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips;
settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips;
settings.active_step_move_pips = input_sltp_active_step_move_pips;
settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop;
settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent;
settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent;
settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit;
}
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
const bool print_summary)
{
g_sltp_settings_valid = false;
g_sltp_manager.SetMagicNumber((ulong)magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(slippage);
g_sltp_manager.SetBreakevenSettings(settings.use_breakeven,
settings.breakeven_trigger_pips,
settings.breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven,
settings.elapsed_breakeven_hours,
settings.elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing,
settings.active_breakeven_pips,
settings.active_stop_loss_offset_pips,
settings.active_step_trigger_pips,
settings.active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop,
settings.tp_progress_trigger_percent,
settings.tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit);
if(!g_sltp_manager.ValidateSettings())
{
Print("HIT SLTP settings rejected. Manager is disabled until valid settings are applied.");
return false;
}
g_sltp_settings = settings;
g_sltp_settings_valid = true;
if(print_summary)
{
Print("HIT SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled),
" BE=", SLTPBoolText(settings.use_breakeven),
" ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven),
" ActiveTrail=", SLTPBoolText(settings.use_active_trailing),
" TPProgress=", SLTPBoolText(settings.use_tp_progress_stop),
" HighVol=", SLTPBoolText(settings.use_high_volatility_limit));
}
return true;
}
bool InitializeSLTPManager()
{
SLTPManagerPanelSettings initial_settings;
LoadSLTPInputSettings(initial_settings);
if(!ApplySLTPSettings(initial_settings, true))
return false;
g_sltp_panel.Init(g_sltp_settings);
if(input_sltp_show_panel)
{
if(!g_sltp_panel.CreatePanel())
{
Print("HIT SLTP panel is unavailable. EA continues with input-based SLTP settings.");
return true;
}
g_sltp_panel.SetInitialValues();
g_sltp_panel_created = true;
}
return true;
}
void ManageSLTPPositions()
{
if(!g_sltp_settings_valid)
return;
if(!g_sltp_settings.manager_enabled)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(!g_sltp_panel_created)
return;
SLTPManagerPanelSettings candidate_settings = g_sltp_settings;
if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings))
{
if(!ApplySLTPSettings(candidate_settings, true))
Print("HIT SLTP panel apply failed. Please review panel values.");
}
}
// Function implementations are kept in project headers so the EA entry points stay compact.
#include <MyLib/Common/HITRuntimeController.mqh>
#include <MyLib/Signals/HITEntrySignal.mqh>
#include <MyLib/Common/HITExternalProcess.mqh>
#include <MyLib/Signals/HITPythonSignalGateway.mqh>
#include <MyLib/Trading/HITTradeManager.mqh>
@@ -1,462 +0,0 @@
//+------------------------------------------------------------------+
//| HIT_EA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.01"
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Panel/SLTPManagerPanel.mqh>
//+------------------------------------------------------------------+
//| バッチファイル実行用の設定
//+------------------------------------------------------------------+
// Windowsプロセス起動・終了確認用
#define CREATE_NO_WINDOW 0x08000000
#define PROCESS_QUERY_LIMITED_INFORMATION 0x00001000
#define SYNCHRONIZE 0x00100000
#define WAIT_OBJECT_0 0
#define WAIT_TIMEOUT 258
#define STILL_ACTIVE 259
struct STARTUPINFO_W
{
uint cb;
string lpReserved;
string lpDesktop;
string lpTitle;
uint dwX;
uint dwY;
uint dwXSize;
uint dwYSize;
uint dwXCountChars;
uint dwYCountChars;
uint dwFillAttribute;
uint dwFlags;
ushort wShowWindow;
ushort cbReserved2;
long lpReserved2;
long hStdInput;
long hStdOutput;
long hStdError;
};
struct PROCESS_INFORMATION
{
long hProcess;
long hThread;
uint dwProcessId;
uint dwThreadId;
};
#import "kernel32.dll"
int CreateProcessW(string lpApplicationName, string lpCommandLine, long lpProcessAttributes, long lpThreadAttributes, int bInheritHandles, uint dwCreationFlags, long lpEnvironment, string lpCurrentDirectory, STARTUPINFO_W &lpStartupInfo, PROCESS_INFORMATION &lpProcessInformation);
int WaitForSingleObject(long hHandle, uint dwMilliseconds);
int GetExitCodeProcess(long hProcess, uint &lpExitCode);
int CloseHandle(long hObject);
long OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
#import
// バッチファイルのパス
string get_trend_reply_bat = "C:\\ea_py\\bat\\get_trend_reply.bat"; // H4: trend
string get_entry_reply_bat = "C:\\ea_py\\bat\\get_entry_reply.bat"; // H1: entry
// プロセス完了ファイルの設定
string done_trend_file = "process_done_trend.txt";
string done_entry_file = "process_done_entry.txt";
// Python出力ファイル
string trend_state_file = "trend_state.txt";
string target_prices_file = "target_prices.txt";
string target_zones_file = "target_zones.txt";
// Python実行中を判定するための管理ファイル
string running_trend_file = "process_running_trend.txt";
string running_entry_file = "process_running_entry.txt";
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| インプットの設定
//+------------------------------------------------------------------+
enum SplitLotMode
{
SPLIT_LOT_TOTAL = 0, // 総ロットをN分割
SPLIT_LOT_FIXED = 1 // 1注文あたり固定ロット
};
//--- 入力パラメータ
input double lot_size = 0.01; // ロット数
input double spread_limit = 60; // 許容スプレッド(point)
input int magic_number = 10001; // マジックナンバー
input int initial_order = 0; // 起動時の注文(0:なし, 1:あり)
input int input_position_limit = 10; // 自EAの未約定注文+ポジション上限
input bool use_split_entry_zone = false; // H1予測ゾーンで分割エントリーする
input int split_entry_count = 3; // 分割エントリー本数(1..10)
input SplitLotMode split_lot_mode = SPLIT_LOT_TOTAL; // 分割ロット配分モード
input double split_total_lot_size = 0.09; // 総量分割モードの合計ロット
input double split_fixed_lot_size = 0.01; // 固定ロットモードの1注文ロット
input bool cancel_old_split_pending_on_new_zone = true; // 新ゾーン読込時に旧分割pendingを取消
input bool use_m15_entry_filter = true; // M15確定足で発注タイミングを確認
input double m15_entry_zone_atr_multiplier = 1.50; // M15平均レンジ何本分まで候補価格への接近を許可
input bool use_m15_imbalance_confirmation = true; // T1/T3でM15初動確認を追加
input int m15_imbalance_avg_body_period = 20; // M15平均実体計算期間
input double m15_imbalance_sensitivity = 2.0; // M15初動検知感度
input double m15_imbalance_min_avg_body_points = 1.0; // 平均実体の最小値(point)
input bool use_m15_imbalance_debug_log = false; // M15初動確認ログ
input int input_entry_max_candidate_age_minutes = 120; // H1候補価格を新規発注に使う最大経過分数
input bool input_sltp_manager_enabled = false; // UI連動SLTP管理を有効化
input bool input_sltp_show_panel = true; // SLTP操作パネルを表示
input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化
input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips
input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips
input bool input_sltp_use_elapsed_breakeven = false; // 保有時間BEを有効化
input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間
input double input_sltp_elapsed_breakeven_buffer_pips = 3.0; // 保有時間BE固定バッファpips
input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化
input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips
input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips
input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips
input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips
input bool input_sltp_use_tp_progress_stop = false; // TP進捗SLを有効化
input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率
input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率
input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化
ulong slippage = 10; // スリッページ
//--- 主要な定数・設定
#define POSITION_LIMIT 48
#define ENTRY_H1_LIMIT 2 // H1本数(=2時間)
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
#define HISTORY_BARS 72
#define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す
#define M15_CONFIRM_BARS 30
#define M15_MIN_ENTRY_ZONE_POINTS 10
#define M15_MIN_BODY_RATIO 0.25
#define M15_REJECTION_WICK_RATIO 0.35
#define ENTRY_RETRY_SECONDS 60
#define ENTRY_RETRY_LIMIT 10
// ANALYZE_TIMEFRAME は削除(H4/H1 両方使うため定数ではなく直接指定)
#define TARGET_SIZE 13
#define TARGET_ZONE_SCHEMA_VERSION 2
#define DEFAULT_TARGET_PRICE 0.0
#define PYTHON_TIMEOUT_SECONDS 600 // Python完了待ちの上限(秒)
#define MARKET_LOW_VOL_RANGE 0
#define MARKET_HIGH_VOL_RANGE 1
#define MARKET_LOW_VOL_UP 2
#define MARKET_HIGH_VOL_UP 3
#define MARKET_LOW_VOL_DOWN 4
#define MARKET_HIGH_VOL_DOWN 5
#define MARKET_TECHNICAL_ERROR_STOP 6
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| EAの状態をまとめる構造体
//+------------------------------------------------------------------+
struct EAState
{
int trend_state; // H4 market_state0..5、6は技術エラー停止)を格納する変数
int res_chk; // GPTの回答が正しく取得できたか
double en_price[5]; // エントリー基準価格
double tp_price[5]; // 利益確定価格
double sl_price[5]; // ロスカット基準価格
int zone_res_chk; // 予測ゾーンが正しく取得できたか
string zone_candidate_id; // H1確定足由来の候補ID
double zone_low[5]; // 分割エントリー用ゾーン下限
double zone_high[5]; // 分割エントリー用ゾーン上限
double zone_tp[5]; // 分割エントリー用TP
double zone_sl[5]; // 分割エントリー用SL
bool load_trend_flg; // ★変更:トレンドを更新するタイミングか
bool load_target_flg; // ★変更:ターゲット価格を更新するタイミングか
int chk_cnt; // エントリー判定の試行回数
datetime last_trend_update; // ★追加:前回トレンドを更新した時刻
datetime last_target_update; // ★変更:前回ターゲット価格を更新した時刻
datetime target_loaded_at; // H1候補価格をEAへ読み込んだサーバー時刻
datetime last_chk;
};
EAState g_ea; // EA全体の状態をここで管理
// initial_order 用の初回処理フラグ
// H4トレンド処理とH1エントリー処理で別々に管理し、初回起動時の再実行ループを防ぐ。
bool g_init_trend_pending = false;
bool g_init_entry_pending = false;
// H4/H1のバー更新状態
int g_pre_bars_H4 = 0;
int g_pre_bars_H1 = 0;
int g_pre_bars_M15 = 0;
bool g_bars_H1_check = false;
bool g_bars_M15_check = false;
// ティックごとの価格情報
struct TickContext
{
double ask;
double bid;
double spread;
double spread_points;
int digits;
};
// 外部Pythonプロセスの状態
struct ExternalProcessState
{
long handle;
uint process_id;
bool active;
bool exit_code_ready;
uint exit_code;
datetime started_at;
};
ExternalProcessState g_trend_process;
ExternalProcessState g_entry_process;
CSLTPManager g_sltp_manager;
CSLTPManagerPanel g_sltp_panel;
SLTPManagerPanelSettings g_sltp_settings;
bool g_sltp_settings_valid = false;
bool g_sltp_panel_created = false;
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
/**
* @brief EA起動時の初期化処理を行います。
*
* Python連携用のdone/runningファイル状態を確認し、`initial_order` が有効な場合は
* H4トレンド判定とH1エントリー価格生成をそれぞれ初回実行対象にします。
* H4/H1の初回フラグを分けることで、起動直後にH4処理だけが繰り返される状態を防ぎます。
*/
int OnInit()
// プロセス完了ファイルと実行中ファイルの状態を初期化
{
PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend");
PrepareDoneFileOnInit(done_entry_file, running_entry_file, "entry");
// initial_order=1 の場合でも、H4/H1を別々に1回だけ初回実行する。
g_init_trend_pending = (initial_order == 1);
g_init_entry_pending = (initial_order == 1);
if(!InitializeSLTPManager())
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| 終了時の処理
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ResetExternalProcessState(g_trend_process);
ResetExternalProcessState(g_entry_process);
if(g_sltp_panel_created)
g_sltp_panel.Destroy(reason);
// Clear chart status text left by Comment() when the EA is removed.
Comment("");
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| ティック毎の処理
//+------------------------------------------------------------------+
/**
* @brief ティック受信ごとにEA全体の処理を制御します。
*
* 処理順序は、ティック情報取得、期限切れ注文/ポジション管理、H4トレンド更新、
* H1エントリー価格更新、M15エントリータイミング更新、ステータス表示、新規注文判定の順です。
* 時間制限処理はPython完了待ちやスプレッド判定より前に実行します。
*/
void OnTick()
{
TickContext ctx;
if(!GetTickContext(ctx))
return;
// 期限切れ注文・ポジションは、Python待ちやスプレッド制限に関係なく先に処理する。
ManageExpiredTrades();
// Existing-position protection stays active even while Python results are pending.
ManageSLTPPositions();
// 外部Pythonがdoneを返さない場合に、一定時間で待機状態を解除して再実行対象にする。
RecoverTimedOutPythonProcesses();
// H4新バーまたは初回起動時に、トレンド判定用Pythonを起動する。
ProcessTrendUpdate(g_ea);
// トレンド判定が完了していない場合、新規注文側の処理だけをスキップする。
if(!IsTrendResultReady())
return;
RefreshTrendState(g_ea);
// H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。
ProcessEntryUpdate(g_ea);
// M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。
ProcessM15EntryTimingUpdate();
UpdateStatusComment(ctx);
// ここから下は新規注文に関する処理。
if(!IsSpreadAllowed(ctx))
return;
if(!IsEntryResultReady())
return;
RefreshTargetPrices(g_ea);
ProcessEntryDecisionIfNeeded(g_ea, ctx);
}
//+------------------------------------------------------------------+
//| SLTP manager panel and settings bridge
//+------------------------------------------------------------------+
string SLTPBoolText(const bool value)
{
return value ? "ON" : "OFF";
}
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
{
settings.manager_enabled = input_sltp_manager_enabled;
settings.use_breakeven = input_sltp_use_breakeven;
settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips;
settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips;
settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven;
settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours;
settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips;
settings.use_active_trailing = input_sltp_use_active_trailing;
settings.active_breakeven_pips = input_sltp_active_breakeven_pips;
settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips;
settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips;
settings.active_step_move_pips = input_sltp_active_step_move_pips;
settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop;
settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent;
settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent;
settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit;
}
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
const bool print_summary)
{
g_sltp_settings_valid = false;
g_sltp_manager.SetMagicNumber((ulong)magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(slippage);
g_sltp_manager.SetBreakevenSettings(settings.use_breakeven,
settings.breakeven_trigger_pips,
settings.breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven,
settings.elapsed_breakeven_hours,
settings.elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing,
settings.active_breakeven_pips,
settings.active_stop_loss_offset_pips,
settings.active_step_trigger_pips,
settings.active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop,
settings.tp_progress_trigger_percent,
settings.tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit);
if(!g_sltp_manager.ValidateSettings())
{
Print("HIT SLTP settings rejected. Manager is disabled until valid settings are applied.");
return false;
}
g_sltp_settings = settings;
g_sltp_settings_valid = true;
if(print_summary)
{
Print("HIT SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled),
" BE=", SLTPBoolText(settings.use_breakeven),
" ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven),
" ActiveTrail=", SLTPBoolText(settings.use_active_trailing),
" TPProgress=", SLTPBoolText(settings.use_tp_progress_stop),
" HighVol=", SLTPBoolText(settings.use_high_volatility_limit));
}
return true;
}
bool InitializeSLTPManager()
{
SLTPManagerPanelSettings initial_settings;
LoadSLTPInputSettings(initial_settings);
if(!ApplySLTPSettings(initial_settings, true))
return false;
g_sltp_panel.Init(g_sltp_settings);
if(input_sltp_show_panel)
{
if(!g_sltp_panel.CreatePanel())
{
Print("HIT SLTP panel is unavailable. EA continues with input-based SLTP settings.");
return true;
}
g_sltp_panel.SetInitialValues();
g_sltp_panel_created = true;
}
return true;
}
void ManageSLTPPositions()
{
if(!g_sltp_settings_valid)
return;
if(!g_sltp_settings.manager_enabled)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(!g_sltp_panel_created)
return;
SLTPManagerPanelSettings candidate_settings = g_sltp_settings;
if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings))
{
if(!ApplySLTPSettings(candidate_settings, true))
Print("HIT SLTP panel apply failed. Please review panel values.");
}
}
// Function implementations are kept in project headers so the EA entry points stay compact.
#include <MyLib/Common/HITRuntimeController.mqh>
#include <MyLib/Signals/HITEntrySignal.mqh>
#include <MyLib/Common/HITExternalProcess.mqh>
#include <MyLib/Signals/HITPythonSignalGateway.mqh>
#include <MyLib/Trading/HITTradeManager.mqh>
@@ -1,14 +1,11 @@
//+------------------------------------------------------------------+
//| HIT_EA.mq5 |
//| HITEntryEA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.01"
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Panel/SLTPManagerPanel.mqh>
#property version "1.11"
//+------------------------------------------------------------------+
//| バッチファイル実行用の設定
@@ -99,15 +96,17 @@ enum SplitLotMode
//--- 入力パラメータ
input double lot_size = 0.01; // ロット数
input double spread_limit = 60; // 許容スプレッド(point)
input int magic_number = 10001; // マジックナンバー
input int initial_order = 0; // 起動時の注文(0:なし, 1:あり)
input int input_entry_magic_number = 10001; // 発注EAのマジックナンバー
input ulong input_slippage_points = 10; // 許容スリッページ(point)
input int initial_order = 0; // 互換性維持用。起動時H4/H1再構築は常時実行
input int input_position_limit = 10; // 自EAの未約定注文+ポジション上限
input bool use_split_entry_zone = false; // H1予測ゾーンで分割エントリーする
input bool use_split_entry_zone = true; // H1予測ゾーンで分割エントリーする
input int split_entry_count = 3; // 分割エントリー本数(1..10)
input SplitLotMode split_lot_mode = SPLIT_LOT_TOTAL; // 分割ロット配分モード
input SplitLotMode split_lot_mode = SPLIT_LOT_FIXED; // 分割ロット配分モード
input double split_total_lot_size = 0.09; // 総量分割モードの合計ロット
input double split_fixed_lot_size = 0.01; // 固定ロットモードの1注文ロット
input bool cancel_old_split_pending_on_new_zone = true; // 新ゾーン読込時に旧分割pendingを取消
input int input_cancel_retry_cooldown_seconds = 60; // pending取消失敗時のticket単位再試行間隔
input bool use_m15_entry_filter = true; // M15確定足で発注タイミングを確認
input double m15_entry_zone_atr_multiplier = 1.50; // M15平均レンジ何本分まで候補価格への接近を許可
input bool use_m15_imbalance_confirmation = true; // T1/T3でM15初動確認を追加
@@ -116,29 +115,25 @@ input double m15_imbalance_sensitivity = 2.0; // M15初動検知感度
input double m15_imbalance_min_avg_body_points = 1.0; // 平均実体の最小値(point)
input bool use_m15_imbalance_debug_log = false; // M15初動確認ログ
input int input_entry_max_candidate_age_minutes = 120; // H1候補価格を新規発注に使う最大経過分数
input bool input_sltp_manager_enabled = false; // UI連動SLTP管理を有効化
input bool input_sltp_show_panel = true; // SLTP操作パネルを表示
input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化
input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips
input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips
input bool input_sltp_use_elapsed_breakeven = false; // 保有時間BEを有効化
input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間
input double input_sltp_elapsed_breakeven_buffer_pips = 3.0; // 保有時間BE固定バッファpips
input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化
input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips
input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips
input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips
input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips
input bool input_sltp_use_tp_progress_stop = false; // TP進捗SLを有効化
input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率
input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率
input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化
ulong slippage = 10; // スリッページ
input double input_tp_multiplier = 1.50; // TP distance multiplier (1.0=no expansion)
input int input_min_tp_points = 0; // Minimum TP distance in points (0=disabled)
input int input_max_tp_points = 0; // Maximum expanded TP distance in points (0=disabled)
input bool input_range_breakout_guard_enabled = true; // レンジ上抜け/下抜け時に逆張りLimitを退避
input ENUM_TIMEFRAMES input_range_breakout_guard_timeframe = PERIOD_M15; // レンジブレイク監視足
input int input_range_breakout_lookback_bars = 20; // レンジ高値安値の参照本数
input double input_range_breakout_max_width_multiplier = 6.0; // 平均レンジに対する最大レンジ幅
input double input_range_breakout_buffer_multiplier = 0.20; // ブレイク確定バッファ倍率
input double input_range_breakout_near_multiplier = 0.50; // ブレイク警戒の境界接近幅倍率
input double input_range_breakout_body_multiplier = 1.50; // 勢い判定の平均実体倍率
input int input_range_breakout_cooldown_bars = 4; // 逆張りLimit停止を継続する足数
// Existing shared HIT include files read these runtime globals.
int magic_number = 10001;
ulong slippage = 10;
//--- 主要な定数・設定
#define POSITION_LIMIT 48
#define ENTRY_H1_LIMIT 2 // H1本数(=2時間)
#define CLOSE_H1_LIMIT 12 // H1本数(=12時間)
#define HISTORY_BARS 72
#define OHLC_START_SHIFT 1 // 1: 確定足のみをPythonへ渡す
#define M15_CONFIRM_BARS 30
@@ -161,6 +156,10 @@ ulong slippage = 10; // スリッページ
#define MARKET_HIGH_VOL_DOWN 5
#define MARKET_TECHNICAL_ERROR_STOP 6
#define RANGE_BREAKOUT_NONE 0
#define RANGE_BREAKOUT_UP 1
#define RANGE_BREAKOUT_DOWN -1
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
@@ -192,8 +191,8 @@ struct EAState
EAState g_ea; // EA全体の状態をここで管理
// initial_order 用の初回処理フラグ
// H4トレンド処理とH1エントリー処理で別々に管理し、初回起動時の再実行ループを防ぐ。
// Startup refresh flags for H4 trend and H1 entry candidates.
// Keep them separate to prevent repeated startup launches.
bool g_init_trend_pending = false;
bool g_init_entry_pending = false;
@@ -204,6 +203,14 @@ int g_pre_bars_M15 = 0;
bool g_bars_H1_check = false;
bool g_bars_M15_check = false;
// pending取消失敗時の過剰な取引サーバー要求を防止する。
ulong g_cancel_retry_tickets[];
datetime g_cancel_retry_at[];
// Range-breakout guard state for adverse reversal Limit orders.
int g_range_breakout_guard_direction = RANGE_BREAKOUT_NONE;
datetime g_range_breakout_guard_until = 0;
// ティックごとの価格情報
struct TickContext
{
@@ -228,12 +235,6 @@ struct ExternalProcessState
ExternalProcessState g_trend_process;
ExternalProcessState g_entry_process;
CSLTPManager g_sltp_manager;
CSLTPManagerPanel g_sltp_panel;
SLTPManagerPanelSettings g_sltp_settings;
bool g_sltp_settings_valid = false;
bool g_sltp_panel_created = false;
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
@@ -373,30 +374,54 @@ void ConfigurePythonGatewayPaths()
Print("Python app dir: ", python_app_dir);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/**
* @brief The split entry/manager design requires ticket-based hedging positions.
*/
bool IsHedgingAccount()
{
return (AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
}
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
/**
* @brief EA起動時の初期化処理を行います。
*
* Python連携用のdone/runningファイル状態を確認し、`initial_order` が有効な場合は
* Python連携用のdone/runningファイル状態を確認し、起動直後は安全側として
* H4トレンド判定とH1エントリー価格生成をそれぞれ初回実行対象にします。
* H4/H1の初回フラグを分けることで、起動直後にH4処理だけが繰り返される状態を防ぎます。
* H4結果を再読込するまでは技術エラー停止値を維持し、古い連携結果での発注を防ぎます。
*/
int OnInit()
// プロセス完了ファイルと実行中ファイルの状態を初期化
{
magic_number = input_entry_magic_number;
slippage = input_slippage_points;
if(!IsHedgingAccount())
{
Print("HITEntryEA requires a retail hedging account. account_margin_mode=",
AccountInfoInteger(ACCOUNT_MARGIN_MODE));
return INIT_FAILED;
}
ConfigurePythonGatewayPaths();
PrepareDoneFileOnInit(done_trend_file, running_trend_file, "trend");
PrepareDoneFileOnInit(done_entry_file, running_entry_file, "entry");
// initial_order=1 の場合でも、H4/H1を別々に1回だけ初回実行する。
g_init_trend_pending = (initial_order == 1);
g_init_entry_pending = (initial_order == 1);
if(!InitializeSLTPManager())
return INIT_FAILED;
// Always rebuild startup state before allowing new orders.
g_ea.trend_state = MARKET_TECHNICAL_ERROR_STOP;
g_ea.res_chk = 0;
g_ea.zone_res_chk = 0;
g_ea.zone_candidate_id = "0";
g_init_trend_pending = true;
g_init_entry_pending = true;
ArrayResize(g_cancel_retry_tickets, 0);
ArrayResize(g_cancel_retry_at, 0);
return INIT_SUCCEEDED;
}
@@ -409,9 +434,6 @@ void OnDeinit(const int reason)
ResetExternalProcessState(g_trend_process);
ResetExternalProcessState(g_entry_process);
if(g_sltp_panel_created)
g_sltp_panel.Destroy(reason);
// Clear chart status text left by Comment() when the EA is removed.
Comment("");
ChartRedraw(0);
@@ -433,11 +455,11 @@ void OnTick()
if(!GetTickContext(ctx))
return;
// 期限切れ注文・ポジションは、Python待ちやスプレッド制限に関係なく先に処理する。
ManageExpiredTrades();
// Expired pending orders are managed by the entry EA before any Python wait state.
ManageExpiredEntryOrders();
// Existing-position protection stays active even while Python results are pending.
ManageSLTPPositions();
// Delete and pause adverse limit orders before breakout spikes can fill them.
ManageRangeBreakoutLimitGuard(ctx);
// 外部Pythonがdoneを返さない場合に、一定時間で待機状態を解除して再実行対象にする。
RecoverTimedOutPythonProcesses();
@@ -454,6 +476,11 @@ void OnTick()
// H1新バーまたは初回起動時に、エントリー価格生成用Pythonを起動する。
ProcessEntryUpdate(g_ea);
// Read completed H1 results before spread gating so stale split orders and state updates are not delayed.
bool entry_result_ready = IsEntryResultReady();
if(entry_result_ready)
RefreshTargetPrices(g_ea);
// M15確定足ごとに、H1候補価格を発注してよいタイミングか再判定する。
ProcessM15EntryTimingUpdate();
@@ -463,144 +490,23 @@ void OnTick()
if(!IsSpreadAllowed(ctx))
return;
if(!IsEntryResultReady())
if(!entry_result_ready)
return;
RefreshTargetPrices(g_ea);
ProcessEntryDecisionIfNeeded(g_ea, ctx);
}
//+------------------------------------------------------------------+
//| SLTP manager panel and settings bridge
//| Entry order lifecycle
//+------------------------------------------------------------------+
string SLTPBoolText(const bool value)
void ManageExpiredEntryOrders()
{
return value ? "ON" : "OFF";
CleanupPendingOrderCancelAttempts();
if(OrdersTotal() > 0)
CancelExpiredOrders();
}
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
{
settings.manager_enabled = input_sltp_manager_enabled;
settings.use_breakeven = input_sltp_use_breakeven;
settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips;
settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips;
settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven;
settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours;
settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips;
settings.use_active_trailing = input_sltp_use_active_trailing;
settings.active_breakeven_pips = input_sltp_active_breakeven_pips;
settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips;
settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips;
settings.active_step_move_pips = input_sltp_active_step_move_pips;
settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop;
settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent;
settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent;
settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit;
}
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
const bool print_summary)
{
g_sltp_settings_valid = false;
g_sltp_manager.SetMagicNumber((ulong)magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(slippage);
g_sltp_manager.SetBreakevenSettings(settings.use_breakeven,
settings.breakeven_trigger_pips,
settings.breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven,
settings.elapsed_breakeven_hours,
settings.elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing,
settings.active_breakeven_pips,
settings.active_stop_loss_offset_pips,
settings.active_step_trigger_pips,
settings.active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop,
settings.tp_progress_trigger_percent,
settings.tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit);
if(!g_sltp_manager.ValidateSettings())
{
Print("HIT SLTP settings rejected. Manager is disabled until valid settings are applied.");
return false;
}
g_sltp_settings = settings;
g_sltp_settings_valid = true;
if(print_summary)
{
Print("HIT SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled),
" BE=", SLTPBoolText(settings.use_breakeven),
" ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven),
" ActiveTrail=", SLTPBoolText(settings.use_active_trailing),
" TPProgress=", SLTPBoolText(settings.use_tp_progress_stop),
" HighVol=", SLTPBoolText(settings.use_high_volatility_limit));
}
return true;
}
bool InitializeSLTPManager()
{
SLTPManagerPanelSettings initial_settings;
LoadSLTPInputSettings(initial_settings);
if(!ApplySLTPSettings(initial_settings, true))
return false;
g_sltp_panel.Init(g_sltp_settings);
if(input_sltp_show_panel)
{
if(!g_sltp_panel.CreatePanel())
{
Print("HIT SLTP panel is unavailable. EA continues with input-based SLTP settings.");
return true;
}
g_sltp_panel.SetInitialValues();
g_sltp_panel_created = true;
}
return true;
}
void ManageSLTPPositions()
{
if(!g_sltp_settings_valid)
return;
if(!g_sltp_settings.manager_enabled)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(!g_sltp_panel_created)
return;
SLTPManagerPanelSettings candidate_settings = g_sltp_settings;
if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings))
{
if(!ApplySLTPSettings(candidate_settings, true))
Print("HIT SLTP panel apply failed. Please review panel values.");
}
}
// Function implementations are kept in project headers so the EA entry points stay compact.
#include <MyLib/Common/HITRuntimeController.mqh>
#include <MyLib/Signals/HITEntrySignal.mqh>
+231
View File
@@ -0,0 +1,231 @@
//+------------------------------------------------------------------+
//| HITPositionManagerEA.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.01"
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Trading/HITPositionLifecycleManager.mqh>
#include <MyLib/Panel/SLTPManagerPanel.mqh>
// This EA never opens new positions. It manages hedging-account tickets created by HITEntryEA.
input int input_managed_magic_number = 10001; // 管理対象のマジックナンバー
input ulong input_slippage_points = 20; // 決済/SL変更の許容偏差(point)
input int input_position_close_after_h1_bars = 12; // 保有時間決済(H1本数、0で無効)
input bool input_sltp_manager_enabled = true; // UI連動SLTP管理を有効化
input bool input_sltp_show_panel = true; // SLTP操作パネルを表示
input bool input_sltp_use_breakeven = false; // 通常ブレークイーブンを有効化
input double input_sltp_breakeven_trigger_pips = 30.0; // 通常BE開始pips
input double input_sltp_breakeven_buffer_pips = 3.0; // 通常BE固定バッファpips
input bool input_sltp_use_elapsed_breakeven = true; // 保有時間BEを有効化
input double input_sltp_elapsed_breakeven_hours = 4.0; // 保有時間BE開始時間
input double input_sltp_elapsed_breakeven_buffer_pips = 5.0; // 保有時間BE固定バッファpips
input bool input_sltp_use_active_trailing = false; // アクティブトレーリングを有効化
input double input_sltp_active_breakeven_pips = 30.0; // アクティブ開始pips
input double input_sltp_active_stop_loss_offset_pips = 5.0; // 初期固定pips
input double input_sltp_active_step_trigger_pips = 10.0; // ステップ更新間隔pips
input double input_sltp_active_step_move_pips = 5.0; // 1ステップ固定追加pips
input bool input_sltp_use_tp_progress_stop = true; // TP進捗SLを有効化
input double input_sltp_tp_progress_trigger_percent = 70.0; // TP進捗SL開始率
input double input_sltp_tp_progress_sl_lock_percent = 30.0; // TP距離固定率
input bool input_sltp_use_high_volatility_limit = false; // 急変時SL引き締めを有効化
CSLTPManager g_sltp_manager;
CSLTPManagerPanel g_sltp_panel;
SLTPManagerPanelSettings g_sltp_settings;
CHITPositionLifecycleManager g_position_lifecycle;
bool g_sltp_settings_valid = false;
bool g_sltp_panel_created = false;
int EffectiveCloseAfterSeconds()
{
int close_bars = input_position_close_after_h1_bars;
if(close_bars < 0)
close_bars = 0;
if(close_bars > 240)
close_bars = 240;
const int h1_seconds = PeriodSeconds(PERIOD_H1);
if(close_bars <= 0 || h1_seconds <= 0)
return 0;
return close_bars * h1_seconds;
}
bool IsHedgingAccount()
{
return (AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
}
string SLTPBoolText(const bool value)
{
return value ? "ON" : "OFF";
}
void LoadSLTPInputSettings(SLTPManagerPanelSettings &settings)
{
settings.manager_enabled = input_sltp_manager_enabled;
settings.use_breakeven = input_sltp_use_breakeven;
settings.breakeven_trigger_pips = input_sltp_breakeven_trigger_pips;
settings.breakeven_buffer_pips = input_sltp_breakeven_buffer_pips;
settings.use_elapsed_breakeven = input_sltp_use_elapsed_breakeven;
settings.elapsed_breakeven_hours = input_sltp_elapsed_breakeven_hours;
settings.elapsed_breakeven_buffer_pips = input_sltp_elapsed_breakeven_buffer_pips;
settings.use_active_trailing = input_sltp_use_active_trailing;
settings.active_breakeven_pips = input_sltp_active_breakeven_pips;
settings.active_stop_loss_offset_pips = input_sltp_active_stop_loss_offset_pips;
settings.active_step_trigger_pips = input_sltp_active_step_trigger_pips;
settings.active_step_move_pips = input_sltp_active_step_move_pips;
settings.use_tp_progress_stop = input_sltp_use_tp_progress_stop;
settings.tp_progress_trigger_percent = input_sltp_tp_progress_trigger_percent;
settings.tp_progress_sl_lock_percent = input_sltp_tp_progress_sl_lock_percent;
settings.use_high_volatility_limit = input_sltp_use_high_volatility_limit;
}
bool ApplySLTPSettings(const SLTPManagerPanelSettings &settings,
const bool print_summary)
{
g_sltp_manager.SetMagicNumber((ulong)input_managed_magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(input_slippage_points);
g_sltp_manager.SetBreakevenSettings(settings.use_breakeven,
settings.breakeven_trigger_pips,
settings.breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(settings.use_elapsed_breakeven,
settings.elapsed_breakeven_hours,
settings.elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(settings.use_active_trailing,
settings.active_breakeven_pips,
settings.active_stop_loss_offset_pips,
settings.active_step_trigger_pips,
settings.active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(settings.use_tp_progress_stop,
settings.tp_progress_trigger_percent,
settings.tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(settings.use_high_volatility_limit);
if(settings.manager_enabled && !g_sltp_manager.ValidateSettings())
{
Print("HIT position manager SLTP settings rejected. Previous valid settings remain active.");
return false;
}
g_sltp_settings = settings;
g_sltp_settings_valid = true;
if(print_summary)
{
Print("HIT position manager SLTP settings: Manager=", SLTPBoolText(settings.manager_enabled),
" BE=", SLTPBoolText(settings.use_breakeven),
" ElapsedBE=", SLTPBoolText(settings.use_elapsed_breakeven),
" ActiveTrail=", SLTPBoolText(settings.use_active_trailing),
" TPProgress=", SLTPBoolText(settings.use_tp_progress_stop),
" HighVol=", SLTPBoolText(settings.use_high_volatility_limit),
" magic=", input_managed_magic_number);
}
return true;
}
bool InitializeSLTPManager()
{
SLTPManagerPanelSettings initial_settings;
LoadSLTPInputSettings(initial_settings);
if(!ApplySLTPSettings(initial_settings, true))
return false;
g_sltp_panel.Init(g_sltp_settings);
if(input_sltp_show_panel)
{
if(!g_sltp_panel.CreatePanel())
{
Print("HIT position manager SLTP panel is unavailable. EA continues with input-based settings.");
return true;
}
g_sltp_panel.SetInitialValues();
g_sltp_panel_created = true;
}
return true;
}
bool InitializePositionLifecycleManager()
{
return g_position_lifecycle.Init(_Symbol,
(ulong)input_managed_magic_number,
input_slippage_points,
EffectiveCloseAfterSeconds());
}
void ManageTargetPositions()
{
g_position_lifecycle.SetCloseAfterSeconds(EffectiveCloseAfterSeconds());
g_position_lifecycle.CloseExpiredPositions();
if(!g_sltp_settings_valid)
return;
if(!g_sltp_settings.manager_enabled)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
int OnInit()
{
if(!IsHedgingAccount())
{
Print("HITPositionManagerEA requires a retail hedging account. account_margin_mode=",
AccountInfoInteger(ACCOUNT_MARGIN_MODE));
return INIT_FAILED;
}
if(!InitializePositionLifecycleManager())
return INIT_FAILED;
if(!InitializeSLTPManager())
return INIT_FAILED;
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
if(g_sltp_panel_created)
g_sltp_panel.Destroy(reason);
Comment("");
ChartRedraw(0);
}
void OnTick()
{
ManageTargetPositions();
}
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if(!g_sltp_panel_created)
return;
SLTPManagerPanelSettings candidate_settings = g_sltp_settings;
if(g_sltp_panel.HandleChartEvent(id, lparam, dparam, sparam, candidate_settings))
{
if(!ApplySLTPSettings(candidate_settings, true))
Print("HIT position manager panel apply failed. Please review panel values.");
}
}
@@ -0,0 +1,243 @@
//+------------------------------------------------------------------+
//| HITPositionManagerTestHarness.mq5 |
//| Copyright 2026, nanpin-martin.com |
//| https://www.nanpin-martin.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, nanpin-martin.com"
#property link "https://nanpin-martin.com/"
#property version "1.00"
#include <Trade/Trade.mqh>
#include <MyLib/Trading/SLTPManager.mqh>
#include <MyLib/Trading/HITPositionLifecycleManager.mqh>
// Strategy Tester harness only. It seeds positions, then calls the production managers.
input int input_managed_magic_number = 10001; // 管理対象magic
input int input_control_magic_number = 20002; // 非対象確認用magic
input ulong input_slippage_points = 10; // 許容偏差(point)
input double input_test_lot_size = 0.01; // 検証用ロット
input bool input_seed_managed_buy = true; // 管理対象BUYを作成
input bool input_seed_managed_sell = true; // 管理対象SELLを作成
input bool input_seed_control_position = true; // magic違いポジションを作成
input int input_position_close_after_h1_bars = 12; // 保有時間決済(H1本数、0で無効)
input bool input_sltp_manager_enabled = true; // SLTP管理を有効化
input bool input_sltp_use_breakeven = true; // 通常BEを有効化
input double input_sltp_breakeven_trigger_pips = 30.0;
input double input_sltp_breakeven_buffer_pips = 3.0;
input bool input_sltp_use_elapsed_breakeven = false;
input double input_sltp_elapsed_breakeven_hours = 4.0;
input double input_sltp_elapsed_breakeven_buffer_pips = 3.0;
input bool input_sltp_use_active_trailing = false;
input double input_sltp_active_breakeven_pips = 30.0;
input double input_sltp_active_stop_loss_offset_pips = 5.0;
input double input_sltp_active_step_trigger_pips = 10.0;
input double input_sltp_active_step_move_pips = 5.0;
input bool input_sltp_use_tp_progress_stop = false;
input double input_sltp_tp_progress_trigger_percent = 70.0;
input double input_sltp_tp_progress_sl_lock_percent = 30.0;
input bool input_sltp_use_high_volatility_limit = false;
CTrade g_test_trade;
CSLTPManager g_sltp_manager;
CHITPositionLifecycleManager g_position_lifecycle;
bool g_seed_done = false;
bool g_sltp_settings_valid = false;
int EffectiveCloseAfterSeconds()
{
int close_bars = input_position_close_after_h1_bars;
if(close_bars < 0)
close_bars = 0;
if(close_bars > 240)
close_bars = 240;
const int h1_seconds = PeriodSeconds(PERIOD_H1);
if(close_bars <= 0 || h1_seconds <= 0)
return 0;
return close_bars * h1_seconds;
}
bool IsHedgingAccount()
{
return (AccountInfoInteger(ACCOUNT_MARGIN_MODE) == ACCOUNT_MARGIN_MODE_RETAIL_HEDGING);
}
double NormalizedVolume(const double volume)
{
const double min_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
const double max_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
const double step_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
if(min_volume <= 0.0 || max_volume <= 0.0 || step_volume <= 0.0)
return volume;
double normalized = volume;
if(normalized < min_volume)
normalized = min_volume;
if(normalized > max_volume)
normalized = max_volume;
const double steps = MathFloor((normalized - min_volume) / step_volume + 0.5);
normalized = min_volume + steps * step_volume;
int volume_digits = 0;
double step = step_volume;
while(step < 1.0 && volume_digits < 8)
{
step *= 10.0;
volume_digits++;
}
return NormalizeDouble(normalized, volume_digits);
}
bool ConfigureManagers()
{
if(!g_position_lifecycle.Init(_Symbol,
(ulong)input_managed_magic_number,
input_slippage_points,
EffectiveCloseAfterSeconds()))
return false;
g_sltp_manager.SetMagicNumber((ulong)input_managed_magic_number);
g_sltp_manager.SetSymbol(_Symbol);
g_sltp_manager.SetDeviationInPoints(input_slippage_points);
g_sltp_manager.SetBreakevenSettings(input_sltp_use_breakeven,
input_sltp_breakeven_trigger_pips,
input_sltp_breakeven_buffer_pips);
g_sltp_manager.SetElapsedBreakevenSettings(input_sltp_use_elapsed_breakeven,
input_sltp_elapsed_breakeven_hours,
input_sltp_elapsed_breakeven_buffer_pips);
g_sltp_manager.SetActiveTrailingSettings(input_sltp_use_active_trailing,
input_sltp_active_breakeven_pips,
input_sltp_active_stop_loss_offset_pips,
input_sltp_active_step_trigger_pips,
input_sltp_active_step_move_pips);
g_sltp_manager.SetTpProgressStopSettings(input_sltp_use_tp_progress_stop,
input_sltp_tp_progress_trigger_percent,
input_sltp_tp_progress_sl_lock_percent);
g_sltp_manager.SetHighVolatilityLimitSettings(input_sltp_use_high_volatility_limit);
g_sltp_settings_valid = g_sltp_manager.ValidateSettings();
return g_sltp_settings_valid;
}
bool SeedBuyPosition(const ulong magic,
const string comment)
{
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick))
{
Print("Harness tick read failed: err=", GetLastError());
return false;
}
const int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
const double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
const double sl = NormalizeDouble(tick.bid - 5000.0 * point, digits);
const double tp = NormalizeDouble(tick.bid + 10000.0 * point, digits);
g_test_trade.SetExpertMagicNumber(magic);
ResetLastError();
if(!g_test_trade.Buy(NormalizedVolume(input_test_lot_size), _Symbol, 0.0, sl, tp, comment))
{
Print("Harness BUY seed failed: magic=", magic,
" retcode=", g_test_trade.ResultRetcode(),
" err=", GetLastError());
return false;
}
Print("Harness BUY seed succeeded: magic=", magic,
" ticket=", g_test_trade.ResultOrder(),
" comment=", comment);
return true;
}
bool SeedSellPosition(const ulong magic,
const string comment)
{
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick))
{
Print("Harness tick read failed: err=", GetLastError());
return false;
}
const int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
const double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
const double sl = NormalizeDouble(tick.ask + 5000.0 * point, digits);
const double tp = NormalizeDouble(tick.ask - 10000.0 * point, digits);
g_test_trade.SetExpertMagicNumber(magic);
ResetLastError();
if(!g_test_trade.Sell(NormalizedVolume(input_test_lot_size), _Symbol, 0.0, sl, tp, comment))
{
Print("Harness SELL seed failed: magic=", magic,
" retcode=", g_test_trade.ResultRetcode(),
" err=", GetLastError());
return false;
}
Print("Harness SELL seed succeeded: magic=", magic,
" ticket=", g_test_trade.ResultOrder(),
" comment=", comment);
return true;
}
void SeedTestPositions()
{
if(g_seed_done)
return;
g_test_trade.SetDeviationInPoints((int)input_slippage_points);
g_test_trade.SetTypeFillingBySymbol(_Symbol);
if(input_seed_managed_buy)
SeedBuyPosition((ulong)input_managed_magic_number, "HIT PM TEST managed BUY");
if(input_seed_managed_sell)
SeedSellPosition((ulong)input_managed_magic_number, "HIT PM TEST managed SELL");
if(input_seed_control_position)
SeedBuyPosition((ulong)input_control_magic_number, "HIT PM TEST control magic");
g_seed_done = true;
}
void ManageTargetPositions()
{
g_position_lifecycle.SetCloseAfterSeconds(EffectiveCloseAfterSeconds());
g_position_lifecycle.CloseExpiredPositions();
if(!input_sltp_manager_enabled || !g_sltp_settings_valid)
return;
g_sltp_manager.ManagePositions();
g_sltp_manager.HighVolatilityLimit();
}
int OnInit()
{
if(!MQLInfoInteger(MQL_TESTER))
{
Print("HITPositionManagerTestHarness is for Strategy Tester only.");
return INIT_FAILED;
}
if(!IsHedgingAccount())
{
Print("HITPositionManagerTestHarness requires a retail hedging account. account_margin_mode=",
AccountInfoInteger(ACCOUNT_MARGIN_MODE));
return INIT_FAILED;
}
if(!ConfigureManagers())
return INIT_FAILED;
return INIT_SUCCEEDED;
}
void OnTick()
{
SeedTestPositions();
ManageTargetPositions();
}
-395
View File
@@ -1,395 +0,0 @@
//+------------------------------------------------------------------+
//| TradingPanel EA entry point
//+------------------------------------------------------------------+
#include <MyLib/Trading/TradingPanelTradingManagers.mqh>
#include <MyLib/Panel/TradingPanelPanel.mqh>
#define POSITION_TYPE_ALL ((ENUM_POSITION_TYPE) - 1) // フィルタ無し
// トータルブレークイーブン
#define BE_BUY "BreakEvenBuy"
#define BE_SELL "BreakEvenSell"
//--- カテゴリ1:取引設定
input group "■ 取引設定";
input int exit_time_interval = 4; // 時間制限クローズまでの保有時間(時間)
//--- カテゴリ2:基本設定
input group "■ 基本設定";
input ulong slippage = 10; // スリッページ
input int magic_number = 10001; // マジックナンバー
input group "■ SLTP設定: Common";
input double take_profit_pips = 150.0; // TP設定値
input double default_sl = 100.0; // SL初期値
input double stop_offset_pips = 10.0; // ストップロスオフセット(pips)
input group "■ SLTP設定: TRAIL";
input bool enable_breakeven = true; // ブレークイーブンを有効化
input double breakeven_pips = 30.0; // ブレークイーブン判定利幅
input double stop_loss_offset_pips = 5.0; // 建値からのマージン
input double step_trigger_pips = 10.0; // トレール更新トリガーpips
input double step_move_pips = 8.0; // トレール更新pips
input double tp_edit_pips = 10.0; // TP更新初期pips
//--- カテゴリ4:フィルター設定
input group "■ レンジフィルター設定";
input double range_pips = 80.0; // レンジ幅pips1
//--- カテゴリ5:時間設定
input group "■ 取引時間設定";
input bool isTradingTimeEnabled = true; // 取引時間を制限
input int TradeStartHour = 4; // 開始時間GMT(時間)
input int TradeStartMin = 0; // 開始時間GMT(分)
input int TradeEndHour = 23; // 終了時間GMT(時間)
input int TradeEndMin = 0; // 終了時間GMT(分)
int TimerPeriod_sec = 1; // n 秒ごとに OnTimer
bool wasInTradingTime = false;
bool beforeTradingInitDone = false;
bool afterTradingInitDone = false;
bool timelimit_exit = true; // 時間制限クローズ 初期状態
bool input_lock = true; // 時間制限クローズ 初期状態
// --------------------------------------------------------------
// EAとの共有用グローバル変数
// --------------------------------------------------------------
int gl_exitTimeIntervalInSeconds = exit_time_interval * 3600;
double gl_breakeven_pips = breakeven_pips;
double gl_stop_loss_offset_pips = stop_loss_offset_pips;
double gl_step_trigger_pips = step_trigger_pips;
double gl_step_move_pips = step_move_pips;
double gl_default_sl_pips = default_sl;
double gl_take_profit_pips = take_profit_pips;
double gl_stop_offset_pips = stop_offset_pips;
int buy_position = 0; // CountPositions() で随時更新
int sell_position = 0;
datetime last_buy_time = 0;
datetime last_sell_time = 0;
bool buy_total_be_flg = false;
bool sell_total_be_flg = false;
//+------------------------------------------------------------------+
//| トータルのブレークイーブン用変数
//+------------------------------------------------------------------+
bool InpShowBuyLine = true; // 買いのブレークイーブンライン
bool InpShowSellLine = true; // 売りのブレークイーブンライン
double BufferPips = 2.0; // BE バッファ
int LabelShiftBars = 60; // 何本前のバーにラベルを置くか
double LabelOffsetPips = 4.0; // ライン ⇔ ラベルの距離
CTradingPanelStopManager g_stop_manager;
CTradingPanelPositionManager g_position_manager;
CTradingPanelBreakEvenLineManager g_break_even_manager;
CTradingPanelPanel g_panel;
//+------------------------------------------------------------------+
//| 起動時の処理
//+------------------------------------------------------------------+
int OnInit()
{
g_stop_manager.Init(_Symbol, (ulong)magic_number, slippage);
g_position_manager.Init(_Symbol, (ulong)magic_number, slippage);
g_break_even_manager.Init(_Symbol, (ulong)magic_number);
g_panel.Init(exit_time_interval,
range_pips,
breakeven_pips,
stop_loss_offset_pips,
step_trigger_pips,
step_move_pips,
default_sl,
take_profit_pips,
tp_edit_pips,
stop_offset_pips);
// EA設定変更用のパネルを表示
if (!g_panel.CreatePanel(input_lock))
return INIT_FAILED;
g_panel.SetInitialValues();
// Backfill missing initial stops for existing matching positions.
g_position_manager.ApplyInitialStops(gl_default_sl_pips, gl_take_profit_pips);
// タイマーをセット
EventSetTimer(TimerPeriod_sec);
return (INIT_SUCCEEDED); // 成功コードを明示しておく
}
//+------------------------------------------------------------------+
//| 削除時の処理
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
// EA適用後のプロパティで変更すると、EAを再読み込みする。
g_panel.Destroy(reason);
// トータルブレークイーブンラインを削除
if (InpShowBuyLine)
g_break_even_manager.DeleteLine(BE_BUY);
if (InpShowSellLine)
g_break_even_manager.DeleteLine(BE_SELL);
// EAが削除された際にコメントを消す
Comment("");
}
//+------------------------------------------------------------------+
//| タイマー処理
//+------------------------------------------------------------------+
void OnTimer()
{
// 時間状態の変化を検知
HandleTradingTimeTransition();
// ティックが少ない時間帯でも時間制限クローズを監視する。
g_position_manager.CloseTimedPositions(POSITION_TYPE_BUY, ORDER_TYPE_SELL,
timelimit_exit, gl_exitTimeIntervalInSeconds, slippage);
g_position_manager.CloseTimedPositions(POSITION_TYPE_SELL, ORDER_TYPE_BUY,
timelimit_exit, gl_exitTimeIntervalInSeconds, slippage);
// 取引時間が指定時間内か確認
if (!IsTradingTime())
return;
}
//+------------------------------------------------------------------+
//| ティック毎の処理
//+------------------------------------------------------------------+
void OnTick()
{
// 時間状態の変化を検知
HandleTradingTimeTransition();
// EAの設定を画面上に表示
DisplayEAValues();
// 時間制限クローズは取引時間フィルターとは独立して実行する。
g_position_manager.CloseTimedPositions(POSITION_TYPE_BUY, ORDER_TYPE_SELL,
timelimit_exit, gl_exitTimeIntervalInSeconds, slippage);
g_position_manager.CloseTimedPositions(POSITION_TYPE_SELL, ORDER_TYPE_BUY,
timelimit_exit, gl_exitTimeIntervalInSeconds, slippage);
// 取引時間が指定時間内か確認
if (!IsTradingTime())
return;
// レート急伸SL
g_stop_manager.HighVolatilityLimit();
//------------------------------------
// ブレークイーブン / トレールストップ監視
//------------------------------------
g_stop_manager.ManageStops(enable_breakeven,
gl_breakeven_pips,
gl_stop_loss_offset_pips,
gl_step_trigger_pips,
gl_step_move_pips);
g_break_even_manager.ManageBuy(buy_total_be_flg && InpShowBuyLine,
buy_total_be_flg,
BufferPips,
LabelShiftBars,
LabelOffsetPips,
gl_default_sl_pips,
g_stop_manager);
g_break_even_manager.ManageSell(sell_total_be_flg && InpShowSellLine,
sell_total_be_flg,
BufferPips,
LabelShiftBars,
LabelOffsetPips,
gl_default_sl_pips,
g_stop_manager);
// 保有ポジションの確認
buy_position = g_position_manager.CountPositions(POSITION_TYPE_BUY, magic_number);
sell_position = g_position_manager.CountPositions(POSITION_TYPE_SELL, magic_number);
}
//+------------------------------------------------------------------+
//| 取引時間を指定する関数
//+------------------------------------------------------------------+
bool IsTradingTime()
{
// 取引時間が有効化されていない場合、常にtrueを返す
if (!isTradingTimeEnabled)
{
return true;
}
MqlDateTime structTime;
TimeCurrent(structTime);
structTime.sec = 0;
structTime.hour = TradeStartHour;
structTime.min = TradeStartMin;
datetime timeStart = StructToTime(structTime);
structTime.hour = TradeEndHour;
structTime.min = TradeEndMin;
datetime timeEnd = StructToTime(structTime);
// エラーチェック
if (TradeStartHour >= TradeEndHour && TradeStartMin >= TradeEndMin)
{
Print("Error: Invalid Time input");
return false;
}
// 現在の時間を取得
datetime now = TimeCurrent();
// 時間内かどうかをチェック
return (now >= timeStart && now < timeEnd);
}
//+------------------------------------------------------------------+
//| 取引時間内外に状態が変化した時の初期化処理
//+------------------------------------------------------------------+
void HandleTradingTimeTransition()
{
bool nowInTradingTime = IsTradingTime();
// --- 時間内に入った瞬間 ---
if (nowInTradingTime && !wasInTradingTime)
{
if (!beforeTradingInitDone)
{
Print("取引時間内 初期化処理");
beforeTradingInitDone = true;
}
afterTradingInitDone = false;
}
// --- 時間外に出た瞬間 ---
if (!nowInTradingTime && wasInTradingTime)
{
if (!afterTradingInitDone)
{
Print("取引時間外 初期化処理");
afterTradingInitDone = true;
}
beforeTradingInitDone = false;
}
wasInTradingTime = nowInTradingTime;
}
//+------------------------------------------------------------------+
//| pipsを価格に換算する関数
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
// 出力処理を関数にまとめる
//+------------------------------------------------------------------+
void DisplayEAValues()
{
Comment("\n",
"ブレークイーブン: ", (int)gl_breakeven_pips, "pips\n",
"時間制限クローズ: ", timelimit_exit ? "ON" : "OFF",
" | 保有時間: ", gl_exitTimeIntervalInSeconds / 3600, "時間\n",
"------------------------------------------------------------------------------------\n");
}
// +------------------------------------------------------------------+
// | チャートイベントのハンドラ
// +------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
ENUM_POSITION_TYPE tp_side = POSITION_TYPE_ALL;
double tp_adjust_pips = 0.0;
if (g_panel.HandleChartEvent(id,
lparam,
dparam,
sparam,
exit_time_interval,
range_pips,
breakeven_pips,
stop_loss_offset_pips,
step_trigger_pips,
step_move_pips,
default_sl,
take_profit_pips,
tp_edit_pips,
stop_offset_pips,
timelimit_exit,
input_lock,
buy_total_be_flg,
sell_total_be_flg,
gl_exitTimeIntervalInSeconds,
gl_breakeven_pips,
gl_stop_loss_offset_pips,
gl_step_trigger_pips,
gl_step_move_pips,
gl_default_sl_pips,
gl_take_profit_pips,
gl_stop_offset_pips,
tp_side,
tp_adjust_pips))
{
g_position_manager.AdjustTakeProfit(tp_adjust_pips, tp_side);
}
}
//------------------------------------------------------------------
// 取引イベントコールバック(再エントリーを防止)
//------------------------------------------------------------------
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
bool recalc_needed = false; // ポジション再集計フラグ
// 1) Deal が追加された(約定)
if (trans.type == TRADE_TRANSACTION_DEAL_ADD)
{
recalc_needed = true;
//---- Deal 詳細を取得 --------------------------------------
if (HistoryDealSelect(trans.deal)) // Deal を選択
{
ENUM_DEAL_REASON deal_reason = (ENUM_DEAL_REASON)
HistoryDealGetInteger(trans.deal, DEAL_REASON);
ENUM_DEAL_ENTRY deal_entry = (ENUM_DEAL_ENTRY)
HistoryDealGetInteger(trans.deal, DEAL_ENTRY);
//==== ★ クローズ条件(手動 or SL/TP ===================
bool is_close =
(deal_entry == DEAL_ENTRY_OUT) &&
(deal_reason == DEAL_REASON_CLIENT || // 手動決済
deal_reason == DEAL_REASON_MOBILE || // スマホアプリ決済
deal_reason == DEAL_REASON_WEB || // WEB版決済
deal_reason == DEAL_REASON_EXPERT || // EAのタイマー決済
deal_reason == DEAL_REASON_SL || // SL ヒット(部分/全量とも)
deal_reason == DEAL_REASON_TP); // TP ヒット(部分/全量とも)
if (is_close)
{
Print("Position closed (", EnumToString(deal_reason), ") — EA waits for next prediction.");
}
}
}
// 2) サーバ側でポジション内容が変更 (数量減少・SL変更等)
else if (trans.type == TRADE_TRANSACTION_POSITION)
{
recalc_needed = true;
}
// 3) 必要に応じてポジション再集計
if (recalc_needed)
{
g_position_manager.CheckPositions(buy_position, sell_position, last_buy_time, last_sell_time);
g_position_manager.ApplyInitialStops(gl_default_sl_pips, gl_take_profit_pips);
}
}
+34 -2
View File
@@ -512,14 +512,46 @@ bool IsProcessResultReady(const string done_file, const string running_file, con
if(!FileIsExist(result_file))
{
Print("[", label, "] done exists but result file is missing: ", result_file);
return false;
Print("[", label, "] done exists but result file is missing: ", result_file);
DeleteDoneFile(done_file);
DeleteRunningFile(running_file);
ResetExternalProcessState(process);
MarkProcessRetryPending(label);
return false;
}
DeleteRunningFile(running_file);
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/**
* @brief Mark a missing-result Python run for immediate retry on the next tick.
*/
void MarkProcessRetryPending(const string label)
{
if(label == "trend")
{
g_ea.trend_state = MARKET_TECHNICAL_ERROR_STOP;
g_ea.load_trend_flg = false;
g_init_trend_pending = true;
return;
}
if(label == "entry")
{
g_ea.res_chk = 0;
g_ea.zone_res_chk = 0;
g_ea.load_target_flg = false;
g_bars_H1_check = false;
g_bars_M15_check = false;
g_ea.chk_cnt = 0;
g_init_entry_pending = true;
}
}
//+------------------------------------------------------------------+
//| Python開始可能状態を返す関数
//+------------------------------------------------------------------+
@@ -25,24 +25,6 @@ bool GetTickContext(TickContext &ctx)
return true;
}
//+------------------------------------------------------------------+
//| 期限切れ注文・期限切れポジションを処理する関数
//+------------------------------------------------------------------+
/**
* @brief 期限切れの未約定注文と保有ポジションを処理します。
*
* 未約定注文はENTRY_H1_LIMIT時間、保有ポジションはCLOSE_H1_LIMIT時間を基準に判定します。
* 新規注文条件とは独立して、OnTickの早い段階で実行される想定です。
*/
void ManageExpiredTrades()
{
if(OrdersTotal() > 0)
CancelExpiredOrders();
if(PositionsTotal() > 0)
CloseExpiredPositions();
}
//+------------------------------------------------------------------+
//| H4更新検知とトレンド判定Python起動を処理する関数
//+------------------------------------------------------------------+
@@ -0,0 +1,289 @@
#ifndef HIT_RUNTIME_CONTROLLER_MQH
#define HIT_RUNTIME_CONTROLLER_MQH
//+------------------------------------------------------------------+
//| ティック情報を取得する関数
//+------------------------------------------------------------------+
/**
* @brief 現在のAsk/Bid/スプレッド情報を取得してTickContextへ格納します。
*
* @param ctx 取得したティック情報を格納する構造体参照。
* @return 取得成功時はtrue、ティック情報を取得できない場合はfalse。
*/
bool GetTickContext(TickContext &ctx)
{
MqlTick last_tick;
if(!SymbolInfoTick(_Symbol, last_tick))
return false;
ctx.ask = last_tick.ask;
ctx.bid = last_tick.bid;
ctx.spread_points = MathRound((ctx.ask - ctx.bid) / Point());
ctx.spread = ctx.spread_points * Point();
ctx.digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
return true;
}
//+------------------------------------------------------------------+
//| 期限切れ注文・期限切れポジションを処理する関数
//+------------------------------------------------------------------+
/**
* @brief 期限切れの未約定注文と保有ポジションを処理します。
*
* 未約定注文はENTRY_H1_LIMIT時間、保有ポジションはCLOSE_H1_LIMIT時間を基準に判定します。
* 新規注文条件とは独立して、OnTickの早い段階で実行される想定です。
*/
void ManageExpiredTrades()
{
if(OrdersTotal() > 0)
CancelExpiredOrders();
if(PositionsTotal() > 0)
CloseExpiredPositions();
}
//+------------------------------------------------------------------+
//| H4更新検知とトレンド判定Python起動を処理する関数
//+------------------------------------------------------------------+
/**
* @brief H4新バーまたは初回起動を検知し、トレンド判定Pythonを起動します。
*
* @param state EA全体の状態。トレンド更新開始フラグを更新します。
*
* Python処理中はdoneファイルが存在しないため、CSVの上書きと二重起動を抑止します。
*/
void ProcessTrendUpdate(EAState &state)
{
int current_bars_H4 = iBars(NULL, PERIOD_H4);
if(g_pre_bars_H4 == 0)
g_pre_bars_H4 = current_bars_H4;
int bars_H4_change = current_bars_H4 - g_pre_bars_H4;
bool trend_trigger = (bars_H4_change > 0 || g_init_trend_pending);
if(!trend_trigger)
return;
if(RecordOHLCAndExecuteBatch_Trend(state))
{
g_init_trend_pending = false;
g_pre_bars_H4 = current_bars_H4;
}
}
//+------------------------------------------------------------------+
//| トレンド判定Pythonの完了状態を返す関数
//+------------------------------------------------------------------+
/**
* @brief H4トレンド判定Pythonの完了状態を確認します。
*
* @return `process_done_trend.txt` が存在する場合はtrue、未完了の場合はfalse。
*/
bool IsTrendResultReady()
{
return IsProcessResultReady(done_trend_file, running_trend_file, trend_state_file, "trend", g_trend_process);
}
//+------------------------------------------------------------------+
//| トレンド判定結果をEA状態へ反映する関数
//+------------------------------------------------------------------+
/**
* @brief 完了済みのH4トレンド判定結果をEA状態へ反映します。
*
* @param state EA全体の状態。`trend_state` と最終更新時刻が更新されます。
*/
void RefreshTrendState(EAState &state)
{
GetTrendState(state);
}
//+------------------------------------------------------------------+
//| H1更新検知とエントリー価格生成Python起動を処理する関数
//+------------------------------------------------------------------+
/**
* @brief H1新バーまたは初回起動を検知し、エントリー価格生成Pythonを起動します。
*
* @param state EA全体の状態。ターゲット価格更新開始フラグや判定リトライ状態を更新します。
*
* Python処理中はdoneファイルが存在しないため、H1 CSVの上書きと二重起動を抑止します。
*/
void ProcessEntryUpdate(EAState &state)
{
int current_bars_H1 = iBars(NULL, PERIOD_H1);
if(g_pre_bars_H1 == 0)
g_pre_bars_H1 = current_bars_H1;
int bars_H1_change = current_bars_H1 - g_pre_bars_H1;
bool entry_trigger = (bars_H1_change > 0 || g_init_entry_pending);
if(!entry_trigger)
return;
if(RecordOHLCAndExecuteBatch_Entry(state))
{
g_init_entry_pending = false;
g_bars_H1_check = true;
state.chk_cnt = 0;
state.last_chk = 0;
g_pre_bars_H1 = current_bars_H1;
}
}
//+------------------------------------------------------------------+
//| M15更新検知とエントリータイミング判定トリガーを処理する関数
//+------------------------------------------------------------------+
/**
* @brief M15新バーを検知し、H1候補価格の発注判定を実行できる状態にします。
*
* M15は方向判定を上書きする足ではなく、H4/H1で決めた候補価格を発注する
* タイミング確認として使います。初回は直近の確定M15足で一度だけ判定可能にします。
*/
void ProcessM15EntryTimingUpdate()
{
int current_bars_M15 = iBars(NULL, PERIOD_M15);
if(current_bars_M15 <= 0)
return;
if(g_pre_bars_M15 == 0)
{
g_pre_bars_M15 = current_bars_M15;
g_bars_M15_check = true;
return;
}
int bars_M15_change = current_bars_M15 - g_pre_bars_M15;
if(bars_M15_change <= 0)
return;
g_bars_M15_check = true;
g_pre_bars_M15 = current_bars_M15;
}
//+------------------------------------------------------------------+
//| チャートコメント文字列を作成する関数
//+------------------------------------------------------------------+
/**
* @brief チャート左上に表示するステータスメッセージを組み立てます。
*
* @param ctx 現在のAsk/Bid/スプレッド情報。
* @return Comment()へ渡す表示用文字列。
*/
string BuildStatusMessage(TickContext &ctx)
{
string message = StringFormat(
" \nAsk: %." + IntegerToString(ctx.digits) + "f"
"\nBid: %." + IntegerToString(ctx.digits) + "f"
"\nSpread: %." + IntegerToString(ctx.digits) + "f"
"\nSpread Points: %.0f"
"\n\nLast Trend Update:\n %s"
"\n\nMarket State: %d (%s)"
"\n\nLast Target Update:\n %s"
"\n\nMy Used Count: %d / %d"
"\nSplit Zone: %s N=%d ZoneID=%s"
"\n\n[T1 Buy Stop ] en: %." + IntegerToString(ctx.digits) + "f tp: %." + IntegerToString(ctx.digits) + "f sl: %." + IntegerToString(ctx.digits) + "f"
"\n[T2 Buy Limit] en: %." + IntegerToString(ctx.digits) + "f tp: %." + IntegerToString(ctx.digits) + "f sl: %." + IntegerToString(ctx.digits) + "f"
"\n[T3 Sell Stop] en: %." + IntegerToString(ctx.digits) + "f tp: %." + IntegerToString(ctx.digits) + "f sl: %." + IntegerToString(ctx.digits) + "f"
"\n[T4 SellLimit] en: %." + IntegerToString(ctx.digits) + "f tp: %." + IntegerToString(ctx.digits) + "f sl: %." + IntegerToString(ctx.digits) + "f\n",
ctx.ask, ctx.bid, ctx.spread, ctx.spread_points,
TimeToString(g_ea.last_trend_update, TIME_DATE | TIME_MINUTES),
g_ea.trend_state, MarketStateName(g_ea.trend_state),
TimeToString(g_ea.last_target_update, TIME_DATE | TIME_MINUTES),
CountMyUsed(), EffectivePositionLimit(),
(use_split_entry_zone ? "ON" : "OFF"), EffectiveSplitEntryCount(), g_ea.zone_candidate_id,
g_ea.en_price[1], g_ea.tp_price[1], g_ea.sl_price[1],
g_ea.en_price[2], g_ea.tp_price[2], g_ea.sl_price[2],
g_ea.en_price[3], g_ea.tp_price[3], g_ea.sl_price[3],
g_ea.en_price[4], g_ea.tp_price[4], g_ea.sl_price[4]
);
return message;
}
//+------------------------------------------------------------------+
//| チャートコメントを更新する関数
//+------------------------------------------------------------------+
/**
* @brief チャート上のステータスコメントを更新します。
*
* @param ctx 現在のAsk/Bid/スプレッド情報。
*/
void UpdateStatusComment(TickContext &ctx)
{
Comment(BuildStatusMessage(ctx));
}
//+------------------------------------------------------------------+
//| market_stateの表示名を返す関数
//+------------------------------------------------------------------+
/**
* @brief H4 market_stateの人間可読名を返します。
*
* @param market_state Pythonが出力したH4環境分類(0..5、6は技術エラー停止)。
* @return 表示用ラベル。
*/
string MarketStateName(const int market_state)
{
switch(market_state)
{
case MARKET_LOW_VOL_RANGE:
return "LOW_VOL_RANGE";
case MARKET_HIGH_VOL_RANGE:
return "HIGH_VOL_RANGE";
case MARKET_LOW_VOL_UP:
return "LOW_VOL_UP";
case MARKET_HIGH_VOL_UP:
return "HIGH_VOL_UP";
case MARKET_LOW_VOL_DOWN:
return "LOW_VOL_DOWN";
case MARKET_HIGH_VOL_DOWN:
return "HIGH_VOL_DOWN";
case MARKET_TECHNICAL_ERROR_STOP:
return "TECHNICAL_ERROR_STOP";
default:
return "UNKNOWN";
}
}
//+------------------------------------------------------------------+
//| スプレッドが許容範囲内か判定する関数
//+------------------------------------------------------------------+
/**
* @brief 現在スプレッドが入力パラメータの許容範囲内か判定します。
*
* @param ctx 現在のスプレッド情報。
* @return 許容範囲内ならtrue、超過している場合はfalse。
*/
bool IsSpreadAllowed(TickContext &ctx)
{
return (ctx.spread <= spread_limit * Point());
}
//+------------------------------------------------------------------+
//| エントリー価格生成Pythonの完了状態を返す関数
//+------------------------------------------------------------------+
/**
* @brief H1エントリー価格生成Pythonの完了状態を確認します。
*
* @return `process_done_entry.txt` が存在する場合はtrue、未完了の場合はfalse。
*/
bool IsEntryResultReady()
{
return IsProcessResultReady(done_entry_file, running_entry_file, target_prices_file, "entry", g_entry_process);
}
//+------------------------------------------------------------------+
//| ターゲット価格をEA状態へ反映する関数
//+------------------------------------------------------------------+
/**
* @brief 完了済みのH1エントリー価格生成結果をEA状態へ反映します。
*
* @param state EA全体の状態。`res_chk` と各注文タイプのen/tp/slが更新されます。
*/
void RefreshTargetPrices(EAState &state)
{
GetTargetPrices(state);
}
//+------------------------------------------------------------------+
#endif
+202 -19
View File
@@ -1,6 +1,131 @@
#ifndef HIT_ENTRY_SIGNAL_MQH
#define HIT_ENTRY_SIGNAL_MQH
//+------------------------------------------------------------------+
//| TP expansion settings
//+------------------------------------------------------------------+
double EffectiveTpMultiplier()
{
double multiplier = input_tp_multiplier;
if(multiplier < 1.0)
multiplier = 1.0;
if(multiplier > 100.0)
multiplier = 100.0;
return multiplier;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double EffectiveMinTpPoints()
{
if(input_min_tp_points <= 0)
return 0.0;
return (double)input_min_tp_points;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double EffectiveMaxTpPoints()
{
if(input_max_tp_points <= 0)
return 0.0;
return (double)input_max_tp_points;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsBuyTargetOrderType(const int orderType)
{
return (orderType == 1 || orderType == 2);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsSellTargetOrderType(const int orderType)
{
return (orderType == 3 || orderType == 4);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsTakeProfitDirectionValid(const int orderType, const double en, const double tp)
{
if(IsBuyTargetOrderType(orderType))
return (tp > en);
if(IsSellTargetOrderType(orderType))
return (tp < en);
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double ExpandedTakeProfitPrice(const int orderType, const double en, const double api_tp)
{
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double normalized_api_tp = NormalizeDouble(api_tp, digits);
if(en <= 0.0 || api_tp <= 0.0)
return normalized_api_tp;
if(!IsTakeProfitDirectionValid(orderType, en, api_tp))
{
Print("[TP Adjust Skip] invalid API TP direction. orderType=", orderType,
" en=", en, " api_tp=", api_tp);
return normalized_api_tp;
}
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
if(point <= 0.0)
point = Point();
if(point <= 0.0)
return normalized_api_tp;
double base_points = MathAbs(api_tp - en) / point;
if(base_points <= 0.0)
return normalized_api_tp;
double final_points = base_points * EffectiveTpMultiplier();
double min_points = EffectiveMinTpPoints();
double max_points = EffectiveMaxTpPoints();
if(min_points > 0.0 && final_points < min_points)
final_points = min_points;
if(max_points > 0.0 && final_points > max_points)
final_points = max_points;
// Never make the final target closer than the API-provided TP.
if(final_points < base_points)
final_points = base_points;
double final_tp = 0.0;
if(IsBuyTargetOrderType(orderType))
final_tp = en + final_points * point;
else
final_tp = en - final_points * point;
final_tp = NormalizeDouble(final_tp, digits);
if(MathAbs(final_tp - normalized_api_tp) >= point * 0.5)
Print("[TP Adjust] orderType=", orderType,
" en=", en,
" api_tp=", normalized_api_tp,
" final_tp=", final_tp,
" base_points=", DoubleToString(base_points, 1),
" final_points=", DoubleToString(final_points, 1),
" multiplier=", DoubleToString(EffectiveTpMultiplier(), 2));
return final_tp;
}
//| エントリー判定が必要な場合のみ注文処理を実行する関数
//+------------------------------------------------------------------+
/**
@@ -198,6 +323,22 @@ string TargetCandidateAgeText(EAState &state)
return IntegerToString(age_seconds) + "s";
}
//+------------------------------------------------------------------+
//| pending注文コメントへ付与するH1候補IDを返す関数
//+------------------------------------------------------------------+
/**
* @brief 復元済みのH1確定足時刻がある場合だけ候補IDをコメントへ付与します。
*/
string TargetCandidateCommentSuffix(EAState &state)
{
if(state.target_candidate_at <= 0 ||
state.zone_candidate_id == "" ||
state.zone_candidate_id == "0")
return "";
return "Z" + state.zone_candidate_id;
}
//+------------------------------------------------------------------+
//| 許可された注文タイプだけを順番に送信する関数
//+------------------------------------------------------------------+
@@ -267,9 +408,10 @@ string TwoDigit(const int value)
//+------------------------------------------------------------------+
//| 分割slot識別子を作る関数
//+------------------------------------------------------------------+
string SplitSlotKey(const string candidate_id, const int slot_index, const int split_count)
string SplitSlotKey(const int orderType, const string candidate_id, const int slot_index, const int split_count)
{
return "Z" + candidate_id + "#" + TwoDigit(slot_index) + "/" + TwoDigit(split_count);
return "Z" + candidate_id + "#T" + IntegerToString(orderType) + "-" +
TwoDigit(slot_index) + "/" + TwoDigit(split_count);
}
//+------------------------------------------------------------------+
@@ -285,6 +427,19 @@ double SplitEntryPrice(const double zone_low, const double zone_high, const int
return NormalizeDouble(zone_low + (zone_high - zone_low) * ratio, digits);
}
//+------------------------------------------------------------------+
//| Split-zone TP reference price
//+------------------------------------------------------------------+
double SplitTakeProfitReferenceEntry(const int orderType, const double zone_low, const double zone_high)
{
if(IsBuyTargetOrderType(orderType))
return zone_high;
if(IsSellTargetOrderType(orderType))
return zone_low;
return (zone_low + zone_high) / 2.0;
}
//+------------------------------------------------------------------+
//| 注文ロットがブローカー制約を満たすか判定する関数
//+------------------------------------------------------------------+
@@ -436,15 +591,26 @@ int TrySendSplitEntryOrders(const int orderType, EAState &state, TickContext &ct
{
string entry_type = EntryTypeName(orderType);
double cur_price = CurrentPriceForOrderType(orderType, ctx);
string guard_reason = "";
if(IsLimitOrderBlockedByRangeBreakoutGuard(orderType, guard_reason))
{
Print("[Split Skip] ", entry_type, " blocked by range breakout guard. ", guard_reason);
return 0;
}
double zone_low = state.zone_low[orderType];
double zone_high = state.zone_high[orderType];
double tp = state.zone_tp[orderType];
double raw_tp = state.zone_tp[orderType];
double tp = ExpandedTakeProfitPrice(orderType,
SplitTakeProfitReferenceEntry(orderType, zone_low, zone_high),
raw_tp);
double sl = state.zone_sl[orderType];
if(!HasValidZonePrices(zone_low, zone_high, tp, sl))
{
Print("[Split Skip] invalid target zone. orderType=", orderType,
" zone=", zone_low, "-", zone_high, " tp=", tp, " sl=", sl,
" zone=", zone_low, "-", zone_high,
" api_tp=", raw_tp, " tp=", tp, " sl=", sl,
" candidate_id=", state.zone_candidate_id);
return 0;
}
@@ -482,7 +648,7 @@ int TrySendSplitEntryOrders(const int orderType, EAState &state, TickContext &ct
break;
}
string slot_key = SplitSlotKey(state.zone_candidate_id, slot, split_count);
string slot_key = SplitSlotKey(orderType, state.zone_candidate_id, slot, split_count);
if(HasExistingSplitSlot(slot_key))
{
Print("[Split Skip] slot already exists. key=", slot_key);
@@ -490,29 +656,34 @@ int TrySendSplitEntryOrders(const int orderType, EAState &state, TickContext &ct
}
double en = SplitEntryPrice(zone_low, zone_high, slot, split_count);
if(!IsTargetPriceOrderConditionMatched(orderType, ctx, en, tp, sl))
double slot_tp = ExpandedTakeProfitPrice(orderType, en, raw_tp);
if(!IsTargetPriceOrderConditionMatched(orderType, ctx, en, slot_tp, sl))
{
Print("[Split Skip] slot price no longer valid. key=", slot_key,
" cur=", cur_price, " en=", en, " tp=", tp, " sl=", sl);
" cur=", cur_price, " en=", en,
" api_tp=", raw_tp, " tp=", slot_tp, " sl=", sl);
continue;
}
if(!MeetsTradeDistanceRules(orderType, ctx, en, tp, sl))
if(!MeetsTradeDistanceRules(orderType, ctx, en, slot_tp, sl))
continue;
Print("[Split ", entry_type, " Order Try] key=", slot_key,
" en=", en, " tp=", tp, " sl=", sl, " volume=", volume);
" en=", en, " api_tp=", raw_tp, " tp=", slot_tp,
" sl=", sl, " volume=", volume);
if(SendOrder(orderType, en, tp, sl, volume, slot_key))
if(SendOrder(orderType, en, slot_tp, sl, volume, slot_key, TargetCandidateReferenceTime(state)))
{
Print("[Split ", entry_type, " Order Sent] key=", slot_key,
" en=", en, " tp=", tp, " sl=", sl, " volume=", volume);
" en=", en, " api_tp=", raw_tp, " tp=", slot_tp,
" sl=", sl, " volume=", volume);
sent_success++;
}
else
{
Print("[Split ", entry_type, " Order Failed] key=", slot_key,
" en=", en, " tp=", tp, " sl=", sl, " volume=", volume);
" en=", en, " api_tp=", raw_tp, " tp=", slot_tp,
" sl=", sl, " volume=", volume);
}
}
@@ -534,15 +705,22 @@ bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx)
{
string entry_type = EntryTypeName(orderType);
double cur_price = CurrentPriceForOrderType(orderType, ctx);
string guard_reason = "";
if(IsLimitOrderBlockedByRangeBreakoutGuard(orderType, guard_reason))
{
Print("[Skip] ", entry_type, " blocked by range breakout guard. ", guard_reason);
return false;
}
double en = state.en_price[orderType];
double tp = state.tp_price[orderType];
double raw_tp = state.tp_price[orderType];
double tp = ExpandedTakeProfitPrice(orderType, en, raw_tp);
double sl = state.sl_price[orderType];
if(!HasValidTargetPrices(en, tp, sl))
{
Print("[Skip] invalid target prices. orderType=", orderType,
" en=", en, " tp=", tp, " sl=", sl,
" en=", en, " api_tp=", raw_tp, " tp=", tp, " sl=", sl,
" candidate_age=", TargetCandidateAgeText(state));
return false;
}
@@ -550,7 +728,8 @@ bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx)
bool ok = IsTargetPriceOrderConditionMatched(orderType, ctx, en, tp, sl);
if(!ok)
{
Print("[No ", entry_type, "] cur=", cur_price, " en=", en, " tp=", tp, " sl=", sl,
Print("[No ", entry_type, "] cur=", cur_price, " en=", en,
" api_tp=", raw_tp, " tp=", tp, " sl=", sl,
" candidate_age=", TargetCandidateAgeText(state));
return false;
}
@@ -566,15 +745,19 @@ bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx)
if(!MeetsTradeDistanceRules(orderType, ctx, en, tp, sl))
return false;
Print("[", entry_type, " Order Try at ", cur_price, "] en=", en, " tp=", tp, " sl=", sl);
Print("[", entry_type, " Order Try at ", cur_price, "] en=", en,
" api_tp=", raw_tp, " tp=", tp, " sl=", sl);
if(SendOrder(orderType, en, tp, sl, lot_size, ""))
if(SendOrder(orderType, en, tp, sl, lot_size,
TargetCandidateCommentSuffix(state), TargetCandidateReferenceTime(state)))
{
Print("[", entry_type, " Order Sent] ticket ok. en=", en, " tp=", tp, " sl=", sl);
Print("[", entry_type, " Order Sent] ticket ok. en=", en,
" api_tp=", raw_tp, " tp=", tp, " sl=", sl);
return true;
}
Print("[", entry_type, " Order Failed] en=", en, " tp=", tp, " sl=", sl);
Print("[", entry_type, " Order Failed] en=", en,
" api_tp=", raw_tp, " tp=", tp, " sl=", sl);
return false;
}
File diff suppressed because it is too large Load Diff
@@ -218,25 +218,23 @@ bool TryParseStrictDouble(const string value, double &parsed)
//| H1候補IDを安全な12桁時刻トークンへ正規化する関数
//+------------------------------------------------------------------+
/**
* @brief Pythonから受け取ったcandidate_idを注文コメントに使える数字だけへ丸めます。
* @brief Pythonから受け取ったcandidate_idが厳格な12桁数字の場合だけ採用します。
*/
string NormalizeTargetCandidateId(const string value)
{
string text = TrimText(value);
string output = "";
int length = StringLen(text);
for(int i = 0; i < length && StringLen(output) < 12; i++)
{
int ch = StringGetCharacter(text, i);
if(IsDecimalDigit(ch))
output += StringSubstr(text, i, 1);
}
if(StringLen(output) <= 0)
if(length != 12)
return "0";
return output;
for(int i = 0; i < length; i++)
{
int ch = StringGetCharacter(text, i);
if(!IsDecimalDigit(ch))
return "0";
}
return text;
}
//+------------------------------------------------------------------+
@@ -406,11 +404,13 @@ bool GetTrendState(EAState &state)
if(ProcessDone && g_ea.load_trend_flg)
{
int trend_state;
LoadTrendState(trend_state);
state.trend_state = trend_state;
Print("market_state: ", state.trend_state, " (", MarketStateName(state.trend_state), ")");
g_ea.load_trend_flg = false;
g_ea.last_trend_update = TimeLocal();
LoadTrendState(trend_state);
state.trend_state = trend_state;
Print("market_state: ", state.trend_state, " (", MarketStateName(state.trend_state), ")");
CancelPendingOrdersNotAllowedByTrend(state.trend_state);
g_init_entry_pending = true; // Rebuild H1 candidates from the refreshed H4 state.
g_ea.load_trend_flg = false;
g_ea.last_trend_update = TimeLocal();
}
return true;
}
@@ -685,6 +685,13 @@ void LoadTargetZones(EAState &state)
datetime candidate_at = 0;
if(TryParseTargetCandidateTime(state.zone_candidate_id, candidate_at))
state.target_candidate_at = candidate_at;
else if(state.zone_res_chk == 1)
{
Print("target_zones invalid candidate_id: ", line);
FileClose(filehandle);
ResetTargetZones(state);
return;
}
else
state.target_candidate_at = 0;
continue;
@@ -0,0 +1,725 @@
#ifndef HIT_PYTHON_SIGNAL_GATEWAY_MQH
#define HIT_PYTHON_SIGNAL_GATEWAY_MQH
//+------------------------------------------------------------------+
//| 最新のOHLCデータを取得する関数
//+------------------------------------------------------------------+
/**
* @brief 指定時間足のOHLCデータを取得します。
*
* @param times 取得したバー時刻を格納する配列。
* @param open_prices 取得したOpen価格を格納する配列。
* @param high_prices 取得したHigh価格を格納する配列。
* @param low_prices 取得したLow価格を格納する配列。
* @param close_prices 取得したClose価格を格納する配列。
* @param tf 取得対象の時間足。
* @param bars_count 取得するバー本数。
* @return 取得に成功した場合はtrue、失敗した場合はfalse。
*
* `OHLC_START_SHIFT=1` のため、形成中のバーではなく確定足から取得します。
*/
bool GetLatestOHLC(datetime &times[], double &open_prices[], double &high_prices[], double &low_prices[], double &close_prices[], ENUM_TIMEFRAMES tf, int bars_count)
{
ArrayResize(times, 0);
ArrayResize(open_prices, 0);
ArrayResize(high_prices, 0);
ArrayResize(low_prices, 0);
ArrayResize(close_prices, 0);
if(bars_count < 2)
return false;
// OHLCデータを取得
// CopyTime と CopyRates を別々に呼ばず、MqlRates の time/open/high/low/close を同一配列から取得する。
// OHLC_START_SHIFT=1 のため、形成中の0本目ではなく確定足からPythonへ渡す。
MqlRates rates[];
int copied = CopyRates(_Symbol, tf, OHLC_START_SHIFT, bars_count, rates);
if(copied <= 0)
{
Print(__FUNCTION__, ": Failed to copy rates data (bars=", bars_count, ") err=", GetLastError());
return false;
}
ArrayResize(times, copied);
ArrayResize(open_prices, copied);
ArrayResize(high_prices, copied);
ArrayResize(low_prices, copied);
ArrayResize(close_prices, copied);
// 必要なデータを配列に格納
for(int i = 0; i < copied; i++)
{
times[i] = rates[i].time;
open_prices[i] = rates[i].open;
high_prices[i] = rates[i].high;
low_prices[i] = rates[i].low;
close_prices[i] = rates[i].close;
}
return true;
}
//+------------------------------------------------------------------+
//| "ohlc.csv"を出力する関数
//+------------------------------------------------------------------+
/**
* @brief OHLC配列をPython入力用CSVとして出力します。
*
* @param filename 出力するCSVファイル名。
* @param times バー時刻配列。
* @param open_prices Open価格配列。
* @param high_prices High価格配列。
* @param low_prices Low価格配列。
* @param close_prices Close価格配列。
* @return CSV出力に成功した場合はtrue。
*/
bool RecordOHLC(const string filename, const datetime &times[], const double &open_prices[], const double &high_prices[], const double &low_prices[], const double &close_prices[])
{
// 出力先ファイル名
// string filename = "ohlc.csv";
// ファイルを "書き込みモード" でオープン (テキスト/ANSI)
int fileHandle = FileOpen(filename, FILE_WRITE | FILE_TXT | FILE_ANSI);
// ファイルが開けたかチェック
if(fileHandle == INVALID_HANDLE)
{
Print(__FUNCTION__, " : Failed to open file: ", GetLastError());
return false;
}
// 配列サイズを取得 (times, open, high, low, close の要素数は同じ前提)
int size = ArraySize(times);
// ヘッダー行を追加
FileWrite(fileHandle, "Time,Open,High,Low,Close");
// 小数点の桁数を取得
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
// フォーマット文字列を動的に生成
string formatString = StringFormat("%%s,%%.%df,%%.%df,%%.%df,%%.%df", digits, digits, digits, digits);
// 1行ずつ "時刻, Open, High, Low, Close" の形式で書き込み
for(int i = 0; i < size; i++)
{
// 時間をフォーマット
string timeStr = TimeToString(times[i], TIME_DATE | TIME_MINUTES);
// 1行分の文字列を生成 (小数点以下の桁数を `digits` に調整)
string line = StringFormat(formatString,
timeStr, open_prices[i], high_prices[i], low_prices[i], close_prices[i]);
// ファイルに書き込み (改行付き)
FileWrite(fileHandle, line);
}
// 書き込み終了後、ファイルを閉じる
FileClose(fileHandle);
return true;
}
//+------------------------------------------------------------------+
//| 文字列の前後空白を除去する関数
//+------------------------------------------------------------------+
/**
* @brief Python連携ファイルから読んだ1行をパース前に正規化します。
*/
string TrimText(const string value)
{
string text = value;
StringTrimLeft(text);
StringTrimRight(text);
return text;
}
//+------------------------------------------------------------------+
//| 10進数字か判定する関数
//+------------------------------------------------------------------+
bool IsDecimalDigit(const int ch)
{
return (ch >= 48 && ch <= 57);
}
//+------------------------------------------------------------------+
//| 厳格な整数パース
//+------------------------------------------------------------------+
/**
* @brief 数字だけで構成された整数行を読み込みます。不正文字があればfalse。
*/
bool TryParseStrictInteger(const string value, int &parsed)
{
string text = TrimText(value);
int length = StringLen(text);
if(length <= 0)
return false;
for(int i = 0; i < length; i++)
{
if(!IsDecimalDigit(StringGetCharacter(text, i)))
return false;
}
parsed = (int)StringToInteger(text);
return true;
}
//+------------------------------------------------------------------+
//| 厳格な小数パース
//+------------------------------------------------------------------+
/**
* @brief 単純な10進数行を読み込みます。指数表記や余計な文字は許可しません。
*/
bool TryParseStrictDouble(const string value, double &parsed)
{
string text = TrimText(value);
int length = StringLen(text);
if(length <= 0)
return false;
bool has_digit = false;
bool has_dot = false;
int start_index = 0;
int first_char = StringGetCharacter(text, 0);
if(first_char == 43 || first_char == 45) // + or -
{
if(length == 1)
return false;
start_index = 1;
}
for(int i = start_index; i < length; i++)
{
int ch = StringGetCharacter(text, i);
if(IsDecimalDigit(ch))
{
has_digit = true;
continue;
}
if(ch == 46 && !has_dot) // dot
{
has_dot = true;
continue;
}
return false;
}
if(!has_digit)
return false;
parsed = StringToDouble(text);
return true;
}
//+------------------------------------------------------------------+
//| H1候補IDを安全な12桁時刻トークンへ正規化する関数
//+------------------------------------------------------------------+
/**
* @brief Pythonから受け取ったcandidate_idを注文コメントに使える数字だけへ丸めます。
*/
string NormalizeTargetCandidateId(const string value)
{
string text = TrimText(value);
string output = "";
int length = StringLen(text);
for(int i = 0; i < length && StringLen(output) < 12; i++)
{
int ch = StringGetCharacter(text, i);
if(IsDecimalDigit(ch))
output += StringSubstr(text, i, 1);
}
if(StringLen(output) <= 0)
return "0";
return output;
}
//+------------------------------------------------------------------+
//| H1候補IDから確定足時刻を復元する関数
//+------------------------------------------------------------------+
/**
* @brief `yyyyMMddHHmm` 形式のcandidate_idをdatetimeへ変換します。
*/
bool TryParseTargetCandidateTime(const string candidate_id, datetime &candidate_at)
{
candidate_at = 0;
string text = NormalizeTargetCandidateId(candidate_id);
if(StringLen(text) != 12)
return false;
int year = (int)StringToInteger(StringSubstr(text, 0, 4));
int month = (int)StringToInteger(StringSubstr(text, 4, 2));
int day = (int)StringToInteger(StringSubstr(text, 6, 2));
int hour = (int)StringToInteger(StringSubstr(text, 8, 2));
int minute = (int)StringToInteger(StringSubstr(text, 10, 2));
if(year < 2000 || month < 1 || month > 12 ||
day < 1 || day > 31 || hour < 0 || hour > 23 ||
minute < 0 || minute > 59)
return false;
string datetime_text = StringFormat("%04d.%02d.%02d %02d:%02d",
year, month, day, hour, minute);
datetime parsed = StringToTime(datetime_text);
if(parsed <= 0)
return false;
MqlDateTime parts;
TimeToStruct(parsed, parts);
if(parts.year != year || parts.mon != month || parts.day != day ||
parts.hour != hour || parts.min != minute)
return false;
candidate_at = parsed;
return true;
}
//+------------------------------------------------------------------+
//| バッチファイル(Pythonスクリプト)を実行する関数
//+------------------------------------------------------------------+
/**
* @brief H4トレンド判定用バッチファイルを起動します。
*
* @return 起動に成功した場合はtrue、Python実行中または起動失敗時はfalse。
*
* 起動直前に`process_done_trend.txt`を削除し、プロセスハンドルを保持して終了確認できる状態にします。
*/
bool ExecuteBatchTrend()
{
if(!IsProcessStartAllowed(done_trend_file, running_trend_file, "trend", g_trend_process))
return false;
DeleteDoneFile(done_trend_file);
int price_digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
return StartBatchProcess(get_trend_reply_bat, running_trend_file, "trend",
g_trend_process, mt5_file_prefix, price_digits);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/**
* @brief H1エントリー価格生成用バッチファイルを起動します。
*
* @return 起動に成功した場合はtrue、Python実行中または起動失敗時はfalse。
*
* 起動直前に`process_done_entry.txt`を削除し、プロセスハンドルを保持して終了確認できる状態にします。
*/
bool ExecuteBatchEntry()
{
if(!IsProcessStartAllowed(done_entry_file, running_entry_file, "entry", g_entry_process))
return false;
DeleteDoneFile(done_entry_file);
int price_digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
return StartBatchProcess(get_entry_reply_bat, running_entry_file, "entry",
g_entry_process, mt5_file_prefix, price_digits);
}
//+------------------------------------------------------------------+
//| "ohlc.csv"を出力後、バッチファイルの実行する関数
//+------------------------------------------------------------------+
/**
* @brief H4 OHLCをCSV出力し、トレンド判定Pythonを起動します。
*
* @param state EA全体の状態。トレンド読込待ちフラグを更新します。
* @return CSV出力とバッチ起動が開始できた場合はtrue。
*/
bool RecordOHLCAndExecuteBatch_Trend(EAState &state)
{
if(!IsProcessStartAllowed(done_trend_file, running_trend_file, "trend", g_trend_process))
{
Print("Trend Python is still running. Skip H4 CSV update.");
return false;
}
datetime times[];
double open_prices[], high_prices[], low_prices[], close_prices[];
if(!GetLatestOHLC(times, open_prices, high_prices, low_prices, close_prices,
PERIOD_H4, HISTORY_BARS))
{ Print("GetLatestOHLC(H4) failed."); return false; }
if(!RecordOHLC(ohlc_h4_file, times, open_prices, high_prices, low_prices, close_prices))
{ Print("RecordOHLC(H4) failed."); return false; }
if(!ExecuteBatchTrend())
return false;
state.load_trend_flg = true;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/**
* @brief H1 OHLCをCSV出力し、エントリー価格生成Pythonを起動します。
*
* @param state EA全体の状態。ターゲット価格読込待ちフラグを更新します。
* @return CSV出力とバッチ起動が開始できた場合はtrue。
*/
bool RecordOHLCAndExecuteBatch_Entry(EAState &state)
{
if(!IsProcessStartAllowed(done_entry_file, running_entry_file, "entry", g_entry_process))
{
Print("Entry Python is still running. Skip H1 CSV update.");
return false;
}
datetime times[];
double open_prices[], high_prices[], low_prices[], close_prices[];
if(!GetLatestOHLC(times, open_prices, high_prices, low_prices, close_prices,
PERIOD_H1, HISTORY_BARS))
{ Print("GetLatestOHLC(H1) failed."); return false; }
if(!RecordOHLC(ohlc_h1_file, times, open_prices, high_prices, low_prices, close_prices))
{ Print("RecordOHLC(H1) failed."); return false; }
if(!ExecuteBatchEntry())
return false;
state.load_target_flg = true;
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/**
* @brief Pythonが出力したトレンド判定結果を必要なタイミングで読み込みます。
*
* @param state EA全体の状態。H4 market_stateと更新フラグを更新します。
* @return 現状は常にtrue。
*/
bool GetTrendState(EAState &state)
{
bool ProcessDone = CheckDoneFile(done_trend_file);
if(ProcessDone && g_ea.load_trend_flg)
{
int trend_state;
LoadTrendState(trend_state);
state.trend_state = trend_state;
Print("market_state: ", state.trend_state, " (", MarketStateName(state.trend_state), ")");
g_ea.load_trend_flg = false;
g_ea.last_trend_update = TimeLocal();
}
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/**
* @brief `trend_state.txt` からH4 market_state判定値を読み込みます。
*
* @param trend_state 読み込んだ値を格納する参照。0..5のmarket_state。6は技術エラー停止。
*
* ファイル未存在、読込失敗、異常値の場合は安全側として6(技術エラー停止)を設定します。
*/
void LoadTrendState(int &trend_state)
{
string filename = trend_state_file;
trend_state = MARKET_TECHNICAL_ERROR_STOP;
if(FileIsExist(filename))
{
int filehandle = FileOpen(filename, FILE_READ | FILE_TXT);
if(filehandle != INVALID_HANDLE)
{
string line = FileReadString(filehandle);
int value = MARKET_TECHNICAL_ERROR_STOP;
if(TryParseStrictInteger(line, value) &&
value >= MARKET_LOW_VOL_RANGE && value <= MARKET_TECHNICAL_ERROR_STOP)
trend_state = value;
else
Print("Invalid market_state value: ", line, ". Use technical error stop(6).");
FileClose(filehandle);
}
else
{ Print("Failed to open trend_state.txt"); trend_state = MARKET_TECHNICAL_ERROR_STOP; }
}
else
{ Print("trend_state.txt not found"); trend_state = MARKET_TECHNICAL_ERROR_STOP; }
}
//+------------------------------------------------------------------+
//| ターゲット価格を取得する関数
//+------------------------------------------------------------------+
/**
* @brief Pythonが出力したエントリー価格群を必要なタイミングで読み込みます。
*
* @param state EA全体の状態。`res_chk` と4タイプ分のen/tp/slを更新します。
* @return 現状は常にtrue。
*/
bool GetTargetPrices(EAState &state)
{
bool ProcessDone = CheckDoneFile(done_entry_file); // ←変更
if(ProcessDone && g_ea.load_target_flg) // ←変更
{
double target_prices[];
LoadTargetPrices(target_prices);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
// 先頭は res_chk
state.res_chk = (int)target_prices[0];
// ★ 1..4 の (en,tp,sl) を読む:合計12個
for(int t=1; t<=4; t++)
{
int base = 1 + (t-1)*3; // 1,4,7,10
state.en_price[t] = NormalizeDouble(target_prices[base + 0], digits);
state.tp_price[t] = NormalizeDouble(target_prices[base + 1], digits);
state.sl_price[t] = NormalizeDouble(target_prices[base + 2], digits);
}
// ログ(任意)
Print("target_prices: res=", state.res_chk,
" | T1 en=", state.en_price[1], " tp=", state.tp_price[1], " sl=", state.sl_price[1],
" | T2 en=", state.en_price[2], " tp=", state.tp_price[2], " sl=", state.sl_price[2],
" | T3 en=", state.en_price[3], " tp=", state.tp_price[3], " sl=", state.sl_price[3],
" | T4 en=", state.en_price[4], " tp=", state.tp_price[4], " sl=", state.sl_price[4]);
LoadTargetZones(state);
if(use_split_entry_zone && cancel_old_split_pending_on_new_zone)
{
if(state.zone_res_chk == 1)
CancelStaleSplitPendingOrders(state.zone_candidate_id);
else
CancelStaleSplitPendingOrders("");
}
g_ea.load_target_flg = false; // ←変更
g_ea.last_target_update = TimeLocal(); // ←変更
g_ea.target_loaded_at = TimeCurrent();
}
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| "target_prices.txt"を読み込む関数
//+------------------------------------------------------------------+
/**
* @brief `target_prices.txt` から13個の数値を読み込みます。
*
* @param target_prices 読み込んだ数値を格納する配列。先頭がres_chk、以降は4タイプ分のen/tp/sl。
*
* 行数不足の場合は`res_chk=0`として、ターゲット価格を無効扱いにします。
*/
void LoadTargetPrices(double &target_prices[])
{
ArrayResize(target_prices, TARGET_SIZE);
for(int i = 0; i < TARGET_SIZE; i++)
target_prices[i] = DEFAULT_TARGET_PRICE;
string filename = target_prices_file;
if(FileIsExist(filename))
{
int filehandle = FileOpen(filename, FILE_READ | FILE_TXT);
if(filehandle != INVALID_HANDLE)
{
int i = 0;
bool parse_failed = false;
while(!FileIsEnding(filehandle) && i < TARGET_SIZE)
{
string line = FileReadString(filehandle);
double parsed = 0.0;
if(!TryParseStrictDouble(line, parsed))
{
Print("target_prices.txt invalid numeric line. index=", i, " line=", line);
parse_failed = true;
break;
}
target_prices[i] = parsed;
i++;
}
FileClose(filehandle);
if(parse_failed || i < TARGET_SIZE)
{
if(!parse_failed)
Print("target_prices.txt line count is short. loaded=", i, " required=", TARGET_SIZE);
for(int j = 0; j < TARGET_SIZE; j++)
target_prices[j] = DEFAULT_TARGET_PRICE;
target_prices[0] = 0; // 不完全なファイルは無効扱い
}
}
else
{
Print("Failed to open file. Error code: ", GetLastError());
}
}
else
{
Print("File does not exist: ", filename);
}
}
//+------------------------------------------------------------------+
//| target_zones.txt の状態を停止値へ初期化する関数
//+------------------------------------------------------------------+
void ResetTargetZones(EAState &state)
{
state.zone_res_chk = 0;
state.zone_candidate_id = "0";
state.target_candidate_at = 0;
for(int t = 1; t <= 4; t++)
{
state.zone_low[t] = 0.0;
state.zone_high[t] = 0.0;
state.zone_tp[t] = 0.0;
state.zone_sl[t] = 0.0;
}
}
//+------------------------------------------------------------------+
//| target_zones.txt の1戦略行を読み込む関数
//+------------------------------------------------------------------+
bool ParseTargetZoneLine(const string line, EAState &state, const int digits)
{
string parts[];
int count = StringSplit(line, StringGetCharacter(",", 0), parts);
if(count < 5)
return false;
int strategy = 0;
if(!TryParseStrictInteger(parts[0], strategy))
return false;
if(strategy < 1 || strategy > 4)
return false;
double zone_low = 0.0;
double zone_high = 0.0;
double zone_tp = 0.0;
double zone_sl = 0.0;
if(!TryParseStrictDouble(parts[1], zone_low) ||
!TryParseStrictDouble(parts[2], zone_high) ||
!TryParseStrictDouble(parts[3], zone_tp) ||
!TryParseStrictDouble(parts[4], zone_sl))
return false;
state.zone_low[strategy] = NormalizeDouble(zone_low, digits);
state.zone_high[strategy] = NormalizeDouble(zone_high, digits);
state.zone_tp[strategy] = NormalizeDouble(zone_tp, digits);
state.zone_sl[strategy] = NormalizeDouble(zone_sl, digits);
return true;
}
//+------------------------------------------------------------------+
//| target_zones.txt を読み込む関数
//+------------------------------------------------------------------+
void LoadTargetZones(EAState &state)
{
ResetTargetZones(state);
string filename = target_zones_file;
if(!FileIsExist(filename))
{
Print("target_zones.txt not found. Split entry zones disabled for this candidate.");
return;
}
int filehandle = FileOpen(filename, FILE_READ | FILE_TXT);
if(filehandle == INVALID_HANDLE)
{
Print("Failed to open target_zones.txt. Error code: ", GetLastError());
return;
}
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
int line_index = 0;
int loaded_strategies = 0;
while(!FileIsEnding(filehandle))
{
string line = FileReadString(filehandle);
if(line == "")
continue;
line_index++;
if(line_index == 1)
{
int schema_version = 0;
if(!TryParseStrictInteger(line, schema_version) ||
schema_version != TARGET_ZONE_SCHEMA_VERSION)
{
Print("target_zones schema mismatch. loaded=", line,
" required=", TARGET_ZONE_SCHEMA_VERSION);
FileClose(filehandle);
ResetTargetZones(state);
return;
}
continue;
}
if(line_index == 2)
{
int zone_res = 0;
if(!TryParseStrictInteger(line, zone_res))
{
Print("target_zones invalid res_chk line: ", line);
FileClose(filehandle);
ResetTargetZones(state);
return;
}
state.zone_res_chk = zone_res;
continue;
}
if(line_index == 3)
{
state.zone_candidate_id = NormalizeTargetCandidateId(line);
datetime candidate_at = 0;
if(TryParseTargetCandidateTime(state.zone_candidate_id, candidate_at))
state.target_candidate_at = candidate_at;
else
state.target_candidate_at = 0;
continue;
}
if(ParseTargetZoneLine(line, state, digits))
loaded_strategies++;
}
FileClose(filehandle);
if(line_index < 7 || loaded_strategies < 4)
{
Print("target_zones.txt line count is short. loaded_lines=", line_index,
" loaded_strategies=", loaded_strategies);
ResetTargetZones(state);
return;
}
if(state.zone_res_chk != 1)
ResetTargetZones(state);
Print("target_zones: res=", state.zone_res_chk,
" id=", state.zone_candidate_id,
" candidate_at=", TimeToString(state.target_candidate_at, TIME_DATE | TIME_MINUTES),
" | T1 zone=", state.zone_low[1], "-", state.zone_high[1],
" tp=", state.zone_tp[1], " sl=", state.zone_sl[1],
" | T2 zone=", state.zone_low[2], "-", state.zone_high[2],
" tp=", state.zone_tp[2], " sl=", state.zone_sl[2],
" | T3 zone=", state.zone_low[3], "-", state.zone_high[3],
" tp=", state.zone_tp[3], " sl=", state.zone_sl[3],
" | T4 zone=", state.zone_low[4], "-", state.zone_high[4],
" tp=", state.zone_tp[4], " sl=", state.zone_sl[4]);
}
//+------------------------------------------------------------------+
#endif
@@ -0,0 +1,172 @@
#ifndef HIT_POSITION_LIFECYCLE_MANAGER_MQH
#define HIT_POSITION_LIFECYCLE_MANAGER_MQH
#include <Trade/Trade.mqh>
// Ticket-based position lifecycle manager for hedging accounts.
class CHITPositionLifecycleManager
{
private:
string m_symbol;
ulong m_magic;
ulong m_deviation_points;
int m_close_after_seconds;
CTrade m_trade;
public:
CHITPositionLifecycleManager()
{
m_symbol = _Symbol;
m_magic = 0;
m_deviation_points = 10;
m_close_after_seconds = 0;
}
bool Init(const string symbol,
const ulong magic,
const ulong deviation_points,
const int close_after_seconds)
{
m_symbol = symbol;
m_magic = magic;
m_deviation_points = deviation_points;
m_close_after_seconds = close_after_seconds;
if(m_symbol == "")
{
Print("HITPositionLifecycleManager init failed: symbol is empty.");
return false;
}
ResetLastError();
if(!SymbolSelect(m_symbol, true))
{
Print("HITPositionLifecycleManager init failed: symbol=", m_symbol,
" err=", GetLastError());
return false;
}
m_trade.SetExpertMagicNumber(m_magic);
m_trade.SetDeviationInPoints((int)m_deviation_points);
m_trade.SetTypeFillingBySymbol(m_symbol);
return true;
}
void SetCloseAfterSeconds(const int close_after_seconds)
{
m_close_after_seconds = close_after_seconds;
}
int CountTargetPositions()
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
const ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
if(!PositionSelectByTicket(ticket))
continue;
if(!IsTargetSelectedPosition())
continue;
count++;
}
return count;
}
bool CloseExpiredPositions()
{
if(m_close_after_seconds <= 0)
return false;
bool result = false;
const datetime current_time = TimeCurrent();
for(int i = PositionsTotal() - 1; i >= 0; --i)
{
const ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
ResetLastError();
if(!PositionSelectByTicket(ticket))
{
Print("HITPositionLifecycleManager select failed: ticket=", ticket,
" err=", GetLastError());
continue;
}
if(!IsTargetSelectedPosition())
continue;
const datetime entry_time = (datetime)PositionGetInteger(POSITION_TIME);
if(entry_time <= 0)
continue;
if(current_time - entry_time < m_close_after_seconds)
continue;
if(CloseSelectedPosition(ticket, "time limit"))
result = true;
}
return result;
}
private:
bool IsTargetSelectedPosition()
{
if(PositionGetString(POSITION_SYMBOL) != m_symbol)
return false;
if((ulong)PositionGetInteger(POSITION_MAGIC) != m_magic)
return false;
return true;
}
string PositionTypeText(const ENUM_POSITION_TYPE type)
{
if(type == POSITION_TYPE_BUY)
return "BUY";
if(type == POSITION_TYPE_SELL)
return "SELL";
return "UNKNOWN";
}
bool CloseSelectedPosition(const ulong ticket,
const string reason)
{
const ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
const double volume = PositionGetDouble(POSITION_VOLUME);
ResetLastError();
if(!m_trade.PositionClose(ticket, m_deviation_points))
{
Print("HITPositionLifecycleManager close failed: ticket=", ticket,
" symbol=", m_symbol,
" magic=", m_magic,
" type=", PositionTypeText(type),
" volume=", DoubleToString(volume, 2),
" reason=", reason,
" retcode=", m_trade.ResultRetcode(),
" err=", GetLastError());
return false;
}
Print("HITPositionLifecycleManager closed position: ticket=", ticket,
" symbol=", m_symbol,
" magic=", m_magic,
" type=", PositionTypeText(type),
" volume=", DoubleToString(volume, 2),
" reason=", reason,
" retcode=", m_trade.ResultRetcode());
return true;
}
};
#endif
+584 -138
View File
@@ -73,10 +73,12 @@ int VolumeDigits()
* @param tp 利確価格。
* @param sl 損切価格。
* @param volume 注文ロット。
* @param comment_suffix 分割注文識別用のコメント接尾辞。空なら従来コメント。
* @param comment_suffix H1候補または分割注文識別用のコメント接尾辞。空なら従来コメント。
* @param candidate_reference_time H1候補の元になった確定足時刻。取得不能時は0。
* @return 注文が正常に受理された場合はtrue、それ以外はfalse。
*/
bool SendOrder(int orderType, double price, double tp, double sl, double volume, string comment_suffix)
bool SendOrder(int orderType, double price, double tp, double sl, double volume,
string comment_suffix, datetime candidate_reference_time)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
@@ -95,7 +97,8 @@ bool SendOrder(int orderType, double price, double tp, double sl, double volume,
// 指値または逆指値注文
request.action = TRADE_ACTION_PENDING;
ApplyPendingOrderExpiration(request);
if(!ApplyPendingOrderExpiration(request, candidate_reference_time))
return false;
switch(orderType)
{
@@ -178,35 +181,48 @@ ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol)
* @brief brokerが対応している範囲でpending orderにサーバー側の期限を設定します。
*
* @param request 更新対象の取引リクエスト。
* @param candidate_reference_time H1候補の元になった確定足時刻。取得不能時は0。
* @return H1候補の期限が残っている場合はtrue。発注前に期限切れならfalse。
*/
void ApplyPendingOrderExpiration(MqlTradeRequest &request)
bool ApplyPendingOrderExpiration(MqlTradeRequest &request, const datetime candidate_reference_time)
{
int expiration_seconds = ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1);
long expiration_mode = SymbolInfoInteger(request.symbol, SYMBOL_EXPIRATION_MODE);
datetime expiration_at = TimeCurrent() + expiration_seconds;
if(candidate_reference_time > 0)
expiration_at = candidate_reference_time + expiration_seconds;
if(expiration_seconds > 0 &&
(expiration_mode & SYMBOL_EXPIRATION_SPECIFIED) != 0)
if(expiration_seconds <= 0 || expiration_at <= TimeCurrent())
{
request.type_time = ORDER_TIME_SPECIFIED;
request.expiration = TimeCurrent() + expiration_seconds;
return;
Print("[Order Skip] H1 candidate expiration is not in the future. candidate_at=",
TimeToString(candidate_reference_time, TIME_DATE | TIME_SECONDS),
" expiration_at=", TimeToString(expiration_at, TIME_DATE | TIME_SECONDS));
return false;
}
if(expiration_seconds > 0 &&
(expiration_mode & SYMBOL_EXPIRATION_SPECIFIED_DAY) != 0)
long expiration_mode = SymbolInfoInteger(request.symbol, SYMBOL_EXPIRATION_MODE);
if((expiration_mode & SYMBOL_EXPIRATION_SPECIFIED) != 0)
{
request.type_time = ORDER_TIME_SPECIFIED;
request.expiration = expiration_at;
return true;
}
if((expiration_mode & SYMBOL_EXPIRATION_SPECIFIED_DAY) != 0)
{
request.type_time = ORDER_TIME_SPECIFIED_DAY;
request.expiration = TimeCurrent() + expiration_seconds;
return;
request.expiration = expiration_at;
return true;
}
if((expiration_mode & SYMBOL_EXPIRATION_DAY) != 0)
{
request.type_time = ORDER_TIME_DAY;
return;
return true;
}
request.type_time = ORDER_TIME_GTC;
return true;
}
//+------------------------------------------------------------------+
@@ -391,6 +407,549 @@ bool IsCurrentSplitCandidateComment(const string comment, const string candidate
return (StringFind(comment, "Z" + candidate_id + "#") >= 0);
}
//+------------------------------------------------------------------+
//| pending取消のticket単位クールダウン管理
//+------------------------------------------------------------------+
// Prevent repeated server-side cancel requests for the same pending ticket.
int EffectiveCancelRetryCooldownSeconds()
{
int cooldown = input_cancel_retry_cooldown_seconds;
if(cooldown < 1)
cooldown = 1;
if(cooldown > 3600)
cooldown = 3600;
return cooldown;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int FindPendingOrderCancelAttempt(const ulong ticket)
{
for(int i = ArraySize(g_cancel_retry_tickets) - 1; i >= 0; i--)
{
if(g_cancel_retry_tickets[i] == ticket)
return i;
}
return -1;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void RemovePendingOrderCancelAttemptAt(const int index)
{
int size = ArraySize(g_cancel_retry_tickets);
if(index < 0 || index >= size)
return;
int last = size - 1;
if(index != last)
{
g_cancel_retry_tickets[index] = g_cancel_retry_tickets[last];
g_cancel_retry_at[index] = g_cancel_retry_at[last];
}
ArrayResize(g_cancel_retry_tickets, last);
ArrayResize(g_cancel_retry_at, last);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ForgetPendingOrderCancelAttempt(const ulong ticket)
{
RemovePendingOrderCancelAttemptAt(FindPendingOrderCancelAttempt(ticket));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CanAttemptPendingOrderCancel(const ulong ticket)
{
int index = FindPendingOrderCancelAttempt(ticket);
if(index < 0)
return true;
return (TimeCurrent() - g_cancel_retry_at[index] >= EffectiveCancelRetryCooldownSeconds());
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void MarkPendingOrderCancelAttempt(const ulong ticket)
{
int index = FindPendingOrderCancelAttempt(ticket);
if(index >= 0)
{
g_cancel_retry_at[index] = TimeCurrent();
return;
}
int size = ArraySize(g_cancel_retry_tickets);
ArrayResize(g_cancel_retry_tickets, size + 1);
ArrayResize(g_cancel_retry_at, size + 1);
g_cancel_retry_tickets[size] = ticket;
g_cancel_retry_at[size] = TimeCurrent();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CleanupPendingOrderCancelAttempts()
{
for(int i = ArraySize(g_cancel_retry_tickets) - 1; i >= 0; i--)
{
if(!OrderSelect(g_cancel_retry_tickets[i]))
RemovePendingOrderCancelAttemptAt(i);
}
}
//+------------------------------------------------------------------+
//| pending取消要求を共通化する関数
//+------------------------------------------------------------------+
/**
* @brief 同一ticketへの取消要求をクールダウンし、取引サーバーへの過剰送信を防ぎます。
*/
bool TryCancelPendingOrder(const ulong ticket, const string reason)
{
if(ticket == 0 || !CanAttemptPendingOrderCancel(ticket))
return false;
MarkPendingOrderCancelAttempt(ticket);
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
request.action = TRADE_ACTION_REMOVE;
request.order = ticket;
ResetLastError();
if(!OrderSend(request, trade_result))
{
Print("Failed to delete order. Ticket: ", ticket,
" Reason: ", reason, " Error: ", GetLastError(),
" RetryAfterSeconds: ", EffectiveCancelRetryCooldownSeconds());
return false;
}
if(trade_result.retcode == TRADE_RETCODE_DONE)
{
Print("Pending order canceled. Ticket: ", ticket, " Reason: ", reason);
ForgetPendingOrderCancelAttempt(ticket);
return true;
}
Print("Order cancellation failed. Ticket: ", ticket,
" Reason: ", reason, " Retcode: ", trade_result.retcode,
" RetryAfterSeconds: ", EffectiveCancelRetryCooldownSeconds());
return false;
}
//+------------------------------------------------------------------+
//| pending注文タイプをEA戦略番号へ変換する関数
//+------------------------------------------------------------------+
int PendingOrderStrategy(const ENUM_ORDER_TYPE order_type)
{
switch(order_type)
{
case ORDER_TYPE_BUY_STOP:
return 1;
case ORDER_TYPE_BUY_LIMIT:
return 2;
case ORDER_TYPE_SELL_STOP:
return 3;
case ORDER_TYPE_SELL_LIMIT:
return 4;
default:
return 0;
}
}
//+------------------------------------------------------------------+
//| H4 market_stateと矛盾するpending注文を取消する関数
//+------------------------------------------------------------------+
// Cancel pending orders that contradict the refreshed H4 market state.
bool CancelPendingOrdersNotAllowedByTrend(const int trend_state)
{
bool result = false;
CleanupPendingOrderCancelAttempts();
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0 || !OrderSelect(ticket))
continue;
if(OrderGetString(ORDER_SYMBOL) != _Symbol)
continue;
if((int)OrderGetInteger(ORDER_MAGIC) != magic_number)
continue;
int strategy = PendingOrderStrategy((ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE));
if(strategy > 0 && IsOrderTypeAllowedByTrend(strategy, trend_state))
continue;
string reason = "H4 market_state=" + IntegerToString(trend_state) +
" strategy=" + IntegerToString(strategy);
if(TryCancelPendingOrder(ticket, reason))
result = true;
}
return result;
}
//+------------------------------------------------------------------+
//| レンジブレイクガード用の入力値を安全な範囲へ丸める関数群
//+------------------------------------------------------------------+
int EffectiveRangeBreakoutLookbackBars()
{
int bars = input_range_breakout_lookback_bars;
if(bars < 5)
bars = 5;
if(bars > 200)
bars = 200;
return bars;
}
double EffectiveRangeBreakoutMaxWidthMultiplier()
{
double multiplier = input_range_breakout_max_width_multiplier;
if(multiplier < 0.0)
multiplier = 0.0;
if(multiplier > 100.0)
multiplier = 100.0;
return multiplier;
}
double EffectiveRangeBreakoutBufferMultiplier()
{
double multiplier = input_range_breakout_buffer_multiplier;
if(multiplier <= 0.0)
multiplier = 0.20;
if(multiplier > 10.0)
multiplier = 10.0;
return multiplier;
}
double EffectiveRangeBreakoutNearMultiplier()
{
double multiplier = input_range_breakout_near_multiplier;
if(multiplier <= 0.0)
multiplier = 0.50;
if(multiplier > 20.0)
multiplier = 20.0;
return multiplier;
}
double EffectiveRangeBreakoutBodyMultiplier()
{
double multiplier = input_range_breakout_body_multiplier;
if(multiplier <= 0.0)
multiplier = 1.50;
if(multiplier > 20.0)
multiplier = 20.0;
return multiplier;
}
int EffectiveRangeBreakoutCooldownBars()
{
int bars = input_range_breakout_cooldown_bars;
if(bars < 1)
bars = 1;
if(bars > 96)
bars = 96;
return bars;
}
//+------------------------------------------------------------------+
//| レンジブレイク方向の表示名
//+------------------------------------------------------------------+
string RangeBreakoutDirectionName(const int direction)
{
if(direction == RANGE_BREAKOUT_UP)
return "UP";
if(direction == RANGE_BREAKOUT_DOWN)
return "DOWN";
return "NONE";
}
//+------------------------------------------------------------------+
//| 価格を現在シンボルの桁数で表示する関数
//+------------------------------------------------------------------+
string RangeBreakoutPriceText(const double price)
{
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
return DoubleToString(price, digits);
}
//+------------------------------------------------------------------+
//| 期限切れのレンジブレイクガード状態を解除する関数
//+------------------------------------------------------------------+
void ExpireRangeBreakoutLimitGuard()
{
if(g_range_breakout_guard_direction == RANGE_BREAKOUT_NONE)
return;
if(g_range_breakout_guard_until <= 0)
return;
if(TimeCurrent() < g_range_breakout_guard_until)
return;
Print("[Range Breakout Guard] cooldown expired. direction=",
RangeBreakoutDirectionName(g_range_breakout_guard_direction));
g_range_breakout_guard_direction = RANGE_BREAKOUT_NONE;
g_range_breakout_guard_until = 0;
}
//+------------------------------------------------------------------+
//| レンジブレイク状態を有効化する関数
//+------------------------------------------------------------------+
void ActivateRangeBreakoutLimitGuard(const int direction, const string reason)
{
if(direction == RANGE_BREAKOUT_NONE)
return;
int timeframe_seconds = PeriodSeconds(input_range_breakout_guard_timeframe);
if(timeframe_seconds <= 0)
timeframe_seconds = PeriodSeconds(_Period);
if(timeframe_seconds <= 0)
timeframe_seconds = 60;
datetime new_until = TimeCurrent() + timeframe_seconds * EffectiveRangeBreakoutCooldownBars();
if(g_range_breakout_guard_direction == direction &&
g_range_breakout_guard_until > TimeCurrent())
return;
g_range_breakout_guard_direction = direction;
g_range_breakout_guard_until = new_until;
Print("[Range Breakout Guard] activated. direction=", RangeBreakoutDirectionName(direction),
" until=", TimeToString(g_range_breakout_guard_until, TIME_DATE | TIME_SECONDS),
" reason=", reason);
}
//+------------------------------------------------------------------+
//| レンジブレイクを分析し、逆張りLimitを止める方向を返す関数
//+------------------------------------------------------------------+
bool AnalyzeRangeBreakoutLimitGuard(TickContext &ctx, int &direction, string &reason)
{
direction = RANGE_BREAKOUT_NONE;
reason = "";
if(!input_range_breakout_guard_enabled)
return false;
int lookback = EffectiveRangeBreakoutLookbackBars();
MqlRates rates[];
int copied = CopyRates(_Symbol, input_range_breakout_guard_timeframe, 1, lookback + 1, rates);
if(copied < lookback + 1)
return false;
int last_index = copied - 1;
int history_count = copied - 1;
if(history_count < lookback || last_index <= 0)
return false;
bool initialized = false;
double range_high = 0.0;
double range_low = 0.0;
double total_range = 0.0;
double total_body = 0.0;
// Build the reference range from closed bars before the latest closed bar.
for(int i = 0; i < history_count; i++)
{
if(!initialized)
{
range_high = rates[i].high;
range_low = rates[i].low;
initialized = true;
}
else
{
if(rates[i].high > range_high)
range_high = rates[i].high;
if(rates[i].low < range_low)
range_low = rates[i].low;
}
total_range += rates[i].high - rates[i].low;
total_body += MathAbs(rates[i].close - rates[i].open);
}
if(!initialized)
return false;
double avg_range = total_range / history_count;
double avg_body = total_body / history_count;
if(avg_range <= 0.0)
avg_range = Point();
if(avg_body <= 0.0)
avg_body = Point();
double range_width = range_high - range_low;
if(range_width <= 0.0)
return false;
double max_width_multiplier = EffectiveRangeBreakoutMaxWidthMultiplier();
if(max_width_multiplier > 0.0 && range_width > avg_range * max_width_multiplier)
return false;
MqlRates last_bar = rates[last_index];
double buffer = MathMax(avg_range * EffectiveRangeBreakoutBufferMultiplier(), ctx.spread);
double near_buffer = MathMax(avg_range * EffectiveRangeBreakoutNearMultiplier(), ctx.spread);
double body_threshold = avg_body * EffectiveRangeBreakoutBodyMultiplier();
double last_body = MathAbs(last_bar.close - last_bar.open);
bool last_bullish = (last_bar.close > last_bar.open);
bool last_bearish = (last_bar.close < last_bar.open);
bool last_large_body = (last_body >= body_threshold);
bool confirmed_up = (last_bar.close > range_high + buffer);
bool confirmed_down = (last_bar.close < range_low - buffer);
bool warning_up = (ctx.bid >= range_high - near_buffer &&
(confirmed_up || ctx.bid > range_high + buffer ||
(last_bullish && (last_large_body || last_bar.close > range_high))));
bool warning_down = (ctx.ask <= range_low + near_buffer &&
(confirmed_down || ctx.ask < range_low - buffer ||
(last_bearish && (last_large_body || last_bar.close < range_low))));
if(confirmed_up || warning_up)
{
direction = RANGE_BREAKOUT_UP;
reason = "upward " + string(confirmed_up ? "confirmed" : "warning") +
" tf=" + EnumToString(input_range_breakout_guard_timeframe) +
" range=[" + RangeBreakoutPriceText(range_low) + "," +
RangeBreakoutPriceText(range_high) + "] bid=" +
RangeBreakoutPriceText(ctx.bid) + " last_close=" +
RangeBreakoutPriceText(last_bar.close);
return true;
}
if(confirmed_down || warning_down)
{
direction = RANGE_BREAKOUT_DOWN;
reason = "downward " + string(confirmed_down ? "confirmed" : "warning") +
" tf=" + EnumToString(input_range_breakout_guard_timeframe) +
" range=[" + RangeBreakoutPriceText(range_low) + "," +
RangeBreakoutPriceText(range_high) + "] ask=" +
RangeBreakoutPriceText(ctx.ask) + " last_close=" +
RangeBreakoutPriceText(last_bar.close);
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| レンジブレイク方向と逆向きのLimit pendingを取消する関数
//+------------------------------------------------------------------+
bool CancelRangeBreakoutOppositeLimitOrders(const int direction, const string reason)
{
if(direction == RANGE_BREAKOUT_NONE)
return false;
bool result = false;
CleanupPendingOrderCancelAttempts();
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0 || !OrderSelect(ticket))
continue;
if(OrderGetString(ORDER_SYMBOL) != _Symbol)
continue;
if((int)OrderGetInteger(ORDER_MAGIC) != magic_number)
continue;
ENUM_ORDER_TYPE order_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
bool should_cancel = ((direction == RANGE_BREAKOUT_UP && order_type == ORDER_TYPE_SELL_LIMIT) ||
(direction == RANGE_BREAKOUT_DOWN && order_type == ORDER_TYPE_BUY_LIMIT));
if(!should_cancel)
continue;
if(TryCancelPendingOrder(ticket, "range breakout guard: " + reason))
result = true;
}
return result;
}
//+------------------------------------------------------------------+
//| レンジブレイクガードを監視し、逆方向Limitを退避する関数
//+------------------------------------------------------------------+
void ManageRangeBreakoutLimitGuard(TickContext &ctx)
{
if(!input_range_breakout_guard_enabled)
return;
ExpireRangeBreakoutLimitGuard();
int direction = RANGE_BREAKOUT_NONE;
string reason = "";
if(AnalyzeRangeBreakoutLimitGuard(ctx, direction, reason))
ActivateRangeBreakoutLimitGuard(direction, reason);
if(g_range_breakout_guard_direction == RANGE_BREAKOUT_NONE ||
g_range_breakout_guard_until <= TimeCurrent())
return;
string active_reason = "active " +
RangeBreakoutDirectionName(g_range_breakout_guard_direction) +
" cooldown until " +
TimeToString(g_range_breakout_guard_until, TIME_DATE | TIME_SECONDS);
CancelRangeBreakoutOppositeLimitOrders(g_range_breakout_guard_direction, active_reason);
}
//+------------------------------------------------------------------+
//| 新規Limit注文がレンジブレイクガードで停止中か判定する関数
//+------------------------------------------------------------------+
bool IsLimitOrderBlockedByRangeBreakoutGuard(const int orderType, string &reason)
{
reason = "";
if(!input_range_breakout_guard_enabled)
return false;
ExpireRangeBreakoutLimitGuard();
if(g_range_breakout_guard_direction == RANGE_BREAKOUT_NONE ||
g_range_breakout_guard_until <= TimeCurrent())
return false;
bool blocked = ((g_range_breakout_guard_direction == RANGE_BREAKOUT_UP && orderType == 4) ||
(g_range_breakout_guard_direction == RANGE_BREAKOUT_DOWN && orderType == 2));
if(!blocked)
return false;
reason = "direction=" + RangeBreakoutDirectionName(g_range_breakout_guard_direction) +
" until=" + TimeToString(g_range_breakout_guard_until, TIME_DATE | TIME_SECONDS);
return true;
}
//+------------------------------------------------------------------+
//| pendingコメントからH1候補時刻を復元する関数
//+------------------------------------------------------------------+
datetime PendingOrderCandidateTime(const string comment)
{
int marker = StringFind(comment, "Z");
if(marker < 0)
return 0;
datetime candidate_at = 0;
string candidate_id = StringSubstr(comment, marker + 1, 12);
if(!TryParseTargetCandidateTime(candidate_id, candidate_at))
return 0;
return candidate_at;
}
//+------------------------------------------------------------------+
//| 分割slotが既存注文/ポジションに存在するか判定する関数
//+------------------------------------------------------------------+
@@ -437,6 +996,7 @@ bool CancelStaleSplitPendingOrders(const string current_candidate_id)
{
bool result = false;
bool keep_current_candidate = (current_candidate_id != "" && current_candidate_id != "0");
CleanupPendingOrderCancelAttempts();
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
@@ -456,26 +1016,8 @@ bool CancelStaleSplitPendingOrders(const string current_candidate_id)
if(keep_current_candidate && IsCurrentSplitCandidateComment(comment, current_candidate_id))
continue;
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
request.action = TRADE_ACTION_REMOVE;
request.order = ticket;
if(!OrderSend(request, trade_result))
{
Print("Failed to delete stale split order. Ticket: ", ticket, " Error: ", GetLastError());
continue;
}
if(trade_result.retcode == TRADE_RETCODE_DONE)
{
Print("Stale split order canceled. Ticket: ", ticket, " comment=", comment);
if(TryCancelPendingOrder(ticket, "stale split comment=" + comment))
result = true;
}
else
{
Print("Stale split order cancellation failed. Ticket: ", ticket, " Retcode: ", trade_result.retcode);
}
}
return result;
@@ -495,6 +1037,7 @@ bool CancelStaleSplitPendingOrders(const string current_candidate_id)
bool CancelExpiredOrders()
{
bool result = false;
CleanupPendingOrderCancelAttempts();
// 未決済注文の数を取得
for(int i = OrdersTotal() - 1; i >= 0; i--)
@@ -508,118 +1051,21 @@ bool CancelExpiredOrders()
continue;
datetime open_time = (datetime)OrderGetInteger(ORDER_TIME_SETUP);
datetime reference_time = PendingOrderCandidateTime(OrderGetString(ORDER_COMMENT));
if(reference_time <= 0)
reference_time = open_time;
int expiration_seconds = ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1);
if(open_time <= 0 || expiration_seconds <= 0)
if(reference_time <= 0 || expiration_seconds <= 0)
continue;
if(TimeCurrent() - open_time >= expiration_seconds)
if(TimeCurrent() - reference_time >= expiration_seconds)
{
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
request.action=TRADE_ACTION_REMOVE; // 取引操作タイプ
request.order = ticket; // 注文チケット
if(!OrderSend(request, trade_result)) // 削除リクエスト送信
{
Print("Failed to delete order. Ticket: ", ticket, " Error: ", GetLastError());
}
else
{
if(trade_result.retcode == TRADE_RETCODE_DONE)
{
Print("Order canceled successfully due to a time limit. Ticket: ", ticket);
result = true; // 削除成功フラグ
}
else
{
Print("Order cancellation failed. Ticket: ", ticket, " Retcode: ", trade_result.retcode);
}
}
if(TryCancelPendingOrder(ticket, "H1 candidate expired"))
result = true;
}
}
}
return result;
}
//+------------------------------------------------------------------+
//| 時間が経過したポジションをクローズする関数
//+------------------------------------------------------------------+
/**
* @brief 実時間でCLOSE_H1_LIMIT時間を超えた保有ポジションをクローズします。
*
* @return 1件以上クローズに成功した場合はtrue。
*
* 対象は`_Symbol` と `magic_number` が一致するポジションのみです。
*/
bool CloseExpiredPositions()
{
bool result = false;
// ポジションを逆順でループ
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string position_symbol = PositionGetSymbol(i);
if(position_symbol!="")
{
// Magic Number とシンボルでフィルタリング
if(position_symbol != _Symbol)
continue;
if(PositionGetInteger(POSITION_MAGIC) == magic_number)
{
// ポジションのエントリー時刻を取得
datetime entry_time = (datetime)PositionGetInteger(POSITION_TIME);
int expiration_seconds = CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1);
if(entry_time <= 0 || expiration_seconds <= 0)
continue;
if(TimeCurrent() - entry_time >= expiration_seconds)
{
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
// ポジションタイプに応じてリクエストを設定
int position_type = (int)PositionGetInteger(POSITION_TYPE);
request.action = TRADE_ACTION_DEAL;
request.position = PositionGetInteger(POSITION_TICKET); // ポジションのチケット番号
request.symbol = position_symbol; // シンボル
request.volume = PositionGetDouble(POSITION_VOLUME); // ポジションサイズ
request.price = (position_type == POSITION_TYPE_BUY)
? SymbolInfoDouble(position_symbol, SYMBOL_BID) // BUYの場合はBIDでクローズ
: SymbolInfoDouble(position_symbol, SYMBOL_ASK); // SELLの場合はASKでクローズ
request.deviation = slippage;
request.type = (position_type == POSITION_TYPE_BUY)
? ORDER_TYPE_SELL // BUYポジションをSELLでクローズ
: ORDER_TYPE_BUY; // SELLポジションをBUYでクローズ
request.type_filling = GetOrderFillingPolicy(position_symbol); // 注文執行ポリシー
request.magic = magic_number;
// 注文送信
if(!OrderSend(request, trade_result))
{
Print("Failed to close position. Ticket: ", request.position, " Error: ", GetLastError());
continue;
}
// 結果の確認
if(trade_result.retcode == TRADE_RETCODE_DONE || trade_result.retcode == TRADE_RETCODE_DONE_PARTIAL)
{
Print("Position closed successfully due to a time limit. Ticket: ", request.position);
result = true; // 少なくとも1つ成功した場合
}
else
{
Print("Failed to close position. Ticket: ", request.position, " Retcode: ", trade_result.retcode);
}
}
}
}
else
{
Print("Failed to select position at index ", i, ". Error: ", GetLastError());
}
}
return result;
}
#endif
@@ -0,0 +1,625 @@
#ifndef HIT_TRADE_MANAGER_MQH
#define HIT_TRADE_MANAGER_MQH
//+------------------------------------------------------------------+
//| 注文ロットがブローカー制約を満たすか判定する関数
//+------------------------------------------------------------------+
/**
* @brief 通常注文と分割注文の最終送信前に volume min/max/step を検証します。
*/
bool IsOrderVolumeAllowed(const double volume, const string context)
{
double min_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double max_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double step_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
if(volume <= 0.0 || min_volume <= 0.0 || max_volume <= 0.0 || step_volume <= 0.0)
{
Print("[Order Skip] invalid volume setting. context=", context,
" volume=", volume, " min=", min_volume,
" max=", max_volume, " step=", step_volume);
return false;
}
if(volume < min_volume || volume > max_volume)
{
Print("[Order Skip] volume out of range. context=", context,
" volume=", volume, " min=", min_volume, " max=", max_volume);
return false;
}
double steps = (volume - min_volume) / step_volume;
double nearest = MathRound(steps);
if(MathAbs(steps - nearest) > 0.000001)
{
Print("[Order Skip] volume does not match broker step. context=", context,
" volume=", volume, " min=", min_volume, " step=", step_volume);
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| ブローカーのロットstepから正規化桁数を推定する関数
//+------------------------------------------------------------------+
int VolumeDigits()
{
int volume_digits = 2;
double step_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
if(step_volume > 0.0)
{
volume_digits = 0;
double step = step_volume;
while(step < 1.0 && volume_digits < 8)
{
step *= 10.0;
volume_digits++;
}
}
return volume_digits;
}
//+------------------------------------------------------------------+
//| エントリー注文を送信する関数 (1:buy-stop, 2:buy-limit, 3:sell-stop, 4:sell-limit)
//+------------------------------------------------------------------+
/**
* @brief 指定された注文タイプでペンディング注文を送信します。
*
* @param orderType 注文タイプ。1=Buy Stop、2=Buy Limit、3=Sell Stop、4=Sell Limit。
* @param price エントリー価格。
* @param tp 利確価格。
* @param sl 損切価格。
* @param volume 注文ロット。
* @param comment_suffix 分割注文識別用のコメント接尾辞。空なら従来コメント。
* @return 注文が正常に受理された場合はtrue、それ以外はfalse。
*/
bool SendOrder(int orderType, double price, double tp, double sl, double volume, string comment_suffix)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.magic = magic_number;
request.symbol = _Symbol;
request.volume = NormalizeDouble(volume, VolumeDigits());
request.deviation = slippage;
request.type_filling = GetOrderFillingPolicy(_Symbol);
request.price = NormalizeDouble(price, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
request.tp = NormalizeDouble(tp, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
request.sl = NormalizeDouble(sl, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS));
request.comment = RequestComment(orderType, comment_suffix);
string orderTypeStr = "";
// 指値または逆指値注文
request.action = TRADE_ACTION_PENDING;
ApplyPendingOrderExpiration(request);
switch(orderType)
{
case 1: // 順張り買い (buy-stop)
request.type = ORDER_TYPE_BUY_STOP;
orderTypeStr = "buy-stop";
break;
case 2: // 逆張り買い (buy-limit)
request.type = ORDER_TYPE_BUY_LIMIT;
orderTypeStr = "buy-limit";
break;
case 3: // 順張り売り (sell-stop)
request.type = ORDER_TYPE_SELL_STOP;
orderTypeStr = "sell-stop";
break;
case 4: // 逆張り売り (sell-limit)
request.type = ORDER_TYPE_SELL_LIMIT;
orderTypeStr = "sell-limit";
break;
default: // 不正なorderType
Print(__FUNCTION__, ": invalid orderType=", orderType);
return false;
}
string volume_context = orderTypeStr;
if(comment_suffix != "")
volume_context += " " + comment_suffix;
if(!IsOrderVolumeAllowed(volume, volume_context))
return false;
// 注文送信
if(!OrderSend(request, result))
{
Print(__FUNCTION__, ": OrderSend failed. err=", GetLastError());
return false;
}
// 注文成功確認
if(result.retcode == TRADE_RETCODE_PLACED ||
result.retcode == TRADE_RETCODE_DONE ||
result.retcode == TRADE_RETCODE_DONE_PARTIAL)
{
Print(request.comment + " - " + orderTypeStr + " order success (ticket=", result.order, ")");
return true;
}
else
{
Print(__FUNCTION__, ": OrderSend retcode=", result.retcode);
return false;
}
}
//+------------------------------------------------------------------+
//| 注文の執行ポリシーを取得する関数
//+------------------------------------------------------------------+
/**
* @brief シンボルに対応する注文執行ポリシーを取得します。
*
* @param symbol 対象シンボル。
* @return 利用可能な執行ポリシー。IOC、FOK、RETURNの順で選択します。
*/
ENUM_ORDER_TYPE_FILLING GetOrderFillingPolicy(string symbol)
{
long fill_mode = SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);
if((fill_mode & SYMBOL_FILLING_IOC) != 0)
return ORDER_FILLING_IOC;
if((fill_mode & SYMBOL_FILLING_FOK) != 0)
return ORDER_FILLING_FOK;
return ORDER_FILLING_RETURN;
}
//+------------------------------------------------------------------+
//| ペンディング注文の有効期限を設定する関数
//+------------------------------------------------------------------+
/**
* @brief brokerが対応している範囲でpending orderにサーバー側の期限を設定します。
*
* @param request 更新対象の取引リクエスト。
*/
void ApplyPendingOrderExpiration(MqlTradeRequest &request)
{
int expiration_seconds = ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1);
long expiration_mode = SymbolInfoInteger(request.symbol, SYMBOL_EXPIRATION_MODE);
if(expiration_seconds > 0 &&
(expiration_mode & SYMBOL_EXPIRATION_SPECIFIED) != 0)
{
request.type_time = ORDER_TIME_SPECIFIED;
request.expiration = TimeCurrent() + expiration_seconds;
return;
}
if(expiration_seconds > 0 &&
(expiration_mode & SYMBOL_EXPIRATION_SPECIFIED_DAY) != 0)
{
request.type_time = ORDER_TIME_SPECIFIED_DAY;
request.expiration = TimeCurrent() + expiration_seconds;
return;
}
if((expiration_mode & SYMBOL_EXPIRATION_DAY) != 0)
{
request.type_time = ORDER_TIME_DAY;
return;
}
request.type_time = ORDER_TIME_GTC;
}
//+------------------------------------------------------------------+
//| 注文コメント(ローカル時刻)を生成する関数(先頭に orderType を付与)
//+------------------------------------------------------------------+
/**
* @brief 注文コメント文字列を生成します。
*
* @param orderType 注文タイプ番号。
* @param comment_suffix 分割注文識別用のコメント接尾辞。
* @return 注文タイプとPCローカル時刻、または分割注文識別子を含むコメント文字列。
*/
string RequestComment(int orderType, string comment_suffix)
{
if(comment_suffix != "")
return "T" + IntegerToString(orderType) + " " + comment_suffix;
datetime localTime = TimeLocal();
string timeStr = TimeToString(localTime, TIME_DATE|TIME_MINUTES);
// 先頭に 1,2,3,4 を付ける(例: "1 | PC Time: 2026.02.14 19:05"
return IntegerToString(orderType) + " | PC Time: " + timeStr;
}
//+------------------------------------------------------------------+
//| H4 market_stateに対して許可された注文タイプか判定する関数
//+------------------------------------------------------------------+
/**
* @brief H4 market_stateに対して指定注文タイプが許可されるか判定します。
*
* @param orderType 注文タイプ番号。
* @param trend_state H4 market_state0..5、6は技術エラー停止)。
* @return 許可される注文タイプならtrue。技術エラー停止または異常値ではfalse。
*/
bool IsOrderTypeAllowedByTrend(const int orderType, const int trend_state)
{
switch(trend_state)
{
case MARKET_LOW_VOL_RANGE:
case MARKET_HIGH_VOL_RANGE:
return (orderType == 2 || orderType == 4); // Range: Buy Limit / Sell Limitのみ
case MARKET_LOW_VOL_UP:
case MARKET_HIGH_VOL_UP:
return (orderType == 1 || orderType == 2); // Up: Buy Stop / Buy Limitのみ
case MARKET_LOW_VOL_DOWN:
case MARKET_HIGH_VOL_DOWN:
return (orderType == 3 || orderType == 4); // Down: Sell Stop / Sell Limitのみ
case MARKET_TECHNICAL_ERROR_STOP:
default:
return false; // 技術エラー停止または異常値は新規注文しない
}
}
//+------------------------------------------------------------------+
//| target_prices.txt の価格が有効か判定する関数
//+------------------------------------------------------------------+
/**
* @brief エントリー価格、利確価格、損切価格が有効値か判定します。
*
* @param en エントリー価格。
* @param tp 利確価格。
* @param sl 損切価格。
* @return すべて0より大きい場合はtrue。
*/
bool HasValidTargetPrices(const double en, const double tp, const double sl)
{
return (en > 0.0 && tp > 0.0 && sl > 0.0);
}
//+------------------------------------------------------------------+
//| 自EAの未約定注文数を数える関数
//+------------------------------------------------------------------+
/**
* @brief このEAが管理対象とする未約定注文数を数えます。
*
* @return `_Symbol` と `magic_number` が一致する未約定注文数。
*/
int CountMyPendingOrders()
{
int count = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0)
continue;
if(!OrderSelect(ticket))
continue;
if(OrderGetString(ORDER_SYMBOL) != _Symbol)
continue;
if((int)OrderGetInteger(ORDER_MAGIC) != magic_number)
continue;
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| 自EAのポジション数を数える関数
//+------------------------------------------------------------------+
/**
* @brief このEAが管理対象とする保有ポジション数を数えます。
*
* @return `_Symbol` と `magic_number` が一致するポジション数。
*/
int CountMyPositions()
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i);
if(symbol == "")
continue;
if(symbol != _Symbol)
continue;
if((int)PositionGetInteger(POSITION_MAGIC) != magic_number)
continue;
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| 自EAの注文+ポジション数を数える関数
//+------------------------------------------------------------------+
/**
* @brief このEAが使用中の注文数とポジション数の合計を返します。
*
* @return 未約定注文数 + 保有ポジション数。
*/
int CountMyUsed()
{
return CountMyPendingOrders() + CountMyPositions();
}
//+------------------------------------------------------------------+
//| 実効ポジション上限を返す関数
//+------------------------------------------------------------------+
/**
* @brief input指定の上限を安全な範囲に丸めて返します。
*/
int EffectivePositionLimit()
{
int limit = input_position_limit;
if(limit < 1)
limit = 1;
if(limit > POSITION_LIMIT)
limit = POSITION_LIMIT;
return limit;
}
//+------------------------------------------------------------------+
//| 分割注文コメントか判定する関数
//+------------------------------------------------------------------+
bool IsSplitOrderComment(const string comment)
{
return (StringFind(comment, " Z") >= 0 && StringFind(comment, "#") >= 0);
}
//+------------------------------------------------------------------+
//| 指定候補IDの分割注文コメントか判定する関数
//+------------------------------------------------------------------+
bool IsCurrentSplitCandidateComment(const string comment, const string candidate_id)
{
if(candidate_id == "" || candidate_id == "0")
return false;
return (StringFind(comment, "Z" + candidate_id + "#") >= 0);
}
//+------------------------------------------------------------------+
//| 分割slotが既存注文/ポジションに存在するか判定する関数
//+------------------------------------------------------------------+
bool HasExistingSplitSlot(const string slot_key)
{
if(slot_key == "")
return false;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0)
continue;
if(!OrderSelect(ticket))
continue;
if(OrderGetString(ORDER_SYMBOL) != _Symbol)
continue;
if((int)OrderGetInteger(ORDER_MAGIC) != magic_number)
continue;
if(StringFind(OrderGetString(ORDER_COMMENT), slot_key) >= 0)
return true;
}
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i);
if(symbol == "")
continue;
if(symbol != _Symbol)
continue;
if((int)PositionGetInteger(POSITION_MAGIC) != magic_number)
continue;
if(StringFind(PositionGetString(POSITION_COMMENT), slot_key) >= 0)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| 古い分割pending注文を取消する関数
//+------------------------------------------------------------------+
bool CancelStaleSplitPendingOrders(const string current_candidate_id)
{
bool result = false;
bool keep_current_candidate = (current_candidate_id != "" && current_candidate_id != "0");
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0)
continue;
if(!OrderSelect(ticket))
continue;
if(OrderGetString(ORDER_SYMBOL) != _Symbol)
continue;
if((int)OrderGetInteger(ORDER_MAGIC) != magic_number)
continue;
string comment = OrderGetString(ORDER_COMMENT);
if(!IsSplitOrderComment(comment))
continue;
if(keep_current_candidate && IsCurrentSplitCandidateComment(comment, current_candidate_id))
continue;
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
request.action = TRADE_ACTION_REMOVE;
request.order = ticket;
if(!OrderSend(request, trade_result))
{
Print("Failed to delete stale split order. Ticket: ", ticket, " Error: ", GetLastError());
continue;
}
if(trade_result.retcode == TRADE_RETCODE_DONE)
{
Print("Stale split order canceled. Ticket: ", ticket, " comment=", comment);
result = true;
}
else
{
Print("Stale split order cancellation failed. Ticket: ", ticket, " Retcode: ", trade_result.retcode);
}
}
return result;
}
//+------------------------------------------------------------------+
//| 時間が経過したエントリー注文をキャンセルする関数
//+------------------------------------------------------------------+
/**
* @brief 実時間でENTRY_H1_LIMIT時間を超えた未約定注文をキャンセルします。
*
* @return 1件以上キャンセルに成功した場合はtrue。
*
* 対象は`_Symbol` と `magic_number` が一致する未約定注文のみです。
*/
bool CancelExpiredOrders()
{
bool result = false;
// 未決済注文の数を取得
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(OrderSelect(ticket)) // 注文を選択
{
if(OrderGetString(ORDER_SYMBOL) != _Symbol)
continue;
if(OrderGetInteger(ORDER_MAGIC) != magic_number)
continue;
datetime open_time = (datetime)OrderGetInteger(ORDER_TIME_SETUP);
int expiration_seconds = ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1);
if(open_time <= 0 || expiration_seconds <= 0)
continue;
if(TimeCurrent() - open_time >= expiration_seconds)
{
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
request.action=TRADE_ACTION_REMOVE; // 取引操作タイプ
request.order = ticket; // 注文チケット
if(!OrderSend(request, trade_result)) // 削除リクエスト送信
{
Print("Failed to delete order. Ticket: ", ticket, " Error: ", GetLastError());
}
else
{
if(trade_result.retcode == TRADE_RETCODE_DONE)
{
Print("Order canceled successfully due to a time limit. Ticket: ", ticket);
result = true; // 削除成功フラグ
}
else
{
Print("Order cancellation failed. Ticket: ", ticket, " Retcode: ", trade_result.retcode);
}
}
}
}
}
return result;
}
//+------------------------------------------------------------------+
//| 時間が経過したポジションをクローズする関数
//+------------------------------------------------------------------+
/**
* @brief 実時間でCLOSE_H1_LIMIT時間を超えた保有ポジションをクローズします。
*
* @return 1件以上クローズに成功した場合はtrue。
*
* 対象は`_Symbol` と `magic_number` が一致するポジションのみです。
*/
bool CloseExpiredPositions()
{
bool result = false;
// ポジションを逆順でループ
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string position_symbol = PositionGetSymbol(i);
if(position_symbol!="")
{
// Magic Number とシンボルでフィルタリング
if(position_symbol != _Symbol)
continue;
if(PositionGetInteger(POSITION_MAGIC) == magic_number)
{
// ポジションのエントリー時刻を取得
datetime entry_time = (datetime)PositionGetInteger(POSITION_TIME);
int expiration_seconds = CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1);
if(entry_time <= 0 || expiration_seconds <= 0)
continue;
if(TimeCurrent() - entry_time >= expiration_seconds)
{
MqlTradeRequest request = {};
MqlTradeResult trade_result = {};
// ポジションタイプに応じてリクエストを設定
int position_type = (int)PositionGetInteger(POSITION_TYPE);
request.action = TRADE_ACTION_DEAL;
request.position = PositionGetInteger(POSITION_TICKET); // ポジションのチケット番号
request.symbol = position_symbol; // シンボル
request.volume = PositionGetDouble(POSITION_VOLUME); // ポジションサイズ
request.price = (position_type == POSITION_TYPE_BUY)
? SymbolInfoDouble(position_symbol, SYMBOL_BID) // BUYの場合はBIDでクローズ
: SymbolInfoDouble(position_symbol, SYMBOL_ASK); // SELLの場合はASKでクローズ
request.deviation = slippage;
request.type = (position_type == POSITION_TYPE_BUY)
? ORDER_TYPE_SELL // BUYポジションをSELLでクローズ
: ORDER_TYPE_BUY; // SELLポジションをBUYでクローズ
request.type_filling = GetOrderFillingPolicy(position_symbol); // 注文執行ポリシー
request.magic = magic_number;
// 注文送信
if(!OrderSend(request, trade_result))
{
Print("Failed to close position. Ticket: ", request.position, " Error: ", GetLastError());
continue;
}
// 結果の確認
if(trade_result.retcode == TRADE_RETCODE_DONE || trade_result.retcode == TRADE_RETCODE_DONE_PARTIAL)
{
Print("Position closed successfully due to a time limit. Ticket: ", request.position);
result = true; // 少なくとも1つ成功した場合
}
else
{
Print("Failed to close position. Ticket: ", request.position, " Retcode: ", trade_result.retcode);
}
}
}
}
else
{
Print("Failed to select position at index ", i, ". Error: ", GetLastError());
}
}
return result;
}
#endif
+31 -5
View File
@@ -335,12 +335,14 @@ public:
continue;
double candidate_sl = 0.0;
const double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
const double evaluation_price = (type == POSITION_TYPE_BUY) ? tick.bid : tick.ask;
if (!CalcHighVolatilitySL(type,
evaluation_price,
open_m1,
open_m3,
open_m5,
evaluation_price,
position_open_price,
open_m1,
open_m3,
open_m5,
open_m10,
open_m15,
pip_size,
@@ -590,6 +592,7 @@ private:
/// @return いずれかの時間足でしきい値を超え、SL候補を出力した場合は true。
bool CalcHighVolatilitySL(const ENUM_POSITION_TYPE type,
const double current_price,
const double position_open_price,
const double open_m1,
const double open_m3,
const double open_m5,
@@ -612,13 +615,36 @@ private:
if (!has_candidate)
return false;
if (!IsProfitProtectingStopLoss(type, candidate_sl, position_open_price))
return false;
sl_value = NormalizeDouble(candidate_sl, digits);
return true;
}
/// @brief 急変時SL候補が建値より不利にならないことを確認する。
bool IsProfitProtectingStopLoss(const ENUM_POSITION_TYPE type,
const double candidate_sl,
const double open_price)
{
if (open_price <= 0.0)
return false;
const double point = SymbolInfoDouble(m_symbol, SYMBOL_POINT);
const double tolerance = point * 0.1;
if (type == POSITION_TYPE_BUY)
return (candidate_sl >= open_price - tolerance);
if (type == POSITION_TYPE_SELL)
return (candidate_sl <= open_price + tolerance);
return false;
}
/// @brief 1本の時間足始値から急変幅を評価し、有効なSL候補なら最良候補へ反映する。
void EvaluateHighVolatilityOpen(const ENUM_POSITION_TYPE type,
const double current_price,
const double current_price,
const double open_price,
const double limit_pips,
const double rate_ratio,
+3559 -3321
View File
File diff suppressed because it is too large Load Diff
+64 -7
View File
@@ -20,7 +20,7 @@
- `lot_size = 0.01`: Order volume.
- `spread_limit = 60`: Maximum allowed spread in points.
- `magic_number = 10001`: Magic number used to identify this EA's orders and positions.
- `initial_order = 0`: Enables initial H4/H1 processing on startup when set to `1`.
- `initial_order = 0`: Retained for compatibility with older settings. Startup always rebuilds H4/H1 results and remains in technical-error stop state until the H4 result is reloaded.
- `input_position_limit = 10`: Practical limit for this EA's pending orders plus positions. Values above the internal `POSITION_LIMIT` are clamped.
- `use_split_entry_zone = false`: Enables split entries based on H1 predicted zones.
- `split_entry_count = 3`: Number of split entry orders, clamped to 1..10.
@@ -28,6 +28,7 @@
- `split_total_lot_size = 0.09`: Total lot used by total-split mode.
- `split_fixed_lot_size = 0.01`: Per-order lot used by fixed-split mode.
- `cancel_old_split_pending_on_new_zone = true`: Cancels older split pending orders when a new H1 zone set is loaded.
- `input_cancel_retry_cooldown_seconds = 60`: Wait time before retrying a failed pending-order cancellation for the same ticket. The effective value is clamped to 1..3600 seconds.
- `use_m15_entry_filter = true`: Enables M15 closed-bar entry timing confirmation.
- `m15_entry_zone_atr_multiplier = 1.50`: Allowed proximity multiplier based on the M15 average range.
- `use_m15_imbalance_confirmation = true`: Adds M15 impulse confirmation for T1/T3 trend-following candidates.
@@ -36,6 +37,17 @@
- `m15_imbalance_min_avg_body_points = 1.0`: Minimum M15 average body in points.
- `use_m15_imbalance_debug_log = false`: Enables detailed M15 impulse-confirmation logs.
- `input_entry_max_candidate_age_minutes = 120`: Maximum age, in minutes, for using an H1 candidate for new execution. This blocks delayed entries when M15 confirmation appears too late.
- `input_tp_multiplier = 1.25`: Expands the API TP distance from the entry price. Values below `1.0` are clamped to `1.0`, and values above `100.0` are clamped to `100.0`.
- `input_min_tp_points = 0`: Minimum final TP distance in points. `0` disables the floor.
- `input_max_tp_points = 0`: Maximum expanded TP distance in points. `0` disables the cap. The EA never makes the final TP closer than the API-provided TP distance.
- `input_range_breakout_guard_enabled = true`: Cancels adverse reversal Limit orders during range breakouts and temporarily blocks new ones.
- `input_range_breakout_guard_timeframe = PERIOD_M15`: Timeframe used by the range-breakout monitor.
- `input_range_breakout_lookback_bars = 20`: Closed-bar count used for range high/low and average range. The range starts from the bar before the latest closed bar.
- `input_range_breakout_max_width_multiplier = 6.0`: Maximum allowed range width versus average range. `0` disables the width filter.
- `input_range_breakout_buffer_multiplier = 0.20`: Average-range multiplier used as the confirmed-breakout buffer.
- `input_range_breakout_near_multiplier = 0.50`: Average-range multiplier used as the pre-breakout proximity band.
- `input_range_breakout_body_multiplier = 1.50`: Required latest closed-bar body multiple for momentum warning.
- `input_range_breakout_cooldown_bars = 4`: Number of monitor-timeframe bars to block adverse Limit entries after detection.
- `input_sltp_manager_enabled = false`: Enables UI-driven existing-position SL management through `CSLTPManager`.
- `input_sltp_show_panel = true`: Shows the SLTP control panel on the chart.
- `input_sltp_use_breakeven = false`: Enables normal break-even.
@@ -81,7 +93,7 @@
- `Include/MyLib/Signals/HITEntrySignal.mqh`: Entry preconditions, order-type price validation, M15 filter, and retry-state updates.
- `Include/MyLib/Common/HITExternalProcess.mqh`: done/running files, external process handles, PID recovery, exit-code checks, and timeout recovery.
- `Include/MyLib/Signals/HITPythonSignalGateway.mqh`: OHLC CSV export, Python batch launch, and `trend_state.txt` / `target_prices.txt` / `target_zones.txt` loading.
- `Include/MyLib/Trading/HITTradeManager.mqh`: Order sending, filling policy, pending-order expiration, order/position counting, expired order cancellation, and expired position closing.
- `Include/MyLib/Trading/HITTradeManager.mqh`: Order sending, filling policy, pending-order expiration, order/position counting, expired order cancellation, expired position closing, and adverse Limit cancellation during range breakouts.
- `Include/MyLib/Trading/SLTPManager.mqh`: Existing-position break-even, elapsed-time break-even, active trailing, TP-progress SL, and high-volatility SL management.
- `Include/MyLib/Panel/SLTPManagerPanel.mqh`: Chart panel that toggles `CSLTPManager` features, validates numeric inputs, and applies settings to the EA.
@@ -107,6 +119,8 @@ When no prefix is provided, such as manual Python execution, Python keeps using
- Running marker: `<prefix>_process_running_entry.txt`
- Batch file: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_entry_reply.bat`
H1 candidate generation uses the OpenAI Responses API. The default model is `gpt-5.5`, the default `reasoning.effort` is `low`, and the default `text.verbosity` is `low`. `temperature` is not set. Runtime overrides are available through `OPENAI_MODEL`, `OPENAI_REASONING_EFFORT`, and `OPENAI_TEXT_VERBOSITY`. Output is validated with `text.format` Structured Outputs JSON Schema; incomplete responses, schema mismatches, price-rule failures, and insufficient reward/risk fall back to safe-stop values.
During `OnInit()`, the EA resolves `MQL5\python_for_ea` from `TerminalInfoString(TERMINAL_DATA_PATH)` and builds absolute batch-file paths. Each batch file resolves the Python project root from its own location, so runtime execution no longer depends on `C:\ea_py`.
`target_prices.txt` must contain 13 lines:
@@ -145,10 +159,13 @@ New entries are allowed only when all conditions below are satisfied:
- The H1 candidate set has not exceeded `input_entry_max_candidate_age_minutes`, measured from the closed H1 bar time that produced the candidate.
- The selected order type has valid `entry/tp/sl` values greater than `0.0`.
- The order type is allowed by the H4 `market_state`.
- Before price-consistency and broker-distance checks, TP is recalculated from the distance between entry and the API TP, multiplied by `input_tp_multiplier`. Buy strategies place the final TP above entry, and Sell strategies place it below entry.
- When split entries are enabled, the final TP is recalculated separately for each slot from that slot's entry price.
- The order-type price relationship and broker minimum distance rules are satisfied.
- When `use_m15_entry_filter = true`, T2/T4 satisfy the M15 direction, rejection, and proximity checks. T1/T3 satisfy M15 impulse confirmation when `use_m15_imbalance_confirmation = true`.
- When `input_range_breakout_guard_enabled = true`, T4 Sell Limit is blocked during an upward range-breakout cooldown and T2 Buy Limit is blocked during a downward range-breakout cooldown.
- This EA's pending orders plus positions are below `input_position_limit`.
- When split entries are enabled, `target_zones.txt` has `res_chk = 1`, the predicted zone prices are valid, split lots fit `SYMBOL_VOLUME_MIN/MAX/STEP`, and no duplicate order or position exists for the same `candidate_id` + slot.
- When split entries are enabled, `target_zones.txt` has `res_chk = 1`, the predicted zone prices are valid, split lots fit `SYMBOL_VOLUME_MIN/MAX/STEP`, and no duplicate order or position exists for the same `candidate_id` + order type + slot.
### market_state and Allowed Order Types
@@ -160,6 +177,16 @@ New entries are allowed only when all conditions below are satisfied:
- `5 MARKET_HIGH_VOL_DOWN`: Allows T3 Sell Stop / T4 Sell Limit.
- `6 MARKET_TECHNICAL_ERROR_STOP`: Blocks new entries.
After an H4 `market_state` reload, the EA cancels existing pending orders whose order types are not allowed by the refreshed state. For `6 MARKET_TECHNICAL_ERROR_STOP`, it cancels all pending orders managed by this EA.
### Range Breakout Guard
- The guard uses closed bars from `input_range_breakout_guard_timeframe`; the reference range is built from `input_range_breakout_lookback_bars` bars before the latest closed bar.
- It treats the market as a range only when the range width is within `input_range_breakout_max_width_multiplier` times the average range. A value of `0` disables this width check.
- If the latest closed bar closes above `rangeHigh + buffer`, or current Bid approaches the range high with upward momentum on the latest closed bar, the guard treats it as an upward warning/confirmation. It cancels existing T4 Sell Limit orders and blocks new T4 entries for `input_range_breakout_cooldown_bars` monitor bars.
- If the latest closed bar closes below `rangeLow - buffer`, or current Ask approaches the range low with downward momentum on the latest closed bar, the guard treats it as a downward warning/confirmation. It cancels existing T2 Buy Limit orders and blocks new T2 entries for `input_range_breakout_cooldown_bars` monitor bars.
- `buffer` and the proximity band use the larger of the average-range multiple and current spread to reduce over-triggering during live spread expansion.
### Order-Type Price Rules
- T1 Buy Stop: `Ask < entry`, `tp > entry`, `sl < entry`
@@ -169,7 +196,7 @@ New entries are allowed only when all conditions below are satisfied:
## 7. Exit Conditions
- Pending orders are cancelled after `ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1)` has elapsed from setup time.
- Pending orders are cancelled after `ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1)` has elapsed from the H1 candidate time restored from the comment. Legacy orders without that token fall back to setup time.
- Positions are closed after `CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1)` has elapsed from entry time.
- Time-limit handling runs early in `OnTick` and is independent of Python readiness or spread checks.
- On EA removal, `OnDeinit()` releases external-process state and the SLTP panel, then clears the chart status text with `Comment("")` and `ChartRedraw(0)`.
@@ -191,10 +218,15 @@ New entries are allowed only when all conditions below are satisfied:
- `input_position_limit` counts only this EA's orders and positions, not the full account. The hard internal limit is `POSITION_LIMIT`.
- The EA selects the filling policy from `SYMBOL_FILLING_MODE`, preferring IOC, then FOK, then RETURN.
- Before sending either single or split orders, the EA verifies the requested lot against `SYMBOL_VOLUME_MIN/MAX/STEP`.
- Pending orders receive server-side expiration when the broker supports it.
- Pending orders receive server-side expiration from the H1 candidate time when the broker supports it. Orders are skipped if that expiration is already in the past.
- `OrderSend` return values and `MqlTradeResult.retcode` are checked. Failures are logged with `GetLastError()` or the retcode.
- Split-entry order comments include `candidate_id` and slot number to prevent duplicate slot execution.
- Single and split order comments keep a valid `candidate_id` for candidate-origin expiration handling.
- Split-entry order comments also include order type and slot number to prevent duplicate execution of the same strategy slot.
- When `cancel_old_split_pending_on_new_zone = true`, a new valid `candidate_id` cancels older split pending orders, and an invalid or stopped `target_zones.txt` cancels all existing split pending orders for this EA/symbol/magic.
- If the API TP direction contradicts the Buy/Sell price rules, the EA does not repair it; the existing price-consistency checks skip the order.
- After an H4 state update, existing pending orders that contradict the refreshed `market_state` are cancelled.
- The range-breakout guard only targets pending orders matching `_Symbol` and `magic_number`; upward breakouts cancel T4 Sell Limit only, and downward breakouts cancel T2 Buy Limit only.
- A failed pending-order cancellation is not retried for the same ticket until `input_cancel_retry_cooldown_seconds` has elapsed, preventing excessive per-tick trade-server requests.
- SLTP management only targets existing positions matching `_Symbol` and `magic_number`, and it preserves each position's current TP.
- SL changes are sent only when the candidate improves protection relative to the current SL and satisfies broker stop-level and freeze-level constraints.
- `HighVolatilityLimit()` evaluates BUY positions with Bid and SELL positions with Ask, and treats GOLD/XAUUSD suffix symbols as 1 pip = 0.1.
@@ -203,13 +235,38 @@ New entries are allowed only when all conditions below are satisfied:
- If `trend_state.txt` is missing, unreadable, not strictly parseable as an integer, or outside `0..6`, the EA uses `MARKET_TECHNICAL_ERROR_STOP`.
- If `target_prices.txt` is missing, unreadable, shorter than 13 lines, or contains a non-strict numeric line, the EA uses `res_chk = 0`.
- When split entries are enabled, missing `target_zones.txt`, schema mismatch, fewer than 7 lines, `res_chk != 1`, or non-strict numeric values stop new split orders.
- When split entries are enabled, missing `target_zones.txt`, schema mismatch, fewer than 7 lines, `res_chk != 1`, a valid-zone `candidate_id` that is not a strict 12-digit timestamp, or non-strict numeric values stop new split orders.
- When Python falls back to H1 safe-stop values, it appends `RESULT: SAFE_STOP`, the stop stage, reason, H4 state, and candidate ID to `debug_entry.txt`. This distinguishes a normal GPT skip from API, configuration, or data failures.
- If a Python process exits with a non-zero code, the code is logged and the next trigger may retry.
- If a Python process remains active beyond `PYTHON_TIMEOUT_SECONDS`, the EA runs `taskkill /T /F` against the cmd/bat process tree, clears done/running files, and allows the next trigger to retry.
- If only a stale running marker remains, the EA attempts PID recovery. If recovery fails and the marker is timed out, it removes the stale marker.
## 10. Changelog
### 2026-06-13
- Added a range-breakout guard that retreats adverse reversal Limit orders. Upward breakouts cancel existing T4 Sell Limit orders and temporarily block new T4 entries; downward breakouts cancel existing T2 Buy Limit orders and temporarily block new T2 entries.
- Added guard inputs for monitor timeframe, lookback bars, range-width multiplier, breakout buffer, proximity band, momentum body multiple, and cooldown bars.
- Added `input_tp_multiplier`, `input_min_tp_points`, and `input_max_tp_points` to expand API-derived TP distances for both standard orders and per-slot split entries.
### 2026-06-06
- Updated the Python-side OpenAI default model to the official `gpt-5.5` slug and made Responses API calls send explicit `reasoning.effort` and `text.verbosity`. For GPT-5.5, the output contract is now documented as primarily enforced by Structured Outputs rather than duplicated prompt schema text.
- Added compatibility declarations to `HIT-EA_refactor_ver5.mq5` so it compiles against the current shared headers, covering split-entry zones, Python linkage filenames, and pending-cancel retry tracking. Since `use_split_entry_zone = false` by default, the normal ver5 entry behavior remains unchanged.
### 2026-06-01
- Added `debug_entry.txt` safe-stop diagnostics with the stop stage and reason so normal candidate skips can be distinguished from guarded failure fallbacks.
### 2026-05-31
- Changed startup initialization to rebuild H4/H1 results regardless of `initial_order`, while holding the technical-error stop state until the H4 result reloads.
- Added cancellation of existing pending orders that contradict a refreshed H4 `market_state`.
- Added per-ticket cooldown after failed pending-order cancellation to prevent excessive per-tick trade-server requests.
- Added order type to split-slot identifiers so different strategies using the same `candidate_id` and slot cannot collide.
- Kept valid `candidate_id` tokens in both single and split order comments and changed pending expiration to use the H1 candidate origin time.
- Required strict 12-digit timestamp `candidate_id` values for valid `target_zones.txt`; malformed values now stop safely.
### 2026-05-30
- Added the `HIT_<symbol>_<magic_number>` linkage-file prefix contract on both the MT5 and Python sides to avoid collisions across multiple EAs or symbols in the same terminal.
@@ -0,0 +1,259 @@
# HIT-EA Specification (English)
## 1. Overview
- This EA sends confirmed H4 OHLC data to an external Python process for market-state analysis and confirmed H1 OHLC data for entry candidate generation.
- The MQL5 side reads Python output files and places pending orders only after checking the H4 market state, H1 candidate prices, M15 confirmation filter, spread, and broker distance constraints.
- For backtest reproducibility, OHLC export uses `OHLC_START_SHIFT = 1`, so the forming bar is excluded and only closed bars are passed to Python.
- For live resilience, the EA tracks external-process running files, process IDs, exit codes, and timeouts to prevent duplicate launches and CSV overwrites.
## 2. Indicators
- No standard or custom indicators are used.
- OHLC data is retrieved with `CopyRates(_Symbol, timeframe, OHLC_START_SHIFT, HISTORY_BARS, rates)`.
- M15 entry confirmation uses candle shape, average range, and distance to the candidate price for T2/T4. For T1/T3 it uses M15 impulse confirmation when that option is enabled.
## 3. Parameters
### input
- `lot_size = 0.01`: Order volume.
- `spread_limit = 60`: Maximum allowed spread in points.
- `magic_number = 10001`: Magic number used to identify this EA's orders and positions.
- `initial_order = 0`: Enables initial H4/H1 processing on startup when set to `1`.
- `input_position_limit = 10`: Practical limit for this EA's pending orders plus positions. Values above the internal `POSITION_LIMIT` are clamped.
- `use_split_entry_zone = false`: Enables split entries based on H1 predicted zones.
- `split_entry_count = 3`: Number of split entry orders, clamped to 1..10.
- `split_lot_mode = SPLIT_LOT_TOTAL`: Split lot mode. `SPLIT_LOT_TOTAL` divides the total lot across slots, and `SPLIT_LOT_FIXED` uses a fixed lot per order.
- `split_total_lot_size = 0.09`: Total lot used by total-split mode.
- `split_fixed_lot_size = 0.01`: Per-order lot used by fixed-split mode.
- `cancel_old_split_pending_on_new_zone = true`: Cancels older split pending orders when a new H1 zone set is loaded.
- `use_m15_entry_filter = true`: Enables M15 closed-bar entry timing confirmation.
- `m15_entry_zone_atr_multiplier = 1.50`: Allowed proximity multiplier based on the M15 average range.
- `use_m15_imbalance_confirmation = true`: Adds M15 impulse confirmation for T1/T3 trend-following candidates.
- `m15_imbalance_avg_body_period = 20`: Average-body period used by M15 impulse confirmation.
- `m15_imbalance_sensitivity = 2.0`: Required multiple of the average body for M15 impulse confirmation.
- `m15_imbalance_min_avg_body_points = 1.0`: Minimum M15 average body in points.
- `use_m15_imbalance_debug_log = false`: Enables detailed M15 impulse-confirmation logs.
- `input_entry_max_candidate_age_minutes = 120`: Maximum age, in minutes, for using an H1 candidate for new execution. This blocks delayed entries when M15 confirmation appears too late.
- `input_sltp_manager_enabled = false`: Enables UI-driven existing-position SL management through `CSLTPManager`.
- `input_sltp_show_panel = true`: Shows the SLTP control panel on the chart.
- `input_sltp_use_breakeven = false`: Enables normal break-even.
- `input_sltp_breakeven_trigger_pips = 30.0`: Profit threshold for normal break-even.
- `input_sltp_breakeven_buffer_pips = 3.0`: Profit-side entry buffer used by normal break-even.
- `input_sltp_use_elapsed_breakeven = false`: Enables elapsed-time break-even.
- `input_sltp_elapsed_breakeven_hours = 4.0`: Holding time required before elapsed-time break-even is allowed.
- `input_sltp_elapsed_breakeven_buffer_pips = 3.0`: Profit-side entry buffer used by elapsed-time break-even.
- `input_sltp_use_active_trailing = false`: Enables active step trailing.
- `input_sltp_active_breakeven_pips = 30.0`: Profit threshold that starts active trailing.
- `input_sltp_active_stop_loss_offset_pips = 5.0`: Initial locked profit offset from entry.
- `input_sltp_active_step_trigger_pips = 10.0`: Additional profit interval required for each SL step.
- `input_sltp_active_step_move_pips = 5.0`: SL movement added per completed step.
- `input_sltp_use_tp_progress_stop = false`: Enables TP-progress-based SL locking.
- `input_sltp_tp_progress_trigger_percent = 70.0`: TP progress required before the SL lock is applied.
- `input_sltp_tp_progress_sl_lock_percent = 30.0`: Entry-to-TP distance percentage locked by SL.
- `input_sltp_use_high_volatility_limit = false`: Enables short-term high-volatility SL tightening.
### Main Constants
- `POSITION_LIMIT = 48`: Maximum number of this EA's pending orders plus positions.
- `ENTRY_H1_LIMIT = 2`: Pending-order lifetime in H1 bars.
- `CLOSE_H1_LIMIT = 12`: Position lifetime in H1 bars.
- `HISTORY_BARS = 72`: Number of OHLC bars exported to Python.
- `OHLC_START_SHIFT = 1`: Shift used to export closed bars only.
- `M15_CONFIRM_BARS = 30`: Number of M15 bars used for average-range calculation.
- `ENTRY_RETRY_SECONDS = 60`: Retry interval for entry checks.
- `ENTRY_RETRY_LIMIT = 10`: Maximum retry count for one H1 candidate set.
- `TARGET_SIZE = 13`: Number of numeric values expected in `target_prices.txt`.
- `TARGET_ZONE_SCHEMA_VERSION = 2`: Schema version used by `target_zones.txt`.
- `PYTHON_TIMEOUT_SECONDS = 600`: External Python wait threshold.
### Python Entry-Candidate Guard
- After H1 candidate generation, Python invalidates any `entry` that is too far from the current price.
- The maximum distance is strategy-specific: T1/T3 Stop candidates use `max(H1 EATR * 1.50, 5.00)`, and T2/T4 Limit candidates use `max(H1 EATR * 1.00, 5.00)`. A strategy beyond its limit is rewritten to `0.00,0.00,0.00`.
- This post-filter is intended to reduce delayed entries from deep limit orders or distant breakout waits after M15 confirmation arrives late.
## 4. File Layout
- `Experts/MyProject/HIT-EA_refactor_ver6.mq5`: EA entry point. Keeps `OnInit`, `OnDeinit`, `OnTick`, inputs, global state, and DLL imports.
- `Include/MyLib/Common/HITRuntimeController.mqh`: Tick flow, H4/H1/M15 update control, status comments, and spread checks.
- `Include/MyLib/Signals/HITEntrySignal.mqh`: Entry preconditions, order-type price validation, M15 filter, and retry-state updates.
- `Include/MyLib/Common/HITExternalProcess.mqh`: done/running files, external process handles, PID recovery, exit-code checks, and timeout recovery.
- `Include/MyLib/Signals/HITPythonSignalGateway.mqh`: OHLC CSV export, Python batch launch, and `trend_state.txt` / `target_prices.txt` / `target_zones.txt` loading.
- `Include/MyLib/Trading/HITTradeManager.mqh`: Order sending, filling policy, pending-order expiration, order/position counting, expired order cancellation, and expired position closing.
- `Include/MyLib/Trading/SLTPManager.mqh`: Existing-position break-even, elapsed-time break-even, active trailing, TP-progress SL, and high-volatility SL management.
- `Include/MyLib/Panel/SLTPManagerPanel.mqh`: Chart panel that toggles `CSLTPManager` features, validates numeric inputs, and applies settings to the EA.
## 5. Python Integration Files
During `OnInit()`, the EA builds a `HIT_<sanitized symbol>_<magic_number>` prefix from `_Symbol` and `magic_number`, then applies it to all MT5 `Files` linkage names. Example: `HIT_GOLD_10001_ohlc_H4.csv`. The same prefix is passed to the batch file as the first argument, and the batch file exposes it to Python as `MT5_EA_FILE_PREFIX`. The EA also passes the symbol's `SYMBOL_DIGITS` as the second argument, exposed to Python as `MT5_PRICE_DIGITS`.
When no prefix is provided, such as manual Python execution, Python keeps using the legacy names like `ohlc_H4.csv`.
### H4 Trend Analysis
- MQL5 output: `<prefix>_ohlc_H4.csv`
- Python output: `<prefix>_trend_state.txt`
- Done marker: `<prefix>_process_done_trend.txt`
- Running marker: `<prefix>_process_running_trend.txt`
- Batch file: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_trend_reply.bat`
### H1 Entry Candidate Generation
- MQL5 output: `<prefix>_ohlc_H1.csv`
- Python output: `<prefix>_target_prices.txt`, `<prefix>_target_zones.txt`
- Done marker: `<prefix>_process_done_entry.txt`
- Running marker: `<prefix>_process_running_entry.txt`
- Batch file: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_entry_reply.bat`
During `OnInit()`, the EA resolves `MQL5\python_for_ea` from `TerminalInfoString(TERMINAL_DATA_PATH)` and builds absolute batch-file paths. Each batch file resolves the Python project root from its own location, so runtime execution no longer depends on `C:\ea_py`.
`target_prices.txt` must contain 13 lines:
```text
Line 1: res_chk
Lines 2-4: T1 Buy Stop entry/tp/sl
Lines 5-7: T2 Buy Limit entry/tp/sl
Lines 8-10: T3 Sell Stop entry/tp/sl
Lines 11-13: T4 Sell Limit entry/tp/sl
```
`target_zones.txt` must contain 7 lines for split entries:
```text
Line 1: schema_version (2)
Line 2: res_chk
Line 3: candidate_id derived from the closed H1 bar time
Line 4: T1 Buy Stop strategy, zone_low, zone_high, tp, sl
Line 5: T2 Buy Limit strategy, zone_low, zone_high, tp, sl
Line 6: T3 Sell Stop strategy, zone_low, zone_high, tp, sl
Line 7: T4 Sell Limit strategy, zone_low, zone_high, tp, sl
```
Python creates `process_done_entry.txt` only after both `target_prices.txt` and `target_zones.txt` have been written. Prices in `target_zones.txt` are formatted with `MT5_PRICE_DIGITS`; manual runs without this value use a conservative 5 decimal places. When split entries are disabled, the EA keeps using the legacy 13-line `target_prices.txt` path.
## 6. Entry Conditions
New entries are allowed only when all conditions below are satisfied:
- Spread is less than or equal to `spread_limit`.
- H4 trend analysis is complete and `trend_state.txt` can be loaded.
- H1 entry candidate generation is complete and `target_prices.txt` can be loaded.
- `res_chk = 1`.
- The H1 candidate set has not expired under `ENTRY_H1_LIMIT`, measured from the closed H1 bar time that produced the candidate.
- The H1 candidate set has not exceeded `input_entry_max_candidate_age_minutes`, measured from the closed H1 bar time that produced the candidate.
- The selected order type has valid `entry/tp/sl` values greater than `0.0`.
- The order type is allowed by the H4 `market_state`.
- The order-type price relationship and broker minimum distance rules are satisfied.
- When `use_m15_entry_filter = true`, T2/T4 satisfy the M15 direction, rejection, and proximity checks. T1/T3 satisfy M15 impulse confirmation when `use_m15_imbalance_confirmation = true`.
- This EA's pending orders plus positions are below `input_position_limit`.
- When split entries are enabled, `target_zones.txt` has `res_chk = 1`, the predicted zone prices are valid, split lots fit `SYMBOL_VOLUME_MIN/MAX/STEP`, and no duplicate order or position exists for the same `candidate_id` + slot.
### market_state and Allowed Order Types
- `0 MARKET_LOW_VOL_RANGE`: Allows T2 Buy Limit / T4 Sell Limit.
- `1 MARKET_HIGH_VOL_RANGE`: Allows T2 Buy Limit / T4 Sell Limit.
- `2 MARKET_LOW_VOL_UP`: Allows T1 Buy Stop / T2 Buy Limit.
- `3 MARKET_HIGH_VOL_UP`: Allows T1 Buy Stop / T2 Buy Limit.
- `4 MARKET_LOW_VOL_DOWN`: Allows T3 Sell Stop / T4 Sell Limit.
- `5 MARKET_HIGH_VOL_DOWN`: Allows T3 Sell Stop / T4 Sell Limit.
- `6 MARKET_TECHNICAL_ERROR_STOP`: Blocks new entries.
### Order-Type Price Rules
- T1 Buy Stop: `Ask < entry`, `tp > entry`, `sl < entry`
- T2 Buy Limit: `Ask > entry`, `tp > entry`, `sl < entry`
- T3 Sell Stop: `Bid > entry`, `tp < entry`, `sl > entry`
- T4 Sell Limit: `Bid < entry`, `tp < entry`, `sl > entry`
## 7. Exit Conditions
- Pending orders are cancelled after `ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1)` has elapsed from setup time.
- Positions are closed after `CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1)` has elapsed from entry time.
- Time-limit handling runs early in `OnTick` and is independent of Python readiness or spread checks.
- On EA removal, `OnDeinit()` releases external-process state and the SLTP panel, then clears the chart status text with `Comment("")` and `ChartRedraw(0)`.
- When `input_sltp_manager_enabled` or the panel `Manager` toggle is ON, the EA runs `CSLTPManager::ManagePositions()` and `HighVolatilityLimit()` after time-limit handling. Existing-position SL protection therefore continues while Python results are pending or new entries are skipped.
- Normal break-even and active trailing are mutually exclusive. The panel turns one mode off when the other is enabled, and `CSLTPManager::ValidateSettings()` also validates the exclusion.
## 7.1 SLTP Control Panel
- The panel is created when `input_sltp_show_panel = true` and appears near the chart's upper-right area.
- If panel creation fails, the EA logs the failure and continues with the already-applied input-based SLTP settings.
- The `Manager` button toggles all SLTP management. When OFF, panel values remain stored but `OnTick` does not modify SL values.
- The `BreakEven`, `Elapsed BE`, `Active Trail`, `TP Progress`, and `High Vol` buttons toggle each `CSLTPManager` feature.
- Numeric fields are validated when `APPLY` is pressed. Invalid or out-of-range values show a `MessageBox`, are logged, and revert to the previous valid value.
- Settings are copied into `CSLTPManager` only after `APPLY` succeeds. The EA then calls `ValidateSettings()`; if validation fails, SLTP management is stopped and the reason is logged.
## 8. Risk Management
- Managed orders and positions are limited to matching `_Symbol` and `magic_number`.
- `input_position_limit` counts only this EA's orders and positions, not the full account. The hard internal limit is `POSITION_LIMIT`.
- The EA selects the filling policy from `SYMBOL_FILLING_MODE`, preferring IOC, then FOK, then RETURN.
- Before sending either single or split orders, the EA verifies the requested lot against `SYMBOL_VOLUME_MIN/MAX/STEP`.
- Pending orders receive server-side expiration when the broker supports it.
- `OrderSend` return values and `MqlTradeResult.retcode` are checked. Failures are logged with `GetLastError()` or the retcode.
- Split-entry order comments include `candidate_id` and slot number to prevent duplicate slot execution.
- When `cancel_old_split_pending_on_new_zone = true`, a new valid `candidate_id` cancels older split pending orders, and an invalid or stopped `target_zones.txt` cancels all existing split pending orders for this EA/symbol/magic.
- SLTP management only targets existing positions matching `_Symbol` and `magic_number`, and it preserves each position's current TP.
- SL changes are sent only when the candidate improves protection relative to the current SL and satisfies broker stop-level and freeze-level constraints.
- `HighVolatilityLimit()` evaluates BUY positions with Bid and SELL positions with Ask, and treats GOLD/XAUUSD suffix symbols as 1 pip = 0.1.
## 9. Error Handling
- If `trend_state.txt` is missing, unreadable, not strictly parseable as an integer, or outside `0..6`, the EA uses `MARKET_TECHNICAL_ERROR_STOP`.
- If `target_prices.txt` is missing, unreadable, shorter than 13 lines, or contains a non-strict numeric line, the EA uses `res_chk = 0`.
- When split entries are enabled, missing `target_zones.txt`, schema mismatch, fewer than 7 lines, `res_chk != 1`, or non-strict numeric values stop new split orders.
- If a Python process exits with a non-zero code, the code is logged and the next trigger may retry.
- If a Python process remains active beyond `PYTHON_TIMEOUT_SECONDS`, the EA runs `taskkill /T /F` against the cmd/bat process tree, clears done/running files, and allows the next trigger to retry.
- If only a stale running marker remains, the EA attempts PID recovery. If recovery fails and the marker is timed out, it removes the stale marker.
## 10. Changelog
### 2026-05-30
- Added the `HIT_<symbol>_<magic_number>` linkage-file prefix contract on both the MT5 and Python sides to avoid collisions across multiple EAs or symbols in the same terminal.
- Updated T1/T3 trend-following candidates so `use_m15_imbalance_confirmation = true` requires M15 impulse confirmation.
- Added strict numeric parsing requirements for `trend_state.txt`, `target_prices.txt`, and `target_zones.txt`, with invalid content handled as a safe stop state.
- Added stale split-pending cancellation behavior when `target_zones.txt` is invalid or stopped.
- Synchronized current defaults for `input_entry_max_candidate_age_minutes`, `ENTRY_H1_LIMIT`, SLTP buffers, and the Python entry-distance guard.
- Added process-tree termination and retry recovery for Python timeouts.
- Changed H1 candidate freshness checks to use the closed H1 bar time restored from `candidate_id`, instead of the Python result load time.
- Added `MT5_PRICE_DIGITS` so Python formats `target_zones.txt` prices with the active symbol's decimal precision.
- Added single-order lot validation, OHLC CSV NaN/inf and consistency checks, Ask-based SELL high-volatility SL evaluation, and GOLD/XAUUSD suffix handling.
### 2026-05-27
- Moved the Python helper application specification from `C:\ea_py` to `MQL5\python_for_ea` under the MT5 data folder.
- Updated the EA startup path model so batch paths are built from `TerminalInfoString(TERMINAL_DATA_PATH)`, and the external process working directory is derived from the batch-file location.
- Updated Python path discovery so the default MT5 linkage is the adjacent `MQL5\Files` directory, with `MT5_FILES_DIR` or `MT5_DATA_PATH` available for explicit overrides.
### 2026-05-24
- Added Python-side `target_zones.txt` output and made `process_done_entry.txt` appear only after both `target_prices.txt` and `target_zones.txt` are written.
- Added `use_split_entry_zone`, `split_entry_count`, `split_lot_mode`, `split_total_lot_size`, `split_fixed_lot_size`, and `input_position_limit`.
- Added split-zone pending order placement with total-lot or fixed-lot sizing.
- Added `candidate_id` + slot identification to prevent duplicate split orders.
### 2026-05-13
- Added a Python-side H1 EATR distance guard that invalidates candidates too far from the current price before they are passed to MT5.
- Added `input_entry_max_candidate_age_minutes` on the EA side so stale H1 candidates are not executed when M15 confirmation arrives late.
- Added H1 candidate age to entry skip logs to make delayed entries, M15 rejection, and price mismatch easier to diagnose.
### 2026-05-05
- Added `Comment("")` and `ChartRedraw(0)` to `OnDeinit()` so the chart status comment is removed when the EA is deleted.
- Connected `CSLTPManager` and the dedicated chart panel `SLTPManagerPanel.mqh` to `HIT-EA_refactor_ver5.mq5`, allowing UI control of break-even, elapsed-time break-even, active trailing, TP-progress SL, and high-volatility SL tightening.
- Added SLTP management immediately after time-limit handling in `OnTick`, so existing-position protection continues independently of Python readiness and spread checks.
- Added SLTP panel inputs, mutual exclusion for normal break-even versus active trailing, and numeric validation on `APPLY`.
- Split the function implementations from `HIT-EA_refactor_ver5.mq5` into purpose-specific `.mqh` files.
- Kept `OnInit`, `OnDeinit`, `OnTick`, inputs, and global state in the EA source while moving behavior functions under `Include/MyLib/`.
- Updated the specification to match the current `CreateProcessW` Python process tracking, M15 filter, `market_state` range `0..6`, and `spread_limit = 60`.
### 2026-05-02
- Added entry suppression when `res_chk = 0`.
- Moved time-limit handling before Python readiness and spread checks.
- Split startup flags for H4 and H1 initial processing.
- Switched OHLC retrieval to `CopyRates` and exported closed bars only.
@@ -0,0 +1,274 @@
# HIT-EA Specification (English)
## 1. Overview
- This EA sends confirmed H4 OHLC data to an external Python process for market-state analysis and confirmed H1 OHLC data for entry candidate generation.
- The MQL5 side reads Python output files and places pending orders only after checking the H4 market state, H1 candidate prices, M15 confirmation filter, spread, and broker distance constraints.
- For backtest reproducibility, OHLC export uses `OHLC_START_SHIFT = 1`, so the forming bar is excluded and only closed bars are passed to Python.
- For live resilience, the EA tracks external-process running files, process IDs, exit codes, and timeouts to prevent duplicate launches and CSV overwrites.
## 2. Indicators
- No standard or custom indicators are used.
- OHLC data is retrieved with `CopyRates(_Symbol, timeframe, OHLC_START_SHIFT, HISTORY_BARS, rates)`.
- M15 entry confirmation uses candle shape, average range, and distance to the candidate price for T2/T4. For T1/T3 it uses M15 impulse confirmation when that option is enabled.
## 3. Parameters
### input
- `lot_size = 0.01`: Order volume.
- `spread_limit = 60`: Maximum allowed spread in points.
- `magic_number = 10001`: Magic number used to identify this EA's orders and positions.
- `initial_order = 0`: Retained for compatibility with older settings. Startup always rebuilds H4/H1 results and remains in technical-error stop state until the H4 result is reloaded.
- `input_position_limit = 10`: Practical limit for this EA's pending orders plus positions. Values above the internal `POSITION_LIMIT` are clamped.
- `use_split_entry_zone = false`: Enables split entries based on H1 predicted zones.
- `split_entry_count = 3`: Number of split entry orders, clamped to 1..10.
- `split_lot_mode = SPLIT_LOT_TOTAL`: Split lot mode. `SPLIT_LOT_TOTAL` divides the total lot across slots, and `SPLIT_LOT_FIXED` uses a fixed lot per order.
- `split_total_lot_size = 0.09`: Total lot used by total-split mode.
- `split_fixed_lot_size = 0.01`: Per-order lot used by fixed-split mode.
- `cancel_old_split_pending_on_new_zone = true`: Cancels older split pending orders when a new H1 zone set is loaded.
- `input_cancel_retry_cooldown_seconds = 60`: Wait time before retrying a failed pending-order cancellation for the same ticket. The effective value is clamped to 1..3600 seconds.
- `use_m15_entry_filter = true`: Enables M15 closed-bar entry timing confirmation.
- `m15_entry_zone_atr_multiplier = 1.50`: Allowed proximity multiplier based on the M15 average range.
- `use_m15_imbalance_confirmation = true`: Adds M15 impulse confirmation for T1/T3 trend-following candidates.
- `m15_imbalance_avg_body_period = 20`: Average-body period used by M15 impulse confirmation.
- `m15_imbalance_sensitivity = 2.0`: Required multiple of the average body for M15 impulse confirmation.
- `m15_imbalance_min_avg_body_points = 1.0`: Minimum M15 average body in points.
- `use_m15_imbalance_debug_log = false`: Enables detailed M15 impulse-confirmation logs.
- `input_entry_max_candidate_age_minutes = 120`: Maximum age, in minutes, for using an H1 candidate for new execution. This blocks delayed entries when M15 confirmation appears too late.
- `input_sltp_manager_enabled = false`: Enables UI-driven existing-position SL management through `CSLTPManager`.
- `input_sltp_show_panel = true`: Shows the SLTP control panel on the chart.
- `input_sltp_use_breakeven = false`: Enables normal break-even.
- `input_sltp_breakeven_trigger_pips = 30.0`: Profit threshold for normal break-even.
- `input_sltp_breakeven_buffer_pips = 3.0`: Profit-side entry buffer used by normal break-even.
- `input_sltp_use_elapsed_breakeven = false`: Enables elapsed-time break-even.
- `input_sltp_elapsed_breakeven_hours = 4.0`: Holding time required before elapsed-time break-even is allowed.
- `input_sltp_elapsed_breakeven_buffer_pips = 3.0`: Profit-side entry buffer used by elapsed-time break-even.
- `input_sltp_use_active_trailing = false`: Enables active step trailing.
- `input_sltp_active_breakeven_pips = 30.0`: Profit threshold that starts active trailing.
- `input_sltp_active_stop_loss_offset_pips = 5.0`: Initial locked profit offset from entry.
- `input_sltp_active_step_trigger_pips = 10.0`: Additional profit interval required for each SL step.
- `input_sltp_active_step_move_pips = 5.0`: SL movement added per completed step.
- `input_sltp_use_tp_progress_stop = false`: Enables TP-progress-based SL locking.
- `input_sltp_tp_progress_trigger_percent = 70.0`: TP progress required before the SL lock is applied.
- `input_sltp_tp_progress_sl_lock_percent = 30.0`: Entry-to-TP distance percentage locked by SL.
- `input_sltp_use_high_volatility_limit = false`: Enables short-term high-volatility SL tightening.
### Main Constants
- `POSITION_LIMIT = 48`: Maximum number of this EA's pending orders plus positions.
- `ENTRY_H1_LIMIT = 2`: Pending-order lifetime in H1 bars.
- `CLOSE_H1_LIMIT = 12`: Position lifetime in H1 bars.
- `HISTORY_BARS = 72`: Number of OHLC bars exported to Python.
- `OHLC_START_SHIFT = 1`: Shift used to export closed bars only.
- `M15_CONFIRM_BARS = 30`: Number of M15 bars used for average-range calculation.
- `ENTRY_RETRY_SECONDS = 60`: Retry interval for entry checks.
- `ENTRY_RETRY_LIMIT = 10`: Maximum retry count for one H1 candidate set.
- `TARGET_SIZE = 13`: Number of numeric values expected in `target_prices.txt`.
- `TARGET_ZONE_SCHEMA_VERSION = 2`: Schema version used by `target_zones.txt`.
- `PYTHON_TIMEOUT_SECONDS = 600`: External Python wait threshold.
### Python Entry-Candidate Guard
- After H1 candidate generation, Python invalidates any `entry` that is too far from the current price.
- The maximum distance is strategy-specific: T1/T3 Stop candidates use `max(H1 EATR * 1.50, 5.00)`, and T2/T4 Limit candidates use `max(H1 EATR * 1.00, 5.00)`. A strategy beyond its limit is rewritten to `0.00,0.00,0.00`.
- This post-filter is intended to reduce delayed entries from deep limit orders or distant breakout waits after M15 confirmation arrives late.
## 4. File Layout
- `Experts/MyProject/HIT-EA_refactor_ver6.mq5`: EA entry point. Keeps `OnInit`, `OnDeinit`, `OnTick`, inputs, global state, and DLL imports.
- `Include/MyLib/Common/HITRuntimeController.mqh`: Tick flow, H4/H1/M15 update control, status comments, and spread checks.
- `Include/MyLib/Signals/HITEntrySignal.mqh`: Entry preconditions, order-type price validation, M15 filter, and retry-state updates.
- `Include/MyLib/Common/HITExternalProcess.mqh`: done/running files, external process handles, PID recovery, exit-code checks, and timeout recovery.
- `Include/MyLib/Signals/HITPythonSignalGateway.mqh`: OHLC CSV export, Python batch launch, and `trend_state.txt` / `target_prices.txt` / `target_zones.txt` loading.
- `Include/MyLib/Trading/HITTradeManager.mqh`: Order sending, filling policy, pending-order expiration, order/position counting, expired order cancellation, and expired position closing.
- `Include/MyLib/Trading/SLTPManager.mqh`: Existing-position break-even, elapsed-time break-even, active trailing, TP-progress SL, and high-volatility SL management.
- `Include/MyLib/Panel/SLTPManagerPanel.mqh`: Chart panel that toggles `CSLTPManager` features, validates numeric inputs, and applies settings to the EA.
## 5. Python Integration Files
During `OnInit()`, the EA builds a `HIT_<sanitized symbol>_<magic_number>` prefix from `_Symbol` and `magic_number`, then applies it to all MT5 `Files` linkage names. Example: `HIT_GOLD_10001_ohlc_H4.csv`. The same prefix is passed to the batch file as the first argument, and the batch file exposes it to Python as `MT5_EA_FILE_PREFIX`. The EA also passes the symbol's `SYMBOL_DIGITS` as the second argument, exposed to Python as `MT5_PRICE_DIGITS`.
When no prefix is provided, such as manual Python execution, Python keeps using the legacy names like `ohlc_H4.csv`.
### H4 Trend Analysis
- MQL5 output: `<prefix>_ohlc_H4.csv`
- Python output: `<prefix>_trend_state.txt`
- Done marker: `<prefix>_process_done_trend.txt`
- Running marker: `<prefix>_process_running_trend.txt`
- Batch file: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_trend_reply.bat`
### H1 Entry Candidate Generation
- MQL5 output: `<prefix>_ohlc_H1.csv`
- Python output: `<prefix>_target_prices.txt`, `<prefix>_target_zones.txt`
- Done marker: `<prefix>_process_done_entry.txt`
- Running marker: `<prefix>_process_running_entry.txt`
- Batch file: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_entry_reply.bat`
During `OnInit()`, the EA resolves `MQL5\python_for_ea` from `TerminalInfoString(TERMINAL_DATA_PATH)` and builds absolute batch-file paths. Each batch file resolves the Python project root from its own location, so runtime execution no longer depends on `C:\ea_py`.
`target_prices.txt` must contain 13 lines:
```text
Line 1: res_chk
Lines 2-4: T1 Buy Stop entry/tp/sl
Lines 5-7: T2 Buy Limit entry/tp/sl
Lines 8-10: T3 Sell Stop entry/tp/sl
Lines 11-13: T4 Sell Limit entry/tp/sl
```
`target_zones.txt` must contain 7 lines for split entries:
```text
Line 1: schema_version (2)
Line 2: res_chk
Line 3: candidate_id derived from the closed H1 bar time
Line 4: T1 Buy Stop strategy, zone_low, zone_high, tp, sl
Line 5: T2 Buy Limit strategy, zone_low, zone_high, tp, sl
Line 6: T3 Sell Stop strategy, zone_low, zone_high, tp, sl
Line 7: T4 Sell Limit strategy, zone_low, zone_high, tp, sl
```
Python creates `process_done_entry.txt` only after both `target_prices.txt` and `target_zones.txt` have been written. Prices in `target_zones.txt` are formatted with `MT5_PRICE_DIGITS`; manual runs without this value use a conservative 5 decimal places. When split entries are disabled, the EA keeps using the legacy 13-line `target_prices.txt` path.
## 6. Entry Conditions
New entries are allowed only when all conditions below are satisfied:
- Spread is less than or equal to `spread_limit`.
- H4 trend analysis is complete and `trend_state.txt` can be loaded.
- H1 entry candidate generation is complete and `target_prices.txt` can be loaded.
- `res_chk = 1`.
- The H1 candidate set has not expired under `ENTRY_H1_LIMIT`, measured from the closed H1 bar time that produced the candidate.
- The H1 candidate set has not exceeded `input_entry_max_candidate_age_minutes`, measured from the closed H1 bar time that produced the candidate.
- The selected order type has valid `entry/tp/sl` values greater than `0.0`.
- The order type is allowed by the H4 `market_state`.
- The order-type price relationship and broker minimum distance rules are satisfied.
- When `use_m15_entry_filter = true`, T2/T4 satisfy the M15 direction, rejection, and proximity checks. T1/T3 satisfy M15 impulse confirmation when `use_m15_imbalance_confirmation = true`.
- This EA's pending orders plus positions are below `input_position_limit`.
- When split entries are enabled, `target_zones.txt` has `res_chk = 1`, the predicted zone prices are valid, split lots fit `SYMBOL_VOLUME_MIN/MAX/STEP`, and no duplicate order or position exists for the same `candidate_id` + order type + slot.
### market_state and Allowed Order Types
- `0 MARKET_LOW_VOL_RANGE`: Allows T2 Buy Limit / T4 Sell Limit.
- `1 MARKET_HIGH_VOL_RANGE`: Allows T2 Buy Limit / T4 Sell Limit.
- `2 MARKET_LOW_VOL_UP`: Allows T1 Buy Stop / T2 Buy Limit.
- `3 MARKET_HIGH_VOL_UP`: Allows T1 Buy Stop / T2 Buy Limit.
- `4 MARKET_LOW_VOL_DOWN`: Allows T3 Sell Stop / T4 Sell Limit.
- `5 MARKET_HIGH_VOL_DOWN`: Allows T3 Sell Stop / T4 Sell Limit.
- `6 MARKET_TECHNICAL_ERROR_STOP`: Blocks new entries.
After an H4 `market_state` reload, the EA cancels existing pending orders whose order types are not allowed by the refreshed state. For `6 MARKET_TECHNICAL_ERROR_STOP`, it cancels all pending orders managed by this EA.
### Order-Type Price Rules
- T1 Buy Stop: `Ask < entry`, `tp > entry`, `sl < entry`
- T2 Buy Limit: `Ask > entry`, `tp > entry`, `sl < entry`
- T3 Sell Stop: `Bid > entry`, `tp < entry`, `sl > entry`
- T4 Sell Limit: `Bid < entry`, `tp < entry`, `sl > entry`
## 7. Exit Conditions
- Pending orders are cancelled after `ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1)` has elapsed from the H1 candidate time restored from the comment. Legacy orders without that token fall back to setup time.
- Positions are closed after `CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1)` has elapsed from entry time.
- Time-limit handling runs early in `OnTick` and is independent of Python readiness or spread checks.
- On EA removal, `OnDeinit()` releases external-process state and the SLTP panel, then clears the chart status text with `Comment("")` and `ChartRedraw(0)`.
- When `input_sltp_manager_enabled` or the panel `Manager` toggle is ON, the EA runs `CSLTPManager::ManagePositions()` and `HighVolatilityLimit()` after time-limit handling. Existing-position SL protection therefore continues while Python results are pending or new entries are skipped.
- Normal break-even and active trailing are mutually exclusive. The panel turns one mode off when the other is enabled, and `CSLTPManager::ValidateSettings()` also validates the exclusion.
## 7.1 SLTP Control Panel
- The panel is created when `input_sltp_show_panel = true` and appears near the chart's upper-right area.
- If panel creation fails, the EA logs the failure and continues with the already-applied input-based SLTP settings.
- The `Manager` button toggles all SLTP management. When OFF, panel values remain stored but `OnTick` does not modify SL values.
- The `BreakEven`, `Elapsed BE`, `Active Trail`, `TP Progress`, and `High Vol` buttons toggle each `CSLTPManager` feature.
- Numeric fields are validated when `APPLY` is pressed. Invalid or out-of-range values show a `MessageBox`, are logged, and revert to the previous valid value.
- Settings are copied into `CSLTPManager` only after `APPLY` succeeds. The EA then calls `ValidateSettings()`; if validation fails, SLTP management is stopped and the reason is logged.
## 8. Risk Management
- Managed orders and positions are limited to matching `_Symbol` and `magic_number`.
- `input_position_limit` counts only this EA's orders and positions, not the full account. The hard internal limit is `POSITION_LIMIT`.
- The EA selects the filling policy from `SYMBOL_FILLING_MODE`, preferring IOC, then FOK, then RETURN.
- Before sending either single or split orders, the EA verifies the requested lot against `SYMBOL_VOLUME_MIN/MAX/STEP`.
- Pending orders receive server-side expiration from the H1 candidate time when the broker supports it. Orders are skipped if that expiration is already in the past.
- `OrderSend` return values and `MqlTradeResult.retcode` are checked. Failures are logged with `GetLastError()` or the retcode.
- Single and split order comments keep a valid `candidate_id` for candidate-origin expiration handling.
- Split-entry order comments also include order type and slot number to prevent duplicate execution of the same strategy slot.
- When `cancel_old_split_pending_on_new_zone = true`, a new valid `candidate_id` cancels older split pending orders, and an invalid or stopped `target_zones.txt` cancels all existing split pending orders for this EA/symbol/magic.
- After an H4 state update, existing pending orders that contradict the refreshed `market_state` are cancelled.
- A failed pending-order cancellation is not retried for the same ticket until `input_cancel_retry_cooldown_seconds` has elapsed, preventing excessive per-tick trade-server requests.
- SLTP management only targets existing positions matching `_Symbol` and `magic_number`, and it preserves each position's current TP.
- SL changes are sent only when the candidate improves protection relative to the current SL and satisfies broker stop-level and freeze-level constraints.
- `HighVolatilityLimit()` evaluates BUY positions with Bid and SELL positions with Ask, and treats GOLD/XAUUSD suffix symbols as 1 pip = 0.1.
## 9. Error Handling
- If `trend_state.txt` is missing, unreadable, not strictly parseable as an integer, or outside `0..6`, the EA uses `MARKET_TECHNICAL_ERROR_STOP`.
- If `target_prices.txt` is missing, unreadable, shorter than 13 lines, or contains a non-strict numeric line, the EA uses `res_chk = 0`.
- When split entries are enabled, missing `target_zones.txt`, schema mismatch, fewer than 7 lines, `res_chk != 1`, a valid-zone `candidate_id` that is not a strict 12-digit timestamp, or non-strict numeric values stop new split orders.
- If a Python process exits with a non-zero code, the code is logged and the next trigger may retry.
- If a Python process remains active beyond `PYTHON_TIMEOUT_SECONDS`, the EA runs `taskkill /T /F` against the cmd/bat process tree, clears done/running files, and allows the next trigger to retry.
- If only a stale running marker remains, the EA attempts PID recovery. If recovery fails and the marker is timed out, it removes the stale marker.
## 10. Changelog
### 2026-05-31
- Changed startup initialization to rebuild H4/H1 results regardless of `initial_order`, while holding the technical-error stop state until the H4 result reloads.
- Added cancellation of existing pending orders that contradict a refreshed H4 `market_state`.
- Added per-ticket cooldown after failed pending-order cancellation to prevent excessive per-tick trade-server requests.
- Added order type to split-slot identifiers so different strategies using the same `candidate_id` and slot cannot collide.
- Kept valid `candidate_id` tokens in both single and split order comments and changed pending expiration to use the H1 candidate origin time.
- Required strict 12-digit timestamp `candidate_id` values for valid `target_zones.txt`; malformed values now stop safely.
### 2026-05-30
- Added the `HIT_<symbol>_<magic_number>` linkage-file prefix contract on both the MT5 and Python sides to avoid collisions across multiple EAs or symbols in the same terminal.
- Updated T1/T3 trend-following candidates so `use_m15_imbalance_confirmation = true` requires M15 impulse confirmation.
- Added strict numeric parsing requirements for `trend_state.txt`, `target_prices.txt`, and `target_zones.txt`, with invalid content handled as a safe stop state.
- Added stale split-pending cancellation behavior when `target_zones.txt` is invalid or stopped.
- Synchronized current defaults for `input_entry_max_candidate_age_minutes`, `ENTRY_H1_LIMIT`, SLTP buffers, and the Python entry-distance guard.
- Added process-tree termination and retry recovery for Python timeouts.
- Changed H1 candidate freshness checks to use the closed H1 bar time restored from `candidate_id`, instead of the Python result load time.
- Added `MT5_PRICE_DIGITS` so Python formats `target_zones.txt` prices with the active symbol's decimal precision.
- Added single-order lot validation, OHLC CSV NaN/inf and consistency checks, Ask-based SELL high-volatility SL evaluation, and GOLD/XAUUSD suffix handling.
### 2026-05-27
- Moved the Python helper application specification from `C:\ea_py` to `MQL5\python_for_ea` under the MT5 data folder.
- Updated the EA startup path model so batch paths are built from `TerminalInfoString(TERMINAL_DATA_PATH)`, and the external process working directory is derived from the batch-file location.
- Updated Python path discovery so the default MT5 linkage is the adjacent `MQL5\Files` directory, with `MT5_FILES_DIR` or `MT5_DATA_PATH` available for explicit overrides.
### 2026-05-24
- Added Python-side `target_zones.txt` output and made `process_done_entry.txt` appear only after both `target_prices.txt` and `target_zones.txt` are written.
- Added `use_split_entry_zone`, `split_entry_count`, `split_lot_mode`, `split_total_lot_size`, `split_fixed_lot_size`, and `input_position_limit`.
- Added split-zone pending order placement with total-lot or fixed-lot sizing.
- Added `candidate_id` + slot identification to prevent duplicate split orders.
### 2026-05-13
- Added a Python-side H1 EATR distance guard that invalidates candidates too far from the current price before they are passed to MT5.
- Added `input_entry_max_candidate_age_minutes` on the EA side so stale H1 candidates are not executed when M15 confirmation arrives late.
- Added H1 candidate age to entry skip logs to make delayed entries, M15 rejection, and price mismatch easier to diagnose.
### 2026-05-05
- Added `Comment("")` and `ChartRedraw(0)` to `OnDeinit()` so the chart status comment is removed when the EA is deleted.
- Connected `CSLTPManager` and the dedicated chart panel `SLTPManagerPanel.mqh` to `HIT-EA_refactor_ver5.mq5`, allowing UI control of break-even, elapsed-time break-even, active trailing, TP-progress SL, and high-volatility SL tightening.
- Added SLTP management immediately after time-limit handling in `OnTick`, so existing-position protection continues independently of Python readiness and spread checks.
- Added SLTP panel inputs, mutual exclusion for normal break-even versus active trailing, and numeric validation on `APPLY`.
- Split the function implementations from `HIT-EA_refactor_ver5.mq5` into purpose-specific `.mqh` files.
- Kept `OnInit`, `OnDeinit`, `OnTick`, inputs, and global state in the EA source while moving behavior functions under `Include/MyLib/`.
- Updated the specification to match the current `CreateProcessW` Python process tracking, M15 filter, `market_state` range `0..6`, and `spread_limit = 60`.
### 2026-05-02
- Added entry suppression when `res_chk = 0`.
- Moved time-limit handling before Python readiness and spread checks.
- Split startup flags for H4 and H1 initial processing.
- Switched OHLC retrieval to `CopyRates` and exported closed bars only.
+64 -7
View File
@@ -20,7 +20,7 @@
- `lot_size = 0.01`: 注文ロット。
- `spread_limit = 60`: 許容スプレッド(point)。
- `magic_number = 10001`: EA識別用マジックナンバー。
- `initial_order = 0`: 起動直後の初回H4/H1処理を実行するか。`1` で有効
- `initial_order = 0`: 旧設定ファイルとの互換性維持用。値にかかわらず起動時はH4/H1を再生成し、H4再読込までは技術エラー停止状態を維持する
- `use_m15_entry_filter = true`: M15確定足によるエントリータイミング確認を使用するか。
- `m15_entry_zone_atr_multiplier = 1.50`: M15平均レンジに対する候補価格接近許容倍率。
- `use_m15_imbalance_confirmation = true`: T1/T3の順張り候補に対して、M15確定足の初動確認を追加するか。
@@ -29,6 +29,17 @@
- `m15_imbalance_min_avg_body_points = 1.0`: M15平均実体の最小値(point)。
- `use_m15_imbalance_debug_log = false`: M15初動確認の詳細ログを出すか。
- `input_entry_max_candidate_age_minutes = 120`: H1候補価格を新規発注に使用できる最大経過分数。古い候補でM15条件が後から整った場合の遅延エントリーを抑止する。
- `input_tp_multiplier = 1.25`: APIから取得したTP距離を、エントリー価格からの距離ベースで拡大する倍率。`1.0` 未満は `1.0``100.0` 超は `100.0` に丸める。
- `input_min_tp_points = 0`: 拡大後TP距離の最小値(point)。`0` の場合は無効化する。
- `input_max_tp_points = 0`: 拡大後TP距離の最大値(point)。`0` の場合は無効化する。API由来TPより近くなる場合は縮小せず、API距離を維持する。
- `input_range_breakout_guard_enabled = true`: レンジ上抜け/下抜け時に逆方向の逆張りLimit注文を退避し、新規発注も一時停止するか。
- `input_range_breakout_guard_timeframe = PERIOD_M15`: レンジブレイクを監視する時間足。
- `input_range_breakout_lookback_bars = 20`: レンジ高値・安値と平均レンジを計算する確定足本数。直近確定足の1本前から参照する。
- `input_range_breakout_max_width_multiplier = 6.0`: 平均レンジに対して許容する最大レンジ幅。`0` の場合はレンジ幅フィルタを無効化する。
- `input_range_breakout_buffer_multiplier = 0.20`: 確定ブレイク判定に使う平均レンジ倍率。
- `input_range_breakout_near_multiplier = 0.50`: ブレイク警戒判定に使うレンジ境界への接近幅倍率。
- `input_range_breakout_body_multiplier = 1.50`: ブレイク警戒に必要な直近確定足実体の平均実体倍率。
- `input_range_breakout_cooldown_bars = 4`: ブレイク検知後に逆方向Limitの新規発注を停止する足数。
- `input_position_limit = 10`: 自EAの未約定注文 + ポジション数の実運用上限。内部上限 `POSITION_LIMIT` を超える指定は丸める。
- `use_split_entry_zone = false`: H1予測ゾーンを使った分割エントリーを有効化するか。
- `split_entry_count = 3`: 分割エントリー本数。1〜10に丸めて使用する。
@@ -36,6 +47,7 @@
- `split_total_lot_size = 0.09`: 総量分割モードの合計ロット。
- `split_fixed_lot_size = 0.01`: 固定ロットモードの1注文ロット。
- `cancel_old_split_pending_on_new_zone = true`: 新しいH1ゾーン読込時に、同じEAの古い分割pending注文を取消するか。
- `input_cancel_retry_cooldown_seconds = 60`: pending注文の取消に失敗した場合、同一ticketへ取消要求を再送するまでの待機秒数。1〜3600秒に丸めて使用する。
- `input_sltp_manager_enabled = false`: UI連動の `CSLTPManager` による既存ポジションSL管理を有効化するか。
- `input_sltp_show_panel = true`: チャート上にSLTP操作パネルを表示するか。
- `input_sltp_use_breakeven = false`: 通常ブレークイーブンを有効化するか。
@@ -81,7 +93,7 @@
- `Include/MyLib/Signals/HITEntrySignal.mqh`: エントリー前提条件、注文タイプ別価格判定、M15フィルタ、リトライ状態更新。
- `Include/MyLib/Common/HITExternalProcess.mqh`: done/runningファイル、外部プロセスハンドル、PID復元、終了コード確認、タイムアウト復旧。
- `Include/MyLib/Signals/HITPythonSignalGateway.mqh`: OHLC CSV出力、Pythonバッチ起動、`trend_state.txt` / `target_prices.txt` / `target_zones.txt` 読込。
- `Include/MyLib/Trading/HITTradeManager.mqh`: 注文送信、執行ポリシー、有効期限設定、注文/ポジション数集計、期限切れ取消/クローズ。
- `Include/MyLib/Trading/HITTradeManager.mqh`: 注文送信、執行ポリシー、有効期限設定、注文/ポジション数集計、期限切れ取消/クローズ、レンジブレイク時の逆方向Limit取消
- `Include/MyLib/Trading/SLTPManager.mqh`: 既存ポジションに対するブレークイーブン、時間経過BE、アクティブトレーリング、TP進捗SL、急変時SL引き締めを管理する。
- `Include/MyLib/Panel/SLTPManagerPanel.mqh`: `CSLTPManager` の各設定をチャート上で切り替え、数値入力を検証してEAへ反映する操作パネル。
@@ -107,6 +119,8 @@ EAは `OnInit()` で `_Symbol` と `magic_number` から `HIT_<sanitized symbol>
- 実行中フラグ: `<prefix>_process_running_entry.txt`
- 起動バッチ: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_entry_reply.bat`
H1候補生成はOpenAI Responses APIを使用する。既定モデルは `gpt-5.5`、既定 `reasoning.effort``low`、既定 `text.verbosity``low` とする。`temperature` は指定せず、`OPENAI_MODEL``OPENAI_REASONING_EFFORT``OPENAI_TEXT_VERBOSITY` で実行時上書きできる。出力は `text.format` のStructured Outputs JSON Schemaで検証し、未完了応答、schema不一致、価格条件違反、reward/risk不足は安全側停止値へ倒す。
EAは `OnInit()``TerminalInfoString(TERMINAL_DATA_PATH)` から `MQL5\python_for_ea` を解決し、各batファイルの絶対パスを組み立てる。batファイルは自身の位置からPythonプロジェクトルートを解決するため、`C:\ea_py` には依存しない。
`target_prices.txt` は13行構成とする。
@@ -145,10 +159,13 @@ Pythonは `target_prices.txt` と `target_zones.txt` の両方を書き終えて
- H1候補価格が、元になったH1確定足時刻から `input_entry_max_candidate_age_minutes` 分を超えていない。
- 対象注文タイプの `entry/tp/sl` がすべて `0.0` より大きい。
- H4 `market_state` に対して注文タイプが許可されている。
- TPは価格整合条件とブローカー距離制約の判定前に、APIのTP価格そのものではなく「エントリー価格からAPI TPまでの距離」を `input_tp_multiplier` で拡大して最終TPへ変換する。Buy系はエントリーより上、Sell系はエントリーより下へ配置する。
- 分割エントリー有効時は、slotごとのエントリー価格を基準に各slotの最終TPを個別に計算する。
- 注文タイプごとの価格整合条件とブローカー最小距離制約を満たす。
- `use_m15_entry_filter = true` の場合、T2/T4はM15確定足の方向・反発・接近条件を満たす。T1/T3は `use_m15_imbalance_confirmation = true` の場合にM15初動確認を満たす。
- `input_range_breakout_guard_enabled = true` の場合、レンジ上抜け後のT4 Sell Limit、レンジ下抜け後のT2 Buy Limitはクールダウン終了まで新規発注しない。
- 自EAの注文 + ポジション数が `input_position_limit` 未満。
- 分割エントリー有効時は `target_zones.txt``res_chk = 1`、予測ゾーンの価格整合、分割ロットの `SYMBOL_VOLUME_MIN/MAX/STEP` 適合、同一 `candidate_id` + slot の重複注文/ポジション不存在を満たす。
- 分割エントリー有効時は `target_zones.txt``res_chk = 1`、予測ゾーンの価格整合、分割ロットの `SYMBOL_VOLUME_MIN/MAX/STEP` 適合、同一 `candidate_id` + 注文タイプ + slot の重複注文/ポジション不存在を満たす。
### market_state と注文タイプ
@@ -160,6 +177,16 @@ Pythonは `target_prices.txt` と `target_zones.txt` の両方を書き終えて
- `5 MARKET_HIGH_VOL_DOWN`: T3 Sell Stop / T4 Sell Limit を許可。
- `6 MARKET_TECHNICAL_ERROR_STOP`: 新規注文を停止。
H4 `market_state` の再読込後は、更新後の状態で許可されない注文タイプの既存pending注文を取消する。`6 MARKET_TECHNICAL_ERROR_STOP` の場合は対象EAのpending注文をすべて取消する。
### レンジブレイクガード
- `input_range_breakout_guard_timeframe` の確定足を使い、直近確定足の1本前から `input_range_breakout_lookback_bars` 本の高値・安値をレンジ境界として計算する。
- レンジ幅が平均レンジの `input_range_breakout_max_width_multiplier` 倍以内の場合のみ、レンジ相場としてブレイク監視を有効にする。倍率が `0` の場合はこの幅判定を行わない。
- 直近確定足終値が `rangeHigh + buffer` を上回る場合、または現在Bidがレンジ上限に接近し直近確定足に上方向の勢いがある場合は上方向ブレイク警戒/確定とする。この時、既存のT4 Sell Limitを取消し、T4新規発注を `input_range_breakout_cooldown_bars` 本分停止する。
- 直近確定足終値が `rangeLow - buffer` を下回る場合、または現在Askがレンジ下限に接近し直近確定足に下方向の勢いがある場合は下方向ブレイク警戒/確定とする。この時、既存のT2 Buy Limitを取消し、T2新規発注を `input_range_breakout_cooldown_bars` 本分停止する。
- `buffer` と接近幅はM15平均レンジ倍率と現在スプレッドの大きい方を使い、ライブ時のスプレッド拡大で過剰検知しにくくする。
### 注文タイプごとの価格整合条件
- T1 Buy Stop: `Ask < entry`, `tp > entry`, `sl < entry`
@@ -169,7 +196,7 @@ Pythonは `target_prices.txt` と `target_zones.txt` の両方を書き終えて
## 7. エグジット条件
- 未約定注文は、注文作成時刻から `ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1)` 以上経過した場合に取消する。
- 未約定注文は、コメントからH1候補時刻を復元できる場合はその時刻から、復元できない旧注文は注文作成時刻から `ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1)` 以上経過した場合に取消する。
- 保有ポジションは、建玉時刻から `CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1)` 以上経過した場合にクローズする。
- 時間制限処理は `OnTick` の早い段階で実行し、Python完了待ちやスプレッド判定に依存させない。
- EA削除時は `OnDeinit()` で外部プロセス状態とSLTPパネルを解放し、`Comment("")``ChartRedraw(0)` によりチャート上のステータス表示を消去する。
@@ -191,10 +218,15 @@ Pythonは `target_prices.txt` と `target_zones.txt` の両方を書き終えて
- `input_position_limit` は口座全体ではなく、自EA対象分のみを数える。内部の絶対上限は `POSITION_LIMIT` とする。
- 送信時は `SYMBOL_FILLING_MODE` を参照し、IOC、FOK、RETURNの順で利用可能な執行ポリシーを選択する。
- 通常注文と分割注文の送信前に、ロットが `SYMBOL_VOLUME_MIN/MAX/STEP` を満たすことを検証する。
- ペンディング注文には、ブローカーが対応する場合にサーバー側の期限を設定する。
- ペンディング注文には、ブローカーが対応する場合にH1候補時刻を起点とするサーバー側の期限を設定する。発注時点で期限切れなら送信しない。
- `OrderSend` の戻り値と `MqlTradeResult.retcode` を確認し、失敗時は `GetLastError()` またはretcodeをログへ出力する。
- 分割エントリーの注文コメントには `candidate_id` とslot番号を入れ、同一slotの二重発注を抑止する。
- 通常注文と分割注文コメントには有効な `candidate_id` を入れ、候補時刻起点の期限管理に使用する。
- 分割エントリーの注文コメントには注文タイプとslot番号も入れ、同一戦略slotの二重発注を抑止する。
- `cancel_old_split_pending_on_new_zone = true` の場合、新しい有効 `candidate_id` を読んだ時は旧candidateの分割pending注文を取消し、`target_zones.txt` が無効または停止値の場合は既存の分割pending注文をすべて取消する。
- API由来TPの方向がBuy/Sell条件と逆の場合、EAは方向を補正せず既存の価格整合チェックで発注を見送る。
- H4状態更新後は、更新後の `market_state` と矛盾する既存pending注文を取消する。
- レンジブレイクガードは `_Symbol``magic_number` が一致するpending注文だけを対象にし、上方向ブレイクではT4 Sell Limit、下方向ブレイクではT2 Buy Limitのみを取消する。
- pending取消に失敗したticketは `input_cancel_retry_cooldown_seconds` の間再送せず、毎tickの過剰な取引サーバー要求を防止する。
- SLTP管理は `_Symbol``magic_number` が一致する既存ポジションのみを対象とし、TPは既存値を維持する。
- SL変更は既存SLより利益保護方向へ改善する場合だけ実行し、ブローカーのstop level / freeze levelを満たさない候補は送信しない。
- `HighVolatilityLimit()` はBUYをBid、SELLをAsk基準で評価し、GOLD/XAUUSDはサフィックス付きシンボルでも1 pip = 0.1として扱う。
@@ -203,13 +235,38 @@ Pythonは `target_prices.txt` と `target_zones.txt` の両方を書き終えて
- `trend_state.txt` が存在しない、読み込めない、整数として厳格にパースできない、または `0..6` 以外の場合は `MARKET_TECHNICAL_ERROR_STOP` として扱う。
- `target_prices.txt` が存在しない、読み込めない、13行未満、またはいずれかの行が数値として厳格にパースできない場合は `res_chk = 0` として扱う。
- 分割エントリー有効時に `target_zones.txt` が存在しない、schema不一致、7行未満、`res_chk != 1`、またはいずれかの数値行を厳格にパースできない場合は新規注文を停止する。
- 分割エントリー有効時に `target_zones.txt` が存在しない、schema不一致、7行未満、`res_chk != 1`有効ゾーンの `candidate_id` が厳格な12桁時刻ではない、またはいずれかの数値行を厳格にパースできない場合は新規注文を停止する。
- Python側がH1候補生成を安全側停止値へ倒した場合は、`debug_entry.txt``RESULT: SAFE_STOP`、停止段階、理由、H4状態、候補IDを追記する。これにより通常のGPT見送りとAPI・設定・データ異常を区別できる。
- Pythonプロセスが異常終了した場合、終了コードをログへ出力し、次回トリガーで再実行できる状態に戻す。
- Pythonプロセスが `PYTHON_TIMEOUT_SECONDS` を超えても実行中の場合、`taskkill /T /F` でcmd/bat配下のプロセスツリーを終了し、done/runningファイルを整理して次回トリガーで再実行できる状態に戻す。
- `running` ファイルだけが残っている場合は、PIDからプロセス復元を試みる。復元できずタイムアウト済みなら古いマーカーとして削除する。
## 10. 変更履歴
### 2026-06-13
- レンジ上抜け/下抜け時に逆方向の逆張りLimitを退避するレンジブレイクガードを追加した。上方向ブレイクでは既存T4 Sell Limitを取消してT4新規発注を一時停止し、下方向ブレイクでは既存T2 Buy Limitを取消してT2新規発注を一時停止する。
- ガード用inputとして、監視時間足、参照本数、レンジ幅倍率、ブレイクバッファ、接近幅、勢い判定倍率、クールダウン本数を追加した。
- API由来TPをエントリー価格からの距離ベースで拡大する `input_tp_multiplier`, `input_min_tp_points`, `input_max_tp_points` を追加し、通常注文と分割slotごとの最終TP計算に反映した。
### 2026-06-06
- Python側のOpenAI既定モデルを公式slugの `gpt-5.5` へ更新し、Responses API呼び出しで `reasoning.effort``text.verbosity` を明示する仕様にした。GPT-5.5向けに、出力形式はプロンプト重複指定ではなくStructured Outputsを主契約として扱う。
- `HIT-EA_refactor_ver5.mq5` が現行の共有ヘッダーを使用してもコンパイルできるよう、split-entry zone、Python連携ファイル名、pending取消リトライ管理に必要な互換宣言を追加した。既定では `use_split_entry_zone = false` のため、ver5の通常エントリー挙動は維持する。
### 2026-06-01
- H1候補生成が安全側停止値へフォールバックした場合も `debug_entry.txt` へ停止段階と理由を追記し、通常の候補見送りと障害停止を判別できるようにした。
### 2026-05-31
- 起動時は `initial_order` の値にかかわらずH4/H1結果を再生成し、H4再読込までは技術エラー停止値を維持するfail-closed初期化へ変更した。
- H4 `market_state` 更新後に、更新状態と矛盾する既存pending注文を取消する仕様を追加した。
- pending取消失敗時にticket単位のクールダウンを設け、毎tickの取消再送による取引サーバーへの過剰リクエストを抑止した。
- 分割slot識別子へ注文タイプを追加し、同一 `candidate_id` の異なる戦略がslotを共有しても衝突しないようにした。
- 通常注文と分割注文のコメントへ有効な `candidate_id` を保持し、pending期限をH1候補時刻起点で管理するようにした。
- 有効な `target_zones.txt``candidate_id` は厳格な12桁数字時刻を要求し、不正値は安全側で停止するようにした。
### 2026-05-30
- 同一Terminal内の複数EA/複数シンボルでPython連携ファイルが衝突しないよう、`HIT_<symbol>_<magic_number>` 接頭辞をMT5/Python双方のファイル名へ適用する仕様に更新した。
@@ -0,0 +1,259 @@
# HIT-EA 仕様書(日本語)
## 1. 概要
- 本EAは、H4の確定足OHLCから外部Pythonで相場状態を判定し、H1の確定足OHLCからエントリー候補価格を生成する。
- MQL5側はPythonの出力ファイルを読み込み、H4相場状態、H1候補価格、M15確定足フィルタ、スプレッド、ブローカー距離制約を確認したうえでペンディング注文を発行する。
- バックテスト再現性のため、Pythonへ渡すOHLCは `OHLC_START_SHIFT = 1` により形成中バーを除外し、確定足だけを使用する。
- ライブ実行時の耐性として、外部プロセスの `running` ファイル、プロセスID、終了コード、タイムアウトを監視し、二重起動とCSV上書きを抑止する。
## 2. 使用インジケータ
- 標準インジケータおよびカスタムインジケータは未使用。
- OHLCは `CopyRates(_Symbol, timeframe, OHLC_START_SHIFT, HISTORY_BARS, rates)` で取得する。
- M15エントリー確認は、T2/T4では直近確定足と1本前の確定足のローソク足形状、平均レンジ、候補価格との距離から判定し、T1/T3では必要に応じてM15初動確認を行う。
## 3. パラメータ設定
### input
- `lot_size = 0.01`: 注文ロット。
- `spread_limit = 60`: 許容スプレッド(point)。
- `magic_number = 10001`: EA識別用マジックナンバー。
- `initial_order = 0`: 起動直後の初回H4/H1処理を実行するか。`1` で有効。
- `use_m15_entry_filter = true`: M15確定足によるエントリータイミング確認を使用するか。
- `m15_entry_zone_atr_multiplier = 1.50`: M15平均レンジに対する候補価格接近許容倍率。
- `use_m15_imbalance_confirmation = true`: T1/T3の順張り候補に対して、M15確定足の初動確認を追加するか。
- `m15_imbalance_avg_body_period = 20`: M15初動確認で使う平均実体計算期間。
- `m15_imbalance_sensitivity = 2.0`: M15初動確認で現在足実体が平均実体を上回る必要倍率。
- `m15_imbalance_min_avg_body_points = 1.0`: M15平均実体の最小値(point)。
- `use_m15_imbalance_debug_log = false`: M15初動確認の詳細ログを出すか。
- `input_entry_max_candidate_age_minutes = 120`: H1候補価格を新規発注に使用できる最大経過分数。古い候補でM15条件が後から整った場合の遅延エントリーを抑止する。
- `input_position_limit = 10`: 自EAの未約定注文 + ポジション数の実運用上限。内部上限 `POSITION_LIMIT` を超える指定は丸める。
- `use_split_entry_zone = false`: H1予測ゾーンを使った分割エントリーを有効化するか。
- `split_entry_count = 3`: 分割エントリー本数。1〜10に丸めて使用する。
- `split_lot_mode = SPLIT_LOT_TOTAL`: 分割ロット配分モード。`SPLIT_LOT_TOTAL` は総ロットをN分割、`SPLIT_LOT_FIXED` は各注文に固定ロットを使う。
- `split_total_lot_size = 0.09`: 総量分割モードの合計ロット。
- `split_fixed_lot_size = 0.01`: 固定ロットモードの1注文ロット。
- `cancel_old_split_pending_on_new_zone = true`: 新しいH1ゾーン読込時に、同じEAの古い分割pending注文を取消するか。
- `input_sltp_manager_enabled = false`: UI連動の `CSLTPManager` による既存ポジションSL管理を有効化するか。
- `input_sltp_show_panel = true`: チャート上にSLTP操作パネルを表示するか。
- `input_sltp_use_breakeven = false`: 通常ブレークイーブンを有効化するか。
- `input_sltp_breakeven_trigger_pips = 30.0`: 通常ブレークイーブンを開始する含み益pips。
- `input_sltp_breakeven_buffer_pips = 3.0`: 通常ブレークイーブン時に建値から利益方向へずらすpips。
- `input_sltp_use_elapsed_breakeven = false`: 保有時間ベースのブレークイーブンを有効化するか。
- `input_sltp_elapsed_breakeven_hours = 4.0`: 保有時間ベースのブレークイーブンを許可するまでの保有時間。
- `input_sltp_elapsed_breakeven_buffer_pips = 3.0`: 保有時間ベースのブレークイーブン時に建値から利益方向へずらすpips。
- `input_sltp_use_active_trailing = false`: アクティブトレーリングを有効化するか。
- `input_sltp_active_breakeven_pips = 30.0`: アクティブトレーリング開始pips。
- `input_sltp_active_stop_loss_offset_pips = 5.0`: 開始時に建値から固定する利益pips。
- `input_sltp_active_step_trigger_pips = 10.0`: SLを1段進めるために必要な追加利益pips。
- `input_sltp_active_step_move_pips = 5.0`: 1段ごとにSLを利益方向へ動かすpips。
- `input_sltp_use_tp_progress_stop = false`: TP進捗率に応じたSL固定を有効化するか。
- `input_sltp_tp_progress_trigger_percent = 70.0`: TP進捗率SLを開始する進捗率。
- `input_sltp_tp_progress_sl_lock_percent = 30.0`: 建値からTPまでの距離のうちSLで固定する割合。
- `input_sltp_use_high_volatility_limit = false`: 短時間急変時のSL引き締めを有効化するか。
### 主要定数
- `POSITION_LIMIT = 48`: 自EAの未約定注文 + ポジション数の上限。
- `ENTRY_H1_LIMIT = 2`: 未約定注文の有効期限(H1本数)。
- `CLOSE_H1_LIMIT = 12`: ポジションの時間制限クローズ(H1本数)。
- `HISTORY_BARS = 72`: Pythonへ渡すOHLC本数。
- `OHLC_START_SHIFT = 1`: 確定足からOHLCを取得するためのシフト。
- `M15_CONFIRM_BARS = 30`: M15平均レンジ計算に使う足数。
- `ENTRY_RETRY_SECONDS = 60`: エントリー判定リトライ間隔。
- `ENTRY_RETRY_LIMIT = 10`: H1候補価格に対する最大リトライ回数。
- `TARGET_SIZE = 13`: `target_prices.txt` から読み込む数値数。
- `TARGET_ZONE_SCHEMA_VERSION = 2`: `target_zones.txt` の形式バージョン。
- `PYTHON_TIMEOUT_SECONDS = 600`: Python完了待ちの監視上限。
### Python側エントリー候補ガード
- H1候補価格生成後、Python側で現在価格から遠すぎる `entry` を無効化する。
- 距離上限は戦略別に計算し、T1/T3のStop系は `max(H1 EATR * 1.50, 5.00)`、T2/T4のLimit系は `max(H1 EATR * 1.00, 5.00)` とする。上限を超えた戦略は `0.00,0.00,0.00` に補正する。
- このガードは、深い指値や遠いブレイク待ちがM15確認後に遅れて発注されることを抑えるための後処理である。
## 4. ファイル構成
- `Experts/MyProject/HIT-EA_refactor_ver6.mq5`: EAエントリーポイント。`OnInit`, `OnDeinit`, `OnTick`、input、グローバル状態、DLL importを保持する。
- `Include/MyLib/Common/HITRuntimeController.mqh`: ティック処理、H4/H1/M15更新制御、ステータス表示、スプレッド判定。
- `Include/MyLib/Signals/HITEntrySignal.mqh`: エントリー前提条件、注文タイプ別価格判定、M15フィルタ、リトライ状態更新。
- `Include/MyLib/Common/HITExternalProcess.mqh`: done/runningファイル、外部プロセスハンドル、PID復元、終了コード確認、タイムアウト復旧。
- `Include/MyLib/Signals/HITPythonSignalGateway.mqh`: OHLC CSV出力、Pythonバッチ起動、`trend_state.txt` / `target_prices.txt` / `target_zones.txt` 読込。
- `Include/MyLib/Trading/HITTradeManager.mqh`: 注文送信、執行ポリシー、有効期限設定、注文/ポジション数集計、期限切れ取消/クローズ。
- `Include/MyLib/Trading/SLTPManager.mqh`: 既存ポジションに対するブレークイーブン、時間経過BE、アクティブトレーリング、TP進捗SL、急変時SL引き締めを管理する。
- `Include/MyLib/Panel/SLTPManagerPanel.mqh`: `CSLTPManager` の各設定をチャート上で切り替え、数値入力を検証してEAへ反映する操作パネル。
## 5. Python連携ファイル
EAは `OnInit()` で `_Symbol` と `magic_number` から `HIT_<sanitized symbol>_<magic_number>` 形式の接頭辞を作り、MT5 `Files` 配下の連携ファイル名へ付与する。例: `HIT_GOLD_10001_ohlc_H4.csv`。batには同じ接頭辞を第1引数で渡し、bat側が `MT5_EA_FILE_PREFIX` としてPythonへ引き継ぐ。第2引数には `_Symbol` の `SYMBOL_DIGITS` を渡し、bat側が `MT5_PRICE_DIGITS` としてPythonへ引き継ぐ。
手動実行などで接頭辞が指定されない場合、Pythonは従来どおり `ohlc_H4.csv` などの旧ファイル名を使う。
### H4トレンド判定
- MQL5出力: `<prefix>_ohlc_H4.csv`
- Python出力: `<prefix>_trend_state.txt`
- 完了フラグ: `<prefix>_process_done_trend.txt`
- 実行中フラグ: `<prefix>_process_running_trend.txt`
- 起動バッチ: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_trend_reply.bat`
### H1エントリー価格生成
- MQL5出力: `<prefix>_ohlc_H1.csv`
- Python出力: `<prefix>_target_prices.txt`, `<prefix>_target_zones.txt`
- 完了フラグ: `<prefix>_process_done_entry.txt`
- 実行中フラグ: `<prefix>_process_running_entry.txt`
- 起動バッチ: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_entry_reply.bat`
EAは `OnInit()` で `TerminalInfoString(TERMINAL_DATA_PATH)` から `MQL5\python_for_ea` を解決し、各batファイルの絶対パスを組み立てる。batファイルは自身の位置からPythonプロジェクトルートを解決するため、`C:\ea_py` には依存しない。
`target_prices.txt` は13行構成とする。
```text
1行目: res_chk
2-4行目: T1 Buy Stop の entry/tp/sl
5-7行目: T2 Buy Limit の entry/tp/sl
8-10行目: T3 Sell Stop の entry/tp/sl
11-13行目: T4 Sell Limit の entry/tp/sl
```
`target_zones.txt` は分割エントリー用の7行構成とする。
```text
1行目: schema_version2
2行目: res_chk
3行目: candidate_idH1確定足時刻由来)
4行目: T1 Buy Stop の strategy, zone_low, zone_high, tp, sl
5行目: T2 Buy Limit の strategy, zone_low, zone_high, tp, sl
6行目: T3 Sell Stop の strategy, zone_low, zone_high, tp, sl
7行目: T4 Sell Limit の strategy, zone_low, zone_high, tp, sl
```
Pythonは `target_prices.txt` と `target_zones.txt` の両方を書き終えてから `process_done_entry.txt` を作成する。`target_zones.txt` の価格小数桁は `MT5_PRICE_DIGITS` に合わせ、未指定時は安全側で5桁を使う。分割エントリーが無効な場合、EAは従来どおり `target_prices.txt` を使用する。
## 6. エントリー条件
新規エントリーは、以下をすべて満たす場合のみ行う。
- スプレッドが `spread_limit` 以下。
- H4トレンド判定結果が完了済みで、`trend_state.txt` を読み込める。
- H1候補価格生成が完了済みで、`target_prices.txt` を読み込める。
- `res_chk = 1`。
- H1候補価格が、元になったH1確定足時刻から `ENTRY_H1_LIMIT` 内で期限切れではない。
- H1候補価格が、元になったH1確定足時刻から `input_entry_max_candidate_age_minutes` 分を超えていない。
- 対象注文タイプの `entry/tp/sl` がすべて `0.0` より大きい。
- H4 `market_state` に対して注文タイプが許可されている。
- 注文タイプごとの価格整合条件とブローカー最小距離制約を満たす。
- `use_m15_entry_filter = true` の場合、T2/T4はM15確定足の方向・反発・接近条件を満たす。T1/T3は `use_m15_imbalance_confirmation = true` の場合にM15初動確認を満たす。
- 自EAの注文 + ポジション数が `input_position_limit` 未満。
- 分割エントリー有効時は `target_zones.txt` の `res_chk = 1`、予測ゾーンの価格整合、分割ロットの `SYMBOL_VOLUME_MIN/MAX/STEP` 適合、同一 `candidate_id` + slot の重複注文/ポジション不存在を満たす。
### market_state と注文タイプ
- `0 MARKET_LOW_VOL_RANGE`: T2 Buy Limit / T4 Sell Limit を許可。
- `1 MARKET_HIGH_VOL_RANGE`: T2 Buy Limit / T4 Sell Limit を許可。
- `2 MARKET_LOW_VOL_UP`: T1 Buy Stop / T2 Buy Limit を許可。
- `3 MARKET_HIGH_VOL_UP`: T1 Buy Stop / T2 Buy Limit を許可。
- `4 MARKET_LOW_VOL_DOWN`: T3 Sell Stop / T4 Sell Limit を許可。
- `5 MARKET_HIGH_VOL_DOWN`: T3 Sell Stop / T4 Sell Limit を許可。
- `6 MARKET_TECHNICAL_ERROR_STOP`: 新規注文を停止。
### 注文タイプごとの価格整合条件
- T1 Buy Stop: `Ask < entry`, `tp > entry`, `sl < entry`
- T2 Buy Limit: `Ask > entry`, `tp > entry`, `sl < entry`
- T3 Sell Stop: `Bid > entry`, `tp < entry`, `sl > entry`
- T4 Sell Limit: `Bid < entry`, `tp < entry`, `sl > entry`
## 7. エグジット条件
- 未約定注文は、注文作成時刻から `ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1)` 以上経過した場合に取消する。
- 保有ポジションは、建玉時刻から `CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1)` 以上経過した場合にクローズする。
- 時間制限処理は `OnTick` の早い段階で実行し、Python完了待ちやスプレッド判定に依存させない。
- EA削除時は `OnDeinit()` で外部プロセス状態とSLTPパネルを解放し、`Comment("")` と `ChartRedraw(0)` によりチャート上のステータス表示を消去する。
- `input_sltp_manager_enabled` またはパネルの `Manager` がONの場合、時間制限処理後に `CSLTPManager::ManagePositions()` と `HighVolatilityLimit()` を実行する。これにより、Python結果待ちや新規注文停止中でも既存ポジションのSL保護を継続する。
- 通常ブレークイーブンとアクティブトレーリングは同時有効化しない。パネル上では片方をONにするともう片方をOFFにし、`CSLTPManager::ValidateSettings()` でも排他条件を検証する。
## 7.1 SLTP操作パネル
- パネルは `input_sltp_show_panel = true` の場合に作成され、チャート右上に表示される。
- パネル生成に失敗した場合はログへ出力し、EA本体はinputで反映済みのSLTP設定のまま継続する。
- `Manager` ボタンでSLTP管理全体のON/OFFを切り替える。OFFの場合、パネル値は保持するが `OnTick` でSL変更は行わない。
- `BreakEven`, `Elapsed BE`, `Active Trail`, `TP Progress`, `High Vol` ボタンで各機能を切り替える。
- 数値入力欄は `APPLY` 押下時に範囲検証される。範囲外または数値以外の場合は `MessageBox` とログで通知し、直前の有効値へ戻す。
- `APPLY` 成功時のみEA内部の `CSLTPManager` 設定へ反映する。反映後は `ValidateSettings()` を通し、失敗した場合はSLTP管理を停止してログへ理由を出力する。
## 8. リスク管理
- 注文/ポジション管理対象は `_Symbol` と `magic_number` が一致するものに限定する。
- `input_position_limit` は口座全体ではなく、自EA対象分のみを数える。内部の絶対上限は `POSITION_LIMIT` とする。
- 送信時は `SYMBOL_FILLING_MODE` を参照し、IOC、FOK、RETURNの順で利用可能な執行ポリシーを選択する。
- 通常注文と分割注文の送信前に、ロットが `SYMBOL_VOLUME_MIN/MAX/STEP` を満たすことを検証する。
- ペンディング注文には、ブローカーが対応する場合にサーバー側の期限を設定する。
- `OrderSend` の戻り値と `MqlTradeResult.retcode` を確認し、失敗時は `GetLastError()` またはretcodeをログへ出力する。
- 分割エントリーの注文コメントには `candidate_id` とslot番号を入れ、同一slotの二重発注を抑止する。
- `cancel_old_split_pending_on_new_zone = true` の場合、新しい有効 `candidate_id` を読んだ時は旧candidateの分割pending注文を取消し、`target_zones.txt` が無効または停止値の場合は既存の分割pending注文をすべて取消する。
- SLTP管理は `_Symbol` と `magic_number` が一致する既存ポジションのみを対象とし、TPは既存値を維持する。
- SL変更は既存SLより利益保護方向へ改善する場合だけ実行し、ブローカーのstop level / freeze levelを満たさない候補は送信しない。
- `HighVolatilityLimit()` はBUYをBid、SELLをAsk基準で評価し、GOLD/XAUUSDはサフィックス付きシンボルでも1 pip = 0.1として扱う。
## 9. 異常系の扱い
- `trend_state.txt` が存在しない、読み込めない、整数として厳格にパースできない、または `0..6` 以外の場合は `MARKET_TECHNICAL_ERROR_STOP` として扱う。
- `target_prices.txt` が存在しない、読み込めない、13行未満、またはいずれかの行が数値として厳格にパースできない場合は `res_chk = 0` として扱う。
- 分割エントリー有効時に `target_zones.txt` が存在しない、schema不一致、7行未満、`res_chk != 1`、またはいずれかの数値行を厳格にパースできない場合は新規注文を停止する。
- Pythonプロセスが異常終了した場合、終了コードをログへ出力し、次回トリガーで再実行できる状態に戻す。
- Pythonプロセスが `PYTHON_TIMEOUT_SECONDS` を超えても実行中の場合、`taskkill /T /F` でcmd/bat配下のプロセスツリーを終了し、done/runningファイルを整理して次回トリガーで再実行できる状態に戻す。
- `running` ファイルだけが残っている場合は、PIDからプロセス復元を試みる。復元できずタイムアウト済みなら古いマーカーとして削除する。
## 10. 変更履歴
### 2026-05-30
- 同一Terminal内の複数EA/複数シンボルでPython連携ファイルが衝突しないよう、`HIT_<symbol>_<magic_number>` 接頭辞をMT5/Python双方のファイル名へ適用する仕様に更新した。
- T1/T3の順張り候補でも `use_m15_imbalance_confirmation = true` の場合はM15初動確認を必須とする仕様に更新した。
- `trend_state.txt`、`target_prices.txt`、`target_zones.txt` の数値読込を厳格化し、不正値は安全側の停止値として扱う仕様を追加した。
- `target_zones.txt` が無効または停止値の場合に、古い分割pending注文を全取消できる仕様を追加した。
- 現行コードに合わせて、`input_entry_max_candidate_age_minutes`、`ENTRY_H1_LIMIT`、SLTPバッファ、Python側距離ガードの既定値を修正した。
- Pythonタイムアウト時に実行中プロセスツリーを強制終了して再試行できる仕様を追加した。
- H1候補の鮮度判定をPython結果の読込時刻ではなく、`candidate_id` から復元したH1確定足時刻基準へ変更した。
- `MT5_PRICE_DIGITS` によりPython側の `target_zones.txt` 出力桁数をシンボル桁数へ合わせる仕様を追加した。
- 通常注文ロットの `SYMBOL_VOLUME_MIN/MAX/STEP` 検証、OHLC CSVのNaN/inf・OHLC整合性検証、SELL高ボラSLのAsk基準評価、GOLD/XAUUSDサフィックス対応を追加した。
### 2026-05-27
- Python補助アプリの配置を `C:\ea_py` からMT5データフォルダ配下の `MQL5\python_for_ea` へ移行する仕様に変更した。
- EA側は `TerminalInfoString(TERMINAL_DATA_PATH)` からbatパスを組み立て、外部プロセスの作業ディレクトリはbatファイルの配置から導出するようにした。
- Python側は `MQL5\python_for_ea` の親にある `MQL5\Files` を既定の連携先として自動検出し、必要に応じて `MT5_FILES_DIR` または `MT5_DATA_PATH` で上書きできる仕様にした。
### 2026-05-24
- Python側で `target_zones.txt` を追加出力し、既存 `target_prices.txt` と両方を書き終えてから `process_done_entry.txt` を作成する仕様にした。
- EA側に `use_split_entry_zone`、`split_entry_count`、`split_lot_mode`、`split_total_lot_size`、`split_fixed_lot_size`、`input_position_limit` を追加した。
- 分割エントリー有効時は、H1予測ゾーンをN本に分割し、総ロット分割または固定ロットでpending注文を出せるようにした。
- `candidate_id` + slot番号で分割注文を識別し、同一slotの二重発注を抑止する仕様を追加した。
### 2026-05-13
- Python側にH1 EATRベースの候補距離ガードを追加し、現在価格から遠すぎる候補をMT5へ渡す前に無効化する仕様を追加。
- EA側に `input_entry_max_candidate_age_minutes` を追加し、M15確認が遅れて整った古いH1候補で新規発注しないようにした。
- エントリー見送りログへH1候補の経過秒数を追加し、遅延・M15未確認・価格不整合の原因を追跡しやすくした。
### 2026-05-05
- EA削除後にチャート左上のステータスコメントが残らないよう、`OnDeinit()` で `Comment("")` と `ChartRedraw(0)` を実行する終了処理を追加。
- `HIT-EA_refactor_ver5.mq5` に `CSLTPManager` と専用チャートパネル `SLTPManagerPanel.mqh` を接続し、UIからブレークイーブン、時間経過BE、アクティブトレーリング、TP進捗SL、急変時SL引き締めを操作できるようにした。
- SLTP管理を `OnTick` の時間制限処理直後に実行し、Python結果待ちやスプレッド判定に依存せず既存ポジション保護を継続する仕様を追加。
- SLTPパネル用inputと、通常ブレークイーブン/アクティブトレーリングの排他検証、`APPLY` 時の数値検証を追加。
- `HIT-EA_refactor_ver5.mq5` の関数群を用途別 `.mqh` に分割。
- `OnInit`, `OnDeinit`, `OnTick`、input、グローバル状態はEA本体に残し、動作ロジックは `Include/MyLib/` 配下へ移動。
- 現行コードに合わせて、`CreateProcessW` ベースのPythonプロセス監視、M15フィルタ、`market_state` 0..6、`spread_limit = 60` を仕様へ反映。
### 2026-05-02
- `res_chk=0` 時にエントリー送信を抑止する分岐を追加。
- 時間制限処理を、Python完了待ち・スプレッド制限より前に移動。
- `initial_order` の初回処理フラグをH4用・H1用に分離。
- OHLC取得を `CopyRates` 中心に変更し、確定足のみをPythonへ渡す仕様に変更。
@@ -0,0 +1,274 @@
# HIT-EA 仕様書(日本語)
## 1. 概要
- 本EAは、H4の確定足OHLCから外部Pythonで相場状態を判定し、H1の確定足OHLCからエントリー候補価格を生成する。
- MQL5側はPythonの出力ファイルを読み込み、H4相場状態、H1候補価格、M15確定足フィルタ、スプレッド、ブローカー距離制約を確認したうえでペンディング注文を発行する。
- バックテスト再現性のため、Pythonへ渡すOHLCは `OHLC_START_SHIFT = 1` により形成中バーを除外し、確定足だけを使用する。
- ライブ実行時の耐性として、外部プロセスの `running` ファイル、プロセスID、終了コード、タイムアウトを監視し、二重起動とCSV上書きを抑止する。
## 2. 使用インジケータ
- 標準インジケータおよびカスタムインジケータは未使用。
- OHLCは `CopyRates(_Symbol, timeframe, OHLC_START_SHIFT, HISTORY_BARS, rates)` で取得する。
- M15エントリー確認は、T2/T4では直近確定足と1本前の確定足のローソク足形状、平均レンジ、候補価格との距離から判定し、T1/T3では必要に応じてM15初動確認を行う。
## 3. パラメータ設定
### input
- `lot_size = 0.01`: 注文ロット。
- `spread_limit = 60`: 許容スプレッド(point)。
- `magic_number = 10001`: EA識別用マジックナンバー。
- `initial_order = 0`: 旧設定ファイルとの互換性維持用。値にかかわらず起動時はH4/H1を再生成し、H4再読込までは技術エラー停止状態を維持する。
- `use_m15_entry_filter = true`: M15確定足によるエントリータイミング確認を使用するか。
- `m15_entry_zone_atr_multiplier = 1.50`: M15平均レンジに対する候補価格接近許容倍率。
- `use_m15_imbalance_confirmation = true`: T1/T3の順張り候補に対して、M15確定足の初動確認を追加するか。
- `m15_imbalance_avg_body_period = 20`: M15初動確認で使う平均実体計算期間。
- `m15_imbalance_sensitivity = 2.0`: M15初動確認で現在足実体が平均実体を上回る必要倍率。
- `m15_imbalance_min_avg_body_points = 1.0`: M15平均実体の最小値(point)。
- `use_m15_imbalance_debug_log = false`: M15初動確認の詳細ログを出すか。
- `input_entry_max_candidate_age_minutes = 120`: H1候補価格を新規発注に使用できる最大経過分数。古い候補でM15条件が後から整った場合の遅延エントリーを抑止する。
- `input_position_limit = 10`: 自EAの未約定注文 + ポジション数の実運用上限。内部上限 `POSITION_LIMIT` を超える指定は丸める。
- `use_split_entry_zone = false`: H1予測ゾーンを使った分割エントリーを有効化するか。
- `split_entry_count = 3`: 分割エントリー本数。1〜10に丸めて使用する。
- `split_lot_mode = SPLIT_LOT_TOTAL`: 分割ロット配分モード。`SPLIT_LOT_TOTAL` は総ロットをN分割、`SPLIT_LOT_FIXED` は各注文に固定ロットを使う。
- `split_total_lot_size = 0.09`: 総量分割モードの合計ロット。
- `split_fixed_lot_size = 0.01`: 固定ロットモードの1注文ロット。
- `cancel_old_split_pending_on_new_zone = true`: 新しいH1ゾーン読込時に、同じEAの古い分割pending注文を取消するか。
- `input_cancel_retry_cooldown_seconds = 60`: pending注文の取消に失敗した場合、同一ticketへ取消要求を再送するまでの待機秒数。1〜3600秒に丸めて使用する。
- `input_sltp_manager_enabled = false`: UI連動の `CSLTPManager` による既存ポジションSL管理を有効化するか。
- `input_sltp_show_panel = true`: チャート上にSLTP操作パネルを表示するか。
- `input_sltp_use_breakeven = false`: 通常ブレークイーブンを有効化するか。
- `input_sltp_breakeven_trigger_pips = 30.0`: 通常ブレークイーブンを開始する含み益pips。
- `input_sltp_breakeven_buffer_pips = 3.0`: 通常ブレークイーブン時に建値から利益方向へずらすpips。
- `input_sltp_use_elapsed_breakeven = false`: 保有時間ベースのブレークイーブンを有効化するか。
- `input_sltp_elapsed_breakeven_hours = 4.0`: 保有時間ベースのブレークイーブンを許可するまでの保有時間。
- `input_sltp_elapsed_breakeven_buffer_pips = 3.0`: 保有時間ベースのブレークイーブン時に建値から利益方向へずらすpips。
- `input_sltp_use_active_trailing = false`: アクティブトレーリングを有効化するか。
- `input_sltp_active_breakeven_pips = 30.0`: アクティブトレーリング開始pips。
- `input_sltp_active_stop_loss_offset_pips = 5.0`: 開始時に建値から固定する利益pips。
- `input_sltp_active_step_trigger_pips = 10.0`: SLを1段進めるために必要な追加利益pips。
- `input_sltp_active_step_move_pips = 5.0`: 1段ごとにSLを利益方向へ動かすpips。
- `input_sltp_use_tp_progress_stop = false`: TP進捗率に応じたSL固定を有効化するか。
- `input_sltp_tp_progress_trigger_percent = 70.0`: TP進捗率SLを開始する進捗率。
- `input_sltp_tp_progress_sl_lock_percent = 30.0`: 建値からTPまでの距離のうちSLで固定する割合。
- `input_sltp_use_high_volatility_limit = false`: 短時間急変時のSL引き締めを有効化するか。
### 主要定数
- `POSITION_LIMIT = 48`: 自EAの未約定注文 + ポジション数の上限。
- `ENTRY_H1_LIMIT = 2`: 未約定注文の有効期限(H1本数)。
- `CLOSE_H1_LIMIT = 12`: ポジションの時間制限クローズ(H1本数)。
- `HISTORY_BARS = 72`: Pythonへ渡すOHLC本数。
- `OHLC_START_SHIFT = 1`: 確定足からOHLCを取得するためのシフト。
- `M15_CONFIRM_BARS = 30`: M15平均レンジ計算に使う足数。
- `ENTRY_RETRY_SECONDS = 60`: エントリー判定リトライ間隔。
- `ENTRY_RETRY_LIMIT = 10`: H1候補価格に対する最大リトライ回数。
- `TARGET_SIZE = 13`: `target_prices.txt` から読み込む数値数。
- `TARGET_ZONE_SCHEMA_VERSION = 2`: `target_zones.txt` の形式バージョン。
- `PYTHON_TIMEOUT_SECONDS = 600`: Python完了待ちの監視上限。
### Python側エントリー候補ガード
- H1候補価格生成後、Python側で現在価格から遠すぎる `entry` を無効化する。
- 距離上限は戦略別に計算し、T1/T3のStop系は `max(H1 EATR * 1.50, 5.00)`、T2/T4のLimit系は `max(H1 EATR * 1.00, 5.00)` とする。上限を超えた戦略は `0.00,0.00,0.00` に補正する。
- このガードは、深い指値や遠いブレイク待ちがM15確認後に遅れて発注されることを抑えるための後処理である。
## 4. ファイル構成
- `Experts/MyProject/HIT-EA_refactor_ver6.mq5`: EAエントリーポイント。`OnInit`, `OnDeinit`, `OnTick`、input、グローバル状態、DLL importを保持する。
- `Include/MyLib/Common/HITRuntimeController.mqh`: ティック処理、H4/H1/M15更新制御、ステータス表示、スプレッド判定。
- `Include/MyLib/Signals/HITEntrySignal.mqh`: エントリー前提条件、注文タイプ別価格判定、M15フィルタ、リトライ状態更新。
- `Include/MyLib/Common/HITExternalProcess.mqh`: done/runningファイル、外部プロセスハンドル、PID復元、終了コード確認、タイムアウト復旧。
- `Include/MyLib/Signals/HITPythonSignalGateway.mqh`: OHLC CSV出力、Pythonバッチ起動、`trend_state.txt` / `target_prices.txt` / `target_zones.txt` 読込。
- `Include/MyLib/Trading/HITTradeManager.mqh`: 注文送信、執行ポリシー、有効期限設定、注文/ポジション数集計、期限切れ取消/クローズ。
- `Include/MyLib/Trading/SLTPManager.mqh`: 既存ポジションに対するブレークイーブン、時間経過BE、アクティブトレーリング、TP進捗SL、急変時SL引き締めを管理する。
- `Include/MyLib/Panel/SLTPManagerPanel.mqh`: `CSLTPManager` の各設定をチャート上で切り替え、数値入力を検証してEAへ反映する操作パネル。
## 5. Python連携ファイル
EAは `OnInit()` で `_Symbol` と `magic_number` から `HIT_<sanitized symbol>_<magic_number>` 形式の接頭辞を作り、MT5 `Files` 配下の連携ファイル名へ付与する。例: `HIT_GOLD_10001_ohlc_H4.csv`。batには同じ接頭辞を第1引数で渡し、bat側が `MT5_EA_FILE_PREFIX` としてPythonへ引き継ぐ。第2引数には `_Symbol` の `SYMBOL_DIGITS` を渡し、bat側が `MT5_PRICE_DIGITS` としてPythonへ引き継ぐ。
手動実行などで接頭辞が指定されない場合、Pythonは従来どおり `ohlc_H4.csv` などの旧ファイル名を使う。
### H4トレンド判定
- MQL5出力: `<prefix>_ohlc_H4.csv`
- Python出力: `<prefix>_trend_state.txt`
- 完了フラグ: `<prefix>_process_done_trend.txt`
- 実行中フラグ: `<prefix>_process_running_trend.txt`
- 起動バッチ: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_trend_reply.bat`
### H1エントリー価格生成
- MQL5出力: `<prefix>_ohlc_H1.csv`
- Python出力: `<prefix>_target_prices.txt`, `<prefix>_target_zones.txt`
- 完了フラグ: `<prefix>_process_done_entry.txt`
- 実行中フラグ: `<prefix>_process_running_entry.txt`
- 起動バッチ: `<TerminalDataPath>\MQL5\python_for_ea\bat\get_entry_reply.bat`
EAは `OnInit()` で `TerminalInfoString(TERMINAL_DATA_PATH)` から `MQL5\python_for_ea` を解決し、各batファイルの絶対パスを組み立てる。batファイルは自身の位置からPythonプロジェクトルートを解決するため、`C:\ea_py` には依存しない。
`target_prices.txt` は13行構成とする。
```text
1行目: res_chk
2-4行目: T1 Buy Stop の entry/tp/sl
5-7行目: T2 Buy Limit の entry/tp/sl
8-10行目: T3 Sell Stop の entry/tp/sl
11-13行目: T4 Sell Limit の entry/tp/sl
```
`target_zones.txt` は分割エントリー用の7行構成とする。
```text
1行目: schema_version2
2行目: res_chk
3行目: candidate_idH1確定足時刻由来)
4行目: T1 Buy Stop の strategy, zone_low, zone_high, tp, sl
5行目: T2 Buy Limit の strategy, zone_low, zone_high, tp, sl
6行目: T3 Sell Stop の strategy, zone_low, zone_high, tp, sl
7行目: T4 Sell Limit の strategy, zone_low, zone_high, tp, sl
```
Pythonは `target_prices.txt` と `target_zones.txt` の両方を書き終えてから `process_done_entry.txt` を作成する。`target_zones.txt` の価格小数桁は `MT5_PRICE_DIGITS` に合わせ、未指定時は安全側で5桁を使う。分割エントリーが無効な場合、EAは従来どおり `target_prices.txt` を使用する。
## 6. エントリー条件
新規エントリーは、以下をすべて満たす場合のみ行う。
- スプレッドが `spread_limit` 以下。
- H4トレンド判定結果が完了済みで、`trend_state.txt` を読み込める。
- H1候補価格生成が完了済みで、`target_prices.txt` を読み込める。
- `res_chk = 1`。
- H1候補価格が、元になったH1確定足時刻から `ENTRY_H1_LIMIT` 内で期限切れではない。
- H1候補価格が、元になったH1確定足時刻から `input_entry_max_candidate_age_minutes` 分を超えていない。
- 対象注文タイプの `entry/tp/sl` がすべて `0.0` より大きい。
- H4 `market_state` に対して注文タイプが許可されている。
- 注文タイプごとの価格整合条件とブローカー最小距離制約を満たす。
- `use_m15_entry_filter = true` の場合、T2/T4はM15確定足の方向・反発・接近条件を満たす。T1/T3は `use_m15_imbalance_confirmation = true` の場合にM15初動確認を満たす。
- 自EAの注文 + ポジション数が `input_position_limit` 未満。
- 分割エントリー有効時は `target_zones.txt` の `res_chk = 1`、予測ゾーンの価格整合、分割ロットの `SYMBOL_VOLUME_MIN/MAX/STEP` 適合、同一 `candidate_id` + 注文タイプ + slot の重複注文/ポジション不存在を満たす。
### market_state と注文タイプ
- `0 MARKET_LOW_VOL_RANGE`: T2 Buy Limit / T4 Sell Limit を許可。
- `1 MARKET_HIGH_VOL_RANGE`: T2 Buy Limit / T4 Sell Limit を許可。
- `2 MARKET_LOW_VOL_UP`: T1 Buy Stop / T2 Buy Limit を許可。
- `3 MARKET_HIGH_VOL_UP`: T1 Buy Stop / T2 Buy Limit を許可。
- `4 MARKET_LOW_VOL_DOWN`: T3 Sell Stop / T4 Sell Limit を許可。
- `5 MARKET_HIGH_VOL_DOWN`: T3 Sell Stop / T4 Sell Limit を許可。
- `6 MARKET_TECHNICAL_ERROR_STOP`: 新規注文を停止。
H4 `market_state` の再読込後は、更新後の状態で許可されない注文タイプの既存pending注文を取消する。`6 MARKET_TECHNICAL_ERROR_STOP` の場合は対象EAのpending注文をすべて取消する。
### 注文タイプごとの価格整合条件
- T1 Buy Stop: `Ask < entry`, `tp > entry`, `sl < entry`
- T2 Buy Limit: `Ask > entry`, `tp > entry`, `sl < entry`
- T3 Sell Stop: `Bid > entry`, `tp < entry`, `sl > entry`
- T4 Sell Limit: `Bid < entry`, `tp < entry`, `sl > entry`
## 7. エグジット条件
- 未約定注文は、コメントからH1候補時刻を復元できる場合はその時刻から、復元できない旧注文は注文作成時刻から `ENTRY_H1_LIMIT * PeriodSeconds(PERIOD_H1)` 以上経過した場合に取消する。
- 保有ポジションは、建玉時刻から `CLOSE_H1_LIMIT * PeriodSeconds(PERIOD_H1)` 以上経過した場合にクローズする。
- 時間制限処理は `OnTick` の早い段階で実行し、Python完了待ちやスプレッド判定に依存させない。
- EA削除時は `OnDeinit()` で外部プロセス状態とSLTPパネルを解放し、`Comment("")` と `ChartRedraw(0)` によりチャート上のステータス表示を消去する。
- `input_sltp_manager_enabled` またはパネルの `Manager` がONの場合、時間制限処理後に `CSLTPManager::ManagePositions()` と `HighVolatilityLimit()` を実行する。これにより、Python結果待ちや新規注文停止中でも既存ポジションのSL保護を継続する。
- 通常ブレークイーブンとアクティブトレーリングは同時有効化しない。パネル上では片方をONにするともう片方をOFFにし、`CSLTPManager::ValidateSettings()` でも排他条件を検証する。
## 7.1 SLTP操作パネル
- パネルは `input_sltp_show_panel = true` の場合に作成され、チャート右上に表示される。
- パネル生成に失敗した場合はログへ出力し、EA本体はinputで反映済みのSLTP設定のまま継続する。
- `Manager` ボタンでSLTP管理全体のON/OFFを切り替える。OFFの場合、パネル値は保持するが `OnTick` でSL変更は行わない。
- `BreakEven`, `Elapsed BE`, `Active Trail`, `TP Progress`, `High Vol` ボタンで各機能を切り替える。
- 数値入力欄は `APPLY` 押下時に範囲検証される。範囲外または数値以外の場合は `MessageBox` とログで通知し、直前の有効値へ戻す。
- `APPLY` 成功時のみEA内部の `CSLTPManager` 設定へ反映する。反映後は `ValidateSettings()` を通し、失敗した場合はSLTP管理を停止してログへ理由を出力する。
## 8. リスク管理
- 注文/ポジション管理対象は `_Symbol` と `magic_number` が一致するものに限定する。
- `input_position_limit` は口座全体ではなく、自EA対象分のみを数える。内部の絶対上限は `POSITION_LIMIT` とする。
- 送信時は `SYMBOL_FILLING_MODE` を参照し、IOC、FOK、RETURNの順で利用可能な執行ポリシーを選択する。
- 通常注文と分割注文の送信前に、ロットが `SYMBOL_VOLUME_MIN/MAX/STEP` を満たすことを検証する。
- ペンディング注文には、ブローカーが対応する場合にH1候補時刻を起点とするサーバー側の期限を設定する。発注時点で期限切れなら送信しない。
- `OrderSend` の戻り値と `MqlTradeResult.retcode` を確認し、失敗時は `GetLastError()` またはretcodeをログへ出力する。
- 通常注文と分割注文のコメントには有効な `candidate_id` を入れ、候補時刻起点の期限管理に使用する。
- 分割エントリーの注文コメントには注文タイプとslot番号も入れ、同一戦略slotの二重発注を抑止する。
- `cancel_old_split_pending_on_new_zone = true` の場合、新しい有効 `candidate_id` を読んだ時は旧candidateの分割pending注文を取消し、`target_zones.txt` が無効または停止値の場合は既存の分割pending注文をすべて取消する。
- H4状態更新後は、更新後の `market_state` と矛盾する既存pending注文を取消する。
- pending取消に失敗したticketは `input_cancel_retry_cooldown_seconds` の間再送せず、毎tickの過剰な取引サーバー要求を防止する。
- SLTP管理は `_Symbol` と `magic_number` が一致する既存ポジションのみを対象とし、TPは既存値を維持する。
- SL変更は既存SLより利益保護方向へ改善する場合だけ実行し、ブローカーのstop level / freeze levelを満たさない候補は送信しない。
- `HighVolatilityLimit()` はBUYをBid、SELLをAsk基準で評価し、GOLD/XAUUSDはサフィックス付きシンボルでも1 pip = 0.1として扱う。
## 9. 異常系の扱い
- `trend_state.txt` が存在しない、読み込めない、整数として厳格にパースできない、または `0..6` 以外の場合は `MARKET_TECHNICAL_ERROR_STOP` として扱う。
- `target_prices.txt` が存在しない、読み込めない、13行未満、またはいずれかの行が数値として厳格にパースできない場合は `res_chk = 0` として扱う。
- 分割エントリー有効時に `target_zones.txt` が存在しない、schema不一致、7行未満、`res_chk != 1`、有効ゾーンの `candidate_id` が厳格な12桁時刻ではない、またはいずれかの数値行を厳格にパースできない場合は新規注文を停止する。
- Pythonプロセスが異常終了した場合、終了コードをログへ出力し、次回トリガーで再実行できる状態に戻す。
- Pythonプロセスが `PYTHON_TIMEOUT_SECONDS` を超えても実行中の場合、`taskkill /T /F` でcmd/bat配下のプロセスツリーを終了し、done/runningファイルを整理して次回トリガーで再実行できる状態に戻す。
- `running` ファイルだけが残っている場合は、PIDからプロセス復元を試みる。復元できずタイムアウト済みなら古いマーカーとして削除する。
## 10. 変更履歴
### 2026-05-31
- 起動時は `initial_order` の値にかかわらずH4/H1結果を再生成し、H4再読込までは技術エラー停止値を維持するfail-closed初期化へ変更した。
- H4 `market_state` 更新後に、更新状態と矛盾する既存pending注文を取消する仕様を追加した。
- pending取消失敗時にticket単位のクールダウンを設け、毎tickの取消再送による取引サーバーへの過剰リクエストを抑止した。
- 分割slot識別子へ注文タイプを追加し、同一 `candidate_id` の異なる戦略がslotを共有しても衝突しないようにした。
- 通常注文と分割注文のコメントへ有効な `candidate_id` を保持し、pending期限をH1候補時刻起点で管理するようにした。
- 有効な `target_zones.txt` の `candidate_id` は厳格な12桁数字時刻を要求し、不正値は安全側で停止するようにした。
### 2026-05-30
- 同一Terminal内の複数EA/複数シンボルでPython連携ファイルが衝突しないよう、`HIT_<symbol>_<magic_number>` 接頭辞をMT5/Python双方のファイル名へ適用する仕様に更新した。
- T1/T3の順張り候補でも `use_m15_imbalance_confirmation = true` の場合はM15初動確認を必須とする仕様に更新した。
- `trend_state.txt`、`target_prices.txt`、`target_zones.txt` の数値読込を厳格化し、不正値は安全側の停止値として扱う仕様を追加した。
- `target_zones.txt` が無効または停止値の場合に、古い分割pending注文を全取消できる仕様を追加した。
- 現行コードに合わせて、`input_entry_max_candidate_age_minutes`、`ENTRY_H1_LIMIT`、SLTPバッファ、Python側距離ガードの既定値を修正した。
- Pythonタイムアウト時に実行中プロセスツリーを強制終了して再試行できる仕様を追加した。
- H1候補の鮮度判定をPython結果の読込時刻ではなく、`candidate_id` から復元したH1確定足時刻基準へ変更した。
- `MT5_PRICE_DIGITS` によりPython側の `target_zones.txt` 出力桁数をシンボル桁数へ合わせる仕様を追加した。
- 通常注文ロットの `SYMBOL_VOLUME_MIN/MAX/STEP` 検証、OHLC CSVのNaN/inf・OHLC整合性検証、SELL高ボラSLのAsk基準評価、GOLD/XAUUSDサフィックス対応を追加した。
### 2026-05-27
- Python補助アプリの配置を `C:\ea_py` からMT5データフォルダ配下の `MQL5\python_for_ea` へ移行する仕様に変更した。
- EA側は `TerminalInfoString(TERMINAL_DATA_PATH)` からbatパスを組み立て、外部プロセスの作業ディレクトリはbatファイルの配置から導出するようにした。
- Python側は `MQL5\python_for_ea` の親にある `MQL5\Files` を既定の連携先として自動検出し、必要に応じて `MT5_FILES_DIR` または `MT5_DATA_PATH` で上書きできる仕様にした。
### 2026-05-24
- Python側で `target_zones.txt` を追加出力し、既存 `target_prices.txt` と両方を書き終えてから `process_done_entry.txt` を作成する仕様にした。
- EA側に `use_split_entry_zone`、`split_entry_count`、`split_lot_mode`、`split_total_lot_size`、`split_fixed_lot_size`、`input_position_limit` を追加した。
- 分割エントリー有効時は、H1予測ゾーンをN本に分割し、総ロット分割または固定ロットでpending注文を出せるようにした。
- `candidate_id` + slot番号で分割注文を識別し、同一slotの二重発注を抑止する仕様を追加した。
### 2026-05-13
- Python側にH1 EATRベースの候補距離ガードを追加し、現在価格から遠すぎる候補をMT5へ渡す前に無効化する仕様を追加。
- EA側に `input_entry_max_candidate_age_minutes` を追加し、M15確認が遅れて整った古いH1候補で新規発注しないようにした。
- エントリー見送りログへH1候補の経過秒数を追加し、遅延・M15未確認・価格不整合の原因を追跡しやすくした。
### 2026-05-05
- EA削除後にチャート左上のステータスコメントが残らないよう、`OnDeinit()` で `Comment("")` と `ChartRedraw(0)` を実行する終了処理を追加。
- `HIT-EA_refactor_ver5.mq5` に `CSLTPManager` と専用チャートパネル `SLTPManagerPanel.mqh` を接続し、UIからブレークイーブン、時間経過BE、アクティブトレーリング、TP進捗SL、急変時SL引き締めを操作できるようにした。
- SLTP管理を `OnTick` の時間制限処理直後に実行し、Python結果待ちやスプレッド判定に依存せず既存ポジション保護を継続する仕様を追加。
- SLTPパネル用inputと、通常ブレークイーブン/アクティブトレーリングの排他検証、`APPLY` 時の数値検証を追加。
- `HIT-EA_refactor_ver5.mq5` の関数群を用途別 `.mqh` に分割。
- `OnInit`, `OnDeinit`, `OnTick`、input、グローバル状態はEA本体に残し、動作ロジックは `Include/MyLib/` 配下へ移動。
- 現行コードに合わせて、`CreateProcessW` ベースのPythonプロセス監視、M15フィルタ、`market_state` 0..6、`spread_limit = 60` を仕様へ反映。
### 2026-05-02
- `res_chk=0` 時にエントリー送信を抑止する分岐を追加。
- 時間制限処理を、Python完了待ち・スプレッド制限より前に移動。
- `initial_order` の初回処理フラグをH4用・H1用に分離。
- OHLC取得を `CopyRates` 中心に変更し、確定足のみをPythonへ渡す仕様に変更。
+72
View File
@@ -0,0 +1,72 @@
# HITEntryEA Specification
## 1. Overview
`HITEntryEA.mq5` is the entry-only Expert Advisor. It runs the H4/H1 Python signal workflow, applies the M15 confirmation rules, and submits pending orders. It does not manage filled positions. Stop management, trailing, and time-based position exits are delegated to `HITPositionManagerEA.mq5`.
The two EAs coordinate through matching `_Symbol` and `input_entry_magic_number` / `input_managed_magic_number`. The operating assumption is a retail hedging account, and initialization fails on non-hedging accounts.
## 2. Indicators
- No standard or custom indicators are used.
- Confirmed H4/H1 OHLC data is exported to Python. The EA reads `trend_state.txt`, `target_prices.txt`, and `target_zones.txt`.
- M15 confirmation uses `CopyRates(_Symbol, PERIOD_M15, OHLC_START_SHIFT, M15_CONFIRM_BARS, rates)`.
## 3. Parameters
- `lot_size = 0.01`: Standard order volume.
- `spread_limit = 60`: Maximum allowed spread in points.
- `input_entry_magic_number = 10001`: Magic number assigned to pending orders.
- `input_slippage_points = 10`: Allowed order deviation in points.
- `input_position_limit = 10`: Limit for same-symbol/same-magic pending orders plus positions.
- `use_split_entry_zone = false`: Enables split entries from the H1 prediction zone.
- `split_entry_count = 3`: Number of split entry orders.
- `split_lot_mode = SPLIT_LOT_TOTAL`: Total-volume split or fixed-volume split.
- `input_cancel_retry_cooldown_seconds = 60`: Ticket-level retry cooldown after pending cancellation failures.
- `use_m15_entry_filter = true`: Enables M15 closed-bar confirmation.
- `input_entry_max_candidate_age_minutes = 120`: Maximum age for using an H1 candidate for new execution.
- `input_tp_multiplier = 1.25`: Expands the API TP distance from the entry price. Values below `1.0` are clamped to `1.0`, and values above `100.0` are clamped to `100.0`.
- `input_min_tp_points = 0`: Minimum final TP distance in points. `0` disables the floor.
- `input_max_tp_points = 0`: Maximum expanded TP distance in points. `0` disables the cap. The EA never makes the final TP closer than the API-provided TP distance.
- `input_range_breakout_guard_enabled = true`: Cancels adverse reversal Limit orders during range breakouts and temporarily blocks new ones.
- `input_range_breakout_guard_timeframe = PERIOD_M15`: Timeframe used by the range-breakout monitor.
- `input_range_breakout_lookback_bars = 20`: Closed-bar count used for range high/low and average range.
- `input_range_breakout_max_width_multiplier = 6.0`: Maximum allowed range width versus average range. `0` disables the width filter.
- `input_range_breakout_buffer_multiplier = 0.20`: Average-range multiplier used as the confirmed-breakout buffer.
- `input_range_breakout_near_multiplier = 0.50`: Average-range multiplier used as the pre-breakout proximity band.
- `input_range_breakout_body_multiplier = 1.50`: Required latest closed-bar body multiple for momentum warning.
- `input_range_breakout_cooldown_bars = 4`: Number of monitor-timeframe bars to block adverse Limit entries after detection.
## 4. Entry And Exit Conditions
- New pending orders are sent only after spread, H4 state, H1 candidate, M15 timing, price consistency, broker distance, volume, and same-symbol/same-magic limit checks pass.
- Before order submission, TP is recalculated from the distance between entry and the API TP, multiplied by `input_tp_multiplier`. Buy strategies place the final TP above entry, and Sell strategies place it below entry.
- Split entries recalculate the final TP separately for each slot, using that slot's entry price.
- Pending orders receive `input_entry_magic_number`.
- The entry EA cancels expired pending orders, pending orders that conflict with the refreshed H4 state, and stale split-entry pending orders.
- When the range-breakout guard is enabled, upward breakout warning/confirmation cancels existing T4 Sell Limit orders and blocks new T4 entries until cooldown expiry. Downward breakout warning/confirmation cancels existing T2 Buy Limit orders and blocks new T2 entries.
- H1 Python results, candidate timestamps, and stale split-pending cleanup are processed before the spread gate; excessive spread only blocks new order submission.
- Filled-position SL updates, trailing, and time-based exits are not performed by this EA.
## 5. Risk Management
- The order limit counts only pending orders and positions matching `_Symbol` and `input_entry_magic_number`.
- Python process markers, process IDs, done files, and timeouts are monitored to prevent duplicate launches and stale-result reuse.
- If a done file exists but the expected result file is missing, the EA clears the done/running state and marks the same workflow for retry on the next tick.
- If the API TP direction contradicts the Buy/Sell price rules, the EA does not repair it; the existing price-consistency checks skip the order.
- The range-breakout guard only touches pending orders matching `_Symbol` and `input_entry_magic_number`; upward breakouts cancel T4 Sell Limit only, and downward breakouts cancel T2 Buy Limit only.
- `OrderSend` return values and `MqlTradeResult.retcode` are checked and logged.
- Because the design assumes hedging accounts, per-ticket position management is handled by `HITPositionManagerEA.mq5`.
## 6. Unit Test Scope
- In the Strategy Tester, this EA is tested for pending-order creation, expired pending cancellation, and H4-state mismatch cancellation.
- Position management behavior is outside this EA's unit-test scope.
- Python linkage filenames include `_Symbol` and `input_entry_magic_number` to preserve reproducibility.
## 7. Changelog
- 2026-06-14: Added initialization failure on non-hedging accounts. Moved H1 result loading before spread gating, added retry recovery for done-without-result Python states, and removed the unused filled-position time-exit path from the entry EA side.
- 2026-06-13: Connected the range-breakout guard from `HIT-EA_refactor_ver6.mq5` to the entry EA, including T4 Sell Limit retreat on upward breakouts, T2 Buy Limit retreat on downward breakouts, and cooldown-based new-entry blocking.
- 2026-06-13: Added `input_tp_multiplier`, `input_min_tp_points`, and `input_max_tp_points` to expand API-derived TP distances for both standard orders and per-slot split entries.
- 2026-06-07: Split entry responsibilities from `HIT-EA_refactor_ver6.mq5`; moved SLTP panel and filled-position management responsibilities to `HITPositionManagerEA.mq5`.
+72
View File
@@ -0,0 +1,72 @@
# HITEntryEA 仕様書(日本語)
## 1. 概要
`HITEntryEA.mq5` は、H4/H1の外部Python判定とM15確認を使って新規pending注文までを実行する発注専用EAです。約定後ポジションのSL移動、トレーリング、時間決済は行わず、同じマジックナンバーを監視する `HITPositionManagerEA.mq5` に委譲します。
2つのEAは `_Symbol``input_entry_magic_number` / `input_managed_magic_number` の一致で連携します。運用口座はhedging口座を前提とし、非hedging口座では初期化に失敗します。
## 2. 使用インジケータ
- 標準・カスタムインジケータは使用しません。
- H4/H1の確定足OHLCをPythonへ渡し、`trend_state.txt`, `target_prices.txt`, `target_zones.txt` を読み込みます。
- M15確認は `CopyRates(_Symbol, PERIOD_M15, OHLC_START_SHIFT, M15_CONFIRM_BARS, rates)` を使用します。
## 3. パラメータ設定
- `lot_size = 0.01`: 通常注文ロット。
- `spread_limit = 60`: 許容スプレッド(point)。
- `input_entry_magic_number = 10001`: 発注EAがpending注文へ付与するマジックナンバー。
- `input_slippage_points = 10`: 注文送信時の許容偏差。
- `input_position_limit = 10`: 同一symbol/magicのpending注文 + ポジション上限。
- `use_split_entry_zone = false`: H1予測ゾーンによる分割エントリーを有効化するか。
- `split_entry_count = 3`: 分割本数。
- `split_lot_mode = SPLIT_LOT_TOTAL`: 総量分割または固定ロット分割。
- `input_cancel_retry_cooldown_seconds = 60`: pending取消失敗後のticket単位再試行間隔。
- `use_m15_entry_filter = true`: M15確定足確認を使うか。
- `input_entry_max_candidate_age_minutes = 120`: H1候補を新規発注に使える最大経過分数。
- `input_tp_multiplier = 1.25`: APIから取得したTP距離を、エントリー価格からの距離ベースで拡大する倍率。`1.0` 未満は `1.0``100.0` 超は `100.0` に丸めます。
- `input_min_tp_points = 0`: 拡大後TP距離の最小値(point)。`0` の場合は無効です。
- `input_max_tp_points = 0`: 拡大後TP距離の最大値(point)。`0` の場合は無効です。ただしAPI由来TPより近くなる場合は縮小せず、API距離を維持します。
- `input_range_breakout_guard_enabled = true`: レンジ上抜け/下抜け時に逆方向の逆張りLimit注文を退避し、新規発注も一時停止するか。
- `input_range_breakout_guard_timeframe = PERIOD_M15`: レンジブレイクを監視する時間足。
- `input_range_breakout_lookback_bars = 20`: レンジ高値・安値と平均レンジを計算する確定足本数。
- `input_range_breakout_max_width_multiplier = 6.0`: 平均レンジに対して許容する最大レンジ幅。`0` の場合はレンジ幅フィルタを無効化します。
- `input_range_breakout_buffer_multiplier = 0.20`: 確定ブレイク判定に使う平均レンジ倍率。
- `input_range_breakout_near_multiplier = 0.50`: ブレイク警戒判定に使うレンジ境界への接近幅倍率。
- `input_range_breakout_body_multiplier = 1.50`: ブレイク警戒に必要な直近確定足実体の平均実体倍率。
- `input_range_breakout_cooldown_bars = 4`: ブレイク検知後に逆方向Limitの新規発注を停止する足数。
## 4. エントリー/エグジット条件
- 新規注文はスプレッド、H4状態、H1候補、M15確認、価格整合、ブローカー距離、ロット制約、同一symbol/magicの上限を満たす場合のみ送信します。
- TPは注文送信前に、APIのTP価格そのものではなく「エントリー価格からAPI TPまでの距離」を `input_tp_multiplier` で拡大して最終TPを計算します。Buy系はエントリーより上、Sell系はエントリーより下へ再配置します。
- 分割エントリーではslotごとのエントリー価格を基準に、各slotの最終TPを個別に計算します。
- pending注文には `input_entry_magic_number` を付与します。
- H4状態と矛盾するpending注文、期限切れpending注文、古い分割pending注文は発注EAが取消します。
- レンジブレイクガードがONの場合、M15監視足で上方向ブレイク警戒/確定を検出すると既存T4 Sell Limitを取消し、T4新規発注をクールダウン終了まで停止します。下方向ブレイクでは既存T2 Buy Limitを取消し、T2新規発注を停止します。
- H1 Python結果の読み込み、候補時刻更新、古い分割pending取消はスプレッド判定より前に実行し、スプレッド超過は新規発注だけを停止します。
- 約定後ポジションのSL変更、時間決済、トレーリングは発注EAでは行いません。
## 5. リスク管理
- 発注上限は口座全体ではなく `_Symbol``input_entry_magic_number` が一致するpending注文 + ポジションで判定します。
- Python連携は起動中/完了ファイルとプロセスIDを監視し、二重起動と古い結果の再利用を抑止します。
- doneファイルが存在しても結果ファイルが欠落している場合は、done/running状態を破棄し、次tickで同じ処理を再実行できる状態へ戻します。
- API由来TPの方向がBuy/Sell条件と逆の場合、EAは方向を補正せず既存の価格整合チェックで発注を見送ります。
- レンジブレイクガードは `_Symbol``input_entry_magic_number` が一致するpending注文だけを対象にし、上方向ではT4 Sell Limit、下方向ではT2 Buy Limitのみを取消します。
- `OrderSend` の戻り値と `MqlTradeResult.retcode` を確認し、失敗時はエラーまたはretcodeをログに出します。
- hedging口座前提のため、約定後の複数ticket管理は `HITPositionManagerEA.mq5` が担当します。
## 6. 単体テスト
- Strategy Testerでは発注EA単体で、pending注文の作成、期限切れ取消、H4状態不一致取消を確認します。
- 管理EA機能はこのテスト対象に含めません。
- Python連携ファイル名は `_Symbol``input_entry_magic_number` を含むprefixで分離し、再現性を保ちます。
## 7. 変更履歴
- 2026-06-14: 非hedging口座での初期化停止を追加。H1結果読み込みをスプレッド判定前へ移動し、doneのみ残るPython不整合時の再実行復旧を追加。発注EA側に残っていた未使用の約定後時間決済経路を削除。
- 2026-06-13: `HIT-EA_refactor_ver6.mq5` と同等のレンジブレイクガードを発注EAへ接続。レンジ上抜け時のT4 Sell Limit退避、レンジ下抜け時のT2 Buy Limit退避、およびクールダウン中の新規発注停止を反映。
- 2026-06-13: API由来TPをエントリー価格からの距離ベースで拡大する `input_tp_multiplier`, `input_min_tp_points`, `input_max_tp_points` を追加し、通常注文と分割slotごとの最終TP計算に反映。
- 2026-06-07: `HIT-EA_refactor_ver6.mq5` から発注責務を分離し、SLTPパネルとポジション管理を `HITPositionManagerEA.mq5` へ移管する仕様を追加。
@@ -0,0 +1,65 @@
# HITPositionManagerEA Specification
## 1. Overview
`HITPositionManagerEA.mq5` is the filled-position manager for positions created by `HITEntryEA.mq5`. It never creates new orders or pending orders. It is a retail hedging account EA and fails initialization on non-hedging accounts.
The managed set is limited to positions whose `POSITION_SYMBOL` equals `_Symbol` and whose `POSITION_MAGIC` equals `input_managed_magic_number`. Multiple tickets, split entries, and simultaneous buy/sell positions are managed independently.
## 2. Indicators
- No standard or custom indicators are used.
- SLTP management uses the current tick, each position's open price, SL, TP, open time, and symbol stop/freeze levels.
- High-volatility stop tightening uses M1/M3/M5/M10/M15 open prices and the current market price.
## 3. Parameters
- `input_managed_magic_number = 10001`: Magic number of positions to manage. It should match the entry EA's `input_entry_magic_number`.
- `input_slippage_points = 10`: Allowed deviation for closes and SL modifications.
- `input_position_close_after_h1_bars = 12`: Time-based close threshold in H1 bars. `0` disables it.
- `input_sltp_manager_enabled = false`: Master switch for SLTP management.
- `input_sltp_show_panel = true`: Shows the SLTP control panel.
- `input_sltp_use_breakeven = false`: Standard breakeven.
- `input_sltp_breakeven_trigger_pips = 30.0`: Profit threshold for standard breakeven.
- `input_sltp_breakeven_buffer_pips = 3.0`: Profit-side entry buffer used by standard breakeven.
- `input_sltp_use_elapsed_breakeven = false`: Elapsed-time breakeven.
- `input_sltp_elapsed_breakeven_hours = 4.0`: Holding time required before elapsed-time breakeven is allowed.
- `input_sltp_elapsed_breakeven_buffer_pips = 3.0`: Profit-side entry buffer used by elapsed-time breakeven.
- `input_sltp_use_active_trailing = false`: Active trailing.
- `input_sltp_active_breakeven_pips = 30.0`: Profit threshold that starts active trailing.
- `input_sltp_active_stop_loss_offset_pips = 5.0`: Initial locked profit offset from entry.
- `input_sltp_active_step_trigger_pips = 10.0`: Additional profit interval required for each SL step.
- `input_sltp_active_step_move_pips = 5.0`: SL movement added per completed step.
- `input_sltp_use_tp_progress_stop = false`: TP-progress stop.
- `input_sltp_tp_progress_trigger_percent = 70.0`: TP progress required before the SL lock is applied.
- `input_sltp_tp_progress_sl_lock_percent = 30.0`: Entry-to-TP distance percentage locked by SL.
- `input_sltp_use_high_volatility_limit = false`: High-volatility stop tightening.
## 4. Entry And Exit Conditions
- There are no entry conditions because this EA does not create orders.
- On every tick, the EA first evaluates ticket-based time exits and then applies SLTP management.
- Time exits close target tickets when `POSITION_TIME` is older than `input_position_close_after_h1_bars * PeriodSeconds(PERIOD_H1)` by using `CTrade::PositionClose(ticket)`.
- SLTP management applies only candidates that improve the current SL in the profit-protection direction, preserving the current TP with `CTrade::PositionModify(ticket, new_sl, current_tp)`.
- High-volatility stop tightening only accepts candidates that are at or beyond breakeven: at or above entry for BUY positions and at or below entry for SELL positions.
## 5. Risk Management
- All position processing uses `PositionGetTicket(i)` followed by `PositionSelectByTicket(ticket)`.
- Only positions matching `_Symbol` and `input_managed_magic_number` are touched.
- Different magic numbers, different symbols, and manual-position equivalents are ignored.
- Logs include ticket, symbol, magic, position type, trade retcode, and `GetLastError()`.
- Standard breakeven and active trailing cannot be enabled together; settings validation rejects that conflict.
- When `input_sltp_manager_enabled=false`, contradictory detailed SLTP settings do not stop the EA; time exits continue to run. Detailed settings are validated when SLTP management is enabled.
## 6. Unit Test Scope
- The production manager EA contains no test-only order creation.
- In the Strategy Tester, `HITPositionManagerTestHarness.mq5` seeds test BUY/SELL positions and a different-magic control position, then calls the same production manager classes.
- Test coverage targets same-symbol/same-magic multi-ticket handling, simultaneous buy/sell positions, magic mismatch exclusion, time exits, and SL updates.
## 7. Changelog
- 2026-06-14: Allowed the EA to continue time-exit management when SLTP master is off even if detailed SLTP settings conflict. Added breakeven protection to high-volatility stop tightening so loss-side SL candidates are discarded.
- 2026-06-13: Synchronized SLTP input defaults with `HIT-EA_refactor_ver6.mq5` and documented each default value.
- 2026-06-07: Split position-management responsibilities from `HIT-EA_refactor_ver6.mq5` and defined a hedging-account, ticket-based manager EA.
@@ -0,0 +1,65 @@
# HITPositionManagerEA 仕様書(日本語)
## 1. 概要
`HITPositionManagerEA.mq5` は、`HITEntryEA.mq5` が作成した約定済みポジションを管理する専用EAです。新規注文やpending注文は作成しません。hedging口座専用とし、起動時に `ACCOUNT_MARGIN_MODE_RETAIL_HEDGING` でない場合は `INIT_FAILED` とします。
管理対象は `_Symbol``input_managed_magic_number` が一致するポジションのみです。複数ポジション、両建て、分割エントリーをticket単位で独立管理します。
## 2. 使用インジケータ
- 標準・カスタムインジケータは使用しません。
- SLTP管理は現在tick、ポジションの建値/SL/TP/保有時間、シンボルのstop level / freeze levelを使用します。
- 急変時SL引き締めは M1/M3/M5/M10/M15 の始値と現在価格を使用します。
## 3. パラメータ設定
- `input_managed_magic_number = 10001`: 管理対象ポジションのマジックナンバー。発注EAの `input_entry_magic_number` と一致させます。
- `input_slippage_points = 10`: 決済とSL変更の許容偏差。
- `input_position_close_after_h1_bars = 12`: 保有時間決済のH1本数。0で無効。
- `input_sltp_manager_enabled = false`: SLTP管理全体のON/OFF。
- `input_sltp_show_panel = true`: SLTP操作パネルを表示するか。
- `input_sltp_use_breakeven = false`: 通常ブレークイーブン。
- `input_sltp_breakeven_trigger_pips = 30.0`: 通常ブレークイーブン開始pips。
- `input_sltp_breakeven_buffer_pips = 3.0`: 通常ブレークイーブン時の利益方向バッファpips。
- `input_sltp_use_elapsed_breakeven = false`: 保有時間ベースのブレークイーブン。
- `input_sltp_elapsed_breakeven_hours = 4.0`: 保有時間ベースのブレークイーブン開始時間。
- `input_sltp_elapsed_breakeven_buffer_pips = 3.0`: 保有時間ベースのブレークイーブン時の利益方向バッファpips。
- `input_sltp_use_active_trailing = false`: アクティブトレーリング。
- `input_sltp_active_breakeven_pips = 30.0`: アクティブトレーリング開始pips。
- `input_sltp_active_stop_loss_offset_pips = 5.0`: 開始時に建値から固定する利益pips。
- `input_sltp_active_step_trigger_pips = 10.0`: SLを1段進めるために必要な追加利益pips。
- `input_sltp_active_step_move_pips = 5.0`: 1段ごとにSLを利益方向へ動かすpips。
- `input_sltp_use_tp_progress_stop = false`: TP進捗率SL。
- `input_sltp_tp_progress_trigger_percent = 70.0`: TP進捗率SL開始率。
- `input_sltp_tp_progress_sl_lock_percent = 30.0`: 建値からTPまでの距離のうちSLで固定する割合。
- `input_sltp_use_high_volatility_limit = false`: 急変時SL引き締め。
## 4. エントリー/エグジット条件
- 新規エントリー条件はありません。このEAは注文作成を行いません。
- `OnTick()` では、まずticket単位で保有時間決済を評価し、その後SLTP管理を実行します。
- 時間決済は `POSITION_TIME` から `input_position_close_after_h1_bars * PeriodSeconds(PERIOD_H1)` 以上経過した対象ticketを `CTrade::PositionClose(ticket)` で閉じます。
- SLTP管理は、対象ticketの現在SLより利益保護方向へ改善する候補だけを `CTrade::PositionModify(ticket, new_sl, current_tp)` で反映します。
- 急変時SL引き締めは、BUYでは建値以上、SELLでは建値以下となる候補だけを採用し、損失側へのSL候補は破棄します。
## 5. リスク管理
- すべてのポジション選択は `PositionGetTicket(i)``PositionSelectByTicket(ticket)` を使います。
- `POSITION_SYMBOL == _Symbol` かつ `POSITION_MAGIC == input_managed_magic_number` のみ処理します。
- magic違い、symbol違い、手動ポジション相当には触れません。
- ログにはticket、symbol、magic、position type、retcode、`GetLastError()` を含めます。
- 通常ブレークイーブンとアクティブトレーリングの同時ONは設定検証で拒否します。
- `input_sltp_manager_enabled=false` の場合、SLTP詳細設定に矛盾があってもEA全体は停止せず、時間決済を継続します。SLTP管理をONにする時点で詳細設定を検証します。
## 6. 単体テスト
- 管理EA本体は本番安全性のため新規注文を持ちません。
- Strategy Testerでは `HITPositionManagerTestHarness.mq5` を使い、検証用のBUY/SELLおよびmagic違いポジションを作成してから同じ管理クラスを呼び出します。
- テスト観点は、同一symbol/magicの複数ticket管理、BUY/SELL両建て、magic違い非対象、時間決済、SL更新です。
## 7. 変更履歴
- 2026-06-14: SLTPマスターOFF時は詳細設定の矛盾でEA全体を停止しないよう変更。急変時SL引き締めに建値保護条件を追加し、損失側SL候補を採用しないようにした。
- 2026-06-13: SLTP関連inputの既定値を `HIT-EA_refactor_ver6.mq5` と同じ初期状態に同期し、仕様書へ各既定値を明記。
- 2026-06-07: `HIT-EA_refactor_ver6.mq5` からポジション管理責務を分離し、hedging口座専用のticket単位管理EAとして新規定義。
@@ -0,0 +1,45 @@
# HITPositionManagerTestHarness Specification
## 1. Overview
`HITPositionManagerTestHarness.mq5` is a Strategy Tester-only EA for unit-testing the management logic used by `HITPositionManagerEA.mq5`. It is not intended for live trading. It fails initialization outside `MQL_TESTER` and on non-hedging accounts.
The harness seeds test positions, then calls the same production `CSLTPManager` and `CHITPositionLifecycleManager` classes used by the manager EA.
## 2. Indicators
- No standard or custom indicators are used.
- The management logic uses the current tick, selected position data, and symbol trading constraints.
## 3. Parameters
- `input_managed_magic_number = 10001`: Magic number for managed test positions.
- `input_control_magic_number = 20002`: Magic number for a different-magic control position.
- `input_slippage_points = 10`: Allowed deviation for seed orders, closes, and SL modifications.
- `input_test_lot_size = 0.01`: Test position volume.
- `input_seed_managed_buy = true`: Seeds a managed BUY position.
- `input_seed_managed_sell = true`: Seeds a managed SELL position.
- `input_seed_control_position = true`: Seeds a different-magic control position.
- `input_position_close_after_h1_bars = 12`: Time-exit threshold in H1 bars.
- `input_sltp_*`: Same SLTP settings as the production manager EA.
## 4. Entry And Exit Conditions
- On the first tick, the harness creates the configured managed BUY, managed SELL, and different-magic BUY positions.
- After seeding, it runs the same management sequence as production: time exits, SLTP management, and high-volatility stop tightening.
- The different-magic control position is expected to remain unmanaged.
## 5. Risk Management
- This EA is tester-only and does not run in live mode.
- Test volume is normalized to `SYMBOL_VOLUME_MIN/MAX/STEP`.
- The target filter is the same as production: `_Symbol + input_managed_magic_number`.
## 6. Unit Test Scope
- The harness keeps test-only order creation out of the production manager EA.
- It verifies buy/sell coexistence, multiple-ticket handling, magic mismatch exclusion, time exits, and SL updates.
## 7. Changelog
- 2026-06-07: Created as the Strategy Tester unit-test harness for `HITPositionManagerEA.mq5`.
@@ -0,0 +1,45 @@
# HITPositionManagerTestHarness 仕様書(日本語)
## 1. 概要
`HITPositionManagerTestHarness.mq5` は、`HITPositionManagerEA.mq5` の管理ロジックをStrategy Testerで単体検証するためのテスト専用EAです。本番運用には使用しません。`MQL_TESTER` 以外では `INIT_FAILED` とし、hedging口座以外でも起動しません。
テスター内で検証用ポジションを作成した後、本番管理EAと同じ `CSLTPManager``CHITPositionLifecycleManager` を呼び出します。
## 2. 使用インジケータ
- 標準・カスタムインジケータは使用しません。
- 管理ロジックは現在tick、ポジション情報、シンボル制約を使用します。
## 3. パラメータ設定
- `input_managed_magic_number = 10001`: 管理対象として作成する検証用ポジションのmagic。
- `input_control_magic_number = 20002`: magic違い非対象確認用ポジションのmagic。
- `input_slippage_points = 10`: 検証用注文、決済、SL変更の許容偏差。
- `input_test_lot_size = 0.01`: 検証用ロット。
- `input_seed_managed_buy = true`: 管理対象BUYを作成するか。
- `input_seed_managed_sell = true`: 管理対象SELLを作成するか。
- `input_seed_control_position = true`: magic違いポジションを作成するか。
- `input_position_close_after_h1_bars = 12`: 保有時間決済のH1本数。
- `input_sltp_*`: 本番管理EAと同じSLTP管理設定。
## 4. エントリー/エグジット条件
- 初回tickで、設定に従って管理対象BUY、管理対象SELL、magic違いBUYを作成します。
- 作成後は本番管理ロジックと同じ順序で、保有時間決済、SLTP管理、急変時SL引き締めを実行します。
- magic違いポジションは管理対象外として残ることを確認します。
## 5. リスク管理
- 本EAはテスター専用であり、ライブ環境では起動しません。
- 検証用ポジションは `_Symbol` 上に作成し、ロットは `SYMBOL_VOLUME_MIN/MAX/STEP` に合わせて正規化します。
- 管理対象判定は本番と同じ `_Symbol + input_managed_magic_number` です。
## 6. 単体テスト
- 管理EA本体に新規注文コードを入れないためのテストハーネスです。
- BUY/SELL両建て、複数ticket、magic違い除外、時間決済、SL更新の再現性を確認します。
## 7. 変更履歴
- 2026-06-07: `HITPositionManagerEA.mq5` のStrategy Tester単体検証用ハーネスとして新規作成。
+10 -3
View File
@@ -92,7 +92,8 @@ MT5 が読む結果ファイルは `utf-16 LE` で出力します。結果ファ
3. H1 の短期 36 本、中期 72 本からチャート PNG と数値要約を作る。
4. H1 インバランス初動を Python 側で判定し、矛盾する候補を抑止する。
5. OpenAI Responses API に候補価格・予測ゾーン生成を依頼する。
6. GPT 出力を既存13行形式と分割エントリー用ゾーン形式へ展開し、価格の大小関係と距離を検証する。
出力は Structured Outputs のJSON Schemaで固定する。
6. GPT JSON出力を既存13行形式と分割エントリー用ゾーン形式へ展開し、価格の大小関係、距離、reward/riskを検証する。
7. `target_prices.txt``target_zones.txt` を書き、両方の完了後に `process_done_entry.txt` を作成する。
H4 状態ごとの許可戦略:
@@ -132,6 +133,11 @@ EA側で分割エントリーを有効にした場合は、この予測ゾーン
## OpenAI 設定
H1 エントリー候補生成では OpenAI API を使用します。
既定モデルは `gpt-5.5` です。Responses APIへ `reasoning.effort`
`text.verbosity` を明示して送り、`temperature` は使用しません。
`text.format` にはJSON Schemaを渡し、GPT出力を自然文やCSV風テキストではなく
`schema_version``strategies` を持つ構造化JSONに固定します。
JSONが不正、API応答が未完了、価格条件やreward/risk条件に合わない場合は停止値へ倒します。
必須:
@@ -142,13 +148,14 @@ $env:OPENAI_API_KEY = "..."
任意:
```powershell
$env:OPENAI_MODEL = "..."
$env:OPENAI_MODEL = "gpt-5.5"
$env:OPENAI_REASONING_EFFORT = "low"
$env:OPENAI_TEXT_VERBOSITY = "low"
$env:MT5_EA_FILE_PREFIX = "HIT_GOLD_10001"
$env:MT5_PRICE_DIGITS = "2"
```
`OPENAI_MODEL` 未設定時は `src/ea_py/constants.py``DEFAULT_GPT_MODEL` を使います。`OPENAI_REASONING_EFFORT``none`, `low`, `medium`, `high`, `xhigh` のいずれかです。`MT5_EA_FILE_PREFIX``MT5_PRICE_DIGITS` は手動実行時だけ指定すればよく、EA/bat経由では自動設定されます。
`OPENAI_MODEL` 未設定時は `src/ea_py/constants.py``DEFAULT_GPT_MODEL` を使います。`OPENAI_REASONING_EFFORT``none`, `low`, `medium`, `high`, `xhigh` のいずれかです。H1候補生成の既定は低遅延と再現性確認のため `low` ですが、品質優先の検証では `medium` も評価してください。`OPENAI_TEXT_VERBOSITY``low`, `medium`, `high` のいずれかで、既定はJSON専用応答に合わせて `low` です。`MT5_EA_FILE_PREFIX``MT5_PRICE_DIGITS` は手動実行時だけ指定すればよく、EA/bat経由では自動設定されます。
## 主なモジュール

Some files were not shown because too many files have changed in this diff Show More