//+------------------------------------------------------------------+
//| 裸K交易系统.mq5 |
//| 基于裸K文档的策略实现 |
//+------------------------------------------------------------------+
#property copyright "Your Name"
#property version "1.00"
#property strict
//--- 输入参数
input int N = 10; // 箱体计算周期
input double PointDistance = 3; // 加仓间隔点数
input double BidOffset = 5; // Bid价偏移点数
input int MaxOrders = 5; // 最大加仓次数
input bool UseEarlySession = false; // 是否启用早盘交易
input int EarlySessionStart = 3; // 早盘开始时间(本地时间)
input int EarlySessionEnd = 9; // 早盘结束时间(本地时间)
input double StopLossPoints = 50; // 止损点数
input bool UseCompound = false; // 是否启用复利
input double RiskPercent = 2; // 风险百分比
input double Lots = 0.01; // 固定手数
input int Slippage = 3; // 滑点
//--- 全局变量
double g_Bid, g_Ask; // 当前买卖价格
//--- 函数声明
bool CheckBuyCondition(bool isEarlySession);
bool CheckAddBuyCondition();
bool CheckSellCondition(bool isEarlySession);
bool CheckAddSellCondition();
bool CheckCloseBuyCondition();
bool CheckCloseSellCondition();
double GetAdaptiveLow(int startBar, int period);
double GetAdaptiveHigh(int startBar, int period);
bool IsEarlySession();
double CalculateLots(bool isBuy);
double CalculateStopLoss(bool isBuy);
double CalculateTakeProfit(bool isBuy);
bool OpenBuyOrder();
bool OpenSellOrder();
bool CloseBuyOrders();
bool CloseSellOrders();
void UpdateStopLossTakeProfit();
int CountOrders(int orderType);
bool IsTradingAllowed(); // 添加交易允许检查函数声明
// 处理函数声明
void ProcessBuyOrders(bool isEarlySession);
void ProcessSellOrders(bool isEarlySession);
void ProcessCloseOrders();
//+------------------------------------------------------------------+
//| 专家初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
// 初始化代码
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 专家去初始化函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// 清理代码
}
//+------------------------------------------------------------------+
//| 检查交易是否允许 |
//+------------------------------------------------------------------+
bool IsTradingAllowed()
{
// 检查交易是否被允许
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Print("交易未允许: 终端交易被禁止");
return false;
}
// 检查账户是否允许交易
if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) || !AccountInfoInteger(ACCOUNT_TRADE_EXPERT))
{
Print("交易未允许: 账户交易被禁止");
return false;
}
// 检查交易品种是否允许交易
if(SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE) != SYMBOL_TRADE_MODE_FULL)
{
Print("交易未允许: 交易品种不允许交易");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| 专家订单检查函数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 获取当前价格
g_Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
g_Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
// 检查是否允许交易
if(!IsTradingAllowed()) return;
// 检查早盘开关
bool isEarlySession = IsEarlySession();
// 处理多单逻辑
ProcessBuyOrders(isEarlySession);
// 处理空单逻辑
ProcessSellOrders(isEarlySession);
// 处理平仓逻辑
ProcessCloseOrders();
// 更新止损止盈
UpdateStopLossTakeProfit();
}
//+------------------------------------------------------------------+
//| 处理多单开仓 |
//+------------------------------------------------------------------+
void ProcessBuyOrders(bool isEarlySession)
{
int buyCount = CountOrders(POSITION_TYPE_BUY);
if(buyCount == 0)
{
// 首单开仓条件
if(CheckBuyCondition(isEarlySession))
{
OpenBuyOrder();
}
}
else if(buyCount < MaxOrders)
{
// 加仓条件检查
if(CheckAddBuyCondition())
{
OpenBuyOrder();
}
}
}
//+------------------------------------------------------------------+
//| 处理空单开仓 |
//+------------------------------------------------------------------+
void ProcessSellOrders(bool isEarlySession)
{
int sellCount = CountOrders(POSITION_TYPE_SELL);
if(sellCount == 0)
{
// 首单开仓条件
if(CheckSellCondition(isEarlySession))
{
OpenSellOrder();
}
}
else if(sellCount < MaxOrders)
{
// 加仓条件检查
if(CheckAddSellCondition())
{
OpenSellOrder();
}
}
}
//+------------------------------------------------------------------+
//| 处理平仓逻辑 |
//+------------------------------------------------------------------+
void ProcessCloseOrders()
{
// 检查平多条件
if(CheckCloseBuyCondition())
{
CloseBuyOrders();
}
// 检查平空条件
if(CheckCloseSellCondition())
{
CloseSellOrders();
}
}
//+------------------------------------------------------------------+
//| 多单开仓条件检查 |
//+------------------------------------------------------------------+
bool CheckBuyCondition(bool isEarlySession)
{
// 条件1:上根K线收盘价高于自适应根K线最低价间距
if(!isEarlySession)
{
double adaptiveLow = GetAdaptiveLow(1, N);
if(iClose(_Symbol, PERIOD_CURRENT, 1) <= adaptiveLow)
return false;
}
// 条件2:上根K线收盘价下破前根K线最低价
double prevLow = iLow(_Symbol, PERIOD_CURRENT, 2);
if(iClose(_Symbol, PERIOD_CURRENT, 1) >= prevLow)
return false;
// 条件3:价格区间位置判断
double highest = iHigh(_Symbol, PERIOD_CURRENT, iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, N, 1));
double lowest = iLow(_Symbol, PERIOD_CURRENT, iLowest(_Symbol, PERIOD_CURRENT, MODE_LOW, N, 1));
double range = highest - lowest;
double closePrice = iClose(_Symbol, PERIOD_CURRENT, 2);
double position = (closePrice - highest) / range * 100; // 转换为百分比位置
if(position > -90) // 根据文档示例调整
return false;
// 条件4:Bid价格小于上根K线收盘价+5点
double lastClose = iClose(_Symbol, PERIOD_CURRENT, 1);
if(g_Bid >= lastClose + BidOffset * _Point)
return false;
return true;
}
//+------------------------------------------------------------------+
//| 加仓多单条件检查 |
//+------------------------------------------------------------------+
bool CheckAddBuyCondition()
{
// 这里需要实现加仓条件
// 条件:前一个多单开仓价下方3个点间隔
// 条件:上根K线的收盘价高于特定位置
// 条件:Bid价格小于上根K线收盘价+5个点
// 条件:只在K线开盘的前10秒开单
// 当前只返回false,需要根据文档实现完整逻辑
return false;
}
//+------------------------------------------------------------------+
//| 空单开仓条件检查 |
//+------------------------------------------------------------------+
bool CheckSellCondition(bool isEarlySession)
{
// 条件1:上根K线收盘价低于自适应根K线最高价间距
if(!isEarlySession)
{
double adaptiveHigh = GetAdaptiveHigh(1, N);
if(iClose(_Symbol, PERIOD_CURRENT, 1) >= adaptiveHigh)
return false;
}
// 条件2:上根K线收盘价上破前根K线最高价
double prevHigh = iHigh(_Symbol, PERIOD_CURRENT, 2);
if(iClose(_Symbol, PERIOD_CURRENT, 1) <= prevHigh)
return false;
// 条件3:价格区间位置判断
double highest = iHigh(_Symbol, PERIOD_CURRENT, iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, N, 1));
double lowest = iLow(_Symbol, PERIOD_CURRENT, iLowest(_Symbol, PERIOD_CURRENT, MODE_LOW, N, 1));
double range = highest - lowest;
double closePrice = iClose(_Symbol, PERIOD_CURRENT, 2);
double position = (closePrice - highest) / range * 100; // 转换为百分比位置
if(position < -10) // 根据文档示例调整
return false;
// 条件4:Bid价格大于上根K线收盘价-5点
double lastClose = iClose(_Symbol, PERIOD_CURRENT, 1);
if(g_Bid <= lastClose - BidOffset * _Point)
return false;
return true;
}
//+------------------------------------------------------------------+
//| 加仓空单条件检查 |
//+------------------------------------------------------------------+
bool CheckAddSellCondition()
{
// 这里需要实现加仓条件
// 条件:前一个空单开仓价上方3个点间隔
// 条件:上根K线的收盘价低于特定位置
// 条件:Bid价格大于上根K线收盘价-5个点
// 条件:只在K线开盘的前10秒开单
// 当前只返回false,需要根据文档实现完整逻辑
return false;
}
//+------------------------------------------------------------------+
//| 平多条件检查 |
//+------------------------------------------------------------------+
bool CheckCloseBuyCondition()
{
// 这里需要实现平多条件
// 条件1:前根K线收盘价上破它的前面N根K线的最高价
// 条件2:价格位置判断
// 条件3:多单总体盈利
// 当前只返回false,需要根据文档实现完整逻辑
return false;
}
//+------------------------------------------------------------------+
//| 平空条件检查 |
//+------------------------------------------------------------------+
bool CheckCloseSellCondition()
{
// 这里需要实现平空条件
// 条件1:前根K线收盘价下破它的前面N根K线的最低价
// 条件2:价格位置判断
// 条件3:空单总体盈利
// 当前只返回false,需要根据文档实现完整逻辑
return false;
}
//+------------------------------------------------------------------+
//| 获取自适应最低价 |
//+------------------------------------------------------------------+
double GetAdaptiveLow(int startBar, int period)
{
// 这里实现自适应逻辑,可能需要根据波动率调整period
double lowest = 1000000; // 使用一个大数作为初始值
for(int i = startBar; i < startBar + period; i++)
{
lowest = MathMin(lowest, iLow(_Symbol, PERIOD_CURRENT, i));
}
return lowest;
}
//+------------------------------------------------------------------+
//| 获取自适应最高价 |
//+------------------------------------------------------------------+
double GetAdaptiveHigh(int startBar, int period)
{
// 这里实现自适应逻辑,可能需要根据波动率调整period
double highest = 0; // 使用0作为初始值
for(int i = startBar; i < startBar + period; i++)
{
highest = MathMax(highest, iHigh(_Symbol, PERIOD_CURRENT, i));
}
return highest;
}
//+------------------------------------------------------------------+
//| 判断是否在早盘时间 |
//+------------------------------------------------------------------+
bool IsEarlySession()
{
if(!UseEarlySession) return false;
MqlDateTime dt;
TimeCurrent(dt);
int hour = dt.hour;
// 根据本地时间判断
if(EarlySessionStart < EarlySessionEnd)
{
return (hour >= EarlySessionStart && hour < EarlySessionEnd);
}
else
{
return (hour >= EarlySessionStart || hour < EarlySessionEnd);
}
}
//+------------------------------------------------------------------+
//| 计算开仓手数 |
//+------------------------------------------------------------------+
double CalculateLots(bool isBuy)
{
double lotSize = Lots;
if(UseCompound)
{
// 复利计算:手数 = 净值 * 风险百分比 / 100万
lotSize = AccountInfoDouble(ACCOUNT_EQUITY) * RiskPercent / 1000000;
}
// 手数限制
lotSize = MathMax(lotSize, 0.01);
lotSize = MathMin(lotSize, 50.0);
return lotSize;
}
//+------------------------------------------------------------------+
//| 开多单 |
//+------------------------------------------------------------------+
bool OpenBuyOrder()
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = CalculateLots(true);
request.type = ORDER_TYPE_BUY;
request.price = g_Ask;
request.sl = CalculateStopLoss(true);
request.tp = CalculateTakeProfit(true);
request.deviation = Slippage;
request.type_filling = ORDER_FILLING_FOK;
// 发送订单并检查结果
bool success = OrderSend(request, result);
if(!success)
{
Print("开多单失败,错误代码: ", result.retcode);
}
return success;
}
//+------------------------------------------------------------------+
//| 开空单 |
//+------------------------------------------------------------------+
bool OpenSellOrder()
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = CalculateLots(false);
request.type = ORDER_TYPE_SELL;
request.price = g_Bid;
request.sl = CalculateStopLoss(false);
request.tp = CalculateTakeProfit(false);
request.deviation = Slippage;
request.type_filling = ORDER_FILLING_FOK;
// 发送订单并检查结果
bool success = OrderSend(request, result);
if(!success)
{
Print("开空单失败,错误代码: ", result.retcode);
}
return success;
}
//+------------------------------------------------------------------+
//| 平掉所有多单 |
//+------------------------------------------------------------------+
bool CloseBuyOrders()
{
bool allClosed = true;
for(int i = PositionsTotal()-1; i >= 0; i--)
{
if(PositionGetSymbol(i) == _Symbol &&
PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = PositionGetDouble(POSITION_VOLUME);
request.type = ORDER_TYPE_SELL;
request.position = PositionGetInteger(POSITION_TICKET);
request.price = g_Bid;
request.deviation = Slippage;
// 发送订单并检查结果
bool success = OrderSend(request, result);
if(!success)
{
Print("平多单失败,错误代码: ", result.retcode);
allClosed = false;
}
}
}
return allClosed;
}
//+------------------------------------------------------------------+
//| 平掉所有空单 |
//+------------------------------------------------------------------+
bool CloseSellOrders()
{
bool allClosed = true;
for(int i = PositionsTotal()-1; i >= 0; i--)
{
if(PositionGetSymbol(i) == _Symbol &&
PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = PositionGetDouble(POSITION_VOLUME);
request.type = ORDER_TYPE_BUY;
request.position = PositionGetInteger(POSITION_TICKET);
request.price = g_Ask;
request.deviation = Slippage;
// 发送订单并检查结果
bool success = OrderSend(request, result);
if(!success)
{
Print("平空单失败,错误代码: ", result.retcode);
allClosed = false;
}
}
}
return allClosed;
}
//+------------------------------------------------------------------+
//| 计算止损价 |
//+------------------------------------------------------------------+
double CalculateStopLoss(bool isBuy)
{
if(UseEarlySession)
{
// 早盘模式:固定点数止损
return (isBuy ?
g_Ask - StopLossPoints * _Point :
g_Bid + StopLossPoints * _Point);
}
else
{
// 非早盘:使用前N根K线的最低价/最高价
if(isBuy)
return iLow(_Symbol, PERIOD_CURRENT, iLowest(_Symbol, PERIOD_CURRENT, MODE_LOW, N, 1));
else
return iHigh(_Symbol, PERIOD_CURRENT, iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, N, 1));
}
}
//+------------------------------------------------------------------+
//| 计算止盈价 |
//+------------------------------------------------------------------+
double CalculateTakeProfit(bool isBuy)
{
double highest = iHigh(_Symbol, PERIOD_CURRENT, iHighest(_Symbol, PERIOD_CURRENT, MODE_HIGH, N, 1));
double lowest = iLow(_Symbol, PERIOD_CURRENT, iLowest(_Symbol, PERIOD_CURRENT, MODE_LOW, N, 1));
double center = (highest + lowest) / 2;
double range = highest - lowest;
if(isBuy)
return center + range; // 多单止盈:中心点+间距
else
return center - range; // 空单止盈:中心点-间距
}
//+------------------------------------------------------------------+
//| 更新止损止盈 |
//+------------------------------------------------------------------+
void UpdateStopLossTakeProfit()
{
// 这里实现动态更新止损止盈的逻辑
// 根据文档,可能需要根据价格变化调整止损止盈
}
//+------------------------------------------------------------------+
//| 统计当前持仓数量 |
//+------------------------------------------------------------------+
int CountOrders(int orderType)
{
int count = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
if(PositionGetSymbol(i) == _Symbol &&
PositionGetInteger(POSITION_TYPE) == orderType)
{
count++;
}
}
return count;
}
|