209 lines
6.4 KiB
Plaintext
209 lines
6.4 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| PaPP_Trading_EA.mq5 |
|
|
//| PaPP Trading |
|
|
//+------------------------------------------------------------------+
|
|
#include <Trade/Trade.mqh>
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "PaPP Trading"
|
|
#property version "1.03"
|
|
#property description "PaPP Trading EA - Mean Reversion su Score multi-TF"
|
|
#property description "Compra quando Score <= BuyThresh (sotto media = ipervenduto)"
|
|
#property description "Vende quando Score >= SellThresh (sopra media = ipercomprato)"
|
|
|
|
input double LotSize = 0.01;
|
|
input int TP_Points = 100;
|
|
input int SL_Points = 10000; // ~1000 pips, safety net largo
|
|
input int BuyThresh = -3;
|
|
input int SellThresh = 3;
|
|
input bool UseAccel = false;
|
|
input bool DebugPrint = true;
|
|
input int MinValidMAs = 4;
|
|
input int Magic = 2024001;
|
|
input int Slippage = 30;
|
|
|
|
int hMA[8];
|
|
int bars[8];
|
|
string pN[8] = {"1Y","6M","4M","1M","2W","1W","3G","1G"};
|
|
datetime lastBar = 0;
|
|
ulong myTicket = 0;
|
|
|
|
//+------------------------------------------------------------------+
|
|
int TimeToBars(int days)
|
|
{
|
|
datetime now = TimeCurrent();
|
|
if(now==0)
|
|
{
|
|
long s = (long)days*86400L;
|
|
long p = PeriodSeconds((ENUM_TIMEFRAMES)_Period);
|
|
return (int)MathMax(1,s/p);
|
|
}
|
|
datetime then = now - days*86400;
|
|
int cnt = Bars(_Symbol,_Period,then,now);
|
|
return MathMax(1,cnt);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
int days[8] = {365,182,121,30,14,7,3,1};
|
|
for(int i=0;i<8;i++)
|
|
{
|
|
bars[i] = (i<7) ? TimeToBars(days[i]) : 1;
|
|
hMA[i] = iMA(_Symbol,_Period,bars[i],0,MODE_SMA,PRICE_CLOSE);
|
|
if(hMA[i]==INVALID_HANDLE) return INIT_FAILED;
|
|
}
|
|
myTicket = 0;
|
|
Print("=== PaPP v1.03 INIT ===");
|
|
for(int i=0;i<8;i++) Print(" MA[",i,"] ",pN[i]," bars=",bars[i]);
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
for(int i=0;i<8;i++)
|
|
if(hMA[i]!=INVALID_HANDLE) IndicatorRelease(hMA[i]);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
double GetMA(int idx,int m)
|
|
{
|
|
double buf[1];
|
|
// idx=0 -> last COMPLETED bar (start_pos=1)
|
|
// idx=1 -> second-to-last (start_pos=2)
|
|
if(CopyBuffer(hMA[m],0,idx+1,1,buf)==1) return buf[0];
|
|
return 0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
datetime curBar = iTime(_Symbol,_Period,0);
|
|
if(curBar==lastBar) return;
|
|
lastBar = curBar;
|
|
|
|
double close0 = iClose(_Symbol,_Period,0);
|
|
if(close0<=0) return;
|
|
|
|
double mv[8], vel[8];
|
|
int validMAs=0;
|
|
for(int m=0;m<8;m++)
|
|
{
|
|
mv[m] = GetMA(0,m);
|
|
if(mv[m]>0) validMAs++;
|
|
double prv = GetMA(1,m);
|
|
if(prv<=0) prv=mv[m];
|
|
vel[m] = mv[m] - prv;
|
|
}
|
|
|
|
if(DebugPrint)
|
|
{
|
|
Print("--- ",TimeToString(curBar)," Close=",DoubleToString(close0,_Digits)," Valid=",validMAs);
|
|
for(int m=0;m<8;m++)
|
|
if(mv[m]>0)
|
|
Print(" ",pN[m],"=",DoubleToString(mv[m],_Digits),
|
|
" diff=",DoubleToString(close0-mv[m],_Digits),
|
|
" vel=",DoubleToString(vel[m],6));
|
|
}
|
|
|
|
if(validMAs < MinValidMAs) return;
|
|
|
|
//--- Score (-validMAs .. +validMAs)
|
|
int score = 0;
|
|
for(int m=0;m<8;m++)
|
|
if(mv[m]>0) score += (close0>mv[m]) ? 1 : -1;
|
|
|
|
//--- Acceleration
|
|
double accel=0;
|
|
int ac=0;
|
|
for(int m=0;m<7;m++)
|
|
{
|
|
if(mv[m]>0 && mv[m+1]>0) { accel+=(vel[m]-vel[m+1]); ac++; }
|
|
}
|
|
if(ac>0) accel/=ac;
|
|
|
|
double point = SymbolInfoDouble(_Symbol,SYMBOL_POINT);
|
|
|
|
if(DebugPrint) Print("Score:",score," Entry:",BuyThresh,"/",SellThresh," Accel:",DoubleToString(accel,6));
|
|
|
|
//--- Position check
|
|
bool hasPos = PositionSelectByTicket(myTicket);
|
|
if(!hasPos) myTicket = 0;
|
|
|
|
//--- Exit
|
|
if(hasPos)
|
|
{
|
|
bool isBuy = (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY);
|
|
bool shouldClose = false;
|
|
if(isBuy && score >= SellThresh) shouldClose = true;
|
|
if(!isBuy && score <= BuyThresh) shouldClose = true;
|
|
if(!shouldClose && score>=-1 && score<=1) shouldClose = true;
|
|
if(shouldClose)
|
|
{
|
|
if(DebugPrint) Print(">>> CLOSE ",isBuy?"BUY":"SELL"," score=",score);
|
|
CTrade trade;
|
|
trade.PositionClose(myTicket,Slippage);
|
|
myTicket = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
//--- BUY
|
|
if(score <= BuyThresh)
|
|
{
|
|
if(!UseAccel || accel > -point*10)
|
|
{
|
|
if(DebugPrint) Print(">>> BUY score=",score);
|
|
double tp = close0 + TP_Points*point;
|
|
double sl = close0 - SL_Points*point;
|
|
if(sl<0) sl = point;
|
|
MqlTradeRequest req={};
|
|
MqlTradeResult res={};
|
|
req.action = TRADE_ACTION_DEAL;
|
|
req.symbol = _Symbol;
|
|
req.volume = LotSize;
|
|
req.type = ORDER_TYPE_BUY;
|
|
req.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
|
|
req.tp = tp;
|
|
req.sl = sl;
|
|
req.deviation = Slippage;
|
|
req.magic = Magic;
|
|
req.comment = "PaPP B"+IntegerToString(score);
|
|
if(OrderSend(req,res))
|
|
{
|
|
if(res.retcode==TRADE_RETCODE_DONE) myTicket = res.order;
|
|
else if(DebugPrint) Print("BUY fail: c",res.retcode);
|
|
}
|
|
}
|
|
}
|
|
|
|
//--- SELL
|
|
if(score >= SellThresh)
|
|
{
|
|
if(!UseAccel || accel < point*10)
|
|
{
|
|
if(DebugPrint) Print(">>> SELL score=",score);
|
|
double tp = close0 - TP_Points*point;
|
|
double sl = close0 + SL_Points*point;
|
|
MqlTradeRequest req={};
|
|
MqlTradeResult res={};
|
|
req.action = TRADE_ACTION_DEAL;
|
|
req.symbol = _Symbol;
|
|
req.volume = LotSize;
|
|
req.type = ORDER_TYPE_SELL;
|
|
req.price = SymbolInfoDouble(_Symbol,SYMBOL_BID);
|
|
req.tp = tp;
|
|
req.sl = sl;
|
|
req.deviation = Slippage;
|
|
req.magic = Magic;
|
|
req.comment = "PaPP S"+IntegerToString(score);
|
|
if(OrderSend(req,res))
|
|
{
|
|
if(res.retcode==TRADE_RETCODE_DONE) myTicket = res.order;
|
|
else if(DebugPrint) Print("SELL fail: c",res.retcode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|