Expand API-derived TP distances

This commit is contained in:
Hiroaki86
2026-06-13 11:58:49 +09:00
parent 4de3d24dcd
commit f9012e19e2
7 changed files with 218 additions and 15 deletions
+167 -15
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;
}
//| エントリー判定が必要な場合のみ注文処理を実行する関数
//+------------------------------------------------------------------+
/**
@@ -302,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;
}
//+------------------------------------------------------------------+
//| 注文ロットがブローカー制約を満たすか判定する関数
//+------------------------------------------------------------------+
@@ -462,13 +600,17 @@ int TrySendSplitEntryOrders(const int orderType, EAState &state, TickContext &ct
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;
}
@@ -514,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, TargetCandidateReferenceTime(state)))
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);
}
}
@@ -566,13 +713,14 @@ bool TrySendEntryOrder(const int orderType, EAState &state, TickContext &ctx)
}
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;
}
@@ -580,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;
}
@@ -596,16 +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,
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;
}