auto_EA/Experts/优化买入.mq5

684 lines
41 KiB
MQL5
Raw Permalink Normal View History

2025-10-21 17:58:11 +08:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Trailing Stop EA |
//+------------------------------------------------------------------+
#property copyright "thRee03"
#property link "None"
#property version "8.88"
#property strict
// <EFBFBD><EFBFBD>eQ<EFBFBD>Spe
input bool EnableCloseAllSellOnBuy = false; // _YUS<EFBFBD>ehQs^zzUS <EFBFBD>true=hQs^ <EFBFBD>false= Ns^
input bool EnableOpenOrder = true; // _US;`_sQ <EFBFBD>false<EFBFBD>e N_USFO<EFBFBD>N<EFBFBD>S<EFBFBD>y<EFBFBD>Rbk<EFBFBD>v
input int Seconds = 133; // NUSg\<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ype
input double Lots = 0.01; // <EFBFBD>k!k NUSKbpe
input int Deviation = 10; // g'YAQ<EFBFBD><EFBFBD><EFBFBD>n<EFBFBD>p<EFBFBD><EFBFBD>p <EFBFBD>
input double TP_Points = 10; // bk<EFBFBD>v<EFBFBD>ppe<EFBFBD> NUS<EFBFBD>e<EFBFBD><EFBFBD>nTP <EFBFBD>
input int MaxOrders = 13; // g'Yc<EFBFBD>NUSpe
input int MagicNumber = 12345; // T<EFBFBD>/g<EFBFBD>S
input double ProfitTargetUSD = 13.0; // US<EFBFBD>N<EFBFBD>v)R<EFBFBD>vh<EFBFBD><EFBFBD>CQ <EFBFBD><EFBFBD>n<EFBFBD><EFBFBD>sSs^<EFBFBD>N <EFBFBD>
input bool CloseOtherMagics = true; // <EFBFBD>v)Rs^<EFBFBD>N<EFBFBD>e/f&TS+TvQ<EFBFBD>NT<EFBFBD>/g<EFBFBD>Sc<EFBFBD>N
input bool EnableSAR = true; // /f&T/T(uSAR<EFBFBD>O<EFBFBD><EFBFBD>n<EFBFBD>false= N_/T<EFBFBD>NUOSARP<EFBFBD>6R <EFBFBD>
input bool iSAR_Reverse = false; // iSAR<EFBFBD>ST_US<EFBFBD>true=<EFBFBD>S<EFBFBD><EFBFBD>SAR(WK<EFBFBD>~
N<EFBFBD>eb1u Nl<EFBFBD>
N1\_Y <EFBFBD>false=<EFBFBD>S<EFBFBD><EFBFBD>SAR(WK<EFBFBD>~ N<EFBFBD>eb1u
Nl<EFBFBD> N1\_Y
input double SAR_Acceleration = 0.007; // SAR<EFBFBD>R<EFBFBD><EFBFBD>^<EFBFBD><EFBFBD>^<EFBFBD><EFBFBD>0.01~0.03 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>R<EFBFBD>O<EFBFBD>S<EFBFBD>fupOe <EFBFBD>
input double SAR_Start = 0.076; // SARR<EFBFBD>Y<P<EFBFBD>0:N؞<EFBFBD><EFBFBD> <EFBFBD>
input double SAR_Maximum = 0.2; // SARg'Y<P<EFBFBD><EFBFBD>^<EFBFBD><EFBFBD>0.1~0.2 <EFBFBD>
input int SAR_SmoothBars = 1; // SARs^<EFBFBD>n9hpe<EFBFBD><EFBFBD>SяN9hGW<P <EFBFBD>
input double TrailingStopUSD = 3.3; // US<EFBFBD>N)R<EFBFBD>m<EFBFBD>V<EFBFBD>dbk<EFBFBD>v<EFBFBD><EFBFBD>CQ <EFBFBD><EFBFBD>y<EFBFBD>Rbk<EFBFBD>v <EFBFBD>
input bool EnableDrawdownOpen = true; // /T(u<EFBFBD>S<EFBFBD><EFBFBD>p<EFBFBD>V<EFBFBD>d<EFBFBD>R<EFBFBD>N<EFBFBD>true=/T(u <EFBFBD>false=sQ<EFBFBD><EFBFBD> <EFBFBD>
input double DrawdownOpenUSD = 10.0; // ݍ<EFBFBD>y<EFBFBD>S<EFBFBD>S<EFBFBD>N<EFBFBD>V<EFBFBD>dN<EFBFBD>CQ<EFBFBD>e_YUS
input bool EnableAddOrderEveryUSD = true; // /T(u<EFBFBD>k̍N<EFBFBD>CQ<EFBFBD>R<EFBFBD>N<EFBFBD>true=/T(u <EFBFBD>false=sQ<EFBFBD><EFBFBD> <EFBFBD>
input double AddOrderEveryUSD = 5.0; // NUST<EFBFBD>k N̍N<EFBFBD>CQ<EFBFBD>Q<EFBFBD>RNUS
input int DrawdownMaxOrders = 3; // <EFBFBD>S<EFBFBD><EFBFBD>p<EFBFBD>V<EFBFBD>d<EFBFBD>R<EFBFBD>Ng'YUSpe<EFBFBD><EFBFBD>r<EFBFBD>z<EFBFBD>NMaxOrders <EFBFBD>
input bool TrailingStopOnlyThisMagic = true; // <EFBFBD>S<EFBFBD>[,gT<EFBFBD>/g<EFBFBD>S<EFBFBD>NMO<EFBFBD>y<EFBFBD>Rbk<EFBFBD>v<EFBFBD>true=<EFBFBD>S,gEA <EFBFBD>false=@b gBUY<EFBFBD>NMO <EFBFBD>
input double MinBalance = 1200.0; // gNO&<EFBFBD>7bYO<EFBFBD><EFBFBD><EFBFBD>NO<EFBFBD>N N NUS <EFBFBD>
// hQ@\<EFBFBD>
double g_point = 0.0;
int g_digits = 0;
double g_min_lot = 0.0;
double g_lot_step = 0.0;
double g_max_lot = 0.0;
int g_filling_mode = 0;
int orderCount = 0;
datetime lastOrderTime = 0;
double g_highest_price = 0.0; // <EFBFBD>S<EFBFBD>S<EFBFBD>N
double g_last_add_price = 0.0; //
N!k<EFBFBD>R<EFBFBD>N<EFBFBD>N
// <EFBFBD>]wQ<EFBFBD>Qpe
double AlignToStep(double val, double step, bool up=false)
{
if(step <= 0.0) return val;
double k = up ? MathCeil(val/step) : MathFloor(val/step);
double v = k*step;
v = NormalizeDouble(v, 2);
return MathMax(step, v);
}
double AlignToPoint(double price)
{
if(g_point <= 0) return price;
return NormalizeDouble(MathRound(price/g_point)*g_point, g_digits);
}
int GetCurrentPositions(const string sym, const ulong magic)
{
int count = 0;
int total = (int)PositionsTotal();
for(int i=0; i<total; ++i)
{
ulong ticket = PositionGetTicket(i);
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) == sym &&
PositionGetInteger(POSITION_MAGIC) == (long)magic &&
PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
count++;
}
}
return count;
}
// <EFBFBD>~<EFBFBD><EFBFBD>S_MREAc<EFBFBD>N-N<EFBFBD>:NDD<EFBFBD>vUSpe<EFBFBD><EFBFBD>V<EFBFBD>d<EFBFBD>R<EFBFBD>NUS <EFBFBD>
int GetDrawdownOrderCount(const string sym, const ulong magic)
{
int count = 0;
int total = (int)PositionsTotal();
for(int i=0; i<total; ++i)
{
ulong ticket = PositionGetTicket(i);
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) == sym &&
PositionGetInteger(POSITION_MAGIC) == (long)magic &&
PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
string comment = PositionGetString(POSITION_COMMENT);
if(comment == "DD")
count++;
}
}
return count;
}
void CheckAndCloseProfitablePositions()
{
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
if(tickValue <= 0) return;
// <EFBFBD><EFBFBD><EFBFBD>SS_MRSAR<P
double sarValue = 0.0;
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(ask > 0.0)
{
double sarSum = 0.0;
int sarCount = 0;
for(int i=1; i<=SAR_SmoothBars; ++i)
{
double v = CustomSAR(i, SAR_Acceleration, SAR_Maximum, SAR_Start);
if(v > 0.0 && v < ask * 100 && v > ask / 100)
{
sarSum += v;
sarCount++;
}
}
if(sarCount > 0)
sarValue = sarSum / sarCount;
}
int total = (int)PositionsTotal();
int closedCount = 0;
for(int i=total-1; i>=0; --i)
{
ulong ticket = PositionGetTicket(i);
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol ||
PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue;
if(!CloseOtherMagics && PositionGetInteger(POSITION_MAGIC) != (long)MagicNumber) continue;
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double volume = PositionGetDouble(POSITION_VOLUME);
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick)) continue;
double currentPrice = tick.bid;
double profit = ((currentPrice - openPrice) / g_point) * volume * tickValue;
Print("[CheckProfit] Ticket:", ticket, " Magic:", PositionGetInteger(POSITION_MAGIC), " Profit:", profit, " USD, Target:", ProfitTargetUSD, " SAR:", sarValue, " Price:", currentPrice);
if(profit >= ProfitTargetUSD)
{
// s^<EFBFBD>N
MqlTradeRequest req; MqlTradeResult res;
ZeroMemory(req); ZeroMemory(res);
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.type = ORDER_TYPE_SELL;
req.volume = volume;
req.price = currentPrice;
req.deviation = Deviation;
req.type_filling = GetFillingMode();
req.magic = PositionGetInteger(POSITION_MAGIC); // O(u<EFBFBD>ST<EFBFBD>/g<EFBFBD>S
req.position = ticket;
if(OrderSend(req, res) && (res.retcode == TRADE_RETCODE_DONE || res.retcode == TRADE_RETCODE_PLACED))
{
Print("Closed profitable position. Ticket: ", ticket, " Profit: ", profit, " USD, Magic: ", PositionGetInteger(POSITION_MAGIC));
closedCount++;
}
else
{
Print("Failed to close position: ", res.retcode);
}
}
}
if(closedCount == 0) {
Print("[CheckProfit] No profitable positions found to close.");
} else {
Print("[CheckProfit] Closed ", closedCount, " profitable positions.");
}
}
void CloseAllSellPositions()
{
int total = (int)PositionsTotal();
for(int i=total-1; i>=0; --i)
{
ulong ticket = PositionGetTicket(i);
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol ||
PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_SELL) continue;
double volume = PositionGetDouble(POSITION_VOLUME);
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick)) continue;
double currentPrice = tick.ask; // s^ SELL (u ask
// s^<EFBFBD>N
MqlTradeRequest req; MqlTradeResult res;
ZeroMemory(req); ZeroMemory(res);
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.type = ORDER_TYPE_BUY;
req.volume = volume;
req.price = currentPrice;
req.deviation = Deviation;
req.type_filling = GetFillingMode();
req.magic = PositionGetInteger(POSITION_MAGIC);
req.position = ticket;
if(OrderSend(req, res) && (res.retcode == TRADE_RETCODE_DONE || res.retcode == TRADE_RETCODE_PLACED))
{
Print("Closed SELL position. Ticket: ", ticket, " Magic: ", PositionGetInteger(POSITION_MAGIC));
}
else
{
Print("Failed to close SELL position: ", res.retcode);
}
}
}
void TrailingStop()
{
if(TrailingStopUSD <= 0) return;
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
if(tickValue <= 0) return;
int total = (int)PositionsTotal();
for(int i=0; i<total; ++i)
{
ulong ticket = PositionGetTicket(i);
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol ||
PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY) continue;
if(TrailingStopOnlyThisMagic && PositionGetInteger(POSITION_MAGIC) != (long)MagicNumber) continue;
// <EFBFBD>r<EFBFBD>z<EFBFBD><EFBFBD><EFBFBD>S<EFBFBD>k*Nc<EFBFBD>N<EFBFBD>v_<EFBFBD>N<EFBFBD>N0Kbpe0S_MRbk_c
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
double volume = PositionGetDouble(POSITION_VOLUME);
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick)) continue;
double currentPrice = tick.bid;
// <EFBFBD><EFBFBD><EFBFBD>{<EFBFBD><EFBFBD>c<EFBFBD>NS_MR<EFBFBD>v)R
double profitUSD = ((currentPrice - openPrice) / g_point) * volume * tickValue;
// <EFBFBD><EFBFBD><EFBFBD>{<EFBFBD><EFBFBD>c<EFBFBD>N<EFBFBD>^<EFBFBD><EFBFBD>n<EFBFBD>vbk_c<EFBFBD>N
double newSL = currentSL;
if(profitUSD > TrailingStopUSD)
{
double priceRetracement = TrailingStopUSD / (volume * tickValue) * g_point;
double candidateSL = currentPrice - priceRetracement;
candidateSL = AlignToPoint(candidateSL);
candidateSL = MathMax(candidateSL, openPrice); // bk_c NNO<EFBFBD>N_<EFBFBD>N<EFBFBD>N
if(candidateSL > currentSL || currentSL == 0.0)
newSL = candidateSL; // <EFBFBD>SAQ<EFBFBD><EFBFBD>
N<EFBFBD>yb<EFBFBD><EFBFBD>!k<EFBFBD><EFBFBD>n
}
// <EFBFBD>v)R*g<EFBFBD><EFBFBD><EFBFBD><Pb<EFBFBD>V<EFBFBD>d <EFBFBD> N N<EFBFBD>ybk_c
// <EFBFBD>NS_bk_c<EFBFBD><EFBFBD><EFBFBD>
N<EFBFBD>y<EFBFBD>eMb<EFBFBD>S<EFBFBD>Q<EFBFBD>O9e<EFBFBD><EFBFBD>Bl
if(newSL > currentSL)
{
MqlTradeRequest req; MqlTradeResult res;
ZeroMemory(req); ZeroMemory(res);
req.action = TRADE_ACTION_SLTP;
req.symbol = _Symbol;
req.position = ticket;
req.sl = newSL;
req.tp = PositionGetDouble(POSITION_TP); // <EFBFBD>OYu<EFBFBD>STP
req.magic = PositionGetInteger(POSITION_MAGIC);
if(OrderSend(req, res) && (res.retcode == TRADE_RETCODE_DONE || res.retcode == TRADE_RETCODE_PLACED))
{
Print("Trailing stop updated for position ", ticket, " to ", newSL, " (Profit: ", profitUSD, " USD), TP kept: ", req.tp);
}
else
{
Print("Failed to update trailing stop: ", res.retcode);
}
}
}
}
bool LoadSymbolSpec()
{
g_point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
g_digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
g_min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
g_lot_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
g_max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
g_filling_mode = (int)SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
if(g_point<=0 || g_min_lot<=0 || g_lot_step<=0 || g_max_lot<=0)
{
Print("Spec load failed");
return false;
}
return true;
}
ENUM_ORDER_TYPE_FILLING GetFillingMode()
{
return ORDER_FILLING_IOC; // :_6RO(u IOC
}
// [INSAR<EFBFBD>{<EFBFBD>l<EFBFBD>/ecR<EFBFBD> <EFBFBD>
double CustomSAR(int barsBack, double step, double max, double start)
{
int bars = Bars(_Symbol, PERIOD_CURRENT);
if(bars < 2 + barsBack) return 0.0;
double sar = 0.0;
double af = (start > 0.0 ? start : step);
bool uptrend;
double ep;
int idx = barsBack + 1;
double high1 = iHigh(_Symbol, PERIOD_CURRENT, idx);
double low1 = iLow(_Symbol, PERIOD_CURRENT, idx);
double close1 = iClose(_Symbol, PERIOD_CURRENT, idx);
double high0 = iHigh(_Symbol, PERIOD_CURRENT, idx-1);
double low0 = iLow(_Symbol, PERIOD_CURRENT, idx-1);
double close0 = iClose(_Symbol, PERIOD_CURRENT, idx-1);
// R<EFBFBD>YS<EFBFBD><EFBFBD><EFBFBD>R
if(close0 > close1)
{
uptrend = true;
ep = high0;
sar = low1 + af * (high0 - low1);
}
else
{
uptrend = false;
ep = low0;
sar = high1 + af * (low0 - high1);
}
// <EFBFBD>V<EFBFBD>n0RS_MRbar
for(int i=idx-2; i>=barsBack; --i)
{
double high = iHigh(_Symbol, PERIOD_CURRENT, i);
double low = iLow(_Symbol, PERIOD_CURRENT, i);
if(uptrend)
{
sar = sar + af * (ep - sar);
if(low < sar)
{
uptrend = false;
sar = ep;
ep = low;
af = (start > 0.0 ? start : step);
}
else
{
if(high > ep)
{
ep = high;
af = MathMin(af + step, max);
}
}
sar = MathMin(sar, low);
}
else
{
sar = sar + af * (ep - sar);
if(high > sar)
{
uptrend = true;
sar = ep;
ep = high;
af = (start > 0.0 ? start : step);
}
else
{
if(low < ep)
{
ep = low;
af = MathMin(af + step, max);
}
}
sar = MathMax(sar, high);
}
}
return sar;
}
// EA R<EFBFBD>YS
int OnInit()
{
if(!LoadSymbolSpec())
{
Print("Failed to load symbol spec");
return INIT_FAILED;
}
orderCount = 0;
lastOrderTime = 0;
Print("EA initialized. Max orders: ", MaxOrders, ", Interval: ", Seconds, " seconds, Magic: ", MagicNumber);
return INIT_SUCCEEDED;
}
// EA <EFBFBD>SR<EFBFBD>YS
void OnDeinit(const int reason)
{
// <EFBFBD>e<EFBFBD><EFBFBD>d\O
}
// EA ;N<EFBFBD>_<EFBFBD>s
void OnTick()
{
TrailingStop(); // <EFBFBD>y<EFBFBD>Rbk<EFBFBD>v
CheckAndCloseProfitablePositions(); // <EFBFBD>h<EFBFBD>gv^s^<EFBFBD>N<EFBFBD>v)R<EFBFBD>NMO
// <EFBFBD><EFBFBD><EFBFBD>SS_MRAsk<EFBFBD>N
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick))
{
Print("Failed to get tick");
return;
}
double ask = tick.ask;
// <EFBFBD><EFBFBD>U_<EFBFBD>S<EFBFBD>S<EFBFBD>N
if(g_highest_price < ask || g_highest_price == 0.0)
g_highest_price = ask;
// <EFBFBD><EFBFBD><EFBFBD>{ݍ<EFBFBD>y<EFBFBD>S<EFBFBD><EFBFBD>p<EFBFBD>v<EFBFBD>V<EFBFBD>d
double drawdown = g_highest_price - ask;
// <EFBFBD>h<EFBFBD>gYO<EFBFBD><EFBFBD>
double currentBalance = AccountInfoDouble(ACCOUNT_BALANCE);
if(currentBalance < MinBalance)
{
Print("Balance too low: ", currentBalance, " < ", MinBalance, ", not opening order");
return;
}
int currentPositions = GetCurrentPositions(_Symbol, MagicNumber);
int remainingOrders = MaxOrders - currentPositions;
if(remainingOrders <= 0) return; // <EFBFBD>]<EFBFBD><EFBFBD>g'Yc<EFBFBD>N
// <EFBFBD>S<EFBFBD><EFBFBD>p<EFBFBD>V<EFBFBD>d NUS<EFBFBD> N<EFBFBD>S<EFBFBD>e<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>6R <EFBFBD><EFBFBD>SDrawdownMaxOrdersP<EFBFBD>6R <EFBFBD>
bool canOpenDrawdown = false;
int drawdownOrders = GetDrawdownOrderCount(_Symbol, MagicNumber);
if(EnableOpenOrder && EnableDrawdownOpen && DrawdownOpenUSD > 0 && drawdown >= DrawdownOpenUSD && drawdownOrders < DrawdownMaxOrders)
{
canOpenDrawdown = true;
}
// <EFBFBD>k̍N<EFBFBD>CQ<EFBFBD>R<EFBFBD>N<EFBFBD> N<EFBFBD>S<EFBFBD>e<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>6R <EFBFBD><EFBFBD>SMaxOrdersP<EFBFBD>6R <EFBFBD>
bool canAddOrder = false;
if(EnableOpenOrder && EnableAddOrderEveryUSD && AddOrderEveryUSD > 0 && currentPositions > 0 && currentPositions < MaxOrders)
{
if(g_last_add_price == 0.0) g_last_add_price = ask; // <EFBFBD><EFBFBD>!kK<EFBFBD><P
double priceDrop = g_last_add_price - ask;
if(priceDrop >= AddOrderEveryUSD)
canAddOrder = true;
}
// <EFBFBD>S<EFBFBD><EFBFBD><EFBFBD>n<EFBFBD><EFBFBD><EFBFBD>NNag<EFBFBD>N1\ NUS<EFBFBD> N<EFBFBD>S<EFBFBD>e<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>6R <EFBFBD>
// <EFBFBD>V<EFBFBD>d<EFBFBD>R<EFBFBD>N<EFBFBD>SDrawdownMaxOrdersP<EFBFBD>6R <EFBFBD><EFBFBD>R<EFBFBD>N<EFBFBD>SMaxOrdersP<EFBFBD>6R
if((canOpenDrawdown && drawdownOrders < DrawdownMaxOrders) || (canAddOrder && currentPositions < MaxOrders))
{
// <EFBFBD>[P<EFBFBD>Kbpe
double vol = Lots;
vol = MathMax(g_min_lot, vol);
vol = AlignToStep(vol, g_lot_step);
vol = MathMin(vol, g_max_lot);
if(vol < g_min_lot - 1e-8)
{
Print("Volume too small");
return;
}
// <EFBFBD>[P<EFBFBD><EFBFBD>N<h
double price = AlignToPoint(ask);
// <EFBFBD><EFBFBD><EFBFBD>{TP
double tp_price = ask + TP_Points;
tp_price = AlignToPoint(tp_price);
// <EFBFBD><EFBFBD>bT<EFBFBD>~
if(!SymbolSelect(_Symbol, true))
{
Print("Symbol not selectable");
return;
}
// <EFBFBD>S<EFBFBD><EFBFBD><EFBFBD>US
MqlTradeRequest req;
MqlTradeResult res;
ZeroMemory(req);
ZeroMemory(res);
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.type = ORDER_TYPE_BUY;
req.volume = vol;
req.price = price;
req.sl = 0.0;
req.tp = tp_price;
req.deviation = Deviation;
req.type_filling = GetFillingMode();
req.magic = MagicNumber;
// <EFBFBD>:SR<EFBFBD><EFBFBD>V<EFBFBD>d<EFBFBD>R<EFBFBD>N<EFBFBD>QDD <EFBFBD>vQYO:Nzz
if(canOpenDrawdown && drawdownOrders < DrawdownMaxOrders)
req.comment = "DD";
else
req.comment = "";
if(OrderSend(req, res))
{
if(res.retcode == TRADE_RETCODE_DONE || res.retcode == TRADE_RETCODE_PLACED)
{
orderCount++;
lastOrderTime = TimeCurrent();
g_last_add_price = ask; // <EFBFBD><EFBFBD>U_,g!k<EFBFBD>R<EFBFBD>N<EFBFBD>N
Print("[DD/Add] BUY order ", orderCount, " placed. Drawdown=", drawdown, " AddOrderEveryUSD=", AddOrderEveryUSD, " Ask=", ask, " Highest=", g_highest_price, " currentPositions=", currentPositions+1, "/", MaxOrders, " comment=", req.comment);
if(EnableCloseAllSellOnBuy)
CloseAllSellPositions();
}
else
{
Print("Order failed: ", res.retcode, " Ask: ", ask);
}
}
else
{
Print("OrderSend failed, error code: ", GetLastError());
}
return; // ,gtick<EFBFBD>S NN*NUS
}
// vQYO<EFBFBD>S g NUS;<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>S<EFBFBD>e<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0SARI{P<EFBFBD>6R <EFBFBD>
// <EFBFBD>SяSAR_SmoothBars9hbar<EFBFBD>vꁚ[INSARGW<P <EFBFBD><EFBFBD>cGSs^<EFBFBD>n<EFBFBD>^
double sarSum = 0.0;
int sarCount = 0;
for(int i=1; i<=SAR_SmoothBars; ++i)
{
double v = CustomSAR(i, SAR_Acceleration, SAR_Maximum, SAR_Start);
if(v > 0.0 && v < ask * 100 && v > ask / 100) // gHe'`<EFBFBD>O<EFBFBD>b
{
sarSum += v;
sarCount++;
}
}
double sarValue = (sarCount > 0) ? (sarSum / sarCount) : 0.0;
// SAR<P gHe'`<EFBFBD>O<EFBFBD>b
if(sarValue <= 0.0 || sarValue > ask * 100 || sarValue < ask / 100)
{
Print("[Warn] s^<5E>nCustomSARGW<P_8^ <0C><><EFBFBD>Ǐ,g!k_US0sarValue=", sarValue, " ask=", ask);
return;
}
// <EFBFBD><EFBFBD><EFBFBD>SS_MRRSI<P
int rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE);
if(rsiHandle == INVALID_HANDLE)
{
Print("Failed to create RSI handle");
return;
}
double rsi[1];
if(CopyBuffer(rsiHandle, 0, 0, 1, rsi) != 1)
{
Print("Failed to copy RSI buffer");
IndicatorRelease(rsiHandle);
return;
}
IndicatorRelease(rsiHandle);
// vQYO<EFBFBD>S g NUS;<EFBFBD><EFBFBD><EFBFBD>
if(lastOrderTime > 0 && TimeCurrent() - lastOrderTime < Seconds) return; // *g0R<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>e<EFBFBD><EFBFBD>
// SAR<EFBFBD>O<EFBFBD><EFBFBD>n
bool sarSignal = true;
if(EnableSAR)
{
sarSignal = false;
double prevSar = 0.0, prevClose = 0.0;
// <EFBFBD>S
NN9hbar<EFBFBD>vSARGW<P
double sarSum2 = 0.0;
int sarCount2 = 0;
for(int i=2; i<=SAR_SmoothBars+1; ++i)
{
double v = CustomSAR(i, SAR_Acceleration, SAR_Maximum, SAR_Start);
if(v > 0.0 && v < ask * 100 && v > ask / 100)
{
sarSum2 += v;
sarCount2++;
}
}
prevSar = (sarCount2 > 0) ? (sarSum2 / sarCount2) : 0.0;
double closeBuf[2];
if(CopyClose(_Symbol, PERIOD_CURRENT, 0, 2, closeBuf) == 2)
{
prevClose = closeBuf[1];
if(iSAR_Reverse)
{
// true<EFBFBD><EFBFBD>S<EFBFBD><EFBFBD>SAR(WK<EFBFBD>~
N<EFBFBD>e b 1u Nl<EFBFBD>
N1\_Y
if(sarValue > ask) sarSignal = true; // SAR(WK<EFBFBD>~
N<EFBFBD>e
else if(prevSar < prevClose && sarValue > ask) sarSignal = true; // 1u Nl<EFBFBD>
N
}
else
{
// false<EFBFBD><EFBFBD>S<EFBFBD><EFBFBD>SAR(WK<EFBFBD>~ N<EFBFBD>e b 1u
Nl<EFBFBD> N1\_Y
if(sarValue < ask) sarSignal = true; // SAR(WK<EFBFBD>~ N<EFBFBD>e
else if(prevSar > prevClose && sarValue < ask) sarSignal = true; // 1u
Nl<EFBFBD> N
}
}
}
if(!sarSignal) return;
// <EFBFBD>[P<EFBFBD>Kbpe
double vol = Lots;
vol = MathMax(g_min_lot, vol);
vol = AlignToStep(vol, g_lot_step);
vol = MathMin(vol, g_max_lot);
if(vol < g_min_lot - 1e-8)
{
Print("Volume too small");
return;
}
// <EFBFBD>[P<EFBFBD><EFBFBD>N<h
double price = AlignToPoint(ask);
// <EFBFBD><EFBFBD><EFBFBD>{TP
double tp_price = ask + TP_Points;
tp_price = AlignToPoint(tp_price);
// <EFBFBD><EFBFBD>bT<EFBFBD>~
if(!SymbolSelect(_Symbol, true))
{
Print("Symbol not selectable");
return;
}
// <EFBFBD>S<EFBFBD><EFBFBD><EFBFBD>US
MqlTradeRequest req;
MqlTradeResult res;
ZeroMemory(req);
ZeroMemory(res);
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.type = ORDER_TYPE_BUY;
req.volume = vol;
req.price = price;
req.sl = 0.0;
req.tp = tp_price;
req.deviation = Deviation;
req.type_filling = GetFillingMode();
req.magic = MagicNumber;
if(OrderSend(req, res))
{
if(res.retcode == TRADE_RETCODE_DONE || res.retcode == TRADE_RETCODE_PLACED)
{
orderCount++;
lastOrderTime = TimeCurrent();
Print("BUY order ", orderCount, " placed successfully. Volume: ", vol, " Price: ", price, " TP: ", tp_price, " TP Spread: ", TP_Points, " Ask: ", ask, " SAR: ", sarValue, " (Remaining: ", remainingOrders-1, ")");
if(EnableCloseAllSellOnBuy)
CloseAllSellPositions(); // 9hnc<EFBFBD>Spe<EFBFBD>Q<EFBFBD>[/f&Ts^zzUS
}
else
{
Print("Order failed: ", res.retcode, " Ask: ", ask, " SAR: ", sarValue);
}
}
else
{
Print("OrderSend failed, error code: ", GetLastError());
}
}
//+------------------------------------------------------------------+