151 lines
5.7 KiB
MQL5
151 lines
5.7 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| AlphaEngine.mq5 |
|
||
|
|
//| MMQ — Muhammad Minhas Qamar |
|
||
|
|
//| www.mql5.com/en/articles/23814 |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "MMQ — Muhammad Minhas Qamar"
|
||
|
|
#property link "https://www.mql5.com/en/articles/23814"
|
||
|
|
#property version "1.00"
|
||
|
|
#property description "Coastline counter-trend trading model of Golub, Glattfelder & Olsen"
|
||
|
|
#property description "(The Alpha Engine, SSRN 2951348). Eight limit-order agents, long and short, at delta = 0.25/0.5/1/1.5%. Requires a hedging account."
|
||
|
|
|
||
|
|
#include <IntrinsicTime\AeLiveTrader.mqh>
|
||
|
|
|
||
|
|
//--- position sizing and risk.
|
||
|
|
input double InpLotPerUnit =0.02; // lots per one abstract unit
|
||
|
|
input double InpMaxUnits =30.0; // per-agent inventory cap, units
|
||
|
|
input long InpMagicBase =990000; // base magic; each agent gets a unique one
|
||
|
|
|
||
|
|
//--- which agents of the ensemble to run.
|
||
|
|
input bool InpTradeLong =true; // run the four long-only agents
|
||
|
|
input bool InpTradeShort =true; // run the four short-only agents
|
||
|
|
|
||
|
|
//--- the paper's four base thresholds.
|
||
|
|
double g_deltas[4]={0.0025,0.0050,0.0100,0.0150};
|
||
|
|
|
||
|
|
CAeLiveTrader g_traders[8];
|
||
|
|
int g_count=0;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Enforce a hedging account and build the requested agents. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnInit(void)
|
||
|
|
{
|
||
|
|
long mode=AccountInfoInteger(ACCOUNT_MARGIN_MODE);
|
||
|
|
if(mode!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
|
||
|
|
{
|
||
|
|
Print("AlphaEngine: a hedging account is required "
|
||
|
|
"(each cascade step must be its own position). Aborting.");
|
||
|
|
return INIT_FAILED;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(InpLotPerUnit<=0.0 || InpMaxUnits<=0.0)
|
||
|
|
{
|
||
|
|
Print("AlphaEngine: LotPerUnit and MaxUnits must be positive.");
|
||
|
|
return INIT_FAILED;
|
||
|
|
}
|
||
|
|
|
||
|
|
g_count=0;
|
||
|
|
for(int s=0;s<4;s++)
|
||
|
|
{
|
||
|
|
if(InpTradeLong)
|
||
|
|
{
|
||
|
|
g_traders[g_count].Init(_Symbol,InpMagicBase+s*2,1,
|
||
|
|
g_deltas[s],InpLotPerUnit,InpMaxUnits);
|
||
|
|
g_count++;
|
||
|
|
}
|
||
|
|
if(InpTradeShort)
|
||
|
|
{
|
||
|
|
g_traders[g_count].Init(_Symbol,InpMagicBase+s*2+1,-1,
|
||
|
|
g_deltas[s],InpLotPerUnit,InpMaxUnits);
|
||
|
|
g_count++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if(g_count==0)
|
||
|
|
{
|
||
|
|
Print("AlphaEngine: no agents enabled.");
|
||
|
|
return INIT_FAILED;
|
||
|
|
}
|
||
|
|
PrintFormat("AlphaEngine: %d agents live on %s (hedging).",g_count,_Symbol);
|
||
|
|
return INIT_SUCCEEDED;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Is the symbol inside a trading session right now. |
|
||
|
|
//| Order operations outside a session are rejected as "market |
|
||
|
|
//| closed"; gating on the session keeps the journal clean and the |
|
||
|
|
//| run fast without changing any decision. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool InTradeSession(void)
|
||
|
|
{
|
||
|
|
MqlDateTime st;
|
||
|
|
TimeToStruct(TimeCurrent(),st);
|
||
|
|
ENUM_DAY_OF_WEEK dow=(ENUM_DAY_OF_WEEK)st.day_of_week;
|
||
|
|
uint sod=(uint)(st.hour*3600+st.min*60+st.sec);
|
||
|
|
datetime from,to;
|
||
|
|
for(uint s=0;SymbolInfoSessionTrade(_Symbol,dow,s,from,to);s++)
|
||
|
|
if(sod>=(uint)from && sod<(uint)to)
|
||
|
|
return true;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Drive every agent with the freshest quote. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnTick(void)
|
||
|
|
{
|
||
|
|
if(!InTradeSession())
|
||
|
|
return;
|
||
|
|
|
||
|
|
MqlTick t;
|
||
|
|
if(!SymbolInfoTick(_Symbol,t))
|
||
|
|
return;
|
||
|
|
if(t.bid<=0.0 || t.ask<=0.0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
for(int i=0;i<g_count;i++)
|
||
|
|
g_traders[i].OnTickUpdate(t.bid,t.ask,t.time);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Cancel resting orders on shutdown; open positions keep their |
|
||
|
|
//| take-profits and unwind on their own. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnDeinit(const int reason)
|
||
|
|
{
|
||
|
|
for(int i=0;i<g_count;i++)
|
||
|
|
g_traders[i].Shutdown();
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Write the pass statistics to a file at the end of a tester run. |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double OnTester(void)
|
||
|
|
{
|
||
|
|
double profit=TesterStatistics(STAT_PROFIT);
|
||
|
|
double trades=TesterStatistics(STAT_TRADES);
|
||
|
|
double pf =TesterStatistics(STAT_PROFIT_FACTOR);
|
||
|
|
double dd =TesterStatistics(STAT_EQUITYDD_PERCENT);
|
||
|
|
double deposit=TesterStatistics(STAT_INITIAL_DEPOSIT);
|
||
|
|
|
||
|
|
HistorySelect(0,TimeCurrent()+1);
|
||
|
|
int deals=HistoryDealsTotal();
|
||
|
|
int open_pos=PositionsTotal();
|
||
|
|
|
||
|
|
int h=FileOpen("AlphaEngine_Result.txt",FILE_WRITE|FILE_TXT|FILE_ANSI|FILE_COMMON);
|
||
|
|
if(h!=INVALID_HANDLE)
|
||
|
|
{
|
||
|
|
FileWrite(h,StringFormat("net_profit=%.2f",profit));
|
||
|
|
FileWrite(h,StringFormat("initial_deposit=%.2f",deposit));
|
||
|
|
FileWrite(h,StringFormat("return_pct=%.2f",(deposit>0.0?profit/deposit*100.0:0.0)));
|
||
|
|
FileWrite(h,StringFormat("trades=%.0f",trades));
|
||
|
|
FileWrite(h,StringFormat("deals=%d",deals));
|
||
|
|
FileWrite(h,StringFormat("open_positions_at_end=%d",open_pos));
|
||
|
|
FileWrite(h,StringFormat("profit_factor=%.3f",pf));
|
||
|
|
FileWrite(h,StringFormat("equity_dd_pct=%.2f",dd));
|
||
|
|
FileClose(h);
|
||
|
|
}
|
||
|
|
return profit;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|