Expand API-derived TP distances
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user