Files
EA_with_Python/Experts/MyProject/TradingPanel.mq5
T

396 lines
15 KiB
Plaintext
Raw Normal View History

//+------------------------------------------------------------------+
//| 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);
}
}