80 라인
3.4 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| 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; }
| |||
}
| |||
//+------------------------------------------------------------------+
|