|
多单过滤:
1.箭头1指标,在15分钟周期(要可选可自定义),颜色为蓝色(上升趋势)
2.箭头1指标,在10分钟周期(要可选可自定义),颜色为蓝色(上升趋势)
多单开单: 满足前面两点后,出现蓝色箭头开多单
空单过滤:
1.箭头1指标,在15分钟周期(要可选可自定义),颜色为红色(下降趋势)
2.箭头1指标,在10分钟周期(要可选可自定义),颜色为红色(下降趋势)
多单开单: 满足前面两点后,出现红色箭头开空单
出场:盈利6000点清仓
亏损5000点清仓
//+------------------------------------------------------------------+
//| HalfTrendEA.mq5 |
//| Copyright 2024, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh> // 必须包含交易类头文件
CTrade Trade; // 声明交易对象
input ENUM_TIMEFRAMES TrendPeriod1 = PERIOD_M15; // 第一过滤周期
input ENUM_TIMEFRAMES TrendPeriod2 = PERIOD_M10; // 第二过滤周期
input double LotSize = 0.1; // 交易手数
input int StopLossPoints = 5000; // 初始止损点数
input int TakeProfitPoints = 6000; // 移动止损启动点数
input double TrailingPercent = 80; // 利润回撤百分比
// 追踪止损数据结构
struct TrailingData {
ulong ticket;
double highest;
double lowest;
};
TrailingData trailArray[];
// 指标句柄
int handle_t1, handle_t2;
datetime lastBarTime;
//+------------------------------------------------------------------+
//| 函数前置声明 |
//+------------------------------------------------------------------+
bool IsNewBar();
bool IsBullish(ENUM_TIMEFRAMES tf);
bool IsBearish(ENUM_TIMEFRAMES tf);
double GetArrowSignal(int buffer);
void OpenTrade(ENUM_ORDER_TYPE type, double signalPrice);
void ManageTrailingStop();
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// 参数检查
if(StopLossPoints <= 0 || TakeProfitPoints <= 0 || TrailingPercent <= 0 || TrailingPercent >= 100) {
Alert("参数错误: 请检查止损/止盈/回撤参数!");
return(INIT_PARAMETERS_INCORRECT);
}
// 初始化指标句柄
handle_t1 = iCustom(Symbol(), TrendPeriod1, "HalfTrend1",2,false,true,false,false,false,false,false);
handle_t2 = iCustom(Symbol(), TrendPeriod2, "HalfTrend1",2,false,true,false,false,false,false,false);
if(handle_t1 == INVALID_HANDLE || handle_t2 == INVALID_HANDLE) {
Print("Error: 指标初始化失败!错误代码:", GetLastError());
return(INIT_FAILED);
}
ArraySetAsSeries(trailArray, true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(!IsNewBar()) return;
ManageTrailingStop();
if(PositionsTotal() > 0) return;
bool t1_bull = IsBullish(TrendPeriod1);
bool t1_bear = IsBearish(TrendPeriod1);
bool t2_bull = IsBullish(TrendPeriod2);
bool t2_bear = IsBearish(TrendPeriod2);
double upSignal = GetArrowSignal(3);
double dnSignal = GetArrowSignal(4);
if(t1_bull && t2_bull && upSignal != EMPTY_VALUE) {
OpenTrade(ORDER_TYPE_BUY, upSignal);
}
if(t1_bear && t2_bear && dnSignal != EMPTY_VALUE) {
OpenTrade(ORDER_TYPE_SELL, dnSignal);
}
}
//+------------------------------------------------------------------+
//| 追踪止损管理函数 |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
for(int i=PositionsTotal()-1; i>=0; i--) {
ulong ticket=PositionGetTicket(i);
if(ticket==0 || !PositionSelectByTicket(ticket)) continue;
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
int idx = -1;
for(int j=0; j<ArraySize(trailArray); j++) {
if(trailArray[j].ticket == ticket) {
idx = j;
break;
}
}
if(idx == -1) {
double priceDiff;
if(posType == POSITION_TYPE_BUY) priceDiff = currentPrice - openPrice;
else priceDiff = openPrice - currentPrice;
if(priceDiff >= TakeProfitPoints * _Point) {
ArrayResize(trailArray, ArraySize(trailArray)+1);
idx = ArraySize(trailArray)-1;
trailArray[idx].ticket = ticket;
trailArray[idx].highest = (posType == POSITION_TYPE_BUY) ? currentPrice : 0;
trailArray[idx].lowest = (posType == POSITION_TYPE_SELL) ? currentPrice : DBL_MAX;
}
}
if(idx != -1) {
if(posType == POSITION_TYPE_BUY) {
trailArray[idx].highest = MathMax(trailArray[idx].highest, currentPrice);
double stopLevel = trailArray[idx].highest - (trailArray[idx].highest - openPrice) * (TrailingPercent/100.0);
stopLevel = NormalizeDouble(stopLevel, _Digits);
if(currentPrice <= stopLevel) {
Trade.PositionClose(ticket);
ArrayRemove(trailArray, idx, 1);
}
} else {
trailArray[idx].lowest = MathMin(trailArray[idx].lowest, currentPrice);
double stopLevel = trailArray[idx].lowest + (openPrice - trailArray[idx].lowest) * (TrailingPercent/100.0);
stopLevel = NormalizeDouble(stopLevel, _Digits);
if(currentPrice >= stopLevel) {
Trade.PositionClose(ticket);
ArrayRemove(trailArray, idx, 1);
}
}
}
}
}
//+------------------------------------------------------------------+
//| 其他功能函数实现 |
//+------------------------------------------------------------------+
bool IsNewBar()
{
datetime currentTime = iTime(Symbol(), 0, 0);
if(currentTime != lastBarTime) {
lastBarTime = currentTime;
return true;
}
return false;
}
bool IsBullish(ENUM_TIMEFRAMES tf)
{
int handle = (tf == TrendPeriod1) ? handle_t1 : handle_t2;
double up[1], dn[1];
if(CopyBuffer(handle, 0, 0, 1, up) != 1) return false;
if(CopyBuffer(handle, 1, 0, 1, dn) != 1) return false;
return (up[0] > 0 && dn[0] == 0);
}
bool IsBearish(ENUM_TIMEFRAMES tf)
{
int handle = (tf == TrendPeriod1) ? handle_t1 : handle_t2;
double up[1], dn[1];
if(CopyBuffer(handle, 0, 0, 1, up) != 1) return false;
if(CopyBuffer(handle, 1, 0, 1, dn) != 1) return false;
return (dn[0] > 0 && up[0] == 0);
}
double GetArrowSignal(int buffer)
{
double arr[1];
if(CopyBuffer(handle_t1, buffer, 0, 1, arr) != 1) return EMPTY_VALUE;
return arr[0];
}
void OpenTrade(ENUM_ORDER_TYPE type, double signalPrice)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = LotSize;
request.type = type;
request.price = NormalizeDouble(signalPrice, _Digits);
if(type == ORDER_TYPE_BUY) {
request.sl = NormalizeDouble(signalPrice - StopLossPoints*_Point, _Digits);
} else {
request.sl = NormalizeDouble(signalPrice + StopLossPoints*_Point, _Digits);
}
request.deviation = 10;
if(!OrderSend(request, result)) {
Print("开单失败!错误代码:", GetLastError());
}
}
//+------------------------------------------------------------------+
|
|