diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9bea433 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +.DS_Store diff --git a/Experts/api.mq5 b/Experts/api.mq5 new file mode 100644 index 0000000..28140e4 Binary files /dev/null and b/Experts/api.mq5 differ diff --git a/Experts/backtrader.mq5 b/Experts/backtrader.mq5 deleted file mode 100644 index ebc4839..0000000 --- a/Experts/backtrader.mq5 +++ /dev/null @@ -1,611 +0,0 @@ -//+------------------------------------------------------------------+ -// -// Copyright (C) 2019 Nikolai Khramkov -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -//+------------------------------------------------------------------+ - -// TODO: Close position -// TODO: Close orders -// TODO: Check If SymbolExist -// TODO: Check TF according to request -> change -// TODO: Check chart symbol according to request -> change -// TODO: RETURN OK or error -// TODO: Write comment about sockets -// TODO: Add defauld dict check -// TODO: Change description -// TODO: Comissinos - -#property copyright "Copyright 2019, Nikolai Khramkov." -#property link "https://github.com/khramkov" -#property version "0.70" - -#include -#include - -extern string PROJECT_NAME="Backtrader <-> Metatrader 5 interface"; -extern string PROTOCOL="tcp"; -extern string HOST="*"; -extern int SYS_PORT=15555; -extern int DATA_PORT=15556; -extern int LIVE_PORT=15557; -extern int MILLISECOND_TIMER=1; // 1 millisecond - -// ZeroMQ Cnnections -Context context(PROJECT_NAME); -Socket sysSocket(context,ZMQ_REP); -Socket dataSocket(context,ZMQ_PUSH); -Socket liveSocket(context,ZMQ_PUSH); - -// Global variables -bool debug = true; -datetime lastBar = 0; -string symbol = _Symbol; -ENUM_TIMEFRAMES period = _Period; - -//+------------------------------------------------------------------+ -//| Expert initialization function | -//+------------------------------------------------------------------+ -int OnInit() - { - /* - Bindinig ZMQ ports on init - */ - - // Set Millisecond Timer to get client socket input - EventSetMillisecondTimer(MILLISECOND_TIMER); - - Print("[REP] Binding System Socket on port "+IntegerToString(SYS_PORT)+"..."); - sysSocket.bind(StringFormat("%s://%s:%d",PROTOCOL,HOST,SYS_PORT)); - - Print("[PUSH] Binding Data Socket on port "+IntegerToString(DATA_PORT)+"..."); - dataSocket.bind(StringFormat("%s://%s:%d",PROTOCOL,HOST,DATA_PORT)); - - Print("[PUSH] Binding Live Socket on port "+IntegerToString(LIVE_PORT)+"..."); - liveSocket.bind(StringFormat("%s://%s:%d",PROTOCOL,HOST,LIVE_PORT)); - - // Maximum amount of time in milliseconds that the thread will try to send messages - // after its socket has been closed (the default value of -1 means to linger forever): - sysSocket.setLinger(1000); - - // How many messages do we want ZeroMQ to buffer in RAM before blocking the socket? - // 3 messages only. - sysSocket.setSendHighWaterMark(3); - dataSocket.setSendHighWaterMark(3); - liveSocket.setSendHighWaterMark(3); - - return(INIT_SUCCEEDED); - } -//+------------------------------------------------------------------+ -//| Expert deinitialization function | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - /* - Closing ports on denit - */ - Print("[REP] Unbinding socket on port "+IntegerToString(SYS_PORT)+".."); - sysSocket.unbind(StringFormat("%s://%s:%d",PROTOCOL,HOST,SYS_PORT)); - - Print("[PUSH] Unbinding socket on port "+IntegerToString(DATA_PORT)+".."); - dataSocket.unbind(StringFormat("%s://%s:%d",PROTOCOL,HOST,DATA_PORT)); - - Print("[PUSH] Unbinding socket on port "+IntegerToString(LIVE_PORT)+".."); - liveSocket.unbind(StringFormat("%s://%s:%d",PROTOCOL,HOST,LIVE_PORT)); - - } -//+------------------------------------------------------------------+ -//| Expert timer function | -//+------------------------------------------------------------------+ -void OnTimer() - { - ZmqMsg request; - - // Get client's response, but don't wait. - sysSocket.recv(request,true); - - // Generating reply by passing request to ZmqMsg MessageHandler() function. - ZmqMsg reply=MessageHandler(request); - - // Reply to client via REP socket. - sysSocket.send(reply); - } - -//+------------------------------------------------------------------+ -//| Request handler | -//+------------------------------------------------------------------+ -ZmqMsg MessageHandler(ZmqMsg &request) - { - ZmqMsg reply; - CJAVal message; - - if(request.size()>0) - { - - string msg=request.getData(); - - if(debug==true) {Print("Processing request:"+msg);} - - if(!message.Deserialize(msg)) - { - Alert("Deserialization Error"); - - //ExpertRemove(); - //return; - } - - string action = message["action"].ToStr(); - - if(action=="CHECK") {CheckConnection(&dataSocket, &liveSocket);} - else if(action=="CONFIG") {ConfigScript(&dataSocket, message);} - else if(action=="ACCOUNT") {AccountInfo(&dataSocket);} - else if(action=="BALANCE") {BalanceInfo(&dataSocket);} - else if(action=="HISTORY") {HistoryInfo(&dataSocket, message);} - else if(action=="POSITIONS_INFO") {GetPositionsInfo(&dataSocket);} - else if(action=="ORDERS_INFO") {GetOrdersInfo(&dataSocket);} - else if(action=="TRADE") {TradingModule(&dataSocket, message);} - else {} // error processing - - // Construct response - ZmqMsg ret("OK"); - reply=ret; - - } - else - { - // NO DATA RECEIVED - ZmqMsg ret("FALSE"); - reply=ret; - } - - return(reply); - } - -//+------------------------------------------------------------------+ -//| Check sockets connection | -//+------------------------------------------------------------------+ -void CheckConnection (Socket &dataSocket, Socket &liveSocket) - { - InformClientSocket(dataSocket,"OK"); - InformClientSocket(liveSocket,"OK"); - } - - -//+------------------------------------------------------------------+ -//| Reconfigure the script params | -//+------------------------------------------------------------------+ -void ConfigScript(Socket &dataSocket, CJAVal &dataObject) - { - - } - -//+------------------------------------------------------------------+ -//| Change chart timeframe | -//+------------------------------------------------------------------+ -void CheckTimeframe(Socket &dataSocket, CJAVal &dataObject) - { - string chartTF=dataObject["chartTF"].ToStr(); - - if(chartTF=="1m") {period=PERIOD_M1;} - else if(chartTF=="5m") {period=PERIOD_M5;} - else if(chartTF=="15m") {period=PERIOD_M15;} - else if(chartTF=="30m") {period=PERIOD_M30;} - else if(chartTF=="1h") {period=PERIOD_H1;} - else if(chartTF=="2h") {period=PERIOD_H2;} - else if(chartTF=="3h") {period=PERIOD_H3;} - else if(chartTF=="4h") {period=PERIOD_H4;} - else if(chartTF=="6h") {period=PERIOD_H6;} - else if(chartTF=="8h") {period=PERIOD_H8;} - else if(chartTF=="12h") {period=PERIOD_H12;} - else if(chartTF=="1d") {period=PERIOD_D1;} - else if(chartTF=="1w") {period=PERIOD_W1;} - else if(chartTF=="1M") {period=PERIOD_MN1;} - } - -//+------------------------------------------------------------------+ -//| Account information | -//+------------------------------------------------------------------+ -void AccountInfo(Socket &dataSocket) - { - CJAVal info; - - info["brocker"] = AccountInfoString(ACCOUNT_COMPANY); - info["currency"] = AccountInfoString(ACCOUNT_CURRENCY); - info["server"] = AccountInfoString(ACCOUNT_SERVER); - info["balance"] = AccountInfoDouble(ACCOUNT_BALANCE); - info["equity"] = AccountInfoDouble(ACCOUNT_EQUITY); - info["margin"] = AccountInfoDouble(ACCOUNT_MARGIN); - info["margin_free"] = AccountInfoDouble(ACCOUNT_MARGIN_FREE); - info["margin_level"] = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); - info["bot_trading"] = AccountInfoInteger(ACCOUNT_TRADE_EXPERT); - string t=info.Serialize(); - if(debug==true) {Print(t);} - InformClientSocket(dataSocket,t); - } - -//+------------------------------------------------------------------+ -//| Balance information | -//+------------------------------------------------------------------+ -void BalanceInfo(Socket &dataSocket) - { - CJAVal info; - - info["balance"] = AccountInfoDouble(ACCOUNT_BALANCE); - info["equity"] = AccountInfoDouble(ACCOUNT_EQUITY); - info["margin"] = AccountInfoDouble(ACCOUNT_MARGIN); - info["margin_free"] = AccountInfoDouble(ACCOUNT_MARGIN_FREE); - string t=info.Serialize(); - if(debug==true) {Print(t);} - InformClientSocket(dataSocket,t); - } - - -//+------------------------------------------------------------------+ -//| Get historical data | -//+------------------------------------------------------------------+ -void HistoryInfo(Socket &dataSocket, CJAVal &dataObject) - { - CJAVal candles; - MqlRates rates[]; - - int copied; - string actionType=dataObject["actionType"].ToStr(); - string symbol=dataObject["symbol"].ToStr(); - string chartTF=dataObject["chartTF"].ToStr(); - datetime startTime=dataObject["startTime"].ToInt(); - - if(debug==true) - { - Print("Fetching HISTORY"); - Print("1) Symbol:"+symbol); - Print("2) Timeframe:"+chartTF); - Print("3) Date from:"+TimeToString(startTime)); - } - copied=CopyRates(symbol,period,startTime,TimeCurrent(),rates); - if(copied) - - { - for(int i=0;i