封装验证与调整函数
为了方便地处理前面讨论的停止级别验证问题,我们可以创建两类辅助函数:
- 验证函数 (Verification Functions): 这类函数只检查给定的价格(如 SL/TP 或挂单价)是否满足最小停止距离要求,并返回一个布尔值 (
true
或false
) 表明其有效性,但不修改原始价格。 - 调整函数 (Adjustment Functions): 这类函数检查给定的价格,如果发现其不满足最小距离要求(无效),则自动将其调整到一个刚好满足要求的边界之外,并可以选择性地加上一个缓冲距离 (Buffer),然后返回调整后的有效价格。如果原始价格本身就是有效的,则直接返回原始价格。
验证价格是否高于上边界 (VerifyUpperStopLevel
)
此函数用于检查一个价格(例如买单止盈、卖单止损、买入止损挂单价、卖出限价挂单价)是否有效地位于上停止级别边界 (Ask + StopLevel*Point
) 之上。
/**
* @brief 验证一个价格是否有效地位亍上停止级别边界之上。
* 适用于需要设置在 Ask 价上方的价格 (买单TP, 卖单SL, BuyStop挂单价, SellLimit挂单价)。
* @param argSymbol 交易品种。
* @param argVerifyPrice 需要验证的目标价格。
* @param argOpenPrice 计算边界的基准价格 (可选)。
* 如果为 0 (默认), 则基准为当前 Ask 价 (用于验证市价单SL/TP或挂单价本身)。
* 如果传入挂单价, 则基准为挂单价 (用于验证该挂单的SL/TP是否距挂单价足够远)。
* @return bool true: 价格有效 (argVerifyPrice > UpperStopLevel); false: 价格无效。
*/
bool VerifyUpperStopLevel(string argSymbol, double argVerifyPrice,
double argOpenPrice = 0)
{
// 1. 计算停止级别对应的价格距离
double stopLevelDist = MarketInfo(argSymbol, MODE_STOPLEVEL) * Point;
if (stopLevelDist < 0) { // 检查 MarketInfo 返回值
Print("VerifyUpperStopLevel 错误: 无法获取 MODE_STOPLEVEL for ", argSymbol);
return false;
}
// 2. 确定计算边界的基准价格 (basePrice)
double basePrice;
if (argOpenPrice == 0) { // 未指定基准价,使用当前 Ask
RefreshRates(); // 确保 Ask 最新
basePrice = MarketInfo(argSymbol, MODE_ASK);
if (basePrice <= 0) {
Print("VerifyUpperStopLevel 错误: 无法获取 Ask price for ", argSymbol);
return false; // 获取 Ask 失败
}
} else { // 使用传入的基准价 (例如挂单价)
basePrice = argOpenPrice;
}
// 3. 计算上停止级别边界 (基准价 + 停止距离)
double upperStopLevelBoundary = NormalizeDouble(basePrice + stopLevelDist, Digits);
// 4. 比较并返回结果 (目标价格必须严格大于上边界才有效)
return (argVerifyPrice > upperStopLevelBoundary);
}
参数解释
argSymbol
: 品种名称。argVerifyPrice
: 要检查的目标价格。argOpenPrice
(可选): 计算边界所依据的基准价。- 默认行为 (argOpenPrice = 0): 函数将使用当前的
Ask
价作为基准来计算上边界。这适用于验证那些需要设置在当前Ask
价之上的价格,比如市价单的买单止盈/卖单止损,或者挂单本身的价格(Buy Stop 或 Sell Limit)。 - 指定基准价: 如果传入一个非零值(通常是某个挂单的价格),函数将使用这个传入的价格作为基准来计算上边界。这适用于验证一个挂单所设置的止损/止盈是否距离其自身的挂单价格足够远(例如,验证 Buy Stop 订单的 Take Profit 是否高于
挂单价 + StopLevel*Point
)。
- 默认行为 (argOpenPrice = 0): 函数将使用当前的
- 返回值:
true
表示argVerifyPrice
合法地处在计算出的上边界之上;false
表示不满足要求(价格等于或低于上边界)。
使用示例: 检查一个计算出的卖单止损价 sellStopLossPrice
是否有效(卖单止损需要高于 Ask + StopLevel):
// 假设 sellStopLossPrice 已计算
if (!VerifyUpperStopLevel(Symbol(), sellStopLossPrice)) // 调用函数验证
{
Alert("计算出的卖单止损价无效 (距离 Ask 过近)!");
// ... 后续可能需要停止操作或调整价格 ...
}
- 下边界验证: 验证价格是否低于下边界 (
Bid - StopLevel*Point
) 的函数 (VerifyLowerStopLevel
) 逻辑相似,主要区别在于使用Bid
价(或传入的argOpenPrice
)作为基准计算下边界,并且比较时要求目标价格严格小于下边界。
自动调整价格至上边界之上 (AdjustAboveStopLevel
)
此函数不仅验证价格,而且如果价格无效(即小于或等于上边界),会自动将其调整到上边界之外,并可选择性地增加 argAddPips
指定的缓冲点数。
/**
* @brief 验证价格是否在上边界之上,如果无效则自动调整到边界之上(加缓冲)。
* 适用于需要设置在 Ask 价上方的价格。
* @param argSymbol 交易品种。
* @param argAdjustPrice 需要验证和可能调整的价格。
* @param argAddPips 调整时在边界基础上额外增加的缓冲点数 (pips, 可选, 默认 0)。
* @param argOpenPrice 计算边界的基准价格 (可选, 默认 0 使用 Ask)。
* @return double 返回调整后的有效价格;如果原始价格已有效则直接返回。获取基准价失败则返回原始价。
*/
double AdjustAboveStopLevel(string argSymbol, double argAdjustPrice, int argAddPips = 0,
double argOpenPrice = 0)
{
// 1. 计算停止级别价格距离
double stopLevelDist = MarketInfo(argSymbol, MODE_STOPLEVEL) * Point;
if (stopLevelDist < 0) {
Print("AdjustAboveStopLevel 错误: 无法获取 MODE_STOPLEVEL for ", argSymbol);
return(argAdjustPrice); // 获取失败则不调整,返回原值
}
// 2. 确定基准价格
double basePrice;
if (argOpenPrice == 0) {
RefreshRates();
basePrice = MarketInfo(argSymbol, MODE_ASK);
if (basePrice <= 0) {
Print("AdjustAboveStopLevel 错误: 无法获取 Ask price for ", argSymbol);
return(argAdjustPrice); // 获取失败不调整
}
} else {
basePrice = argOpenPrice;
}
// 3. 计算上停止级别边界
double upperStopLevelBoundary = NormalizeDouble(basePrice + stopLevelDist, Digits);
// 4. 检查价格是否无效 (小于或等于边界)
double finalPrice; // (已修正: 在 if 外声明)
if (argAdjustPrice <= upperStopLevelBoundary)
{
// 价格无效,需要调整
// 计算缓冲距离对应的价格值 (需要 PipPoint 函数,假设已定义)
double buffer = argAddPips * PipPoint(argSymbol);
// 调整后的价格 = 上边界 + 缓冲
finalPrice = upperStopLevelBoundary + buffer;
// 规范化调整后的价格
finalPrice = NormalizeDouble(finalPrice, Digits);
Print("价格 ", argAdjustPrice, " 无效 (未高于上边界 ", upperStopLevelBoundary, "), 自动调整为: ", finalPrice); // 日志记录调整
}
else // 价格本身已有效 (严格大于边界)
{
finalPrice = argAdjustPrice; // 无需调整,使用原始价格
}
// 5. 返回最终有效价格
return(finalPrice);
}
- 参数解释:
argAdjustPrice
: 需要被处理的目标价格。argAddPips
(可选): 整数,指定在自动调整时,在刚好满足要求的边界价格基础上,再额外增加多少个 pips 作为缓冲。默认为 0,即调整到刚好在边界之外(理论上刚好等于边界可能仍有问题,建议设置少量缓冲)。argOpenPrice
(可选): 计算边界的基准价,用法同VerifyUpperStopLevel
。
- 逻辑: 函数计算出上边界
upperStopLevelBoundary
。检查argAdjustPrice
是否小于或等于该边界。如果是(即无效),则计算调整后的价格为upperStopLevelBoundary + 缓冲价格距离
;否则(即有效),保持argAdjustPrice
不变。最终返回这个保证有效的价格。 - 返回值: 该函数总是返回一个保证有效(位于上边界之上)的价格,可以直接用于设置相应的止盈、止损或挂单价。
- 下边界调整: 自动调整价格至下边界之下的函数 (
AdjustBelowStopLevel
) 逻辑类似,只是比较方向和调整方向相反(调整为lowerStopLevelBoundary - 缓冲
)。