| //+------------------------------------------------------------------+
|
| //| TF_DemoEA.mq5 - a deliberately simple demo Expert for Tick Forge. |
|
| //| It exists only to show what the audit set exposes. MIT licence. |
|
| //| |
|
| //| Rule (both modes): on weekdays, at InpHour server time, buy if |
|
| //| yesterday closed up, sell if it closed down; hold InpHoldHours. |
|
| //| InpMode 0 = LOGIC trades every weekday by that rule. |
|
| //| InpMode 1 = DATE LIST same rule, but ONLY on the dates listed |
|
| //| in InpDates (a stand-in for a fitted, memorised |
|
| //| schedule). |
|
| //+------------------------------------------------------------------+
|
| #property strict
|
| #property version "1.00"
|
|
|
| input int InpMode = 0; // 0 = logic, 1 = only on the dates in InpDates
|
| input int InpHour = 10; // entry hour (server time)
|
| input int InpHoldHours = 3; // hours to hold
|
| input double InpLots = 0.10; // volume
|
| input string InpDates = ""; // YYYY.MM.DD,YYYY.MM.DD,... (mode 1)
|
|
|
| ulong g_ticket = 0;
|
| datetime g_opened = 0;
|
| string g_dates = "";
|
| int g_last_day = -1;
|
|
|
| int OnInit()
|
| {
|
| g_dates = "," + InpDates + ",";
|
| PrintFormat("TF_DemoEA v1.00 | mode=%d hour=%d hold=%d", InpMode, InpHour, InpHoldHours);
|
| return INIT_SUCCEEDED;
|
| }
|
|
|
| ENUM_ORDER_TYPE_FILLING Filling()
|
| {
|
| const long m = SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
|
| if((m & SYMBOL_FILLING_FOK) != 0) return ORDER_FILLING_FOK;
|
| if((m & SYMBOL_FILLING_IOC) != 0) return ORDER_FILLING_IOC;
|
| return ORDER_FILLING_RETURN;
|
| }
|
|
|
| bool AllowedToday(const datetime t)
|
| {
|
| if(InpMode == 0) return true;
|
| return StringFind(g_dates, "," + TimeToString(t, TIME_DATE) + ",") >= 0;
|
| }
|
|
|
| void OnTick()
|
| {
|
| const datetime now = TimeCurrent();
|
| MqlDateTime dt; TimeToStruct(now, dt);
|
| if(PositionSelect(_Symbol))
|
| {
|
| if(now - g_opened >= InpHoldHours * 3600)
|
| {
|
| MqlTradeRequest r; MqlTradeResult s; ZeroMemory(r); ZeroMemory(s);
|
| r.action = TRADE_ACTION_DEAL; r.symbol = _Symbol; r.volume = PositionGetDouble(POSITION_VOLUME);
|
| const bool buy = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY);
|
| r.type = buy ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
|
| r.price = SymbolInfoDouble(_Symbol, buy ? SYMBOL_BID : SYMBOL_ASK);
|
| r.position = PositionGetInteger(POSITION_TICKET);
|
| r.type_filling = Filling(); r.deviation = 50;
|
| if(!OrderSend(r, s)) Print("TF_DemoEA close failed: ", s.retcode);
|
| }
|
| return;
|
| }
|
| if(dt.day_of_week == 0 || dt.day_of_week == 6) return;
|
| if(dt.hour != InpHour || dt.day_of_year == g_last_day) return;
|
| if(!AllowedToday(now)) return;
|
| MqlRates d[];
|
| if(CopyRates(_Symbol, PERIOD_D1, 1, 1, d) != 1) return;
|
| MqlTradeRequest r; MqlTradeResult s; ZeroMemory(r); ZeroMemory(s);
|
| const bool buy = (d[0].close >= d[0].open);
|
| r.action = TRADE_ACTION_DEAL; r.symbol = _Symbol; r.volume = InpLots;
|
| r.type = buy ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
|
| r.price = SymbolInfoDouble(_Symbol, buy ? SYMBOL_ASK : SYMBOL_BID);
|
| r.type_filling = Filling(); r.deviation = 50;
|
| if(OrderSend(r, s) && (s.retcode == TRADE_RETCODE_DONE || s.retcode == TRADE_RETCODE_PLACED))
|
| { g_opened = now; g_last_day = dt.day_of_year; }
|
| }
|
| //+------------------------------------------------------------------+
|