0. EA 参数设置
input int MAGIC = 0; // 幻数表示特定 EA
input int Slippage = 3; // 滑点(Pips)
input int MaxPosition = 1; // 最大持仓
input double BaseLots = 0.01; // 下单手数
input int takeprofit = 0; // 止盈(Pips)
input int stoploss = 0; // 止损(Pips)
input int exitTypePer = 1; // 盈亏平衡(Pips)
1. 调整小数位,主要是为了以 Pips 来设置止损止盈和滑点
double AdjustPoint(string Currency)
{
int Symbol_Digits = (int)MarketInfo(Currency, MODE_DIGITS);
double Calculated_Point = 0;
if (Symbol_Digits == 2 || Symbol_Digits == 3) {
Calculated_Point = 0.01;
} else if (Symbol_Digits == 4 || Symbol_Digits == 5) {
Calculated_Point = 0.0001;
} else if (Symbol_Digits == 1) {
Calculated_Point = 0.1;
} else if (Symbol_Digits == 0) {
Calculated_Point = 1;
}
return (Calculated_Point);
}
int AdjustSlippage(string Currency, int Slippage_pips)
{
int Calculated_Slippage = 0;
int Symbol_Digits = (int)MarketInfo(Currency, MODE_DIGITS);
if (Symbol_Digits == 2 || Symbol_Digits == 3) {
Calculated_Slippage = Slippage_pips;
} else if (Symbol_Digits == 4 || Symbol_Digits == 5) {
Calculated_Slippage = Slippage_pips * 10;
}
return (Calculated_Slippage);
}
2. 统计已有开仓
int LongPosition()
{
int buys = 0;
for (int i = 0; i < OrdersTotal(); i++) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true && OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC) {
if (OrderType() == OP_BUY)
buys++;
}
}
return (buys);
}
int ShortPosition()
{
int sells = 0;
for (int i = 0; i < OrdersTotal(); i++) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true && OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC) {
if (OrderType() == OP_SELL)
sells++;
}
}
return (sells);
}
3. 开仓
// 开仓
void OpenOrder(int EntryPosition) {
int res;
bool Modified;
double SL;
double TP;
int SLP = AdjustSlippage(Symbol(), Slippage);
Lots = BaseLots; // 参数化的手数
if (EntryPosition == 1) // 开多单
{
res = OrderSend(Symbol(), OP_BUY, Lots, Ask, SLP, 0, 0, "test002", MAGIC, 0, Red);
if (OrderSelect(res, SELECT_BY_TICKET) == true) {
if (stoploss != 0)
SL = OrderOpenPrice() - stoploss * AdjustPoint(Symbol());
if (takeprofit != 0)
TP = OrderOpenPrice() + takeprofit * AdjustPoint(Symbol());
}
if (SL != 0 || TP != 0)
Modified = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Red);
} else if (EntryPosition == -1) // 开空单
{
res = OrderSend(Symbol(), OP_SELL, Lots, Bid, SLP, 0, 0, "test002", MAGIC, 0, White);
if (OrderSelect(res, SELECT_BY_TICKET) == true) {
if (stoploss != 0)
SL = OrderOpenPrice() + stoploss * AdjustPoint(Symbol());
if (takeprofit != 0)
TP = OrderOpenPrice() - takeprofit * AdjustPoint(Symbol());
}
if (SL != 0 || TP != 0)
Modified = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, White);
}
return;
}
4. 平仓
void CloseOrder(int ClosePosition) {
for (int i = OrdersTotal() - 1; i >= 0; i--) {
int res;
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true) {
if (OrderMagicNumber() == MAGIC && OrderSymbol() == Symbol()) {
if (OrderType() == OP_SELL && (ClosePosition == -1 || ClosePosition == 0)) // 平空单
{
res = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, Silver);
} else if (OrderType() == OP_BUY && (ClosePosition == 1 || ClosePosition == 0)) // 平多单
{
res = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, Silver);
}
}
}
}
}
5. 盈亏平衡保护止损
input int exitTypePer = 1; // 盈亏平衡的 Pips
void BreakEvenStop() {
int res;
double Pips_Profit;
double Min_Profit;
for (int i = OrdersTotal() - 1; i >= 0; i--) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true && OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC) {
if (OrderType() == OP_BUY) {
Pips_Profit = Bid - OrderOpenPrice();
Min_Profit = exitTypePer * AdjustPoint(Symbol());
if (Pips_Profit >= Min_Profit && OrderOpenPrice() != OrderStopLoss()) {
res = OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, Orange);
}
} else if (OrderType() == OP_SELL) {
Pips_Profit = OrderOpenPrice() - Ask;
Min_Profit = exitTypePer * AdjustPoint(Symbol());
if (Pips_Profit >= Min_Profit && OrderOpenPrice() != OrderStopLoss()) {
res = OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, Orange);
}
}
}
}
}
6. 计算进入信号的指标
int Indicator1_19(int i, int TimeScale, int MaPer1, int LineType1, int PType1, int MaPer2, int LineType2, int PType2) {
double Ma1 = iMA(NULL, TimeScale, MaPer1, 0, LineType1, PType1, i);
double Ma2 = iMA(NULL, TimeScale, MaPer2, 0, LineType2, PType2, i);
double Ma1_1 = iMA(NULL, TimeScale, MaPer1, 0, LineType1, PType1, i + 1);
double Ma2_1 = iMA(NULL, TimeScale, MaPer2, 0, LineType2, PType2, i + 1);
int ret = 0;
if (Ma1 > Ma2 && Ma1_1 < Ma2_1) {
ret = 1;
} else if (Ma1 < Ma2 && Ma1_1 > Ma2_1) {
ret = -1;
}
return (ret);
}
7. 每个 tick 响应的回调函数
void OnTick() {
// 不需要频繁的调整的盈亏平衡
static bool checkDone;
int sec = TimeSeconds(TimeGMT());
if (sec == 0 || sec == 10 || sec == 20 || sec == 30 || sec == 40 || sec == 50) {
if (checkDone == false) {
BreakEvenStop();
checkDone = true;
}
} else {
checkDone = false;
}
// 每根 bar 上只计算一次
static datetime bartime = Time[0];
if (Time[0] == bartime)
return;
bartime = Time[0];
checkDone = false;
// 各种信号
int EntryBuy = 0;
int EntrySell = 0;
int ExitBuy = 0;
int ExitSell = 0;
int LongNum = LongPosition();
int ShortNum = ShortPosition();
// 指标买卖信号
int Strtagy1 = Indicator1_19(Entry1, TimeScale1, MA1_1, MaType1_1, PriceType1_1, MA1_2, MaType1_2, PriceType1_2);
int TotalNum = ShortNum + LongNum; // 总持仓
// 小于最大持仓
if ((TotalNum < MaxPosition && Strtagy1 == 1)) {
EntryBuy = 1;
} else if ((TotalNum < MaxPosition && Strtagy1 == -1)) {
EntrySell = 1;
}
// 开仓处理
if (EntryBuy != 0) {
OpenOrder(1);
}
if (EntrySell != 0) {
OpenOrder(-1);
}
}
平仓变化一,达到总收益平仓
void OnTick() {
static datetime bartime = Time[0];
if (Time[0] == bartime)
return;
bartime = Time[0];
int EntryBuy = 0;
int EntrySell = 0;
int ExitBuy = 0;
int ExitSell = 0;
int LongNum = LongPosition();
int ShortNum = ShortPosition();
int Strtagy1 = Indicator1_19(Entry1, TimeScale1, MA1_1, MaType1_1, PriceType1_1, MA1_2, MaType1_2, PriceType1_2);
int TotalNum = ShortNum + LongNum;
if ((TotalNum < MaxPosition && Strtagy1 == 1)) {
EntryBuy = 1;
} else if ((TotalNum < MaxPosition && Strtagy1 == -1)) {
EntrySell = 1;
}
if (EntryBuy != 0) {
OpenOrder(1);
}
if (EntrySell != 0) {
OpenOrder(-1);
}
// 统计获得所有收益 pips
double Total_Profit = 0;
for (int i = OrdersTotal() - 1; i >= 0; i--) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true) {
if (OrderMagicNumber() == MAGIC && OrderSymbol() == Symbol()) {
double Or;
if (OrderType() == OP_BUY) {
Or = OrderLots();
Total_Profit = Total_Profit + ((Bid - OrderOpenPrice()) * (Or / BaseLots));
}
if (OrderType() == OP_SELL) {
Or = OrderLots();
Total_Profit = Total_Profit + ((OrderOpenPrice() - Ask) * (Or / BaseLots));
}
}
}
}
if (Total_Profit > takeprofit * AdjustPoint(Symbol())) {
CloseOrder(1);
CloseOrder(-1);
}
if (Total_Profit < stoploss * AdjustPoint(Symbol()) * -1) {
CloseOrder(1);
CloseOrder(-1);
}
}
追踪止损
void TrailingStop() {
double new_sl;
int res;
for (int i = OrdersTotal() - 1; i >= 0; i--) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true && OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC) {
if (OrderType() == OP_BUY && OrderOpenPrice() < Bid && OrderStopLoss() < Bid) {
new_sl = Bid - (stoploss * AdjustPoint(Symbol()));
if (new_sl > OrderStopLoss() + 0.005 * AdjustPoint(Symbol())) {
res = OrderModify(OrderTicket(), OrderOpenPrice(), new_sl, OrderTakeProfit(), 0, clrNONE);
}
} else if (OrderType() == OP_SELL && OrderOpenPrice() > Ask && (OrderStopLoss() > Ask || OrderStopLoss() == 0)) {
new_sl = Ask + (stoploss * AdjustPoint(Symbol()));
if (new_sl < OrderStopLoss() - 0.005 * AdjustPoint(Symbol()) || OrderStopLoss() == 0) {
res = OrderModify(OrderTicket(), OrderOpenPrice(), new_sl, OrderTakeProfit(), 0, clrNONE);
}
}
}
}
}
void OnTick() {
static bool checkDone;
int sec = TimeSeconds(TimeGMT());
if (sec == 0 || sec == 10 || sec == 20 || sec == 30 || sec == 40 || sec == 50) {
if (checkDone == false) {
TrailingStop();
checkDone = true;
}
} else {
checkDone = false;
}
static datetime bartime = Time[0];
if (Time[0] == bartime)
return;
bartime = Time[0];
checkDone = false;
int EntryBuy = 0;
int EntrySell = 0;
int ExitBuy = 0;
int ExitSell = 0;
int LongNum = LongPosition();
int ShortNum = ShortPosition();
int Strtagy1 = Indicator1_19(Entry1, TimeScale1, MA1_1, MaType1_1, PriceType1_1, MA1_2, MaType1_2, PriceType1_2);
int TotalNum = ShortNum + LongNum;
if ((TotalNum < MaxPosition && Strtagy1 == 1)) {
EntryBuy = 1;
} else if ((TotalNum < MaxPosition && Strtagy1 == -1)) {
EntrySell = 1;
}
if (EntryBuy != 0) {
OpenOrder(1);
}
if (EntrySell != 0) {
OpenOrder(-1);
}
}
达到目标收益执行步进跟踪止损
input int takeprofit = 100; // 达到 100 Pips 收益开启步进跟踪止损
input int stoploss = 50; // 初始设置 50 Pips 止损
input int exitTypePer = 5; // 每次抬高 5 Pips
void TrailingStop() {
double new_sl;
int res;
for (int i = OrdersTotal() - 1; i >= 0; i--) {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true && OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC) {
if (OrderType() == OP_BUY && OrderOpenPrice() + takeprofit * AdjustPoint(Symbol()) < Bid && OrderStopLoss() < Bid) {
new_sl = Bid - ((takeprofit - exitTypePer) * AdjustPoint(Symbol()));
if (new_sl > OrderStopLoss() + 0.005 * AdjustPoint(Symbol())) {
res = OrderModify(OrderTicket(), OrderOpenPrice(), new_sl, OrderTakeProfit(), 0, clrNONE);
}
} else if (OrderType() == OP_SELL && OrderOpenPrice() - takeprofit * AdjustPoint(Symbol()) > Ask && (OrderStopLoss() > Ask || OrderStopLoss() == 0)) {
new_sl = Ask + ((takeprofit - exitTypePer) * AdjustPoint(Symbol()));
if (new_sl < OrderStopLoss() - 0.005 * AdjustPoint(Symbol()) || OrderStopLoss() == 0) {
res = OrderModify(OrderTicket(), OrderOpenPrice(), new_sl, OrderTakeProfit(), 0, clrNONE);
}
}
}
}
}
开仓时以 ATR 设置止盈止损
void OpenOrder(int EntryPosition) {
int res;
bool Modified;
double SL;
double TP;
int SLP = AdjustSlippage(Symbol(), Slippage);
Lots = BaseLots;
if (EntryPosition == 1)
{
res = OrderSend(Symbol(), OP_BUY, Lots, Ask, SLP, 0, 0, "test002", MAGIC, 0, Red);
if (OrderSelect(res, SELECT_BY_TICKET) == true) {
if (stoploss != 0)
SL = OrderOpenPrice() - stoploss * iATR(NULL, 0, exitTypePer, 1);
if (takeprofit != 0)
TP = OrderOpenPrice() + takeprofit * iATR(NULL, 0, exitTypePer, 1);
}
if (SL != 0 || TP != 0)
Modified = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Red);
} else if (EntryPosition == -1)
{
res = OrderSend(Symbol(), OP_SELL, Lots, Bid, SLP, 0, 0, "test002", MAGIC, 0, White);
if (OrderSelect(res, SELECT_BY_TICKET) == true) {
if (stoploss != 0)
SL = OrderOpenPrice() + stoploss * iATR(NULL, 0, exitTypePer, 1);
if (takeprofit != 0)
TP = OrderOpenPrice() - takeprofit * iATR(NULL, 0, exitTypePer, 1);
}
if (SL != 0 || TP != 0)
Modified = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, White);
}
return;
}
开仓后 10 分钟无盈利平仓
int TimeExit = 3;
input int TimeExitPer = 10; // 10 分钟后
void TimeLimitStop(int profit, int ExitMinutes)
{
for (int i = OrdersTotal() - 1; i >= 0; i--) {
int res;
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true) {
if (OrderMagicNumber() == MAGIC && OrderSymbol() == Symbol()) {
if (OrderType() == OP_SELL)
{
if (TimeCurrent() - OrderOpenTime() >= ExitMinutes * 60 && (OrderProfit() < 0 && profit == 3)) {
res = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, Silver);
}
} else if (OrderType() == OP_BUY)
{
if (TimeCurrent() - OrderOpenTime() >= ExitMinutes * 60 && (OrderProfit() < 0 && profit == 3)) {
res = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10, Silver);
}
}
}
}
}
}
在每一次 OnTick 时调用。