Compare commits

..

40 Commits

Author SHA1 Message Date
Vyacheslav Demidyuk 4491ef39c2 PyMtApi5: implemented function ChartGetInteger 2025-03-13 12:39:40 +02:00
Vyacheslav Demidyuk 74a64b6fbd PyMtApi5: implemented function ChartGetDouble 2025-03-13 12:32:54 +02:00
Vyacheslav Demidyuk 5f55fa68f1 PyMtApi5: implemented function ChartSetString 2025-03-11 18:57:57 +02:00
Vyacheslav Demidyuk dc37543f83 PyMtApi5: implemented function ChartSetInteger 2025-03-11 18:25:30 +02:00
Vyacheslav Demidyuk fe11646cd6 PyMtApi5: implemented function ChartSetDouble 2025-03-08 18:01:14 +02:00
Vyacheslav Demidyuk 782115d644 PyMtApi5: implemented function ChartPeriod 2025-03-08 10:46:44 +02:00
Vyacheslav Demidyuk 6763dcdc26 PyMtApi5: implemented function ChartSymbol 2025-03-07 23:36:02 +02:00
Vyacheslav Demidyuk 1fc6ab77ed PyMtApi5: implemented function ChartClose 2025-03-07 23:27:39 +02:00
Vyacheslav Demidyuk 80e4886d4f PyMtApi5: implemented function ChartNext 2025-03-07 14:19:53 +02:00
Vyacheslav Demidyuk f3360cf6d6 PyMtApi5: implemented function ChartFirst 2025-02-21 12:23:42 +02:00
Vyacheslav Demidyuk 6a9739ff1e PyMtApi5: implemented function ChartOpen 2025-02-19 16:14:41 +02:00
Vyacheslav Demidyuk a3ded61946 PyMtApi5: implemented function ChartXYToTimePrice 2025-02-14 23:26:46 +02:00
Vyacheslav Demidyuk ad9589e444 PyMtApi5: implemented function ChartTimePriceToXY 2025-02-14 23:00:17 +02:00
Vyacheslav Demidyuk 8e996960fe PyMtApi5: implemented function ChartWindowFind 2025-02-14 22:22:30 +02:00
Vyacheslav Demidyuk 4263f319c4 PyMtApi5: implemented function ChartSaveTemplate" 2025-02-14 21:40:39 +02:00
Vyacheslav Demidyuk 3eba06a73b PyMtApi5: implemented function ChartApplyTemplate 2025-02-08 12:41:41 +02:00
Vyacheslav Demidyuk bd59c4052d PyMtApi5: implemented function ChartRedraw 2025-02-08 12:09:57 +02:00
Vyacheslav Demidyuk beacad1a10 PyMtApi5: implemented function ChartId 2025-01-26 12:01:14 +02:00
Vyacheslav Demidyuk d728e10923 PyMtApi5: implemented functions CopyOpen, CopyHigh, CopyLow, CopyClose, CopyTickVolume, CopyRealVolume, CopySpread, CopyTicks 2025-01-26 01:46:23 +02:00
Vyacheslav Demidyuk c61c773fb9 PyMtApi5: implemented function CopyTime 2025-01-26 00:09:24 +02:00
Vyacheslav Demidyuk 05aa533e3b PyMtApi5: implemented function CopyRates 2025-01-26 00:01:38 +02:00
Vyacheslav Demidyuk 58acc52fa2 PyMtApi5: implemented function CopyBuffer 2025-01-24 23:33:38 +02:00
Vyacheslav Demidyuk 669e3604f3 PyMtApi5: implemented function MarketBookGet 2025-01-24 22:49:13 +02:00
Vyacheslav Demidyuk 7a7d1f33d9 PyMtApi5: implemented function MarketBookAdd, MarketBookRelease 2025-01-23 23:28:55 +02:00
Vyacheslav Demidyuk 9f4a247048 PyMtApi5: implemented function SymbolInfoSessionTrade 2025-01-23 22:53:23 +02:00
Vyacheslav Demidyuk fdd09f2170 PyMtApi5: implemented function SymbolInfoSessionQuote 2025-01-23 22:38:19 +02:00
Vyacheslav Demidyuk fdb9ebb5de PyMtApi5: implemented function SymbolInfoTick 2025-01-22 13:57:19 +02:00
Vyacheslav Demidyuk 33bff44b39 PyMtApi5: implemented function SymbolInfoString; formatted code. 2025-01-18 00:32:44 +02:00
Vyacheslav Demidyuk 150995baea PyMtApi5: using dictionary to define functions for processing user commands 2025-01-17 17:19:28 +02:00
Vyacheslav Demidyuk 583aaa9627 PyMtApi5: implemented function SymbolInfoInteger 2025-01-16 23:34:53 +02:00
Vyacheslav Demidyuk 9d2884b608 PyMtApi5: implemented function InfoDouble 2025-01-16 23:13:22 +02:00
Vyacheslav Demidyuk a3ba4e7642 PyMtApi5: Implemented function SymbolIsSynchronized 2025-01-16 16:03:30 +02:00
Vyacheslav Demidyuk 573db07ce7 PyMtApi5: Implemented function SymbolSelect 2025-01-16 14:23:39 +02:00
Vyacheslav Demidyuk 7c1d2e53d4 PyMtApi5: Implemented function SymbolName 2025-01-16 14:01:57 +02:00
Vyacheslav Demidyuk ee149feef1 update gitignore to ignore python cache files 2025-01-15 23:20:02 +02:00
Vyacheslav Demidyuk 04d2f2e189 PyMtApi5: started implementation MtApi client MT5 for python3 2025-01-15 18:31:56 +02:00
Viacheslav Demydiuk 6b3d54b9d5 MtApi5: added default value to properites of MqlParam for correct json serialization 2025-01-09 17:06:36 +02:00
Viacheslav Demydiuk ba1754d59b MtApi/MtApi5: updated logic of connection with requesting expert list and quotes 2024-12-21 23:12:59 +02:00
Viacheslav Demydiuk b89f00d310 Added missed boost headers files 2024-11-14 14:16:28 +02:00
Viacheslav Demydiuk 19d9cb23d3 MtService: include string to fix build 2024-11-14 12:35:46 +02:00
23 changed files with 4428 additions and 146 deletions
+3
View File
@@ -188,3 +188,6 @@ UpgradeLog*.htm
# Microsoft Fakes
FakesAssemblies/
# Python cache
__pycache__/
+44 -50
View File
@@ -27,7 +27,6 @@ namespace MtApi
private readonly Dictionary<MtEventTypes, Action<int, string>> _mtEventHandlers = [];
private HashSet<int> _experts = [];
private Dictionary<int, MtQuote> _quotes = [];
private readonly EventWaitHandle _quotesWaiter = new AutoResetEvent(false);
private MtConnectionState _connectionState = MtConnectionState.Disconnected;
private int _executorHandle;
@@ -83,7 +82,6 @@ namespace MtApi
///</summary>
public List<MtQuote> GetQuotes()
{
_quotesWaiter.WaitOne(10000); // wait 10 sec for loading all quotes from MetaTrader
lock (_locker)
{
return _quotes.Values.ToList();
@@ -3041,7 +3039,6 @@ namespace MtApi
ConnectionStateChanged?.Invoke(this, new MtConnectionEventArgs(MtConnectionState.Connecting, message));
var client = new MtRpcClient(host, port, new RpcClientLogger(Log));
client.ExpertList += Client_ExpertList;
client.ExpertAdded += Client_ExpertAdded;
client.ExpertRemoved += Client_ExpertRemoved;
client.MtEventReceived += Client_MtEventReceived;
@@ -3052,13 +3049,44 @@ namespace MtApi
{
await client.Connect();
Log.Info($"Connected to {host}:{port}");
var experts = client.RequestExpertsList();
if (experts == null || experts.Count == 0)
{
var errorMessage = "Failed to load expert list";
Log.Error(errorMessage);
client.Disconnect();
ConnectionStateChanged?.Invoke(this, new MtConnectionEventArgs(MtConnectionState.Failed, errorMessage));
throw new Exception($"Connection to {host}:{port} failed. Error: {errorMessage}");
}
// Load quotes
Dictionary<int, MtQuote> quotes = [];
foreach (var handle in experts)
{
var quote = GetQuote(client, handle);
if (quote != null)
quotes[handle] = quote;
}
lock (_locker)
{
_client = client;
_experts = experts;
_quotes = quotes;
if (_executorHandle == 0)
_executorHandle = (_experts.Count > 0) ? _experts.ElementAt(0) : 0;
_connectionState = MtConnectionState.Connected;
}
client.NotifyClientReady();
if (IsTesting())
{
BacktestingReady();
}
ConnectionStateChanged?.Invoke(this, new MtConnectionEventArgs(MtConnectionState.Connected, $"Connected to {host}:{port}"));
QuoteList?.Invoke(this, new(quotes.Values.ToList()));
}
catch (Exception e)
{
@@ -3102,7 +3130,11 @@ namespace MtApi
private T? SendCommand<T>(int expertHandle, MtCommandType commandType, object? payload = null)
{
var client = Client;
return SendCommand<T>(Client, expertHandle, commandType, payload);
}
private T? SendCommand<T>(MtRpcClient? client, int expertHandle, MtCommandType commandType, object? payload = null)
{
if (client == null)
{
Log.Warn("SendCommand: No connection");
@@ -3143,11 +3175,6 @@ namespace MtApi
Task.Run(() => _mtEventHandlers[(MtEventTypes)e.EventType](e.ExpertHandle, e.Payload));
}
private void Client_ExpertList(object? sender, MtExpertListEventArgs e)
{
Task.Run(() => ProcessExpertList(e.Experts));
}
private void Client_ExpertAdded(object? sender, MtExpertEventArgs e)
{
Task.Run(() => ProcessExpertAdded(e.Expert));
@@ -3213,39 +3240,6 @@ namespace MtApi
OnLockTicks?.Invoke(this, new MtLockTicksEventArgs(expertHandle, e.Instrument));
}
private void ProcessExpertList(HashSet<int> experts)
{
if (experts == null || experts.Count == 0)
{
Log.Warn("ProcessExpertList: expert list invalid or empty");
return;
}
Dictionary<int, MtQuote> quotes = [];
foreach (var handle in experts)
{
var quote = GetQuote(handle);
if (quote != null)
quotes[handle] = quote;
}
lock (_locker)
{
_experts = experts;
_quotes = quotes;
if (_executorHandle == 0)
_executorHandle = (_experts.Count > 0) ? _experts.ElementAt(0) : 0;
}
_quotesWaiter.Set();
QuoteList?.Invoke(this, new(quotes.Values.ToList()));
if (IsTesting())
{
BacktestingReady();
}
}
private void ProcessExpertAdded(int handle)
{
Log.Debug($"ProcessExpertAdded: {handle}");
@@ -3260,7 +3254,7 @@ namespace MtApi
if (added)
{
var quote = GetQuote(handle);
var quote = GetQuote(Client, handle);
if (quote != null)
{
lock (_locker)
@@ -3295,19 +3289,19 @@ namespace MtApi
QuoteRemoved?.Invoke(this, new MtQuoteEventArgs(quote));
}
private MtQuote? GetQuote(int expertHandle)
private MtQuote? GetQuote(MtRpcClient? client, int expertHandle)
{
Log.Debug($"GetQuote: expertHandle = {expertHandle}");
var e = SendCommand<MtRpcQuote>(expertHandle, MtCommandType.GetQuote);
if (e == null || string.IsNullOrEmpty(e.Instrument) || e.Tick == null)
var q = SendCommand<MtRpcQuote>(client, expertHandle, MtCommandType.GetQuote);
if (q == null || string.IsNullOrEmpty(q.Instrument) || q.Tick == null)
return null;
MtQuote quote = new()
{
Instrument = e.Instrument,
Bid = e.Tick.Bid,
Ask = e.Tick.Ask,
Instrument = q.Instrument,
Bid = q.Tick.Bid,
Ask = q.Tick.Ask,
ExpertHandle = expertHandle,
};
+3 -3
View File
@@ -3,8 +3,8 @@
public class MqlParam
{
public ENUM_DATATYPE DataType { get; set; }
public long? IntegerValue { get; set; }
public double? DoubleValue { get; set; }
public string? StringValue { get; set; }
public long IntegerValue { get; set; } = 0;
public double DoubleValue { get; set; } = 0.0;
public string StringValue { get; set; } = String.Empty;
}
}
+46 -60
View File
@@ -31,7 +31,6 @@ namespace MtApi5
private HashSet<int> _experts = [];
private Dictionary<int, Mt5Quote> _quotes = [];
private readonly EventWaitHandle _quotesWaiter = new AutoResetEvent(false);
#endregion
#region Public Methods
@@ -94,17 +93,13 @@ namespace MtApi5
{
if (_connectionState == Mt5ConnectionState.Connected
|| _connectionState == Mt5ConnectionState.Connecting)
{
return;
}
_connectionState = Mt5ConnectionState.Connecting;
}
ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connecting, $"Connecting to {host}:{port}"));
var client = new MtRpcClient(host, port, new RpcClientLogger(Log));
client.ExpertList += Client_ExpertList;
client.ExpertAdded += Client_ExpertAdded;
client.ExpertRemoved += Client_ExpertRemoved;
client.MtEventReceived += Client_MtEventReceived;
@@ -115,13 +110,42 @@ namespace MtApi5
{
await client.Connect();
Log.Info($"Connected to {host}:{port}");
var experts = client.RequestExpertsList();
if (experts == null || experts.Count == 0)
{
var errorMessage = "Failed to load expert list";
Log.Error(errorMessage);
client.Disconnect();
ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Failed, errorMessage));
throw new Exception($"Connection to {host}:{port} failed. Error: {errorMessage}");
}
// Load quotes
Dictionary<int, Mt5Quote> quotes = [];
foreach (var handle in experts)
{
var quote = GetQuote(client, handle);
if (quote != null)
quotes[handle] = quote;
}
lock (_locker)
{
_client = client;
_experts = experts;
_quotes = quotes;
if (_executorHandle == 0)
_executorHandle = (_experts.Count > 0) ? _experts.ElementAt(0) : 0;
_connectionState = Mt5ConnectionState.Connected;
}
client.NotifyClientReady();
if (IsTesting())
BacktestingReady();
ConnectionStateChanged?.Invoke(this, new Mt5ConnectionEventArgs(Mt5ConnectionState.Connected, $"Connected to {host}:{port}"));
QuoteList?.Invoke(this, new(quotes.Values.ToList()));
}
catch (Exception e)
{
@@ -154,14 +178,10 @@ namespace MtApi5
}
///<summary>
///Load quotes connected into MetaTrader API (deprecated)
///Load quotes connected into MetaTrader API
///</summary>
public IEnumerable<Mt5Quote> GetQuotes()
{
// this function is deprecated.
// should be used event OnQuoteList
_quotesWaiter.WaitOne(10000); // wait 10 sec for loading all quotes from MetaTrader
lock (_locker)
{
return _quotes.Values.ToList();
@@ -3345,11 +3365,6 @@ namespace MtApi5
Task.Run(() => _mtEventHandlers[(Mt5EventTypes)e.EventType](e.ExpertHandle, e.Payload));
}
private void Client_ExpertList(object? sender, MtExpertListEventArgs e)
{
Task.Run(()=>ProcessExpertList(e.Experts));
}
private void Client_ExpertAdded(object? sender, MtExpertEventArgs e)
{
Task.Run(() => ProcessExpertAdded(e.Expert));
@@ -3360,39 +3375,6 @@ namespace MtApi5
Task.Run(() => ProcessExpertRemoved(e.Expert));
}
private void ProcessExpertList(HashSet<int> experts)
{
if (experts == null || experts.Count == 0)
{
Log.Warn("ProcessExpertList: expert list invalid or empty");
return;
}
Dictionary<int, Mt5Quote> quotes = [];
foreach (var handle in experts)
{
var quote = GetQuote(handle);
if (quote != null)
quotes[handle] = quote;
}
lock (_locker)
{
_experts = experts;
_quotes = quotes;
if (_executorHandle == 0)
_executorHandle = (_experts.Count > 0) ? _experts.ElementAt(0) : 0;
}
_quotesWaiter.Set();
QuoteList?.Invoke(this, new(quotes.Values.ToList()));
if (IsTesting())
{
BacktestingReady();
}
}
private void ProcessExpertAdded(int handle)
{
Log.Debug($"ProcessExpertAdded: {handle}");
@@ -3407,7 +3389,7 @@ namespace MtApi5
if (added)
{
var quote = GetQuote(handle);
var quote = GetQuote(Client, handle);
if (quote != null)
{
lock (_locker)
@@ -3444,23 +3426,23 @@ namespace MtApi5
QuoteRemoved?.Invoke(this, new Mt5QuoteEventArgs(quote));
}
private Mt5Quote? GetQuote(int expertHandle)
private Mt5Quote? GetQuote(MtRpcClient? client, int expertHandle)
{
Log.Debug($"GetQuote: expertHandle = {expertHandle}");
var e = SendCommand<MtQuote>(expertHandle, Mt5CommandType.GetQuote);
if (e == null || string.IsNullOrEmpty(e.Instrument) || e.Tick == null)
var q = SendCommand<MtQuote>(client, expertHandle, Mt5CommandType.GetQuote);
if (q == null || string.IsNullOrEmpty(q.Instrument) || q.Tick == null)
return null;
Mt5Quote quote = new()
{
Instrument = e.Instrument,
Bid = e.Tick.Bid,
Ask = e.Tick.Ask,
Instrument = q.Instrument,
Bid = q.Tick.Bid,
Ask = q.Tick.Ask,
ExpertHandle = expertHandle,
Volume = e.Tick.Volume,
Time = Mt5TimeConverter.ConvertFromMtTime(e.Tick.Time),
Last = e.Tick.Last
Volume = q.Tick.Volume,
Time = Mt5TimeConverter.ConvertFromMtTime(q.Tick.Time),
Last = q.Tick.Last
};
return quote;
@@ -3572,7 +3554,11 @@ namespace MtApi5
private T? SendCommand<T>(int expertHandle, Mt5CommandType commandType, object? payload = null)
{
var client = Client;
return SendCommand<T>(Client, expertHandle, commandType, payload);
}
private T? SendCommand<T>(MtRpcClient? client, int expertHandle, Mt5CommandType commandType, object? payload = null)
{
if (client == null)
{
Log.Warn("SendCommand: No connection");
+38 -33
View File
@@ -1,5 +1,4 @@
using System.Diagnostics;
using System.Net.WebSockets;
using System.Net.WebSockets;
using System.Text;
namespace MtClient
@@ -68,7 +67,7 @@ namespace MtClient
public string? SendCommand(int expertHandle, int commandType, string payload)
{
CommandTask commandTask = new();
CommandTask<string> commandTask = new();
int commandId;
lock (tasks_)
{
@@ -88,10 +87,24 @@ namespace MtClient
return response;
}
public void NotifyClientReady()
public HashSet<int>? RequestExpertsList()
{
CommandTask<object> notificationTask = new();
lock (notification_tasks_)
{
notification_tasks_[MtNotificationType.ClientReady] = notificationTask;
}
MtNotification notification = new(MtNotificationType.ClientReady);
Send(notification);
var response = notificationTask.WaitResponse(10000); // 10 sec
lock (notification_tasks_)
{
notification_tasks_.Remove(MtNotificationType.ClientReady);
}
return response as HashSet<int>;
}
private void Send(MtMessage message)
@@ -118,7 +131,7 @@ namespace MtClient
{
sendWaiter_.WaitOne();
continue;
}
}
try
{
@@ -166,30 +179,12 @@ namespace MtClient
else if (result.MessageType == WebSocketMessageType.Text)
{
var msg = Encoding.UTF8.GetString(ms.ToArray(), 0, recvCount);
//var msg = Encoding.ASCII.GetString(recvBuffer, 0, result.Count);
OnReceive(msg);
}
ms.Seek(0, SeekOrigin.Begin);
ms.Position = 0;
}
}
//byte[] recvBuffer = new byte[64 * 1024];
//while (ws_.State == WebSocketState.Open)
//{
// var result = await ws_.ReceiveAsync(new ArraySegment<byte>(recvBuffer), CancellationToken.None);
// if (result.MessageType == WebSocketMessageType.Close)
// {
// logger_.Info($"MtRpcClient.DoReceive: close signal {result.CloseStatusDescription}");
// Disconnected?.Invoke(this, EventArgs.Empty);
// break;
// }
// else
// {
// var msg = Encoding.ASCII.GetString(recvBuffer, 0, result.Count);
// OnReceive(msg);
// }
//}
}
catch (Exception ex)
{
@@ -216,7 +211,7 @@ namespace MtClient
{
logger_.Warn("MtRpcClient.OnReceive: Invalid message format.");
return;
}
}
MessageType msgType;
try
@@ -250,7 +245,7 @@ namespace MtClient
break;
case MessageType.ExpertList:
if (message is MtExpertListMsg expertListMsg)
ExpertList?.Invoke(this, new(expertListMsg.Experts));
ProcessExpertList(expertListMsg.Experts);
break;
case MessageType.ExpertAdded:
if (message is MtExpertAddedMsg expertAddedMsg)
@@ -273,14 +268,24 @@ namespace MtClient
lock (tasks_)
{
if (tasks_.TryGetValue(commandId, out CommandTask? value))
if (tasks_.TryGetValue(commandId, out CommandTask<string>? value))
value.SetResponse(payload);
}
}
private void ProcessExpertList(HashSet<int> experts)
{
logger_.Debug($"MtRpcClient.ProcessExpertList: experts count - {experts.Count}");
lock (notification_tasks_)
{
if (notification_tasks_.TryGetValue(MtNotificationType.ClientReady, out CommandTask<object>? value))
value.SetResponse(experts);
}
}
public event EventHandler<EventArgs>? ConnectionFailed;
public event EventHandler<EventArgs>? Disconnected;
public event EventHandler<MtExpertListEventArgs>? ExpertList;
public event EventHandler<MtExpertEventArgs>? ExpertAdded;
public event EventHandler<MtExpertEventArgs>? ExpertRemoved;
public event EventHandler<MtEventArgs>? MtEventReceived;
@@ -288,7 +293,6 @@ namespace MtClient
private readonly ClientWebSocket ws_ = new();
private readonly string host_;
private readonly int port_;
private readonly byte[] buf_ = new byte[10000];
private readonly Queue<MtMessage> pendingMessages_ = [];
private readonly Thread receiveThread_;
@@ -296,18 +300,19 @@ namespace MtClient
private readonly EventWaitHandle sendWaiter_ = new AutoResetEvent(false);
private int nextCommandId = 0;
private readonly Dictionary<int, CommandTask> tasks_ = [];
private readonly Dictionary<int, CommandTask<string>> tasks_ = [];
private readonly Dictionary<MtNotificationType, CommandTask<object>> notification_tasks_ = [];
private readonly IRpcLogger logger_;
}
internal class CommandTask
internal class CommandTask<T>
{
private readonly EventWaitHandle responseWaiter_ = new AutoResetEvent(false);
private string? response_;
private T? response_;
private readonly object locker_ = new();
public string? WaitResponse(int time)
public T? WaitResponse(int time)
{
responseWaiter_.WaitOne(time);
lock (locker_)
@@ -316,7 +321,7 @@ namespace MtClient
}
}
public void SetResponse(string result)
public void SetResponse(T result)
{
lock (locker_)
{
+1
View File
@@ -1,5 +1,6 @@
#pragma once
#include <string>
#include <thread>
#include <unordered_map>
+609
View File
@@ -0,0 +1,609 @@
import logging
import os
import os.path
import signal
import sys
import time
from functools import partial
from threading import Thread
import mt5enums
from mt5apiclient import Mt5ApiClient
logger = logging.getLogger(__name__)
def signal_handler(mtapi, _, __):
del __
if mtapi.is_connected():
mtapi.disconnect()
class Mt5ApiApp:
def __init__(self, address, port):
self.__address = address
self.__port = port
self.cmd_functions = {
"AccountInfoDouble": self.process_account_info_double,
"AccountInfoInteger": self.process_account_info_integer,
"AccountInfoString": self.process_account_info_string,
"SeriesInfoInteger": self.process_series_info_integer,
"Bars": self.process_bars,
"BarsPeriod": self.process_bars_period,
"BarsCalculated": self.process_bars_calculated,
"IndicatorCreate": self.process_indicator_create,
"IndicatorRelease": self.process_indicator_release,
"SymbolsTotal": self.process_symbols_total,
"SymbolName": self.process_symbol_name,
"SymbolSelect": self.process_symbol_select,
"SymbolIsSynchronized": self.process_symbol_is_synchronized,
"SymbolInfoDouble": self.process_symbol_info_double,
"SymbolInfoInteger": self.process_symbol_info_integer,
"SymbolInfoString": self.process_symbol_info_string,
"SymbolInfoTick": self.process_symbol_info_tick,
"SymbolInfoSessionQuote": self.process_symbol_info_session_quote,
"SymbolInfoSessionTrade": self.process_symbol_info_session_trade,
"MarketBookAdd": self.process_market_book_add,
"MarketBookRelease": self.process_market_book_release,
"MarketBookGet": self.process_market_book_get,
"CopyBuffer": self.process_copy_buffer,
"CopyRates": self.process_copy_rates,
"CopyTime": self.process_copy_time,
"CopyOpen": self.process_copy_open,
"CopyHigh": self.process_copy_high,
"CopyLow": self.process_copy_low,
"CopyClose": self.process_copy_close,
"CopyTickVolume": self.process_copy_tick_volume,
"CopyRealVolume": self.process_copy_real_volume,
"CopySpread": self.process_copy_spread,
"CopyTicks": self.process_copy_ticks,
"ChartId": self.process_chart_id,
"ChartRedraw": self.process_chart_redraw,
"ChartApplyTemplate": self.process_chart_apply_template,
"ChartSaveTemplate": self.process_chart_save_template,
"ChartWindowFind": self.process_chart_window_find,
"ChartTimePriceToXY": self.process_chart_time_price_to_xy,
"ChartXYToTimePrice": self.process_chart_xy_to_time_price,
"ChartOpen": self.process_chart_open,
"ChartFirst": self.process_chart_first,
"ChartNext": self.process_chart_next,
"ChartClose": self.process_chart_close,
"ChartSymbol": self.process_chart_symbol,
"ChartPeriod": self.process_chart_period,
"ChartSetDouble": self.process_chart_set_double,
"ChartSetInteger": self.process_chart_set_integer,
"ChartSetString": self.process_chart_set_string,
"ChartGetDouble": self.process_chart_get_double,
"ChartGetInteger": self.process_chart_get_integer,
}
def on_disconnect(self, error_msg=None):
if error_msg is not None:
print(f"> Disconnected with error: {error_msg}")
else:
print("> Normal disconnected")
os.kill(os.getpid(), signal.SIGINT)
def on_quote_update(self, quote):
print(f"> update quote: {quote}")
def on_quote_added(self, quote):
print(f"> added quote: {quote}")
def on_quote_removed(self, quote):
print(f"> removed quote: {quote}")
def on_book_event(self, expert_handle, symbol):
print(f"> received book event: {expert_handle} - {symbol}")
def on_last_time_bar(self, expert_handle, instrument, rates):
print(f"> received last time bar event: {expert_handle} - {instrument}, {rates}")
def on_trade_transaction(self, expert_handle, trade_transaction, trade_request, trade_result):
print(
f"> received trade transaction event: {expert_handle} - {trade_transaction}, {trade_request}, {trade_result}"
)
def process_command(self, mtapi, command):
pieces = command.split(" ", 1)
if len(pieces) == 0 or len(pieces) > 2:
print(f"! Invalid command format: {command.rstrip()}")
return
command_name = pieces[0].rstrip()
if command_name not in self.cmd_functions:
print(f"! Unknown command: '{command_name}'")
return
if len(pieces) == 1:
pieces.append("")
params = pieces[1].rstrip()
try:
self.cmd_functions[command_name](mtapi, params)
except Exception as e:
print(f"Failed to process command {command.rstrip()}: {e}")
def process_account_info_double(self, mtapi, parameters):
property_id = mt5enums.ENUM_ACCOUNT_INFO_DOUBLE(int(parameters))
result = mtapi.account_info_double(property_id)
print(f"> AccountInfoDouble {property_id}: result = {result}")
def process_account_info_integer(self, mtapi, parameters):
property_id = mt5enums.ENUM_ACCOUNT_INFO_INTEGER(int(parameters))
value = mtapi.account_info_integer(property_id)
print(f"> AccountInfoInteger {property_id}: response = {value}")
def process_account_info_string(self, mtapi, parameters):
property_id = mt5enums.ENUM_ACCOUNT_INFO_STRING(int(parameters))
result = mtapi.account_info_string(property_id)
print(f"> AccountInfoString {property_id}: result = {result}")
def process_series_info_integer(self, mtpapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command SeriesInfoInteger: {parameters}")
return
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
prop_id = mt5enums.ENUM_SERIES_INFO_INTEGER(int(pieces[2]))
result = mtpapi.series_info_integer(pieces[0], timeframe, prop_id)
print(f"> SeriesInfoInteger: result = {result}")
def process_bars(self, mtpapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
print(f"! Invalid parameters for command Bars: {parameters}")
return
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
result = mtpapi.bars(pieces[0], timeframe)
print(f"> Bars: result = {result}")
def process_bars_period(self, mtpapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command BarsPeriod: {parameters}")
return
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_time = int(pieces[2])
stop_time = int(pieces[3])
result = mtpapi.bars_period(pieces[0], timeframe, start_time, stop_time)
print(f"> Bars: result = {result}")
def process_bars_calculated(self, mtpapi, parameters):
if not parameters:
print(f"! Invalid parameters for command BarsCalculated: {parameters}")
return
indicator_handle = int(parameters)
result = mtpapi.bars_calculated(indicator_handle)
print(f"> BarsCalculated: result = {result}")
def process_indicator_create(self, mtpapi, parameters):
pieces = parameters.split(" ")
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command IndicatorCreate: {parameters}")
return
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
indicator_type = mt5enums.ENUM_INDICATOR(int(pieces[2]))
result = mtpapi.indicator_create(pieces[0], timeframe, indicator_type)
print(f"> IndicatorCreate: result = {result}")
def process_indicator_release(self, mtpapi, parameters):
if not parameters:
print(f"! Invalid parameters for command IndicatorRelease: {parameters}")
return
indicator_handle = int(parameters)
result = mtpapi.indicator_release(indicator_handle)
print(f"> IndicatorRelease: response = {result}")
def process_symbols_total(self, mtpapi, parameters):
if not parameters or len(parameters) == 0:
print(f"! Invalid parameters for command SymbolsTotal: {parameters}")
return
selected = parameters == "True"
result = mtpapi.symbols_total(selected)
print(f"> SymbolsTotal: response = {result}")
def process_symbol_name(self, mtpapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1] or len(pieces[1]) == 0:
print(f"! Invalid parameters for command SymbolName: {parameters}")
return
pos = int(pieces[0])
selected = pieces[1] == "True"
result = mtpapi.symbol_name(pos, selected)
print(f"> SymbolName: response = {result}")
def process_symbol_select(self, mtpapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1] or len(pieces[1]) == 0:
print(f"! Invalid parameters for command SymbolSelect: {parameters}")
return
selected = pieces[1] == "True"
result = mtpapi.symbol_select(pieces[0], selected)
print(f"> SymbolSelect: response = {result}")
def process_symbol_is_synchronized(self, mtpapi, parameters):
if not parameters or len(parameters) == 0:
print(f"! Invalid parameters for command SymbolIsSynchronized: {parameters}")
return
symbol = parameters
result = mtpapi.symbol_is_synchronized(symbol)
print(f"> SymbolIsSynchronized: response = {result}")
def process_symbol_info_double(self, mtapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
print(f"! Invalid parameters for command SymbolInfoDouble: {parameters}")
return
symbol = pieces[0]
prop_id = mt5enums.ENUM_SYMBOL_INFO_DOUBLE(int(pieces[1]))
result = mtapi.symbol_info_double(symbol, prop_id)
print(f"> SymbolInfoDouble: response = {result}")
def process_symbol_info_integer(self, mtapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
print(f"! Invalid parameters for command SymbolInfoInteger: {parameters}")
return
symbol = pieces[0]
prop_id = mt5enums.ENUM_SYMBOL_INFO_INTEGER(int(pieces[1]))
result = mtapi.symbol_info_integer(symbol, prop_id)
print(f"> SymbolInfoInteger: response = {result}")
def process_symbol_info_string(self, mtapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
print(f"! Invalid parameters for command SymbolInfoString: {parameters}")
return
symbol = pieces[0]
prop_id = mt5enums.ENUM_SYMBOL_INFO_STRING(int(pieces[1]))
result = mtapi.symbol_info_string(symbol, prop_id)
print(f"> SymbolInfoString: response = {result}")
def process_symbol_info_tick(self, mtapi, parameters):
if len(parameters) == 0:
print(f"! Invalid parameters for command SymbolInfoTick: {parameters} - {len(parameters)}")
return
symbol = parameters
result = mtapi.symbol_info_tick(symbol)
print(f"> SymbolInfoTick: response = {result}")
def process_symbol_info_session_quote(self, mtapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command SymbolInfoSessionQuote: {parameters}")
return
symbol = pieces[0]
day_of_week = mt5enums.ENUM_DAY_OF_WEEK(int(pieces[1]))
session_index = int(pieces[2])
result = mtapi.symbol_info_session_quote(symbol, day_of_week, session_index)
print(f"> SymbolInfoSessionQuote: response = {result}")
def process_symbol_info_session_trade(self, mtapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command SymbolInfoSessionTrade: {parameters}")
return
symbol = pieces[0]
day_of_week = mt5enums.ENUM_DAY_OF_WEEK(int(pieces[1]))
session_index = int(pieces[2])
result = mtapi.symbol_info_session_trade(symbol, day_of_week, session_index)
print(f"> SymbolInfoSessionTrade: response = {result}")
def process_market_book_add(self, mtapi, parameters):
if len(parameters) == 0:
print(f"! Invalid parameters for command MarketBookAdd: {parameters} - {len(parameters)}")
return
symbol = parameters
result = mtapi.market_book_add(symbol)
print(f"> MarketBookAdd: response = {result}")
def process_market_book_release(self, mtapi, parameters):
if len(parameters) == 0:
print(f"! Invalid parameters for command MarketBookRelease: {parameters} - {len(parameters)}")
return
symbol = parameters
result = mtapi.market_book_release(symbol)
print(f"> MarketBookRelease: response = {result}")
def process_market_book_get(self, mtapi, parameters):
if len(parameters) == 0:
print(f"! Invalid parameters for command MarketBookGet: {parameters} - {len(parameters)}")
return
symbol = parameters
result = mtapi.market_book_get(symbol)
print(f"> MarketBookGet: response = {result}")
def process_copy_buffer(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyBuffer: {parameters}")
return
indicator_handle = int(pieces[0])
buffer_num = int(pieces[1])
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_buffer(indicator_handle, buffer_num, start_pos, count)
print(f"> CopyBuffer: response = {result}")
def process_copy_rates(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyRates: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_rates(symbol_name, timeframe, start_pos, count)
print(f"> CopyRates: response = {result}")
def process_copy_time(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyTime: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_time(symbol_name, timeframe, start_pos, count)
print(f"> CopyTime: response = {result}")
def process_copy_open(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyOpen: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_open(symbol_name, timeframe, start_pos, count)
print(f"> CopyOpen: response = {result}")
def process_copy_high(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyHigh: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_high(symbol_name, timeframe, start_pos, count)
print(f"> CopyHigh: response = {result}")
def process_copy_low(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyLow: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_low(symbol_name, timeframe, start_pos, count)
print(f"> CopyLow: response = {result}")
def process_copy_close(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyClose: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_close(symbol_name, timeframe, start_pos, count)
print(f"> CopyClose: response = {result}")
def process_copy_tick_volume(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyTickVolume: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_tick_volume(symbol_name, timeframe, start_pos, count)
print(f"> CopyTickVolume: response = {result}")
def process_copy_real_volume(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyRealVolume: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_real_volume(symbol_name, timeframe, start_pos, count)
print(f"> CopyRealVolume: response = {result}")
def process_copy_spread(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopySpread: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
start_pos = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_spread(symbol_name, timeframe, start_pos, count)
print(f"> CopySpread: response = {result}")
def process_copy_ticks(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command CopyTicks: {parameters}")
return
symbol_name = pieces[0]
timeframe = mt5enums.CopyTicksFlag(int(pieces[1]))
from_date = int(pieces[2])
count = int(pieces[3])
result = mtapi.copy_ticks(symbol_name, timeframe, from_date, count)
print(f"> CopyTicks: response = {result}")
def process_chart_id(self, mtapi, parameters):
result = mtapi.chart_id(int(parameters))
print(f"> ChatId: response = {result}")
def process_chart_redraw(self, mtapi, parameters):
mtapi.chart_redraw(int(parameters))
print(f"> ChartRedraw: success")
def process_chart_apply_template(self, mtapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
print(f"! Invalid parameters for command ChartApplyTemplate: {parameters}")
return
result = mtapi.chart_apply_template(int(pieces[0]), pieces[1])
print(f"> ChartApplyTemplate: response = {result}")
def process_chart_save_template(self, mtapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
print(f"! Invalid parameters for command ChartSaveTemplate: {parameters}")
return
result = mtapi.chart_save_template(int(pieces[0]), pieces[1])
print(f"> ChartSaveTemplate: response = {result}")
def process_chart_window_find(self, mtapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
print(f"! Invalid parameters for command ChartWindowFind: {parameters}")
return
result = mtapi.chart_window_find(int(pieces[0]), pieces[1])
print(f"> ChartWindowFind: response = {result}")
def process_chart_time_price_to_xy(self, mtapi, parameters):
pieces = parameters.split(" ", 3)
if len(pieces) != 4 or not pieces[0] or not pieces[1] or not pieces[2] or not pieces[3]:
print(f"! Invalid parameters for command ChartTimePriceToXY: {parameters}")
return
result = mtapi.chart_time_price_to_xy(int(pieces[0]), int(pieces[1]), int(pieces[2]), float(pieces[3]))
print(f"> ChartTimePriceToXY: response = {result}")
def process_chart_xy_to_time_price(self, mtapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command ChartXYToTimePrice: {parameters}")
return
result = mtapi.chart_xy_to_time_price(int(pieces[0]), int(pieces[1]), int(pieces[2]))
print(f"> ChartXYToTimePrice: response = {result}")
def process_chart_open(self, mtapi, parameters):
pieces = parameters.split(" ", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
print(f"! Invalid parameters for command ChartOpen: {parameters}")
return
period = mt5enums.ENUM_TIMEFRAMES(int(pieces[1]))
result = mtapi.chart_open(pieces[0], period)
print(f"> ChartOpen: response = {result}")
def process_chart_first(self, mtapi, _):
result = mtapi.chart_first()
print(f"> ChartFirst: response = {result}")
def process_chart_next(self, mtapi, parameters):
result = mtapi.chart_next(int(parameters))
print(f"> ChartNext: response = {result}")
def process_chart_close(self, mtapi, parameters):
result = mtapi.chart_close(int(parameters))
print(f"> ChartClose: response = {result}")
def process_chart_symbol(self, mtapi, parameters):
result = mtapi.chart_symbol(int(parameters))
print(f"> ChartSymbol: response = {result}")
def process_chart_period(self, mtapi, parameters):
result = mtapi.chart_period(int(parameters))
print(f"> ChartPeriod: response = {result}")
def process_chart_set_double(self, mtapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command ChartSetDouble: {parameters}")
return
prop_id = mt5enums.ENUM_CHART_PROPERTY_DOUBLE(int(pieces[1]))
result = mtapi.chart_set_double(int(pieces[0]), prop_id, float(pieces[2]))
print(f"> ChartSetDouble: response = {result}")
def process_chart_set_integer(self, mtapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command ChartSetInteger: {parameters}")
return
prop_id = mt5enums.ENUM_CHART_PROPERTY_INTEGER(int(pieces[1]))
result = mtapi.chart_set_integer(int(pieces[0]), prop_id, int(pieces[2]))
print(f"> ChartSetInteger: response = {result}")
def process_chart_set_string(self, mtapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command ChartSetString: {parameters}")
return
prop_id = mt5enums.ENUM_CHART_PROPERTY_STRING(int(pieces[1]))
result = mtapi.chart_set_string(int(pieces[0]), prop_id, pieces[2])
print(f"> ChartSetString: response = {result}")
def process_chart_get_double(self, mtapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command ChartGetDouble: {parameters}")
return
prop_id = mt5enums.ENUM_CHART_PROPERTY_DOUBLE(int(pieces[1]))
result = mtapi.chart_get_double(int(pieces[0]), prop_id, int(pieces[2]))
print(f"> ChartGetDouble: response = {result}")
def process_chart_get_integer(self, mtapi, parameters):
pieces = parameters.split(" ", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
print(f"! Invalid parameters for command ChartGetInteger: {parameters}")
return
prop_id = mt5enums.ENUM_CHART_PROPERTY_INTEGER(int(pieces[1]))
result = mtapi.chart_get_integer(int(pieces[0]), prop_id, int(pieces[2]))
print(f"> ChartGetInteger: response = {result}")
def mtapi_command_thread(self, mtapi):
while mtapi.is_connected():
filename = "client.cmd"
if os.path.isfile(filename):
f = open("client.cmd", "r")
command = f.read()
f.close()
os.remove(filename)
self.process_command(mtapi, command)
time.sleep(0.5)
def run(self):
with Mt5ApiClient(self.__address, self.__port, self) as mtapi:
print(f"> Connected to {self.__address}:{self.__port}")
signal.signal(signal.SIGINT, partial(signal_handler, mtapi))
quotes = mtapi.get_quotes()
print(f"> quotes: {quotes}")
command_thread = Thread(target=self.mtapi_command_thread, args=(mtapi,))
command_thread.start()
while mtapi.is_connected():
signal.pause()
command_thread.join()
def main():
logging.basicConfig(filename="client.log", filemode="w", level=logging.DEBUG)
logger.info("Started")
args_num = len(sys.argv)
if args_num != 3:
print("Incorrect arguments. For using input:\n\tclient <address> <port>")
exit(1)
address = sys.argv[1]
port = int(sys.argv[2])
app = Mt5ApiApp(address, port)
app.run()
if __name__ == "__main__":
main()
+685
View File
@@ -0,0 +1,685 @@
import asyncio
import json
import logging
from enum import IntEnum
from threading import Lock, Thread
from mt5commandtype import Mt5CommandType
from mt5enums import *
from mtrpcclient import MtRpcClient
class Mt5EventType(IntEnum):
OnTradeTransaction = 1
OnBookEvent = 2
OnTick = 3
OnLastTimeBar = 4
OnLockTicks = 5
class Mt5Quote:
def __init__(self, quote_json):
self.instrument = quote_json["Instrument"]
self.expert_handle = quote_json["ExpertHandle"]
self.bid = quote_json["Tick"]["Bid"]
self.ask = quote_json["Tick"]["Ask"]
self.volume = quote_json["Tick"]["Volume"]
def __repr__(self):
return f"{self.expert_handle}-{self.instrument}: Bid = {self.bid}, Ask = {self.ask}, Volume = {self.volume}"
class MqlTick:
def __init__(self, tick_json):
self.bid = tick_json["Bid"]
self.ask = tick_json["Ask"]
self.last = tick_json["Last"]
self.volume = tick_json["Volume"]
self.time = tick_json["Time"]
def __repr__(self):
return f"Bid = {self.bid}, Ask = {self.ask}, Last = {self.last}, Volume = {self.volume}, Time = {self.time}"
class MqlRates:
def __init__(self, mql_rates_json):
self.time = mql_rates_json["mt_time"]
self.open = mql_rates_json["open"]
self.high = mql_rates_json["high"]
self.low = mql_rates_json["low"]
self.close = mql_rates_json["close"]
self.tick_volume = mql_rates_json["tick_volume"]
self.spread = mql_rates_json["spread"]
self.real_volume = mql_rates_json["real_volume"]
def __repr__(self):
return f"time = {self.time}, open = {self.open}, high = {self.high}, low = {self.low}, close = {self.close}, tick_volume = {self.tick_volume}, spread = {self.spread}, real_volume = {self.real_volume}"
class MqlTradeTransaction:
def __init__(self, mql_trade_transaction_json):
self.deal = mql_trade_transaction_json["Deal"]
self.order = mql_trade_transaction_json["Order"]
self.symbol = mql_trade_transaction_json["Symbol"]
self.transaction_type = mql_trade_transaction_json["Type"]
self.order_type = mql_trade_transaction_json["OrderType"]
self.order_state = mql_trade_transaction_json["OrderState"]
self.deal_type = mql_trade_transaction_json["DealType"]
self.time_type = mql_trade_transaction_json["TimeType"]
self.price = mql_trade_transaction_json["Price"]
self.price_trigger = mql_trade_transaction_json["PriceTrigger"]
self.price_sl = mql_trade_transaction_json["PriceSl"]
self.price_tp = mql_trade_transaction_json["PriceTp"]
self.volume = mql_trade_transaction_json["Volume"]
self.position = mql_trade_transaction_json["Position"]
self.position_by = mql_trade_transaction_json["PositionBy"]
self.time_expiration = mql_trade_transaction_json["MtTimeExpiration"]
def __repr__(self):
return (
f"deal = {self.deal}, order = {self.order}, symbol = {self.symbol}, transaction_type = {self.transaction_type}, "
f"order_type = {self.order_type}, order_state = {self.order_state}, deal_type = {self.deal_type}, time_type = {self.time_type}, "
f"price = {self.price}, price_trigger = {self.price_trigger}, price_sl = {self.price_sl}, price_tp = {self.price_tp}, volume = {self.volume}, "
f"position = {self.position}, position_by = {self.position_by}, time_expiration = {self.time_expiration}"
)
class MqlTradeRequest:
def __init__(self, mql_trade_request_json):
self.action = mql_trade_request_json["Action"]
self.magic = mql_trade_request_json["Magic"]
self.order = mql_trade_request_json["Order"]
self.symbol = mql_trade_request_json["Symbol"]
self.volume = mql_trade_request_json["Volume"]
self.price = mql_trade_request_json["Price"]
self.stop_limit = mql_trade_request_json["Stoplimit"]
self.sl = mql_trade_request_json["Sl"]
self.tp = mql_trade_request_json["Tp"]
self.deviation = mql_trade_request_json["Deviation"]
self.order_type = mql_trade_request_json["Type"]
self.type_filling = mql_trade_request_json["Type_filling"]
self.type_time = mql_trade_request_json["Type_time"]
self.expiration = mql_trade_request_json["MtExpiration"]
self.comment = mql_trade_request_json["Comment"]
# self.position = mql_trade_request_json["Position"]
# self.position_by = mql_trade_request_json["PositionBy"]
def __repr__(self):
return (
f"action = {self.action}, magic = {self.magic}, order = {self.order}, symbol = {self.symbol}, volume = {self.volume}, "
f"price = {self.price}, stop_limit = {self.stop_limit}, sl = {self.sl}, tp = {self.tp}, deviation = {self.deviation}, "
f"order_type = {self.order_type}, type_filling = {self.type_filling}, type_time = {self.type_time}, expiration = {self.expiration}, "
f"comment = {self.comment}"
)
class MqlTradeResult:
def __init__(self, mql_trade_result_json):
self.retcode = mql_trade_result_json["Retcode"]
self.deal = mql_trade_result_json["Deal"]
self.order = mql_trade_result_json["Order"]
self.volume = mql_trade_result_json["Volume"]
self.price = mql_trade_result_json["Price"]
self.bid = mql_trade_result_json["Bid"]
self.ask = mql_trade_result_json["Ask"]
self.comment = mql_trade_result_json["Comment"]
self.request_id = mql_trade_result_json["Request_id"]
def __repr__(self):
return (
f"retcode = {self.retcode}, deal = {self.deal}, order = {self.order}, volume = {self.volume}, price = {self.price}, "
f"bid = {self.bid}, ask = {self.ask}, comment = {self.comment}, request_id = {self.request_id}"
)
class MqlBookInfo:
def __init__(self, mql_book_info):
self.book_type = ENUM_BOOK_TYPE(mql_book_info["type"])
self.price = mql_book_info["price"]
self.volume = mql_book_info["volume"]
self.volume_real = mql_book_info["volume_real"]
def __repr__(self):
return f"book_type = {self.book_type}, price = {self.price}, volume = {self.volume}, volume_real = {self.volume_real}"
class Mt5ApiClient:
def __init__(self, address, port, callback=None):
self.__address = address
self.__port = port
self.__callback = callback
self.__logger = logging.getLogger(__name__)
self.__rpcclient = MtRpcClient(self)
self.__is_connected = False
self.__quotes = dict()
self.__experts = list()
self.__lock = Lock()
def __enter__(self):
self.connect()
return self
def __exit__(self, *_):
self.disconnect()
def connect(self):
self.__logger.info(f"Connecting to {self.__address}:{self.__port}")
url = f"ws://{self.__address}:{self.__port}"
self.__rpcclient.connect(url)
experts = self.__rpcclient.request_expert_list()
if experts is None:
self.__rpcclient.disconnect()
raise Exception("Failed to load expert list")
self.__logger.info(f"loaded exerts {self.__experts}")
for expert_handle in experts:
quote = self.__get_quote(expert_handle)
if quote is not None:
self.__experts.append(expert_handle)
self.__quotes[expert_handle] = quote
self.__logger.info(f"loaded quotes {self.__quotes}")
# TODO: send backtesting ready
self.__event_loop = asyncio.new_event_loop()
self.__event_thread = Thread(target=self.__event_thread_func)
self.__event_thread.start()
self.__is_connected = True
def disconnect(self):
self.__rpcclient.disconnect()
self.__event_loop.call_soon_threadsafe(self.__event_loop.stop)
self.__event_thread.join()
self.__quotes.clear()
self.__experts.clear()
def is_connected(self):
with self.__lock:
return self.__is_connected
def get_quotes(self):
with self.__lock:
return list(self.__quotes.values())
def is_testing(self):
return False
# Account Information functions
# AccountInfoDouble
def account_info_double(self, property_id: ENUM_ACCOUNT_INFO_DOUBLE):
cmd_params = {"PropertyId": property_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.AccountInfoDouble, cmd_params)
# AccountInfoInteger
def account_info_integer(self, property_id: ENUM_ACCOUNT_INFO_INTEGER):
cmd_params = {"PropertyId": property_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.AccountInfoInteger, cmd_params)
# AccountInfoString
def account_info_string(self, property_id: ENUM_ACCOUNT_INFO_STRING):
cmd_params = {"PropertyId": property_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.AccountInfoString, cmd_params)
# Timeseries and Indicators Access
# SeriesInfoInteger
def series_info_integer(self, symbol_name, timeframe: ENUM_TIMEFRAMES, prop_id: ENUM_SERIES_INFO_INTEGER):
if symbol_name is None:
symbol_name = ""
cmd_params = {"Symbol": symbol_name, "Timeframe": timeframe, "PropId": prop_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.SeriesInfoInteger, cmd_params)
# Bars
def bars(self, symbol_name, timeframe: ENUM_TIMEFRAMES):
if symbol_name is None:
symbol_name = ""
cmd_params = {"Symbol": symbol_name, "Timeframe": timeframe}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.Bars, cmd_params)
# Bars (for a specified period)
def bars_period(self, symbol_name, timeframe: ENUM_TIMEFRAMES, start_time: int, stop_time: int):
if symbol_name is None:
symbol_name = ""
cmd_params = {"Symbol": symbol_name, "Timeframe": timeframe, "StartTime": start_time, "StopTime": stop_time}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.Bars2, cmd_params)
# BarsCalculated
def bars_calculated(self, indicator_handle: int):
cmd_params = {"IndicatorHandle": indicator_handle}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.BarsCalculated, cmd_params)
# CopyBuffer
def copy_buffer(self, indicator_handle: int, buffer_num: int, start_pos: int, count: int):
cmd_params = {
"IndicatorHandle": indicator_handle,
"BufferNum": buffer_num,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyBuffer, cmd_params)
# CopyRates
def copy_rates(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyRates, cmd_params)
rates = [MqlRates(obj) for obj in res]
return rates
# CopyTime
def copy_time(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyTime, cmd_params)
# CopyOpen
def copy_open(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyOpen, cmd_params)
# CopyHigh
def copy_high(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyHigh, cmd_params)
# CopyLow
def copy_low(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyLow, cmd_params)
# CopyClose
def copy_close(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyClose, cmd_params)
# CopyTickVolume
def copy_tick_volume(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyTickVolume, cmd_params)
# CopyRealVolume
def copy_real_volume(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyRealVolume, cmd_params)
# CopySpread
def copy_spread(self, symbol_name: str, timeframe: ENUM_TIMEFRAMES, start_pos: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Timeframe": timeframe,
"StartPos": start_pos,
"Count": count,
}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.CopySpread, cmd_params)
# CopyTicks
def copy_ticks(self, symbol_name: str, flags: CopyTicksFlag, from_date: int, count: int):
cmd_params = {
"Symbol": symbol_name,
"Flags": flags,
"From": from_date,
"Count": count,
}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.CopyTicks, cmd_params)
if res is None:
return None
ticks = [MqlTick(obj) for obj in res]
return ticks
# IndicatorCreate
def indicator_create(
self, symbol: str, period: ENUM_TIMEFRAMES, indicator_type: ENUM_INDICATOR, parameters: list = []
):
cmd_params = {"Period": period, "IndicatorType": indicator_type}
if symbol is not None:
cmd_params["Symbol"] = symbol
if len(parameters) != 0:
cmd_params["Parameters"] = parameters
return self.__send_command(self.__get_default_expert(), Mt5CommandType.IndicatorCreate, cmd_params)
# IndicatorRelease
def indicator_release(self, indicator_handle: int):
cmd_params = {"IndicatorHandle": indicator_handle}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.IndicatorRelease, cmd_params)
# Market Info
# SymbolsTotal
def symbols_total(self, selected: bool):
cmd_params = {"Selected": selected}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolsTotal, cmd_params)
# SymbolName
def symbol_name(self, pos: int, selected: bool):
cmd_params = {"Pos": pos, "Selected": selected}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolName, cmd_params)
# SymbolSelect
def symbol_select(self, symbol_name: str, selected: bool):
cmd_params = {"Symbol": symbol_name, "Selected": selected}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolSelect, cmd_params)
# SymbolIsSynchronized
def symbol_is_synchronized(self, symbol_name: str):
cmd_params = {"Symbol": symbol_name}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolIsSynchronized, cmd_params)
# SymbolInfoDouble
def symbol_info_double(self, symbol_name: str, prop_id: ENUM_SYMBOL_INFO_DOUBLE):
cmd_params = {"Symbol": symbol_name, "PropId": prop_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolInfoDouble, cmd_params)
# SymbolInfoInteger
def symbol_info_integer(self, symbol_name: str, prop_id: ENUM_SYMBOL_INFO_INTEGER):
cmd_params = {"Symbol": symbol_name, "PropId": prop_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolInfoInteger, cmd_params)
# SymbolInfoString
def symbol_info_string(self, symbol_name: str, prop_id: ENUM_SYMBOL_INFO_STRING):
cmd_params = {"Symbol": symbol_name, "PropId": prop_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolInfoString, cmd_params)
# SymbolInoTick
def symbol_info_tick(self, symbol_name: str):
cmd_params = {"Symbol": symbol_name}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolInfoTick, cmd_params)
if res is not None and res["RetVal"] == True:
return MqlTick(res["Result"])
return None
# SymbolInfoSessionQuote
def symbol_info_session_quote(self, name: str, day_of_week: ENUM_DAY_OF_WEEK, session_index: int):
cmd_params = {"Symbol": name, "DayOfWeek": day_of_week, "SessionIndex": session_index}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolInfoSessionQuote, cmd_params)
if res is not None and res["RetVal"] == True:
return (res["Result"]["From"], res["Result"]["To"])
return None
# SymbolInfoSessionTrade
def symbol_info_session_trade(self, name: str, day_of_week: ENUM_DAY_OF_WEEK, session_index: int):
cmd_params = {"Symbol": name, "DayOfWeek": day_of_week, "SessionIndex": session_index}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.SymbolInfoSessionTrade, cmd_params)
if res is not None and res["RetVal"] == True:
return (res["Result"]["From"], res["Result"]["To"])
return None
# MarketBookAdd
def market_book_add(self, symbol: str):
cmd_params = {"Symbol": symbol}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.MarketBookAdd, cmd_params)
# MarketBookRelease
def market_book_release(self, symbol: str):
cmd_params = {"Symbol": symbol}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.MarketBookRelease, cmd_params)
# MarketBookGet
def market_book_get(self, symbol: str):
cmd_params = {"Symbol": symbol}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.MarketBookGet, cmd_params)
# ChartId
def chart_id(self, expert_handle=0):
if expert_handle == 0:
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartId)
else:
return self.__send_command(expert_handle, Mt5CommandType.ChartId)
# ChartRedraw
def chart_redraw(self, chart_id=0):
cmd_params = {"ChartId": chart_id}
self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartRedraw, cmd_params)
# ChartApplyTemplate
def chart_apply_template(self, chart_id, filename: str):
cmd_params = {"ChartId": chart_id, "TemplateFileName": filename}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartApplyTemplate, cmd_params)
# ChartSaveTemplate
def chart_save_template(self, chart_id, filename: str):
cmd_params = {"ChartId": chart_id, "TemplateFileName": filename}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartSaveTemplate, cmd_params)
# ChartWindowFind
def chart_window_find(self, chart_id, indicator_short_name: str):
cmd_params = {"ChartId": chart_id, "IndicatorShortname": indicator_short_name}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartWindowFind, cmd_params)
# ChartTimePriceToXY
def chart_time_price_to_xy(self, chart_id, sub_window, time, price):
cmd_params = {"ChartId": chart_id, "SubWindow": sub_window, "Time": time, "Price": price}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartTimePriceToXY, cmd_params)
if res is not None and res["RetVal"] == True:
return (res["Result"]["X"], res["Result"]["Y"])
return None
# ChartXYToTimePrice
def chart_xy_to_time_price(self, chart_id, x, y):
cmd_params = {"ChartId": chart_id, "X": x, "Y": y}
res = self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartXYToTimePrice, cmd_params)
if res is not None and res["RetVal"] == True:
return (res["Result"]["SubWindow"], res["Result"]["Time"], res["Result"]["Price"])
return None
# ChartOpen
def chart_open(self, symbol: str, period: ENUM_TIMEFRAMES):
cmd_params = {"Symbol": symbol, "Timeframe": period}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartOpen, cmd_params)
# ChartFirst
def chart_first(self):
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartFirst)
# ChartNext
def chart_next(self, chart_id):
cmd_params = {"ChartId": chart_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartNext, cmd_params)
# ChartClose
def chart_close(self, chart_id):
cmd_params = {"ChartId": chart_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartClose, cmd_params)
# ChartSymbol
def chart_symbol(self, chart_id):
cmd_params = {"ChartId": chart_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartSymbol, cmd_params)
# ChartPeriod
def chart_period(self, chart_id):
cmd_params = {"ChartId": chart_id}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartPeriod, cmd_params)
# ChartSetDouble
def chart_set_double(self, chart_id, prop_id: ENUM_CHART_PROPERTY_DOUBLE, value):
cmd_params = {"ChartId": chart_id, "PropId": prop_id, "Value": value}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartSetDouble, cmd_params)
# ChartSetInteger
def chart_set_integer(self, chart_id, prop_id: ENUM_CHART_PROPERTY_INTEGER, value):
cmd_params = {"ChartId": chart_id, "PropId": prop_id, "Value": value}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartSetInteger, cmd_params)
# ChartSetString
def chart_set_string(self, chart_id, prop_id: ENUM_CHART_PROPERTY_STRING, value):
cmd_params = {"ChartId": chart_id, "PropId": prop_id, "Value": value}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartSetString, cmd_params)
# ChartGetDouble
def chart_get_double(self, chart_id, prop_id: ENUM_CHART_PROPERTY_DOUBLE, sub_window=0):
cmd_params = {"ChartId": chart_id, "PropId": prop_id, "SubWindow": sub_window}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartGetDouble, cmd_params)
# ChartGetInteger
def chart_get_integer(self, chart_id, prop_id: ENUM_CHART_PROPERTY_INTEGER, sub_window=0):
cmd_params = {"ChartId": chart_id, "PropId": prop_id, "SubWindow": sub_window}
return self.__send_command(self.__get_default_expert(), Mt5CommandType.ChartGetInteger, cmd_params)
# Private methods
def __event_thread_func(self):
self.__logger.debug(f"__event_thread started")
asyncio.set_event_loop(self.__event_loop)
self.__event_loop.run_forever()
self.__logger.debug(f"__event_thread stopped")
def __get_quote(self, expert_handle):
response = self.__send_command(expert_handle, Mt5CommandType.GetQuote)
quote = Mt5Quote(response) if response is not None else None
return quote
def __get_default_expert(self):
with self.__lock:
if len(self.__experts) > 0:
return self.__experts[0]
return 0
def __send_command(self, expert_handle, command_type, payload=None):
payload_json = None if payload is None else json.dumps(payload)
response = self.__rpcclient.send_command(expert_handle, command_type, payload_json)
if response is None:
self.__logger.warning("Failed to send commad. Result is None")
raise Exception("Failed to send commad. Result is None")
response_json = json.loads(response)
error_code = int(response_json["ErrorCode"])
if error_code != 0:
error_message = response_json["ErrorMessage"]
self.__logger.warning(f"send_command: ErrorCode = {error_code}. {error_message}")
raise Exception(f"Failed to send command: ErrorCode = {error_code}. {error_message} ")
if "Value" in response_json:
return response_json["Value"]
return None
def __process_tick_event(self, payload):
quote_json = json.loads(payload)
if quote_json is not None:
quote = Mt5Quote(quote_json)
with self.__lock:
self.__quotes[quote.expert_handle] = quote
if self.__callback is not None:
self.__callback.on_quote_update(quote)
def __process_event_disconnect(self, error_msg=None):
with self.__lock:
self.__is_connected = False
if self.__callback is not None:
self.__callback.on_disconnect(error_msg)
def __process_expert_added(self, expert_handle):
quote = self.__get_quote(expert_handle)
if quote is not None:
with self.__lock:
self.__quotes[expert_handle] = quote
self.__experts.append(expert_handle)
if self.__callback is not None:
self.__callback.on_quote_added(quote)
def __process_expert_removed(self, expert_handle):
quote = None
with self.__lock:
self.__experts.remove(expert_handle)
if expert_handle in self.__quotes:
quote = self.__quotes.pop(expert_handle)
if quote is not None and self.__callback is not None:
self.__callback.on_quote_removed(quote)
def __process_on_book_event(self, expert_handle, payload):
book_event_json = json.loads(payload)
if book_event_json is None:
self.__logger.error("Failed to parse book event json")
return
symbol = book_event_json["Symbol"]
if self.__callback is not None:
self.__callback.on_book_event(expert_handle, symbol)
def __process_on_last_time_bar(self, expert_handle, payload):
last_time_bar_event_json = json.loads(payload)
if last_time_bar_event_json is None:
self.__logger.error("Failed to parse last time bar event json")
return
instrument = last_time_bar_event_json["Instrument"]
rates = MqlRates(last_time_bar_event_json["Rates"])
if self.__callback is not None:
self.__callback.on_last_time_bar(expert_handle, instrument, rates)
def __process_on_lock_tick(self, expert_handle, payload):
# TODO: must be implemented
self.__logger.warning(f"event type OnLockTicks is not supported. {expert_handle} - {payload}")
def __process_on_trade_transaction(self, expert_handle, payload):
trade_transaction_json = json.loads(payload)
trade_transaction = MqlTradeTransaction(trade_transaction_json["Trans"])
trade_request = MqlTradeRequest(trade_transaction_json["Request"])
trade_result = MqlTradeResult(trade_transaction_json["Result"])
if self.__callback is not None:
self.__callback.on_trade_transaction(expert_handle, trade_transaction, trade_request, trade_result)
# RPC event handlers
def mt_rpc_on_event(self, expert_handle, event_type, payload):
self.__logger.debug(f"received event from {expert_handle}: {event_type}, {payload}")
mt_event_type = Mt5EventType(int(event_type))
if mt_event_type == Mt5EventType.OnTick:
self.__event_loop.call_soon_threadsafe(self.__process_tick_event, payload)
elif mt_event_type == Mt5EventType.OnBookEvent:
self.__event_loop.call_soon_threadsafe(self.__process_on_book_event, expert_handle, payload)
elif mt_event_type == Mt5EventType.OnLastTimeBar:
self.__event_loop.call_soon_threadsafe(self.__process_on_last_time_bar, expert_handle, payload)
elif mt_event_type == Mt5EventType.OnLockTicks:
self.__event_loop.call_soon_threadsafe(self.__process_on_lock_tick, expert_handle, payload)
elif mt_event_type == Mt5EventType.OnTradeTransaction:
self.__event_loop.call_soon_threadsafe(self.__process_on_trade_transaction, expert_handle, payload)
else:
self.__logger.warning(f"received unsupported event {event_type}")
def mt_rcp_on_disconnect(self):
self.__logger.info("normal disconnected")
self.__event_loop.call_soon_threadsafe(self.__process_event_disconnect)
def mt_rpc_on_connection_failed(self, error_msg=None):
self.__logger.info(f"connection failed: {error_msg}")
self.__event_loop.call_soon_threadsafe(self.__process_event_disconnect, error_msg)
def mt_rpc_on_expert_added(self, expert_handle):
self.__logger.info(f"expert added: {expert_handle}")
self.__event_loop.call_soon_threadsafe(self.__process_expert_added, expert_handle)
def mt_rpc_on_expert_removed(self, expert_handle):
self.__logger.info(f"expert removed: {expert_handle}")
self.__event_loop.call_soon_threadsafe(self.__process_expert_removed, expert_handle)
+254
View File
@@ -0,0 +1,254 @@
from enum import IntEnum
class Mt5CommandType(IntEnum):
# NoCommand = 0
GetQuote = 1
#trade operations
OrderCalcMargin = 2
OrderCalcProfit = 3
PositionsTotal = 6
PositionGetSymbol = 7
PositionSelect = 8
PositionGetDouble = 9
PositionGetInteger = 10
PositionGetString = 11
PositionGetTicket = 4
OrdersTotal = 12
OrderGetTicket = 13
OrderSelect = 14
OrderGetDouble = 15
OrderGetInteger = 16
OrderGetString = 17
HistorySelect = 18
HistorySelectByPosition = 19
HistoryOrderSelect = 20
HistoryOrdersTotal = 21
HistoryOrderGetTicket = 22
HistoryOrderGetDouble = 23
HistoryOrderGetInteger = 24
HistoryOrderGetString = 25
HistoryDealSelect = 26
HistoryDealsTotal = 27
HistoryDealGetTicket = 28
HistoryDealGetDouble = 29
HistoryDealGetInteger = 30
HistoryDealGetString = 31
#Account Information
AccountInfoDouble = 32
AccountInfoInteger = 33
AccountInfoString = 34
#Access to Timeseries and Indicator Data
SeriesInfoInteger = 35
Bars = 36
Bars2 = 1036
BarsCalculated = 37
IndicatorCreate = 38
IndicatorRelease = 39
CopyBuffer = 40
CopyBuffer1 = 1040
CopyBuffer2 = 1140
CopyRates = 41
CopyRates1 = 1041
CopyRates2 = 1141
CopyTime = 42
CopyTime1 = 1042
CopyTime2 = 1142
CopyOpen = 43
CopyOpen1 = 1043
CopyOpen2 = 1143
CopyHigh = 44
CopyHigh1 = 1044
CopyHigh2 = 1144
CopyLow = 45
CopyLow1 = 1045
CopyLow2 = 1145
CopyClose = 46
CopyClose1 = 1046
CopyClose2 = 1146
CopyTickVolume = 47
CopyTickVolume1 = 1047
CopyTickVolume2 = 1147
CopyRealVolume = 48
CopyRealVolume1 = 1048
CopyRealVolume2 = 1148
CopySpread = 49
CopySpread1 = 1049
CopySpread2 = 1149
#Market Information
SymbolsTotal = 50
SymbolName = 51
SymbolSelect = 52
SymbolIsSynchronized = 53
SymbolInfoDouble = 54
SymbolInfoInteger = 55
SymbolInfoString = 56
SymbolInfoString2 = 1056
SymbolInfoTick = 57
SymbolInfoSessionQuote = 58
SymbolInfoSessionTrade = 59
MarketBookAdd = 60
MarketBookRelease = 61
MarketBookGet = 62
OrderCloseAll = 63
#CTrade
PositionClose = 64
PositionOpen = 65
PositionOpen2 = 1065
PositionModify = 6066
PositionClosePartial_bySymbol = 6067
PositionClosePartial_byTicket = 6068
#Backtesting
BacktestingReady = 66
IsTesting = 67
PositionSelectByTicket = 69
ObjectCreate = 70
ObjectName = 71
ObjectDelete = 72
ObjectsDeleteAll = 73
ObjectFind = 74
ObjectGetTimeByValue = 75
ObjectGetValueByTime = 76
ObjectMove = 77
ObjectsTotal = 78
ObjectGetDouble = 79
ObjectGetInteger = 80
ObjectGetString = 81
ObjectSetDouble = 82
ObjectSetInteger = 83
ObjectSetString = 84
iAC = 88
iAD = 89
iADX = 90
iADXWilder = 91
iAlligator = 92
iAMA = 93
iAO = 94
iATR = 95
iBearsPower = 96
iBands = 97
iBullsPower = 98
iCCI = 99
iChaikin = 100
iCustom = 101
iDEMA = 102
iDeMarker = 103
iEnvelopes = 104
iForce = 105
iFractals = 106
iFrAMA = 107
iGator = 108
iIchimoku = 109
iBWMFI = 110
iMomentum = 111
iMFI = 112
iMA = 113
iOsMA = 114
iMACD = 115
iOBV = 116
iSAR = 117
iRSI = 118
iRVI = 119
iStdDev = 120
iStochastic = 121
iTEMA = 122
iTriX = 123
iWPR = 124
iVIDyA = 125
iVolumes = 126
#Date and Time
TimeCurrent = 127
TimeTradeServer = 128
TimeLocal = 129
TimeGMT = 130
#Chart Operations
ChartId = 206
ChartRedraw = 207
ChartApplyTemplate = 236
ChartSaveTemplate = 237
ChartWindowFind = 238
ChartTimePriceToXY = 239
ChartXYToTimePrice = 240
ChartOpen = 241
ChartFirst = 242
ChartNext = 243
ChartClose = 244
ChartSymbol = 245
ChartPeriod = 246
ChartSetDouble = 247
ChartSetInteger = 248
ChartSetString = 249
ChartGetDouble = 250
ChartGetInteger = 251
ChartGetString = 252
ChartNavigate = 253
ChartIndicatorDelete = 254
ChartIndicatorName = 255
ChartIndicatorsTotal = 256
ChartWindowOnDropped = 257
ChartPriceOnDropped = 258
ChartTimeOnDropped = 259
ChartXOnDropped = 260
ChartYOnDropped = 261
ChartSetSymbolPeriod = 262
ChartScreenShot = 263
ChartIndicatorAdd = 280
ChartIndicatorGet = 281
# Terminal Operations
TerminalCompany = 68
TerminalName = 69
TerminalPath = 70
#Checkup
GetLastError = 132
TerminalInfoString = 153
TerminalInfoInteger = 204
TerminalInfoDouble = 205
#Common Functions
Alert = 136
Comment = 137
GetTickCount = 138
GetMicrosecondCount = 139
MessageBox = 140
PeriodSeconds = 141
PlaySound = 142
Print = 68
ResetLastError = 143
SendNotification = 144
SendMail = 145
#Global Variables
GlobalVariableCheck = 146
GlobalVariableTime = 147
GlobalVariableDel = 148
GlobalVariableGet = 149
GlobalVariableName = 150
GlobalVariableSet = 151
GlobalVariablesFlush = 152
GlobalVariableTemp = 154
GlobalVariableSetOnCondition = 156
GlobalVariablesDeleteAll = 157
GlobalVariablesTotal = 158
UnlockTicks = 159
PositionCloseAll = 160
TesterStop = 161
CopyTicks = 300
OrderSend = 301
OrderSendAsync = 302
OrderCheck = 303
Buy = 304
Sell = 305
+901
View File
@@ -0,0 +1,901 @@
from enum import IntEnum
# Chart Timeframes
class ENUM_TIMEFRAMES(IntEnum):
PERIOD_CURRENT = 0
PERIOD_M1 = 1
PERIOD_M2 = 2
PERIOD_M3 = 3
PERIOD_M4 = 4
PERIOD_M5 = 5
PERIOD_M6 = 6
PERIOD_M10 = 10
PERIOD_M12 = 12
PERIOD_M15 = 15
PERIOD_M20 = 20
PERIOD_M30 = 30
PERIOD_H1 = 16385
PERIOD_H2 = 16386
PERIOD_H3 = 16387
PERIOD_H4 = 16388
PERIOD_H6 = 16390
PERIOD_H8 = 16392
PERIOD_H12 = 1639
PERIOD_D1 = 16408
PERIOD_W1 = 32769
PERIOD_MN1 = 49153
# Charts Properties
class ENUM_CHART_PROPERTY_DOUBLE(IntEnum):
CHART_SHIFT_SIZE = 3
CHART_FIXED_POSITION = 41
CHART_FIXED_MAX = 8
CHART_FIXED_MIN = 9
CHART_POINTS_PER_BAR = 11
CHART_PRICE_MIN = 108
CHART_PRICE_MAX = 109
class ENUM_CHART_PROPERTY_INTEGER(IntEnum):
CHART_SHOW = 46
CHART_IS_OBJECT = 111
CHART_BRING_TO_TOP = 35
CHART_CONTEXT_MENU = 50
CHART_CROSSHAIR_TOOL = 49
CHART_MOUSE_SCROLL = 42
CHART_EVENT_MOUSE_WHEEL = 48
CHART_EVENT_MOUSE_MOVE = 40
CHART_EVENT_OBJECT_CREATE = 38
CHART_EVENT_OBJECT_DELETE = 39
CHART_MODE = 0
CHART_FOREGROUND = 1
CHART_SHIFT = 2
CHART_AUTOSCROLL = 4
CHART_KEYBOARD_CONTROL = 47
CHART_QUICK_NAVIGATION = 45
CHART_SCALE = 5
CHART_SCALEFIX = 6
CHART_SCALEFIX_11 = 7
CHART_SCALE_PT_PER_BAR = 10
CHART_SHOW_OHLC = 12
CHART_SHOW_BID_LINE = 13
CHART_SHOW_ASK_LINE = 14
CHART_SHOW_LAST_LINE = 15
CHART_SHOW_PERIOD_SEP = 16
CHART_SHOW_GRID = 17
CHART_SHOW_VOLUMES = 18
CHART_SHOW_OBJECT_DESCR = 19
CHART_VISIBLE_BARS = 100
CHART_WINDOWS_TOTAL = 101
CHART_WINDOW_IS_VISIBLE = 102
CHART_WINDOW_HANDLE = 103
CHART_WINDOW_YDISTANCE = 110
CHART_FIRST_VISIBLE_BAR = 104
CHART_WIDTH_IN_BARS = 105
CHART_WIDTH_IN_PIXELS = 106
CHART_HEIGHT_IN_PIXELS = 107
CHART_COLOR_BACKGROUND = 21
CHART_COLOR_FOREGROUND = 22
CHART_COLOR_GRID = 23
CHART_COLOR_VOLUME = 24
CHART_COLOR_CHART_UP = 25
CHART_COLOR_CHART_DOWN = 26
CHART_COLOR_CHART_LINE = 27
CHART_COLOR_CANDLE_BULL = 28
CHART_COLOR_CANDLE_BEAR = 29
CHART_COLOR_BID = 30
CHART_COLOR_ASK = 31
CHART_COLOR_LAST = 32
CHART_COLOR_STOP_LEVEL = 33
CHART_SHOW_TRADE_LEVELS = 34
CHART_DRAG_TRADE_LEVELS = 43
CHART_SHOW_DATE_SCALE = 36
CHART_SHOW_PRICE_SCALE = 37
CHART_SHOW_ONE_CLICK = 44
CHART_IS_MAXIMIZED = 115
CHART_IS_MINIMIZED = 116
class ENUM_CHART_PROPERTY_STRING(IntEnum):
CHART_COMMENT = 20
CHART_EXPERT_NAME = 113
CHART_SCRIPT_NAME = 114
class ENUM_CHART_POSITION(IntEnum):
CHART_BEGIN = 0 # Chart beginning (the oldest prices)
CHART_CURRENT_POS = 1 # Current position
CHART_END = 2 # Chart end (the latest prices)
# Client Terminal Properties
class ENUM_TERMINAL_INFO_INTEGER(IntEnum):
TERMINAL_BUILD = 5
TERMINAL_COMMUNITY_ACCOUNT = 23
TERMINAL_COMMUNITY_CONNECTION = 24
TERMINAL_CONNECTED = 6
TERMINAL_DLLS_ALLOWED = 7
TERMINAL_TRADE_ALLOWED = 8
TERMINAL_EMAIL_ENABLED = 9
TERMINAL_FTP_ENABLED = 10
TERMINAL_NOTIFICATIONS_ENABLED = 26
TERMINAL_MAXBARS = 11
TERMINAL_MQID = 22
TERMINAL_CODEPAGE = 12
TERMINAL_CPU_CORES = 21
TERMINAL_DISK_SPACE = 20
TERMINAL_MEMORY_PHYSICAL = 14
TERMINAL_MEMORY_TOTAL = 15
TERMINAL_MEMORY_AVAILABLE = 16
TERMINAL_MEMORY_USED = 17
TERMINAL_X64 = 18
TERMINAL_OPENCL_SUPPORT = 19
TERMINAL_SCREEN_DPI = 27
TERMINAL_PING_LAST = 29
class ENUM_TERMINAL_INFO_DOUBLE(IntEnum):
TERMINAL_COMMUNITY_BALANCE = 25
class ENUM_TERMINAL_INFO_STRING(IntEnum):
TERMINAL_LANGUAGE = 13
TERMINAL_COMPANY = 0
TERMINAL_NAME = 1
TERMINAL_PATH = 2
TERMINAL_DATA_PATH = 3
TERMINAL_COMMONDATA_PATH = 4
# Symbol Properties
class ENUM_SYMBOL_INFO_INTEGER(IntEnum):
SYMBOL_CUSTOM = 78
SYMBOL_BACKGROUND_COLOR = 79
SYMBOL_CHART_MODE = 80
SYMBOL_SELECT = 0
SYMBOL_VISIBLE = 76
SYMBOL_SESSION_DEALS = 56
SYMBOL_SESSION_BUY_ORDERS = 60
SYMBOL_SESSION_SELL_ORDERS = 62
SYMBOL_VOLUME = 10
SYMBOL_VOLUMEHIGH = 11
SYMBOL_VOLUMELOW = 12
SYMBOL_TIME = 15
SYMBOL_DIGITS = 17
SYMBOL_SPREAD_FLOAT = 41
SYMBOL_SPREAD = 18
SYMBOL_TICKS_BOOKDEPTH = 25
SYMBOL_TRADE_CALC_MODE = 29
SYMBOL_TRADE_MODE = 30
SYMBOL_START_TIME = 51
SYMBOL_EXPIRATION_TIME = 52
SYMBOL_TRADE_STOPS_LEVEL = 31
SYMBOL_TRADE_FREEZE_LEVEL = 32
SYMBOL_TRADE_EXEMODE = 33
SYMBOL_SWAP_MODE = 37
SYMBOL_SWAP_ROLLOVER3DAYS = 40
SYMBOL_MARGIN_HEDGED_USE_LEG = 82
SYMBOL_EXPIRATION_MODE = 49
SYMBOL_FILLING_MODE = 50
SYMBOL_ORDER_MODE = 71
SYMBOL_ORDER_GTC_MODE = 81
SYMBOL_ORDER_CLOSEBY = 64
SYMBOL_OPTION_MODE = 75
SYMBOL_OPTION_RIGHT = 74
class ENUM_SYMBOL_INFO_DOUBLE(IntEnum):
SYMBOL_BID = 1
SYMBOL_BIDHIGH = 2
SYMBOL_BIDLOW = 3
SYMBOL_ASK = 4
SYMBOL_ASKHIGH = 5
SYMBOL_ASKLOW = 6
SYMBOL_LAST = 7
SYMBOL_LASTHIGH = 8
SYMBOL_LASTLOW = 9
SYMBOL_VOLUME_REAL = 10
SYMBOL_VOLUMEHIGH_REAL = 11
SYMBOL_VOLUMELOW_REAL = 12
SYMBOL_OPTION_STRIKE = 72
SYMBOL_POINT = 16
SYMBOL_TRADE_TICK_VALUE = 26
SYMBOL_TRADE_TICK_VALUE_PROFIT = 53
SYMBOL_TRADE_TICK_VALUE_LOSS = 54
SYMBOL_TRADE_TICK_SIZE = 27
SYMBOL_TRADE_CONTRACT_SIZE = 28
SYMBOL_TRADE_ACCRUED_INTEREST = 87
SYMBOL_TRADE_FACE_VALUE = 86
SYMBOL_TRADE_LIQUIDITY_RATE = 85
SYMBOL_VOLUME_MIN = 34
SYMBOL_VOLUME_MAX = 35
SYMBOL_VOLUME_STEP = 36
SYMBOL_VOLUME_LIMIT = 55
SYMBOL_SWAP_LONG = 38
SYMBOL_SWAP_SHORT = 39
SYMBOL_MARGIN_INITIAL = 42
SYMBOL_MARGIN_MAINTENANCE = 43
SYMBOL_MARGIN_LONG = 44 # FIXME: Undocumented!
SYMBOL_MARGIN_SHORT = 45 # FIXME: Undocumented!
SYMBOL_MARGIN_LIMIT = 46 # FIXME: Undocumented!
SYMBOL_MARGIN_STOP = 47 # FIXME: Undocumented!
SYMBOL_MARGIN_STOPLIMIT = 48 # FIXME: Undocumented!
SYMBOL_SESSION_VOLUME = 57
SYMBOL_SESSION_TURNOVER = 58
SYMBOL_SESSION_INTEREST = 59
SYMBOL_SESSION_BUY_ORDERS_VOLUME = 61
SYMBOL_SESSION_SELL_ORDERS_VOLUME = 63
SYMBOL_SESSION_OPEN = 64
SYMBOL_SESSION_CLOSE = 65
SYMBOL_SESSION_AW = 66
SYMBOL_SESSION_PRICE_SETTLEMENT = 67
SYMBOL_SESSION_PRICE_LIMIT_MIN = 68
SYMBOL_SESSION_PRICE_LIMIT_MAX = 69
SYMBOL_MARGIN_HEDGED = 77
class ENUM_SYMBOL_INFO_STRING(IntEnum):
SYMBOL_BASIS = 73
SYMBOL_CURRENCY_BASE = 22
SYMBOL_CURRENCY_PROFIT = 23
SYMBOL_CURRENCY_MARGIN = 24
SYMBOL_BANK = 19
SYMBOL_DESCRIPTION = 20
SYMBOL_FORMULA = 84
SYMBOL_PAGE = 83
SYMBOL_ISIN = 70
SYMBOL_PATH = 21
class ENUM_SYMBOL_CHART_MODE(IntEnum):
SYMBOL_CHART_MODE_BID = 0
SYMBOL_CHART_MODE_LAST = 1
class ENUM_SYMBOL_ORDER_GTC_MODE(IntEnum):
SYMBOL_ORDERS_GTC = 0
SYMBOL_ORDERS_DAILY = 1
SYMBOL_ORDERS_DAILY_EXCLUDING_STOPS = 2
class ENUM_SYMBOL_CALC_MODE(IntEnum):
SYMBOL_CALC_MODE_FOREX = 0
SYMBOL_CALC_MODE_FUTURES = 1
SYMBOL_CALC_MODE_CFD = 2
SYMBOL_CALC_MODE_CFDINDEX = 3
SYMBOL_CALC_MODE_CFDLEVERAGE = 4
SYMBOL_CALC_MODE_EXCH_STOCKS = 32
SYMBOL_CALC_MODE_EXCH_FUTURES = 33
SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS = 34
SYMBOL_CALC_MODE_SERV_COLLATERAL = 64
class ENUM_SYMBOL_TRADE_MODE(IntEnum):
SYMBOL_TRADE_MODE_DISABLED = 0
SYMBOL_TRADE_MODE_LONGONLY = 1
SYMBOL_TRADE_MODE_SHORTONLY = 2
SYMBOL_TRADE_MODE_CLOSEONLY = 3
SYMBOL_TRADE_MODE_FULL = 4
class ENUM_SYMBOL_TRADE_EXECUTION(IntEnum):
SYMBOL_TRADE_EXECUTION_REQUEST = 0
SYMBOL_TRADE_EXECUTION_INSTANT = 1
SYMBOL_TRADE_EXECUTION_MARKET = 2
SYMBOL_TRADE_EXECUTION_EXCHANGE = 3
class ENUM_SYMBOL_SWAP_MODE(IntEnum):
SYMBOL_SWAP_MODE_DISABLED = 0
SYMBOL_SWAP_MODE_POINTS = 1
SYMBOL_SWAP_MODE_CURRENCY_SYMBOL = 2
SYMBOL_SWAP_MODE_CURRENCY_MARGIN = 3
SYMBOL_SWAP_MODE_CURRENCY_DEPOSIT = 4
SYMBOL_SWAP_MODE_INTEREST_CURRENT = 5
SYMBOL_SWAP_MODE_INTEREST_OPEN = 6
SYMBOL_SWAP_MODE_REOPEN_CURRENT = 7
SYMBOL_SWAP_MODE_REOPEN_BID = 8
class ENUM_DAY_OF_WEEK(IntEnum):
SUNDAY = 0
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
class ENUM_SYMBOL_OPTION_RIGHT(IntEnum):
SYMBOL_OPTION_RIGHT_CALL = 0
SYMBOL_OPTION_RIGHT_PUT = 1
class ENUM_SYMBOL_OPTION_MODE(IntEnum):
SYMBOL_OPTION_MODE_EUROPEAN = 0
SYMBOL_OPTION_MODE_AMERICAN = 1
# Account Properties
class ENUM_ACCOUNT_INFO_INTEGER(IntEnum):
ACCOUNT_LOGIN = 0 # Account number
ACCOUNT_TRADE_MODE = 32 # Account trade mode
ACCOUNT_LEVERAGE = 35 # Account leverage
ACCOUNT_LIMIT_ORDERS = 47 # Maximum allowed number of active pending orders
ACCOUNT_MARGIN_SO_MODE = 44 # Mode for setting the minimal allowed margin
ACCOUNT_TRADE_ALLOWED = 33 # Allowed trade for the current account
ACCOUNT_TRADE_EXPERT = 34 # Allowed trade for an Expert Advisor
ACCOUNT_MARGIN_MODE = 53 # Margin calculation mode
class ENUM_ACCOUNT_INFO_DOUBLE(IntEnum):
ACCOUNT_BALANCE = 37 # Account balance in the deposit currency
ACCOUNT_CREDIT = 38 # Account credit in the deposit currency
ACCOUNT_PROFIT = 39 # Current profit of an account in the deposit currency
ACCOUNT_EQUITY = 40 # Account equity in the deposit currency
ACCOUNT_MARGIN = 41 # Account margin used in the deposit currency
ACCOUNT_MARGIN_FREE = 42 # Free margin of an account in the deposit currency
ACCOUNT_MARGIN_LEVEL = 43 # Account margin level in percents
ACCOUNT_MARGIN_SO_CALL = 45 # Margin call level
ACCOUNT_MARGIN_SO_SO = 46 # Margin stop out level
ACCOUNT_MARGIN_INITIAL = 48 # Initial margin
ACCOUNT_MARGIN_MAINTENANCE = 49 # Maintenance margin
ACCOUNT_ASSETS = 50 # The current assets of an account
ACCOUNT_LIABILITIES = 51 # The current liabilities on an account
ACCOUNT_COMMISSION_BLOCKED = 52 # The current blocked commission amount on an account
class ENUM_ACCOUNT_INFO_STRING(IntEnum):
ACCOUNT_NAME = 1 # Client name
ACCOUNT_SERVER = 3 # Trade server name
ACCOUNT_CURRENCY = 36 # Account currency
ACCOUNT_COMPANY = 2 # Name of a company that serves the account
class ENUM_ACCOUNT_TRADE_MODE(IntEnum):
ACCOUNT_TRADE_MODE_DEMO = 0 # Demo account
ACCOUNT_TRADE_MODE_CONTEST = 1 # Contest account
ACCOUNT_TRADE_MODE_REAL = 2 # Real account
class ENUM_ACCOUNT_STOPOUT_MODE(IntEnum):
ACCOUNT_STOPOUT_MODE_PERCENT = 0 # Account stop out mode in percents
ACCOUNT_STOPOUT_MODE_MONEY = 1 # Account stop out mode in money
class ENUM_ACCOUNT_MARGIN_MODE(IntEnum):
ACCOUNT_MARGIN_MODE_RETAIL_NETTING = 0 # Used for the OTC markets to interpret positions in the "netting" mode
ACCOUNT_MARGIN_MODE_EXCHANGE = 1 # Used for the exchange markets
ACCOUNT_MARGIN_MODE_RETAIL_HEDGING = 2 # Used for the exchange markets where individual positions are possible
# Trade Constants:
# History Database Properties
class ENUM_SERIES_INFO_INTEGER(IntEnum):
SERIES_BARS_COUNT = 0 # Bars count for the symbol-period for the current moment
SERIES_FIRSTDATE = 1 # The very first date for the symbol-period for the current moment
SERIES_LASTBAR_DATE = 5 # Open time of the last bar of the symbol-period
SERIES_SERVER_FIRSTDATE = (
2 # The very first date in the history of the symbol on the server regardless of the timeframe
)
SERIES_TERMINAL_FIRSTDATE = (
3 # The very first date in the history of the symbol in the client terminal, regardless of the timeframe
)
SERIES_SYNCHRONIZED = 4 # S ymbol/period data synchronization flag for the current moment
# Order Properties
class ENUM_ORDER_PROPERTY_INTEGER(IntEnum):
ORDER_TICKET = 22 # Order ticket. Unique number assigned to each order
ORDER_TIME_SETUP = 1 # Order setup time
ORDER_TYPE = 4 # Order type
ORDER_STATE = 14 # Order state
ORDER_TIME_EXPIRATION = 2 # Order expiration time
ORDER_TIME_DONE = 3 # Order execution or cancellation time
ORDER_TIME_SETUP_MSC = 18 # The time of placing an order for execution in milliseconds since 01.01.1970
ORDER_TIME_DONE_MSC = 19 # Order execution/cancellation time in milliseconds since 01.01.1970
ORDER_TYPE_FILLING = 5 # Order filling type
ORDER_TYPE_TIME = 6 # Order lifetime
ORDER_MAGIC = 15 # ID of an Expert Advisor that has placed the order (designed to ensure that each Expert Advisor places its own unique number)
ORDER_REASON = 23 # The reason or source for placing an order
ORDER_POSITION_ID = 17 # Position identifier that is set to an order as soon as it is executed.
# Each executed order results in a deal that opens or modifies an already existing position. The identifier of exactly this position is set to the executed order at this moment.
ORDER_POSITION_BY_ID = 21 # Identifier of an opposite position used for closing by order ORDER_TYPE_CLOSE_BY
class ENUM_ORDER_PROPERTY_DOUBLE(IntEnum):
ORDER_VOLUME_INITIAL = 7 # Order initial volume
ORDER_VOLUME_CURRENT = 8 # Order current volume
ORDER_PRICE_OPEN = 9 # Price specified in the order
ORDER_SL = 12 # Stop Loss value
ORDER_TP = 13 # Take Profit value
ORDER_PRICE_CURRENT = 10 # The current price of the order symbol
ORDER_PRICE_STOPLIMIT = 11 # The Limit order price for the StopLimit order
class ENUM_ORDER_PROPERTY_STRING(IntEnum):
ORDER_SYMBOL = 0 # Symbol of the order
ORDER_COMMENT = 16 # Order comment
ORDER_EXTERNAL_ID = 20 # Order identifier in an external trading system (on the Exchange)
class ENUM_ORDER_TYPE(IntEnum):
ORDER_TYPE_BUY = 0 # Market Buy order
ORDER_TYPE_SELL = 1 # Market Sell order
ORDER_TYPE_BUY_LIMIT = 2 # Buy Limit pending order
ORDER_TYPE_SELL_LIMIT = 3 # Sell Limit pending order
ORDER_TYPE_BUY_STOP = 4 # Buy Stop pending order
ORDER_TYPE_SELL_STOP = 5 # Sell Stop pending order
ORDER_TYPE_BUY_STOP_LIMIT = (
6 # Upon reaching the order price, a pending Buy Limit order is places at the StopLimit price
)
ORDER_TYPE_SELL_STOP_LIMIT = (
7 # Upon reaching the order price, a pending Sell Limit order is places at the StopLimit price
)
ORDER_TYPE_CLOSE_BY = 8 # Order to close a position by an opposite one
class ENUM_ORDER_STATE(IntEnum):
ORDER_STATE_STARTED = 0 # Order checked, but not yet accepted by broker
ORDER_STATE_PLACED = 1 # Order accepted
ORDER_STATE_CANCELED = 2 # Order canceled by client
ORDER_STATE_PARTIAL = 3 # Order partially executed
ORDER_STATE_FILLED = 4 # Order fully executed
ORDER_STATE_REJECTED = 5 # Order rejected
ORDER_STATE_EXPIRED = 6 # Order expired
ORDER_STATE_REQUEST_ADD = 7 # Order is being registered (placing to the trading system)
ORDER_STATE_REQUEST_MODIFY = 8 # Order is being modified (changing its parameters)
ORDER_STATE_REQUEST_CANCEL = 9 # Order is being deleted (deleting from the trading system)
class ENUM_ORDER_TYPE_FILLING(IntEnum):
ORDER_FILLING_FOK = 0
ORDER_FILLING_IOC = 1
ORDER_FILLING_RETURN = 2
class ENUM_ORDER_TYPE_TIME(IntEnum):
ORDER_TIME_GTC = 0
ORDER_TIME_DAY = 1
ORDER_TIME_SPECIFIED = 2
ORDER_TIME_SPECIFIED_DAY = 3
class ENUM_ORDER_REASON(IntEnum):
ORDER_REASON_CLIENT = 0 # The order was placed from a desktop terminal
ORDER_REASON_MOBILE = 1 # The order was placed from a mobile application
ORDER_REASON_WEB = 2 # The order was placed from a web platform
ORDER_REASON_EXPERT = 3 # The order was placed from an MQL5-program, i.e. by an Expert Advisor or a script
ORDER_REASON_SL = 4 # The order was placed as a result of Stop Loss activation
ORDER_REASON_TP = 5 # The order was placed as a result of Take Profit activation
ORDER_REASON_SO = 6 # The order was placed as a result of the Stop Out event
# Position Properties
class ENUM_POSITION_PROPERTY_INTEGER(IntEnum):
POSITION_TICKET = 17 # Position ticket
POSITION_TIME = 1 # Position open time
POSITION_TIME_MSC = 14 # Position opening time in milliseconds since 01.01.1970
POSITION_TIME_UPDATE = 15 # Position changing time in seconds since 01.01.1970
POSITION_TIME_UPDATE_MSC = 16 # Position changing time in milliseconds since 01.01.1970
POSITION_TYPE = 2 # Position type
POSITION_MAGIC = 12 # Position magic number
POSITION_IDENTIFIER = 13 # Position identifier is a unique number that is assigned to every newly opened position
# and doesn't change during the entire lifetime of the position. Position turnover doesn't change its identifier.
POSITION_REASON = 18 # The reason for opening a position
class ENUM_POSITION_PROPERTY_DOUBLE(IntEnum):
POSITION_VOLUME = 3 # Position volume
POSITION_PRICE_OPEN = 4 # Position open price
POSITION_SL = 6 # Stop Loss level of opened position
POSITION_TP = 7 # Take Profit level of opened position
POSITION_PRICE_CURRENT = 5 # Current price of the position symbol
POSITION_SWAP = 9 # Cumulative swap
POSITION_PROFIT = 10 # Current profit
class ENUM_POSITION_PROPERTY_STRING(IntEnum):
POSITION_SYMBOL = 0 # Symbol of the position
POSITION_COMMENT = 11 # Position comment
class ENUM_POSITION_TYPE(IntEnum):
POSITION_TYPE_BUY = 0 # Buy
POSITION_TYPE_SELL = 1 # Sell
class ENUM_POSITION_REASON(IntEnum):
POSITION_REASON_CLIENT = (
0 # The position was opened as a result of activation of an order placed from a desktop terminal
)
POSITION_REASON_MOBILE = (
1 # The position was opened as a result of activation of an order placed from a mobile application
)
POSITION_REASON_WEB = (
2 # The position was opened as a result of activation of an order placed from the web platform
)
POSITION_REASON_EXPERT = (
3 # The position was opened as a result of activation of an order placed from an MQL5 program
)
# Deal Properties
class ENUM_DEAL_PROPERTY_INTEGER(IntEnum):
DEAL_TICKET = 15 # Deal ticket. Unique number assigned to each deal
DEAL_ORDER = 1 # Deal order number
DEAL_TIME = 2 # Deal time
DEAL_TIME_MSC = 13 # The time of a deal execution in milliseconds since 01.01.1970
DEAL_TYPE = 3 # Deal type
DEAL_ENTRY = 4 # Deal entry - entry in, entry out, reverse
DEAL_MAGIC = 11 # Deal magic number
DEAL_REASON = 16 # The reason or source for deal execution
DEAL_POSITION_ID = 12 # Identifier of a position
class ENUM_DEAL_PROPERTY_DOUBLE(IntEnum):
DEAL_VOLUME = 5 # Deal volume
DEAL_PRICE = 6 # Deal price
DEAL_COMMISSION = 7 # Deal commission
DEAL_SWAP = 8 # Cumulative swap on close
DEAL_PROFIT = 9 # Deal profit
class ENUM_DEAL_PROPERTY_STRING(IntEnum):
DEAL_SYMBOL = 0 # Deal symbol
DEAL_COMMENT = 10 # Deal comment
DEAL_EXTERNAL_ID = 14 # Deal identifier in an external trading system (on the Exchange)
class ENUM_DEAL_TYPE(IntEnum):
DEAL_TYPE_BUY = 0 # Buy
DEAL_TYPE_SELL = 1 # Sell
DEAL_TYPE_BALANCE = 2 # Balance
DEAL_TYPE_CREDIT = 3 # Credit
DEAL_TYPE_CHARGE = 4 # Additional charge
DEAL_TYPE_CORRECTION = 5 # Correction
DEAL_TYPE_BONUS = 6 # Bonus
DEAL_TYPE_COMMISSION = 7 # Additional commission
DEAL_TYPE_COMMISSION_DAILY = 8 # Daily commission
DEAL_TYPE_COMMISSION_MONTHLY = 9 # Monthly commission
DEAL_TYPE_COMMISSION_AGENT_DAILY = 10 # Daily agent commission
DEAL_TYPE_COMMISSION_AGENT_MONTHLY = 11 # Monthly agent commission
DEAL_TYPE_INTEREST = 12 # Interest rate
DEAL_TYPE_BUY_CANCELED = 13 # Canceled buy deal
DEAL_TYPE_SELL_CANCELED = 14 # Canceled sell deal
DEAL_DIVIDEND = 15 # Dividend operations
DEAL_DIVIDEND_FRANKED = 16 # Franked (non-taxable) dividend operations
DEAL_TAX = 17 # Tax charges
class ENUM_DEAL_ENTRY(IntEnum):
DEAL_ENTRY_IN = 0 # Entry in
DEAL_ENTRY_OUT = 1 # Entry out
DEAL_ENTRY_INOUT = 2 # Reverse
DEAL_ENTRY_STATE = 255 # Close a position by an opposite one
class ENUM_DEAL_REASON(IntEnum):
DEAL_REASON_CLIENT = 0 # The deal was executed as a result of activation of an order placed from a desktop terminal
DEAL_REASON_MOBILE = (
1 # The deal was executed as a result of activation of an order placed from a mobile application
)
DEAL_REASON_WEB = 2 # The deal was executed as a result of activation of an order placed from the web platform
DEAL_REASON_EXPERT = 3 # The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script
DEAL_REASON_SL = 4 # The deal was executed as a result of Stop Loss activation
DEAL_REASON_TP = 5 # The deal was executed as a result of Take Profit activation
DEAL_REASON_SO = 6 # The deal was executed as a result of the Stop Out event
DEAL_REASON_ROLLOVER = 7 # The deal was executed due to a rollover
DEAL_REASON_VMARGIN = 8 # The deal was executed after charging the variation margin
DEAL_REASON_SPLIT = 9 # The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement
# Trade Operation Types
class ENUM_TRADE_REQUEST_ACTIONS(IntEnum):
TRADE_ACTION_DEAL = 1 # Place a trade order for an immediate execution with the specified parameters (market order)
TRADE_ACTION_PENDING = 5 # Place a trade order for the execution under specified conditions (pending order)
TRADE_ACTION_SLTP = 6 # Modify Stop Loss and Take Profit values of an opened position
TRADE_ACTION_MODIFY = 7 # Modify the parameters of the order placed previously
TRADE_ACTION_REMOVE = 8 # Delete the pending order placed previously
TRADE_ACTION_CLOSE_BY = 10 # Close a position by an opposite one
# Trade Transaction Types
class ENUM_TRADE_TRANSACTION_TYPE(IntEnum):
TRADE_TRANSACTION_ORDER_ADD = 0 # Adding a new open order
TRADE_TRANSACTION_ORDER_UPDATE = (
1 # Updating an open order. The updates include not only evident changes from the client terminal
)
# or a trade server sides but also changes of an order state when setting it
# (for example, transition from ORDER_STATE_STARTED to ORDER_STATE_PLACED or from ORDER_STATE_PLACED to ORDER_STATE_PARTIAL, etc.).
TRADE_TRANSACTION_ORDER_DELETE = 2 # Removing an order from the list of the open ones. An order can be deleted from the open ones as a result of setting an appropriate request
# or execution (filling) and moving to the history.
TRADE_TRANSACTION_DEAL_ADD = 6 # Adding a deal to the history. The action is performed as a result of an order execution or performing operations with an account balance.
TRADE_TRANSACTION_DEAL_UPDATE = (
7 # Updating a deal in the history. There may be cases when a previously executed deal is changed on a server.
)
# For example, a deal has been changed in an external trading system (exchange) where it was previously transferred by a broker.
TRADE_TRANSACTION_DEAL_DELETE = 8 # Deleting a deal from the history. There may be cases when a previously executed deal is deleted from a server.
# For example, a deal has been deleted in an external trading system (exchange) where it was previously transferred by a broker.
TRADE_TRANSACTION_HISTORY_ADD = 3 # Adding an order to the history as a result of execution or cancellation.
TRADE_TRANSACTION_HISTORY_UPDATE = 4 # Changing an order located in the orders history. This type is provided for enhancing functionality on a trade server side.
TRADE_TRANSACTION_HISTORY_DELETE = 5 # Deleting an order from the orders history. This type is provided for enhancing functionality on a trade server side.
TRADE_TRANSACTION_POSITION = 9 # Changing a position not related to a deal execution. This type of transaction shows that a position has been changed on a trade server side.
# Position volume, open price, Stop Loss and Take Profit levels can be changed. Data on changes are submitted in MqlTradeTransaction structure via OnTradeTransaction handler.
# Position change (adding, changing or closing), as a result of a deal execution, does not lead to the occurrence of TRADE_TRANSACTION_POSITION transaction.
TRADE_TRANSACTION_REQUEST = 10 # Notification of the fact that a trade request has been processed by a server and processing result has been received.
# Only type field (trade transaction type) must be analyzed for such transactions in MqlTradeTransaction structure.
# The second and third parameters of OnTradeTransaction (request and result) must be analyzed for additional data.
# Trade Orders in Depth Of Market
class ENUM_BOOK_TYPE(IntEnum):
BOOK_TYPE_SELL = 1 # Sell order (Offer)
BOOK_TYPE_BUY = 2 # Buy order (Bid)
BOOK_TYPE_SELL_MARKET = 3 # Sell order by Market
BOOK_TYPE_BUY_MARKET = 4 # Buy order by Market
# Object Types
class ENUM_OBJECT(IntEnum):
OBJ_VLINE = 0 # Vertical Line
OBJ_HLINE = 1 # Horizontal Line
OBJ_TREND = 2 # Trend Line
OBJ_TRENDBYANGLE = 3 # Trend Line By Angle
OBJ_CYCLES = 4 # Cycle Lines
OBJ_ARROWED_LINE = 108 # Arrowed Line
OBJ_CHANNEL = 5 # Equidistant Channel
OBJ_STDDEVCHANNEL = 6 # Standard Deviation Channel
OBJ_REGRESSION = 7 # Linear Regression Channel
OBJ_PITCHFORK = 8 # Andrews’ Pitchfork
OBJ_GANNLINE = 9 # Gann Line
OBJ_GANNFAN = 10 # Gann Fan
OBJ_GANNGRID = 11 # Gann Grid
OBJ_FIBO = 12 # Fibonacci Retracement
OBJ_FIBOTIMES = 13 # Fibonacci Time Zones
OBJ_FIBOFAN = 14 # Fibonacci Fan
OBJ_FIBOARC = 15 # Fibonacci Arcs
OBJ_FIBOCHANNEL = 16 # Fibonacci Channel
OBJ_EXPANSION = 17 # Fibonacci Expansion
OBJ_ELLIOTWAVE5 = 18 # Elliott Motive Wave
OBJ_ELLIOTWAVE3 = 19 # Elliott Correction Wave
OBJ_RECTANGLE = 20 # Rectangle
OBJ_TRIANGLE = 21 # Triangle
OBJ_ELLIPSE = 22 # Ellipse
OBJ_ARROW_THUMB_UP = 23 # Thumbs Up
OBJ_ARROW_THUMB_DOWN = 24 # Thumbs Down
OBJ_ARROW_UP = 25 # Arrow Up
OBJ_ARROW_DOWN = 26 # Arrow Down
OBJ_ARROW_STOP = 27 # Stop Sign
OBJ_ARROW_CHECK = 28 # Check Sign
OBJ_ARROW_LEFT_PRICE = 29 # Left Price Label
OBJ_ARROW_RIGHT_PRICE = 30 # Right Price Label
OBJ_ARROW_BUY = 31 # Buy Sign
OBJ_ARROW_SELL = 32 # Sell Sign
OBJ_ARROW = 100 # Arrow
OBJ_TEXT = 101 # Text
OBJ_LABEL = 102 # Label
OBJ_BUTTON = 103 # Button
OBJ_CHART = 104 # Chart
OBJ_BITMAP = 105 # Bitmap
OBJ_BITMAP_LABEL = 106 # Bitmap Label
OBJ_EDIT = 107 # Edit
OBJ_EVENT = 109 # The "Event" object corresponding to an event in the economic calendar
OBJ_RECTANGLE_LABEL = 110 # The "Rectangle label" object for creating and designing the custom graphical interface.
# Object Properties
class ENUM_OBJECT_PROPERTY_DOUBLE(IntEnum):
OBJPROP_PRICE = 9 # Price coordinate
OBJPROP_LEVELVALUE = 204 # Level value
OBJPROP_SCALE = 1006 # Scale (properties of Gann objects and Fibonacci Arcs)
OBJPROP_ANGLE = 1007 # Angle. For the objects with no angle specified, created from a program, the value is equal to EMPTY_VALUE
OBJPROP_DEVIATION = 1010 # Deviation for the Standard Deviation Channel
class ENUM_OBJECT_PROPERTY_INTEGER(IntEnum):
OBJPROP_COLOR = 0 # Color
OBJPROP_STYLE = 1 # Style
OBJPROP_WIDTH = 2 # Line thickness
OBJPROP_BACK = 3 # Object in the background
OBJPROP_ZORDER = (
207 # Priority of a graphical object for receiving events of clicking on a chart (CHARTEVENT_CLICK).
)
# The default zero value is set when creating an object; the priority can be increased if necessary.
# When objects are placed one atop another, only one of them with the highest priority will receive the CHARTEVENT_CLICK event.
OBJPROP_FILL = 1031 # Fill an object with color (for OBJ_RECTANGLE, OBJ_TRIANGLE, OBJ_ELLIPSE, OBJ_CHANNEL, OBJ_STDDEVCHANNEL, OBJ_REGRESSION)
OBJPROP_HIDDEN = 208 # Prohibit showing of the name of a graphical object in the list of objects from the terminal menu "Charts" - "Objects" - "List of objects".
# The true value allows to hide an object from the list. By default, true is set to the objects that display calendar events,
# trading history and to the objects created from MQL5 programs. To see such graphical objects and access their properties, click on the "All" button in the "List of objects" window.
OBJPROP_SELECTED = 4 # Object is selected
OBJPROP_READONLY = 1028 # Ability to edit text in the Edit object
OBJPROP_TYPE = 7 # Object type
OBJPROP_TIME = 8 # Time coordinate
OBJPROP_SELECTABLE = 10 # Object availability
OBJPROP_CREATETIME = 11 # Time of object creation
OBJPROP_LEVELS = 200 # Number of levels
OBJPROP_LEVELCOLOR = 201 # Color of the line-level
OBJPROP_LEVELSTYLE = 202 # Style of the line-level
OBJPROP_LEVELWIDTH = 203 # Thickness of the line-level
OBJPROP_ALIGN = 1036 # Horizontal text alignment in the "Edit" object (OBJ_EDIT)
OBJPROP_FONTSIZE = 1002 # Font size
OBJPROP_RAY_LEFT = 1003 # Ray goes to the left
OBJPROP_RAY_RIGHT = 1004 # Ray goes to the right
OBJPROP_RAY = 1032 # A vertical line goes through all the windows of a chart
OBJPROP_ELLIPSE = 1005 # Showing the full ellipse of the Fibonacci Arc object (OBJ_FIBOARC)
OBJPROP_ARROWCODE = 1008 # Arrow code for the Arrow object
OBJPROP_TIMEFRAMES = 12 # Visibility of an object at timeframes
OBJPROP_ANCHOR = 1011 # Location of the anchor point of a graphical object
OBJPROP_XDISTANCE = 1012 # The distance in pixels along the X axis from the binding corner
OBJPROP_YDISTANCE = 1013 # The distance in pixels along the Y axis from the binding corner
OBJPROP_DIRECTION = 1014 # Trend of the Gann object
OBJPROP_DEGREE = 1015 # Level of the Elliott Wave Marking
OBJPROP_DRAWLINES = 1016 # Displaying lines for marking the Elliott Wave
OBJPROP_STATE = 1018 # Button state (pressed / depressed)
OBJPROP_CHART_ID = 1030 # ID of the "Chart" object (OBJ_CHART). It allows working with the properties of this object like with a normal chart using the functions described in Chart Operations, but there some exceptions.
OBJPROP_XSIZE = 1019 # The object's width along the X axis in pixels. Specified for OBJ_LABEL (read only), OBJ_BUTTON, OBJ_CHART, OBJ_BITMAP, OBJ_BITMAP_LABEL, OBJ_EDIT, OBJ_RECTANGLE_LABEL objects.
OBJPROP_YSIZE = 1020 # The object's height along the Y axis in pixels. Specified for OBJ_LABEL (read only), OBJ_BUTTON, OBJ_CHART, OBJ_BITMAP, OBJ_BITMAP_LABEL, OBJ_EDIT, OBJ_RECTANGLE_LABEL objects.
OBJPROP_XOFFSET = 1033 # The X coordinate of the upper left corner of the rectangular visible area in the graphical objects "Bitmap Label" and "Bitmap" (OBJ_BITMAP_LABEL and OBJ_BITMAP).
# The value is set in pixels relative to the upper left corner of the original image.
OBJPROP_YOFFSET = 1034 # The Y coordinate of the upper left corner of the rectangular visible area in the graphical objects "Bitmap Label" and "Bitmap" (OBJ_BITMAP_LABEL and OBJ_BITMAP).
# The value is set in pixels relative to the upper left corner of the original image.
OBJPROP_PERIOD = 1022 # Timeframe for the Chart object
OBJPROP_DATE_SCALE = 1023 # Displaying the time scale for the Chart object
OBJPROP_PRICE_SCALE = 1024 # Displaying the price scale for the Chart object
OBJPROP_CHART_SCALE = 1027 # The scale for the Chart object
OBJPROP_BGCOLOR = 1025 # The background color for OBJ_EDIT, OBJ_BUTTON, OBJ_RECTANGLE_LABEL
OBJPROP_CORNER = 1026 # The corner of the chart to link a graphical object
OBJPROP_BORDER_TYPE = 1029 # Border type for the "Rectangle label" object
OBJPROP_BORDER_COLOR = 1035 # Border color for the OBJ_EDIT and OBJ_BUTTON objects
class ENUM_OBJECT_PROPERTY_STRING(IntEnum):
OBJPROP_NAME = 5 # Object name
OBJPROP_TEXT = 6 # Description of the object (the text contained in the object)
OBJPROP_TOOLTIP = 206 # The text of a tooltip. If the property is not set, then the tooltip generated automatically by the terminal is shown. A tooltip can be disabled by setting the "\n" (line feed) value to it
OBJPROP_LEVELTEXT = 205 # Level description
OBJPROP_FONT = 1001 # Font
OBJPROP_BMPFILE = 1017 # The name of BMP-file for Bitmap Label.
OBJPROP_SYMBOL = 1021 # Symbol for the Chart object
class ENUM_BORDER_TYPE(IntEnum):
BORDER_FLAT = 0 # Flat form
BORDER_RAISED = 1 # Prominent form
BORDER_SUNKEN = 2 # Concave form
class ENUM_ALIGN_MODE(IntEnum):
ALIGN_LEFT = 1 # Left alignment
ALIGN_CENTER = 2 # Centered (only for the Edit object)
ALIGN_RIGHT = 0 # Right alignment
# Price Constants
class ENUM_APPLIED_PRICE(IntEnum):
PRICE_CLOSE = 1 # Close price
PRICE_OPEN = 2 # Open price
PRICE_HIGH = 3 # The maximum price for the period
PRICE_LOW = 4 # The minimum price for the period
PRICE_MEDIAN = 5 # Median price, (high + low)/2
PRICE_TYPICAL = 6 # Typical price, (high + low + close)/3
PRICE_WEIGHTED = 7 # Average price, (high + low + close + close)/4
class ENUM_APPLIED_VOLUME(IntEnum):
VOLUME_TICK = 0 # Tick volume
VOLUME_REAL = 1 # Trade volume
class ENUM_STO_PRICE(IntEnum):
STO_LOWHIGH = 0 # Calculation is based on Low/High prices
STO_CLOSECLOSE = 1 # Calculation is based on Close/Close prices
# Smoothing Methods
class ENUM_MA_METHOD(IntEnum):
MODE_SMA = 0 # Simple averaging
MODE_EMA = 1 # Exponential averaging
MODE_SMMA = 2 # Smoothed averaging
MODE_LWMA = 3 # Linear-weighted averaging
# Indicator constants
class ENUM_INDICATOR(IntEnum):
IND_AC = 5 # Accelerator Oscillator
IND_AD = 6 # Accumulation/Distribution
IND_ADX = 8 # Average Directional Index
IND_ADXW = 9 # ADX by Welles Wilder
IND_ALLIGATOR = 7 # Alligator
IND_AMA = 40 # Adaptive Moving Average
IND_AO = 11 # Awesome Oscillator
IND_ATR = 10 # Average True Range
IND_BANDS = 13 # Bollinger Bands®
IND_BEARS = 12 # Bears Power
IND_BULLS = 14 # Bulls Power
IND_BWMFI = 22 # Market Facilitation Index
IND_CCI = 15 # Commodity Channel Index
IND_CHAIKIN = 41 # Chaikin Oscillator
IND_CUSTOM = 43 # Custom indicator
IND_DEMA = 36 # Double Exponential Moving Average
IND_DEMARKER = 16 # DeMarker
IND_ENVELOPES = 17 # Envelopes
IND_FORCE = 18 # Force Index
IND_FRACTALS = 19 # Fractals
IND_FRAMA = 39 # Fractal Adaptive Moving Average
IND_GATOR = 20 # Gator Oscillator
IND_ICHIMOKU = 21 # Ichimoku Kinko Hyo
IND_MA = 26 # Moving Average
IND_MACD = 23 # MACD
IND_MFI = 25 # Money Flow Index
IND_MOMENTUM = 24 # Momentum
IND_OBV = 28 # On Balance Volume
IND_OSMA = 27 # OsMA
IND_RSI = 30 # Relative Strength Index
IND_RVI = 31 # Relative Vigor Index
IND_SAR = 29 # Parabolic SAR
IND_STDDEV = 32 # Standard Deviation
IND_STOCHASTIC = 33 # Stochastic Oscillator
IND_TEMA = 37 # Triple Exponential Moving Average
IND_TRIX = 38 # Triple Exponential Moving Averages Oscillator
IND_VIDYA = 42 # Variable Index Dynamic Average
IND_VOLUMES = 34 # Volumes
IND_WPR = 35 # Williams' Percent Ranges
class ENUM_DATATYPE(IntEnum):
TYPE_BOOL = 1
TYPE_CHAR = 2
TYPE_UCHAR = 3
TYPE_SHORT = 4
TYPE_USHORT = 5
TYPE_COLOR = 6
TYPE_INT = 7
TYPE_UINT = 8
TYPE_DATETIME = 9
TYPE_LONG = 10
TYPE_ULONG = 11
TYPE_FLOAT = 12
TYPE_DOUBLE = 13
TYPE_STRING = 14
class CopyTicksFlag(IntEnum):
Info = 1 # ticks with Bid and/or Ask changes
Trade = 2 # ticks with changes in Last and Volume
All = -1 # all ticks
+167
View File
@@ -0,0 +1,167 @@
import logging
from enum import IntEnum
from threading import Condition, Lock, Thread
import websockets
from websockets.sync.client import connect as ws_connect
class MtNotification(IntEnum):
ClientReady = 0
class MtMessageType(IntEnum):
Command = 0
Response = 1
Event = 2
ExpertList = 3
ExpertAdded = 4
ExpertRemoved = 5
Notification = 6
class CommandTask:
def __init__(self):
self.locker = Lock()
self.waiter = Condition()
self.response = None
def wait_response(self, time):
with self.waiter:
self.waiter.wait(time)
with self.locker:
return self.response
def set_response(self, response):
with self.locker:
self.response = response
with self.waiter:
self.waiter.notify()
class MtRpcClient:
def __init__(self, callback=None):
self.__logger = logging.getLogger(__name__)
self.__callback = callback
self.__notification_tasks = dict()
self.__tasks = dict()
self.__next_command_id = 0
self.__lock = Lock()
def connect(self, url):
self.__logger.debug(f"connecting to {url}")
self.__ws = ws_connect(url)
self.__receive_thread = Thread(target=self.__receive_messages_thread)
self.__receive_thread.start()
def disconnect(self):
self.__ws.close()
self.__receive_thread.join()
self.__logger.debug("disconnected")
def request_expert_list(self):
task = CommandTask()
with self.__lock:
self.__notification_tasks[MtNotification.ClientReady] = task
self.__ws.send(self.__create_notification(MtNotification.ClientReady))
response = task.wait_response(10)
with self.__lock:
self.__notification_tasks.pop(MtNotification.ClientReady)
return response
def send_command(self, expert_handle, command_type, payload=None):
command_id = self.__next_command_id
self.__next_command_id += 1
task = CommandTask()
with self.__lock:
self.__tasks[command_id] = task
self.__ws.send(self.__create_mt_command(expert_handle, command_id, command_type, payload))
response = task.wait_response(10)
with self.__lock:
self.__tasks.pop(command_id)
return response
# Private methods
def __process_message(self, message):
self.__logger.debug(f"process_message: {message}")
pieces = message.split(";", 1)
if len(pieces) != 2 or not pieces[0] or not pieces[1]:
self.__logger.warning("process_message: Invalid message format")
return
message_type = MtMessageType(int(pieces[0]))
if message_type == MtMessageType.ExpertList:
self.__process_expert_list(pieces[1])
elif message_type == MtMessageType.Event:
self.__process_event(pieces[1])
elif message_type == MtMessageType.Response:
self.__process_response(pieces[1])
elif message_type == MtMessageType.ExpertAdded:
self.__process_expert_added(pieces[1])
elif message_type == MtMessageType.ExpertRemoved:
self.__process_expert_removed(pieces[1])
else:
self.__logger.warning(f"received unknown message type: {message_type}")
def __process_expert_list(self, payload):
pieces = payload.split(",")
experts = list()
for p in pieces:
experts.append(int(p))
with self.__lock:
task = self.__notification_tasks.get(MtNotification.ClientReady)
if task is not None:
task.set_response(experts)
def __process_event(self, payload):
pieces = payload.split(";", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
self.__logger.warning("process_event: Invalid message format")
return
if self.__callback is not None:
self.__callback.mt_rpc_on_event(int(pieces[0]), int(pieces[1]), pieces[2])
def __process_response(self, payload):
pieces = payload.split(";", 2)
if len(pieces) != 3 or not pieces[0] or not pieces[1] or not pieces[2]:
self.__logger.warning("process_response: Invalid message format")
return
command_id = int(pieces[1])
with self.__lock:
task = self.__tasks.get(command_id)
if task is not None:
task.set_response(pieces[2])
def __process_expert_added(self, payload):
if self.__callback is not None:
self.__callback.mt_rpc_on_expert_added(int(payload))
def __process_expert_removed(self, payload):
if self.__callback is not None:
self.__callback.mt_rpc_on_expert_removed(int(payload))
def __receive_messages_thread(self):
self.__logger.debug("started receive_messages thread")
while True:
try:
message = self.__ws.recv()
self.__process_message(message)
except websockets.exceptions.ConnectionClosed:
self.__logger.info("Connection closed")
if self.__callback is not None:
self.__callback.mt_rcp_on_disconnect()
break
except Exception as e:
self.__logger.error(e)
if self.__callback is not None:
self.__callback.mt_rpc_on_connection_failed(str(e))
break
self.__logger.debug("function receive_messages finished")
def __create_notification(self, notification_type):
return f"{int(MtMessageType.Notification)};{notification_type}"
def __create_mt_command(self, expert_handle, command_id, command_type, payload):
if payload is None:
return f"{MtMessageType.Command};{expert_handle};{command_id};{command_type}"
return f"{MtMessageType.Command};{expert_handle};{command_id};{command_type};{payload}"
+35
View File
@@ -0,0 +1,35 @@
// Boost.Bimap
//
// Copyright (c) 2006-2007 Matias Capeletto
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
/// \file detail/debug/static_error.hpp
/// \brief Formatted compile time error
#ifndef BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP
#define BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/preprocessor/cat.hpp>
// Easier way to call BOOST_MPL_ASSERT_MSG in class scope to generate
// a static error.
/*===========================================================================*/
#define BOOST_BIMAP_STATIC_ERROR(MESSAGE,VARIABLES) \
BOOST_MPL_ASSERT_MSG(false, \
BOOST_PP_CAT(BIMAP_STATIC_ERROR__,MESSAGE), \
VARIABLES)
/*===========================================================================*/
#endif // BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP
+93
View File
@@ -0,0 +1,93 @@
/*
Copyright Rene Rivera 2008-2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_PREDEF_ARCHITECTURE_X86_32_H
#define BOOST_PREDEF_ARCHITECTURE_X86_32_H
#include <boost/predef/version_number.h>
#include <boost/predef/make.h>
/* tag::reference[]
= `BOOST_ARCH_X86_32`
http://en.wikipedia.org/wiki/X86[Intel x86] architecture:
If available versions [3-6] are specifically detected.
[options="header"]
|===
| {predef_symbol} | {predef_version}
| `i386` | {predef_detection}
| `+__i386__+` | {predef_detection}
| `+__i486__+` | {predef_detection}
| `+__i586__+` | {predef_detection}
| `+__i686__+` | {predef_detection}
| `+__i386+` | {predef_detection}
| `+_M_IX86+` | {predef_detection}
| `+_X86_+` | {predef_detection}
| `+__THW_INTEL__+` | {predef_detection}
| `+__I86__+` | {predef_detection}
| `+__INTEL__+` | {predef_detection}
| `+__I86__+` | V.0.0
| `+_M_IX86+` | V.0.0
| `+__i686__+` | 6.0.0
| `+__i586__+` | 5.0.0
| `+__i486__+` | 4.0.0
| `+__i386__+` | 3.0.0
|===
*/ // end::reference[]
#define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER_NOT_AVAILABLE
#if defined(i386) || defined(__i386__) || \
defined(__i486__) || defined(__i586__) || \
defined(__i686__) || defined(__i386) || \
defined(_M_IX86) || defined(_X86_) || \
defined(__THW_INTEL__) || defined(__I86__) || \
defined(__INTEL__)
# undef BOOST_ARCH_X86_32
# if !defined(BOOST_ARCH_X86_32) && defined(__I86__)
# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(__I86__,0,0)
# endif
# if !defined(BOOST_ARCH_X86_32) && defined(_M_IX86)
# define BOOST_ARCH_X86_32 BOOST_PREDEF_MAKE_10_VV00(_M_IX86)
# endif
# if !defined(BOOST_ARCH_X86_32) && defined(__i686__)
# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(6,0,0)
# endif
# if !defined(BOOST_ARCH_X86_32) && defined(__i586__)
# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(5,0,0)
# endif
# if !defined(BOOST_ARCH_X86_32) && defined(__i486__)
# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(4,0,0)
# endif
# if !defined(BOOST_ARCH_X86_32) && defined(__i386__)
# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(3,0,0)
# endif
# if !defined(BOOST_ARCH_X86_32)
# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER_AVAILABLE
# endif
#endif
#if BOOST_ARCH_X86_32
# define BOOST_ARCH_X86_32_AVAILABLE
#endif
#if BOOST_ARCH_X86_32
# undef BOOST_ARCH_WORD_BITS_32
# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE
#endif
#define BOOST_ARCH_X86_32_NAME "Intel x86-32"
#include <boost/predef/architecture/x86.h>
#endif
#include <boost/predef/detail/test.h>
BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_X86_32,BOOST_ARCH_X86_32_NAME)
+56
View File
@@ -0,0 +1,56 @@
/*
Copyright Rene Rivera 2008-2021
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_PREDEF_ARCHITECTURE_X86_64_H
#define BOOST_PREDEF_ARCHITECTURE_X86_64_H
#include <boost/predef/version_number.h>
#include <boost/predef/make.h>
/* tag::reference[]
= `BOOST_ARCH_X86_64`
https://en.wikipedia.org/wiki/X86-64[X86-64] architecture.
[options="header"]
|===
| {predef_symbol} | {predef_version}
| `+__x86_64+` | {predef_detection}
| `+__x86_64__+` | {predef_detection}
| `+__amd64__+` | {predef_detection}
| `+__amd64+` | {predef_detection}
| `+_M_X64+` | {predef_detection}
|===
*/ // end::reference[]
#define BOOST_ARCH_X86_64 BOOST_VERSION_NUMBER_NOT_AVAILABLE
#if defined(__x86_64) || defined(__x86_64__) || \
defined(__amd64__) || defined(__amd64) || \
defined(_M_X64)
# undef BOOST_ARCH_X86_64
# define BOOST_ARCH_X86_64 BOOST_VERSION_NUMBER_AVAILABLE
#endif
#if BOOST_ARCH_X86_64
# define BOOST_ARCH_X86_64_AVAILABLE
#endif
#if BOOST_ARCH_X86_64
# undef BOOST_ARCH_WORD_BITS_64
# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE
#endif
#define BOOST_ARCH_X86_64_NAME "Intel x86-64"
#include <boost/predef/architecture/x86.h>
#endif
#include <boost/predef/detail/test.h>
BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_X86_64,BOOST_ARCH_X86_64_NAME)
+135
View File
@@ -0,0 +1,135 @@
/*
Copyright Charly Chevalier 2015
Copyright Joel Falcou 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_VERSIONS_H
#define BOOST_PREDEF_HARDWARE_SIMD_X86_VERSIONS_H
#include <boost/predef/version_number.h>
/* tag::reference[]
= `BOOST_HW_SIMD_X86_*_VERSION`
Those defines represent x86 SIMD extensions versions.
NOTE: You *MUST* compare them with the predef `BOOST_HW_SIMD_X86`.
*/ // end::reference[]
// ---------------------------------
/* tag::reference[]
= `BOOST_HW_SIMD_X86_MMX_VERSION`
The https://en.wikipedia.org/wiki/MMX_(instruction_set)[MMX] x86 extension
version number.
Version number is: *0.99.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_MMX_VERSION BOOST_VERSION_NUMBER(0, 99, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_SSE_VERSION`
The https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions[SSE] x86 extension
version number.
Version number is: *1.0.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_SSE_VERSION BOOST_VERSION_NUMBER(1, 0, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_SSE2_VERSION`
The https://en.wikipedia.org/wiki/SSE2[SSE2] x86 extension version number.
Version number is: *2.0.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_SSE2_VERSION BOOST_VERSION_NUMBER(2, 0, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_SSE3_VERSION`
The https://en.wikipedia.org/wiki/SSE3[SSE3] x86 extension version number.
Version number is: *3.0.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_SSE3_VERSION BOOST_VERSION_NUMBER(3, 0, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_SSSE3_VERSION`
The https://en.wikipedia.org/wiki/SSSE3[SSSE3] x86 extension version number.
Version number is: *3.1.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_SSSE3_VERSION BOOST_VERSION_NUMBER(3, 1, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_SSE4_1_VERSION`
The https://en.wikipedia.org/wiki/SSE4#SSE4.1[SSE4_1] x86 extension version
number.
Version number is: *4.1.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_SSE4_1_VERSION BOOST_VERSION_NUMBER(4, 1, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_SSE4_2_VERSION`
The https://en.wikipedia.org/wiki/SSE4##SSE4.2[SSE4_2] x86 extension version
number.
Version number is: *4.2.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_SSE4_2_VERSION BOOST_VERSION_NUMBER(4, 2, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_AVX_VERSION`
The https://en.wikipedia.org/wiki/Advanced_Vector_Extensions[AVX] x86
extension version number.
Version number is: *5.0.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_AVX_VERSION BOOST_VERSION_NUMBER(5, 0, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_FMA3_VERSION`
The https://en.wikipedia.org/wiki/FMA_instruction_set[FMA3] x86 extension
version number.
Version number is: *5.2.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_FMA3_VERSION BOOST_VERSION_NUMBER(5, 2, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_AVX2_VERSION`
The https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2[AVX2]
x86 extension version number.
Version number is: *5.3.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_AVX2_VERSION BOOST_VERSION_NUMBER(5, 3, 0)
/* tag::reference[]
= `BOOST_HW_SIMD_X86_MIC_VERSION`
The https://en.wikipedia.org/wiki/Xeon_Phi[MIC] (Xeon Phi) x86 extension
version number.
Version number is: *9.0.0*.
*/ // end::reference[]
#define BOOST_HW_SIMD_X86_MIC_VERSION BOOST_VERSION_NUMBER(9, 0, 0)
/* tag::reference[]
*/ // end::reference[]
#endif
+44
View File
@@ -0,0 +1,44 @@
# /* Copyright (C) 2001
# * Housemarque Oy
# * http://www.housemarque.com
# *
# * Distributed under the Boost Software License, Version 1.0. (See
# * accompanying file LICENSE_1_0.txt or copy at
# * http://www.boost.org/LICENSE_1_0.txt)
# */
#
# /* Revised by Paul Mensonides (2002) */
#
# /* See http://www.boost.org for most recent version. */
#
# ifndef BOOST_PREPROCESSOR_DEBUG_ASSERT_HPP
# define BOOST_PREPROCESSOR_DEBUG_ASSERT_HPP
#
# include <boost/preprocessor/config/config.hpp>
# include <boost/preprocessor/control/expr_iif.hpp>
# include <boost/preprocessor/control/iif.hpp>
# include <boost/preprocessor/logical/not.hpp>
# include <boost/preprocessor/tuple/eat.hpp>
#
# /* BOOST_PP_ASSERT */
#
# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
# define BOOST_PP_ASSERT BOOST_PP_ASSERT_D
# else
# define BOOST_PP_ASSERT(cond) BOOST_PP_ASSERT_D(cond)
# endif
#
# define BOOST_PP_ASSERT_D(cond) BOOST_PP_IIF(BOOST_PP_NOT(cond), BOOST_PP_ASSERT_ERROR, BOOST_PP_TUPLE_EAT_1)(...)
# define BOOST_PP_ASSERT_ERROR(x, y, z)
#
# /* BOOST_PP_ASSERT_MSG */
#
# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
# define BOOST_PP_ASSERT_MSG BOOST_PP_ASSERT_MSG_D
# else
# define BOOST_PP_ASSERT_MSG(cond, msg) BOOST_PP_ASSERT_MSG_D(cond, msg)
# endif
#
# define BOOST_PP_ASSERT_MSG_D(cond, msg) BOOST_PP_EXPR_IIF(BOOST_PP_NOT(cond), msg)
#
# endif
+33
View File
@@ -0,0 +1,33 @@
# /* **************************************************************************
# * *
# * (C) Copyright Paul Mensonides 2002.
# * Distributed under the Boost Software License, Version 1.0. (See
# * accompanying file LICENSE_1_0.txt or copy at
# * http://www.boost.org/LICENSE_1_0.txt)
# * *
# ************************************************************************** */
#
# /* See http://www.boost.org for most recent version. */
#
# ifndef BOOST_PREPROCESSOR_DEBUG_ERROR_HPP
# define BOOST_PREPROCESSOR_DEBUG_ERROR_HPP
#
# include <boost/preprocessor/cat.hpp>
# include <boost/preprocessor/config/config.hpp>
#
# /* BOOST_PP_ERROR */
#
# if BOOST_PP_CONFIG_ERRORS
# define BOOST_PP_ERROR(code) BOOST_PP_CAT(BOOST_PP_ERROR_, code)
# endif
#
# define BOOST_PP_ERROR_0x0000 BOOST_PP_ERROR(0x0000, BOOST_PP_INDEX_OUT_OF_BOUNDS)
# define BOOST_PP_ERROR_0x0001 BOOST_PP_ERROR(0x0001, BOOST_PP_WHILE_OVERFLOW)
# define BOOST_PP_ERROR_0x0002 BOOST_PP_ERROR(0x0002, BOOST_PP_FOR_OVERFLOW)
# define BOOST_PP_ERROR_0x0003 BOOST_PP_ERROR(0x0003, BOOST_PP_REPEAT_OVERFLOW)
# define BOOST_PP_ERROR_0x0004 BOOST_PP_ERROR(0x0004, BOOST_PP_LIST_FOLD_OVERFLOW)
# define BOOST_PP_ERROR_0x0005 BOOST_PP_ERROR(0x0005, BOOST_PP_SEQ_FOLD_OVERFLOW)
# define BOOST_PP_ERROR_0x0006 BOOST_PP_ERROR(0x0006, BOOST_PP_ARITHMETIC_OVERFLOW)
# define BOOST_PP_ERROR_0x0007 BOOST_PP_ERROR(0x0007, BOOST_PP_DIVISION_BY_ZERO)
#
# endif
+35
View File
@@ -0,0 +1,35 @@
# /* **************************************************************************
# * *
# * (C) Copyright Paul Mensonides 2002.
# * Distributed under the Boost Software License, Version 1.0. (See
# * accompanying file LICENSE_1_0.txt or copy at
# * http://www.boost.org/LICENSE_1_0.txt)
# * *
# ************************************************************************** */
#
# /* See http://www.boost.org for most recent version. */
#
# ifndef BOOST_PREPROCESSOR_DEBUG_LINE_HPP
# define BOOST_PREPROCESSOR_DEBUG_LINE_HPP
#
# include <boost/preprocessor/cat.hpp>
# include <boost/preprocessor/config/config.hpp>
# include <boost/preprocessor/iteration/iterate.hpp>
# include <boost/preprocessor/stringize.hpp>
#
# /* BOOST_PP_LINE */
#
# if BOOST_PP_CONFIG_EXTENDED_LINE_INFO
# define BOOST_PP_LINE(line, file) line BOOST_PP_CAT(BOOST_PP_LINE_, BOOST_PP_IS_ITERATING)(file)
# define BOOST_PP_LINE_BOOST_PP_IS_ITERATING(file) #file
# define BOOST_PP_LINE_1(file) BOOST_PP_STRINGIZE(file BOOST_PP_CAT(BOOST_PP_LINE_I_, BOOST_PP_ITERATION_DEPTH())())
# define BOOST_PP_LINE_I_1() [BOOST_PP_FRAME_ITERATION(1)]
# define BOOST_PP_LINE_I_2() BOOST_PP_LINE_I_1()[BOOST_PP_FRAME_ITERATION(2)]
# define BOOST_PP_LINE_I_3() BOOST_PP_LINE_I_2()[BOOST_PP_FRAME_ITERATION(3)]
# define BOOST_PP_LINE_I_4() BOOST_PP_LINE_I_3()[BOOST_PP_FRAME_ITERATION(4)]
# define BOOST_PP_LINE_I_5() BOOST_PP_LINE_I_4()[BOOST_PP_FRAME_ITERATION(5)]
# else
# define BOOST_PP_LINE(line, file) line __FILE__
# endif
#
# endif
+319
View File
@@ -0,0 +1,319 @@
/*=============================================================================
Copyright (c) 2001-2003 Joel de Guzman
Copyright (c) 2002-2003 Hartmut Kaiser
Copyright (c) 2003 Gustavo Guerra
http://spirit.sourceforge.net/
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
#define BOOST_SPIRIT_DEBUG_NODE_HPP
#if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP)
#error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/debug_node.hpp"
#endif
#if defined(BOOST_SPIRIT_DEBUG)
#include <string>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/core/primitives/primitives.hpp> // for iscntrl_
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
//
// Debug helper classes for rules, which ensure maximum non-intrusiveness of
// the Spirit debug support
//
///////////////////////////////////////////////////////////////////////////////
namespace impl {
struct token_printer_aux_for_chars
{
template<typename CharT>
static void print(std::ostream& o, CharT c)
{
if (c == static_cast<CharT>('\a'))
o << "\\a";
else if (c == static_cast<CharT>('\b'))
o << "\\b";
else if (c == static_cast<CharT>('\f'))
o << "\\f";
else if (c == static_cast<CharT>('\n'))
o << "\\n";
else if (c == static_cast<CharT>('\r'))
o << "\\r";
else if (c == static_cast<CharT>('\t'))
o << "\\t";
else if (c == static_cast<CharT>('\v'))
o << "\\v";
else if (iscntrl_(c))
o << "\\" << static_cast<int>(c);
else
o << static_cast<char>(c);
}
};
// for token types where the comparison with char constants wouldn't work
struct token_printer_aux_for_other_types
{
template<typename CharT>
static void print(std::ostream& o, CharT c)
{
o << c;
}
};
template <typename CharT>
struct token_printer_aux
: mpl::if_<
mpl::and_<
is_convertible<CharT, char>,
is_convertible<char, CharT> >,
token_printer_aux_for_chars,
token_printer_aux_for_other_types
>::type
{
};
template<typename CharT>
inline void token_printer(std::ostream& o, CharT c)
{
#if !defined(BOOST_SPIRIT_DEBUG_TOKEN_PRINTER)
token_printer_aux<CharT>::print(o, c);
#else
BOOST_SPIRIT_DEBUG_TOKEN_PRINTER(o, c);
#endif
}
///////////////////////////////////////////////////////////////////////////////
//
// Dump infos about the parsing state of a rule
//
///////////////////////////////////////////////////////////////////////////////
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
template <typename IteratorT>
inline void
print_node_info(bool hit, int level, bool close, std::string const& name,
IteratorT first, IteratorT last)
{
if (!name.empty())
{
for (int i = 0; i < level; ++i)
BOOST_SPIRIT_DEBUG_OUT << " ";
if (close)
{
if (hit)
BOOST_SPIRIT_DEBUG_OUT << "/";
else
BOOST_SPIRIT_DEBUG_OUT << "#";
}
BOOST_SPIRIT_DEBUG_OUT << name << ":\t\"";
IteratorT iter = first;
IteratorT ilast = last;
for (int j = 0; j < BOOST_SPIRIT_DEBUG_PRINT_SOME; ++j)
{
if (iter == ilast)
break;
token_printer(BOOST_SPIRIT_DEBUG_OUT, *iter);
++iter;
}
BOOST_SPIRIT_DEBUG_OUT << "\"\n";
}
}
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
template <typename ResultT>
inline ResultT &
print_closure_info(ResultT &hit, int level, std::string const& name)
{
if (!name.empty())
{
for (int i = 0; i < level-1; ++i)
BOOST_SPIRIT_DEBUG_OUT << " ";
// for now, print out the return value only
BOOST_SPIRIT_DEBUG_OUT << "^" << name << ":\t";
if (hit.has_valid_attribute())
BOOST_SPIRIT_DEBUG_OUT << hit.value();
else
BOOST_SPIRIT_DEBUG_OUT << "undefined attribute";
BOOST_SPIRIT_DEBUG_OUT << "\n";
}
return hit;
}
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
}
///////////////////////////////////////////////////////////////////////////////
//
// Implementation note: The parser_context_linker, parser_scanner_linker and
// closure_context_linker classes are wrapped by a PP constant to allow
// redefinition of this classes outside of Spirit
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
#define BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED
///////////////////////////////////////////////////////////////////////////
//
// parser_context_linker is a debug wrapper for the ContextT template
// parameter of the rule<>, subrule<> and the grammar<> classes
//
///////////////////////////////////////////////////////////////////////////
template<typename ContextT>
struct parser_context_linker : public ContextT
{
typedef ContextT base_t;
template <typename ParserT>
parser_context_linker(ParserT const& p)
: ContextT(p) {}
template <typename ParserT, typename ScannerT>
void pre_parse(ParserT const& p, ScannerT &scan)
{
this->base_t::pre_parse(p, scan);
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
if (trace_parser(p.derived())) {
impl::print_node_info(
false,
scan.get_level(),
false,
parser_name(p.derived()),
scan.first,
scan.last);
}
scan.get_level()++;
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
}
template <typename ResultT, typename ParserT, typename ScannerT>
ResultT& post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
{
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
--scan.get_level();
if (trace_parser(p.derived())) {
impl::print_node_info(
hit,
scan.get_level(),
true,
parser_name(p.derived()),
scan.first,
scan.last);
}
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_NODES
return this->base_t::post_parse(hit, p, scan);
}
};
#endif // !defined(BOOST_SPIRIT_PARSER_CONTEXT_LINKER_DEFINED)
#if !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
#define BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED
///////////////////////////////////////////////////////////////////////////////
// This class is to avoid linker problems and to ensure a real singleton
// 'level' variable
struct debug_support
{
int& get_level()
{
static int level = 0;
return level;
}
};
template<typename ScannerT>
struct parser_scanner_linker : public ScannerT
{
parser_scanner_linker(ScannerT const &scan_) : ScannerT(scan_)
{}
int &get_level()
{ return debug.get_level(); }
private: debug_support debug;
};
#endif // !defined(BOOST_SPIRIT_PARSER_SCANNER_LINKER_DEFINED)
#if !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
#define BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED
///////////////////////////////////////////////////////////////////////////
//
// closure_context_linker is a debug wrapper for the closure template
// parameter of the rule<>, subrule<> and grammar classes
//
///////////////////////////////////////////////////////////////////////////
template<typename ContextT>
struct closure_context_linker : public parser_context_linker<ContextT>
{
typedef parser_context_linker<ContextT> base_t;
template <typename ParserT>
closure_context_linker(ParserT const& p)
: parser_context_linker<ContextT>(p) {}
template <typename ParserT, typename ScannerT>
void pre_parse(ParserT const& p, ScannerT &scan)
{ this->base_t::pre_parse(p, scan); }
template <typename ResultT, typename ParserT, typename ScannerT>
ResultT&
post_parse(ResultT& hit, ParserT const& p, ScannerT &scan)
{
#if BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
if (hit && trace_parser(p.derived())) {
// for now, print out the return value only
return impl::print_closure_info(
this->base_t::post_parse(hit, p, scan),
scan.get_level(),
parser_name(p.derived())
);
}
#endif // BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES
return this->base_t::post_parse(hit, p, scan);
}
};
#endif // !defined(BOOST_SPIRIT_CLOSURE_CONTEXT_LINKER_DEFINED)
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} // namespace BOOST_SPIRIT_CLASSIC_NS
#endif // defined(BOOST_SPIRIT_DEBUG)
#endif // !defined(BOOST_SPIRIT_DEBUG_NODE_HPP)
+555
View File
@@ -0,0 +1,555 @@
/*=============================================================================
Copyright (c) 2001-2003 Joel de Guzman
Copyright (c) 2002-2003 Hartmut Kaiser
http://spirit.sourceforge.net/
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(BOOST_SPIRIT_PARSER_NAMES_IPP)
#define BOOST_SPIRIT_PARSER_NAMES_IPP
#if defined(BOOST_SPIRIT_DEBUG)
#include <string>
#include <iostream>
#include <map>
#include <boost/config.hpp>
#ifdef BOOST_NO_STRINGSTREAM
#include <strstream>
#define BOOST_SPIRIT_SSTREAM std::strstream
std::string BOOST_SPIRIT_GETSTRING(std::strstream& ss)
{
ss << ends;
std::string rval = ss.str();
ss.freeze(false);
return rval;
}
#else
#include <sstream>
#define BOOST_SPIRIT_GETSTRING(ss) ss.str()
#define BOOST_SPIRIT_SSTREAM std::stringstream
#endif
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
// from actions.hpp
template <typename ParserT, typename ActionT>
inline std::string
parser_name(action<ParserT, ActionT> const& p)
{
return std::string("action")
+ std::string("[")
+ parser_name(p.subject())
+ std::string("]");
}
///////////////////////////////////////////////////////////////////////////////
// from directives.hpp
template <typename ParserT>
inline std::string
parser_name(contiguous<ParserT> const& p)
{
return std::string("contiguous")
+ std::string("[")
+ parser_name(p.subject())
+ std::string("]");
}
template <typename ParserT>
inline std::string
parser_name(inhibit_case<ParserT> const& p)
{
return std::string("inhibit_case")
+ std::string("[")
+ parser_name(p.subject())
+ std::string("]");
}
template <typename A, typename B>
inline std::string
parser_name(longest_alternative<A, B> const& p)
{
return std::string("longest_alternative")
+ std::string("[")
+ parser_name(p.left()) + std::string(", ") + parser_name(p.right())
+ std::string("]");
}
template <typename A, typename B>
inline std::string
parser_name(shortest_alternative<A, B> const& p)
{
return std::string("shortest_alternative")
+ std::string("[")
+ parser_name(p.left()) + std::string(", ") + parser_name(p.right())
+ std::string("]");
}
///////////////////////////////////////////////////////////////////////////////
// from numerics.hpp
template <typename T, int Radix, unsigned MinDigits, int MaxDigits>
inline std::string
parser_name(uint_parser<T, Radix, MinDigits, MaxDigits> const& /*p*/)
{
BOOST_SPIRIT_SSTREAM stream;
stream << Radix << ", " << MinDigits << ", " << MaxDigits;
return std::string("uint_parser<")
+ BOOST_SPIRIT_GETSTRING(stream)
+ std::string(">");
}
template <typename T, int Radix, unsigned MinDigits, int MaxDigits>
inline std::string
parser_name(int_parser<T, Radix, MinDigits, MaxDigits> const& /*p*/)
{
BOOST_SPIRIT_SSTREAM stream;
stream << Radix << ", " << MinDigits << ", " << MaxDigits;
return std::string("int_parser<")
+ BOOST_SPIRIT_GETSTRING(stream)
+ std::string(">");
}
template <typename T, typename RealPoliciesT>
inline std::string
parser_name(real_parser<T, RealPoliciesT> const& /*p*/)
{
return std::string("real_parser");
}
///////////////////////////////////////////////////////////////////////////////
// from operators.hpp
template <typename A, typename B>
inline std::string
parser_name(sequence<A, B> const& p)
{
return std::string("sequence")
+ std::string("[")
+ parser_name(p.left()) + std::string(", ") + parser_name(p.right())
+ std::string("]");
}
template <typename A, typename B>
inline std::string
parser_name(sequential_or<A, B> const& p)
{
return std::string("sequential_or")
+ std::string("[")
+ parser_name(p.left()) + std::string(", ") + parser_name(p.right())
+ std::string("]");
}
template <typename A, typename B>
inline std::string
parser_name(alternative<A, B> const& p)
{
return std::string("alternative")
+ std::string("[")
+ parser_name(p.left()) + std::string(", ") + parser_name(p.right())
+ std::string("]");
}
template <typename A, typename B>
inline std::string
parser_name(intersection<A, B> const& p)
{
return std::string("intersection")
+ std::string("[")
+ parser_name(p.left()) + std::string(", ") + parser_name(p.right())
+ std::string("]");
}
template <typename A, typename B>
inline std::string
parser_name(difference<A, B> const& p)
{
return std::string("difference")
+ std::string("[")
+ parser_name(p.left()) + std::string(", ") + parser_name(p.right())
+ std::string("]");
}
template <typename A, typename B>
inline std::string
parser_name(exclusive_or<A, B> const& p)
{
return std::string("exclusive_or")
+ std::string("[")
+ parser_name(p.left()) + std::string(", ") + parser_name(p.right())
+ std::string("]");
}
template <typename S>
inline std::string
parser_name(optional<S> const& p)
{
return std::string("optional")
+ std::string("[")
+ parser_name(p.subject())
+ std::string("]");
}
template <typename S>
inline std::string
parser_name(kleene_star<S> const& p)
{
return std::string("kleene_star")
+ std::string("[")
+ parser_name(p.subject())
+ std::string("]");
}
template <typename S>
inline std::string
parser_name(positive<S> const& p)
{
return std::string("positive")
+ std::string("[")
+ parser_name(p.subject())
+ std::string("]");
}
///////////////////////////////////////////////////////////////////////////////
// from parser.hpp
template <typename DerivedT>
inline std::string
parser_name(parser<DerivedT> const& /*p*/)
{
return std::string("parser");
}
///////////////////////////////////////////////////////////////////////////////
// from primitives.hpp
template <typename DerivedT>
inline std::string
parser_name(char_parser<DerivedT> const &/*p*/)
{
return std::string("char_parser");
}
template <typename CharT>
inline std::string
parser_name(chlit<CharT> const &p)
{
return std::string("chlit(\'")
+ std::string(1, p.ch)
+ std::string("\')");
}
template <typename CharT>
inline std::string
parser_name(range<CharT> const &p)
{
return std::string("range(")
+ std::string(1, p.first) + std::string(", ") + std::string(1, p.last)
+ std::string(")");
}
template <typename IteratorT>
inline std::string
parser_name(chseq<IteratorT> const &p)
{
return std::string("chseq(\"")
+ std::string(p.first, p.last)
+ std::string("\")");
}
template <typename IteratorT>
inline std::string
parser_name(strlit<IteratorT> const &p)
{
return std::string("strlit(\"")
+ std::string(p.seq.first, p.seq.last)
+ std::string("\")");
}
inline std::string
parser_name(nothing_parser const&)
{
return std::string("nothing");
}
inline std::string
parser_name(epsilon_parser const&)
{
return std::string("epsilon");
}
inline std::string
parser_name(anychar_parser const&)
{
return std::string("anychar");
}
inline std::string
parser_name(alnum_parser const&)
{
return std::string("alnum");
}
inline std::string
parser_name(alpha_parser const&)
{
return std::string("alpha");
}
inline std::string
parser_name(cntrl_parser const&)
{
return std::string("cntrl");
}
inline std::string
parser_name(digit_parser const&)
{
return std::string("digit");
}
inline std::string
parser_name(graph_parser const&)
{
return std::string("graph");
}
inline std::string
parser_name(lower_parser const&)
{
return std::string("lower");
}
inline std::string
parser_name(print_parser const&)
{
return std::string("print");
}
inline std::string
parser_name(punct_parser const&)
{
return std::string("punct");
}
inline std::string
parser_name(blank_parser const&)
{
return std::string("blank");
}
inline std::string
parser_name(space_parser const&)
{
return std::string("space");
}
inline std::string
parser_name(upper_parser const&)
{
return std::string("upper");
}
inline std::string
parser_name(xdigit_parser const&)
{
return std::string("xdigit");
}
inline std::string
parser_name(eol_parser const&)
{
return std::string("eol");
}
inline std::string
parser_name(end_parser const&)
{
return std::string("end");
}
///////////////////////////////////////////////////////////////////////////////
// from rule.hpp
namespace impl {
struct node_registry
{
typedef std::pair<std::string, bool> rule_info;
typedef std::map<void const *, rule_info> rule_infos;
std::string find_node(void const *r)
{
rule_infos::const_iterator cit = infos.find(r);
if (cit != infos.end())
return (*cit).second.first;
return std::string("<unknown>");
}
bool trace_node(void const *r)
{
rule_infos::const_iterator cit = infos.find(r);
if (cit != infos.end())
return (*cit).second.second;
return BOOST_SPIRIT_DEBUG_TRACENODE;
}
bool register_node(void const *r, char const *name_to_register,
bool trace_node)
{
if (infos.find(r) != infos.end())
return false;
return infos.insert(rule_infos::value_type(r,
rule_info(std::string(name_to_register), trace_node))
).second;
}
bool unregister_node(void const *r)
{
if (infos.find(r) == infos.end())
return false;
return (1 == infos.erase(r));
}
private:
rule_infos infos;
};
inline node_registry &
get_node_registry()
{
static node_registry node_infos;
return node_infos;
}
} // namespace impl
template<
typename DerivedT, typename EmbedT,
typename T0, typename T1, typename T2
>
inline std::string
parser_name(impl::rule_base<DerivedT, EmbedT, T0, T1, T2> const& p)
{
return std::string("rule_base")
+ std::string("(")
+ impl::get_node_registry().find_node(&p)
+ std::string(")");
}
template<typename T0, typename T1, typename T2>
inline std::string
parser_name(rule<T0, T1, T2> const& p)
{
return std::string("rule")
+ std::string("(")
+ impl::get_node_registry().find_node(&p)
+ std::string(")");
}
///////////////////////////////////////////////////////////////////////////////
// from subrule.hpp
template <typename FirstT, typename RestT>
inline std::string
parser_name(subrule_list<FirstT, RestT> const &p)
{
return std::string("subrule_list")
+ std::string("(")
+ impl::get_node_registry().find_node(&p)
+ std::string(")");
}
template <int ID, typename DefT, typename ContextT>
inline std::string
parser_name(subrule_parser<ID, DefT, ContextT> const &p)
{
return std::string("subrule_parser")
+ std::string("(")
+ impl::get_node_registry().find_node(&p)
+ std::string(")");
}
template <int ID, typename ContextT>
inline std::string
parser_name(subrule<ID, ContextT> const &p)
{
BOOST_SPIRIT_SSTREAM stream;
stream << ID;
return std::string("subrule<")
+ BOOST_SPIRIT_GETSTRING(stream)
+ std::string(">(")
+ impl::get_node_registry().find_node(&p)
+ std::string(")");
}
///////////////////////////////////////////////////////////////////////////////
// from grammar.hpp
template <typename DerivedT, typename ContextT>
inline std::string
parser_name(grammar<DerivedT, ContextT> const& p)
{
return std::string("grammar")
+ std::string("(")
+ impl::get_node_registry().find_node(&p)
+ std::string(")");
}
///////////////////////////////////////////////////////////////////////////////
// decide, if a node is to be traced or not
template<
typename DerivedT, typename EmbedT,
typename T0, typename T1, typename T2
>
inline bool
trace_parser(impl::rule_base<DerivedT, EmbedT, T0, T1, T2>
const& p)
{
return impl::get_node_registry().trace_node(&p);
}
template<typename T0, typename T1, typename T2>
inline bool
trace_parser(rule<T0, T1, T2> const& p)
{
return impl::get_node_registry().trace_node(&p);
}
template <typename DerivedT, typename ContextT>
inline bool
trace_parser(grammar<DerivedT, ContextT> const& p)
{
return impl::get_node_registry().trace_node(&p);
}
template <typename DerivedT, int N, typename ContextT>
inline bool
trace_parser(impl::entry_grammar<DerivedT, N, ContextT> const& p)
{
return impl::get_node_registry().trace_node(&p);
}
template <int ID, typename ContextT>
bool
trace_parser(subrule<ID, ContextT> const& p)
{
return impl::get_node_registry().trace_node(&p);
}
template <typename ParserT, typename ActorTupleT>
bool
trace_parser(init_closure_parser<ParserT, ActorTupleT> const& p)
{
return impl::get_node_registry().trace_node(&p);
}
///////////////////////////////////////////////////////////////////////////////
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} // namespace boost::spirit
#undef BOOST_SPIRIT_SSTREAM
#undef BOOST_SPIRIT_GETSTRING
#endif // defined(BOOST_SPIRIT_DEBUG)
#endif // !defined(BOOST_SPIRIT_PARSER_NAMES_IPP)
+81
View File
@@ -0,0 +1,81 @@
/*=============================================================================
Copyright (c) 2001-2003 Joel de Guzman
Copyright (c) 2002-2003 Hartmut Kaiser
http://spirit.sourceforge.net/
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(BOOST_SPIRIT_MINIMAL_DEBUG_HPP)
#define BOOST_SPIRIT_MINIMAL_DEBUG_HPP
#if !defined(BOOST_SPIRIT_DEBUG_MAIN_HPP)
#error "You must include boost/spirit/debug.hpp, not boost/spirit/debug/minimal.hpp"
#endif
///////////////////////////////////////////////////////////////////////////////
//
// Minimum debugging tools support
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_SPIRIT_DEBUG_OUT)
#define BOOST_SPIRIT_DEBUG_OUT std::cout
#endif
///////////////////////////////////////////////////////////////////////////
//
// BOOST_SPIRIT_DEBUG_FLAGS controls the level of diagnostics printed
//
///////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_SPIRIT_DEBUG_FLAGS_NONE)
#define BOOST_SPIRIT_DEBUG_FLAGS_NONE 0x0000 // no diagnostics at all
#endif
#if !defined(BOOST_SPIRIT_DEBUG_FLAGS_MAX)
#define BOOST_SPIRIT_DEBUG_FLAGS_MAX 0xFFFF // print maximal diagnostics
#endif
#if !defined(BOOST_SPIRIT_DEBUG_FLAGS)
#define BOOST_SPIRIT_DEBUG_FLAGS BOOST_SPIRIT_DEBUG_FLAGS_MAX
#endif
#if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME)
#define BOOST_SPIRIT_DEBUG_PRINT_SOME 20
#endif
#if !defined(BOOST_SPIRIT_DEBUG_RULE)
#define BOOST_SPIRIT_DEBUG_RULE(r)
#endif // !defined(BOOST_SPIRIT_DEBUG_RULE)
#if !defined(BOOST_SPIRIT_DEBUG_NODE)
#define BOOST_SPIRIT_DEBUG_NODE(r)
#endif // !defined(BOOST_SPIRIT_DEBUG_NODE)
#if !defined(BOOST_SPIRIT_DEBUG_GRAMMAR)
#define BOOST_SPIRIT_DEBUG_GRAMMAR(r)
#endif // !defined(BOOST_SPIRIT_DEBUG_GRAMMAR)
#if !defined(BOOST_SPIRIT_DEBUG_TRACE_RULE)
#define BOOST_SPIRIT_DEBUG_TRACE_RULE(r, t)
#endif // !defined(BOOST_SPIRIT_DEBUG_TRACE_RULE)
#if !defined(BOOST_SPIRIT_DEBUG_TRACE_NODE)
#define BOOST_SPIRIT_DEBUG_TRACE_NODE(r, t)
#endif // !defined(BOOST_SPIRIT_DEBUG_TRACE_NODE)
#if !defined(BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR)
#define BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR(r, t)
#endif // !defined(BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR)
#if !defined(BOOST_SPIRIT_DEBUG_TRACE_RULE_NAME)
#define BOOST_SPIRIT_DEBUG_TRACE_RULE_NAME(r, n, t)
#endif // !defined(BOOST_SPIRIT_DEBUG_TRACE_RULE_NAME)
#if !defined(BOOST_SPIRIT_DEBUG_TRACE_NODE_NAME)
#define BOOST_SPIRIT_DEBUG_TRACE_NODE_NAME(r, n, t)
#endif // !defined(BOOST_SPIRIT_DEBUG_TRACE_NODE_NAME)
#if !defined(BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME)
#define BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(r, n, t)
#endif // !defined(BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME)
#endif // !defined(BOOST_SPIRIT_MINIMAL_DEBUG_HPP)
+254
View File
@@ -0,0 +1,254 @@
/*=============================================================================
Copyright (c) 2001-2003 Joel de Guzman
Copyright (c) 2002-2003 Hartmut Kaiser
http://spirit.sourceforge.net/
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(BOOST_SPIRIT_PARSER_NAMES_HPP)
#define BOOST_SPIRIT_PARSER_NAMES_HPP
#if defined(BOOST_SPIRIT_DEBUG)
//////////////////////////////////
#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/core.hpp>
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
//
// Declaration of helper functions, which return the name of a concrete
// parser instance. The functions are specialized on the parser types. The
// functions declared in this file are for the predefined parser types from
// the Spirit core library only, so additional functions might be provided as
// needed.
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// from actions.hpp
template <typename ParserT, typename ActionT>
std::string
parser_name(action<ParserT, ActionT> const& p);
///////////////////////////////////////////////////////////////////////////////
// from directives.hpp
template <typename ParserT>
std::string
parser_name(contiguous<ParserT> const& p);
template <typename ParserT>
std::string
parser_name(inhibit_case<ParserT> const& p);
template <typename A, typename B>
std::string
parser_name(longest_alternative<A, B> const& p);
template <typename A, typename B>
std::string
parser_name(shortest_alternative<A, B> const& p);
///////////////////////////////////////////////////////////////////////////////
// from grammar.hpp
template <typename DerivedT, typename ContextT>
std::string
parser_name(grammar<DerivedT, ContextT> const& p);
///////////////////////////////////////////////////////////////////////////////
// from numerics.hpp
template <typename T, int Radix, unsigned MinDigits, int MaxDigits>
std::string
parser_name(uint_parser<T, Radix, MinDigits, MaxDigits> const& p);
template <typename T, int Radix, unsigned MinDigits, int MaxDigits>
std::string
parser_name(int_parser<T, Radix, MinDigits, MaxDigits> const& p);
template <typename T, typename RealPoliciesT>
std::string
parser_name(real_parser<T, RealPoliciesT> const& p);
///////////////////////////////////////////////////////////////////////////////
// from operators.hpp
template <typename A, typename B>
std::string
parser_name(sequence<A, B> const& p);
template <typename A, typename B>
std::string
parser_name(sequential_or<A, B> const& p);
template <typename A, typename B>
std::string
parser_name(alternative<A, B> const& p);
template <typename A, typename B>
std::string
parser_name(intersection<A, B> const& p);
template <typename A, typename B>
std::string
parser_name(difference<A, B> const& p);
template <typename A, typename B>
std::string
parser_name(exclusive_or<A, B> const& p);
template <typename S>
std::string
parser_name(optional<S> const& p);
template <typename S>
std::string
parser_name(kleene_star<S> const& p);
template <typename S>
std::string
parser_name(positive<S> const& p);
///////////////////////////////////////////////////////////////////////////////
// from parser.hpp
template <typename DerivedT>
std::string
parser_name(parser<DerivedT> const& p);
///////////////////////////////////////////////////////////////////////////////
// from primitives.hpp
template <typename DerivedT>
std::string
parser_name(char_parser<DerivedT> const &p);
template <typename CharT>
std::string
parser_name(chlit<CharT> const &p);
template <typename CharT>
std::string
parser_name(range<CharT> const &p);
template <typename IteratorT>
std::string
parser_name(chseq<IteratorT> const &p);
template <typename IteratorT>
std::string
parser_name(strlit<IteratorT> const &p);
std::string
parser_name(nothing_parser const &p);
std::string
parser_name(epsilon_parser const &p);
std::string
parser_name(anychar_parser const &p);
std::string
parser_name(alnum_parser const &p);
std::string
parser_name(alpha_parser const &p);
std::string
parser_name(cntrl_parser const &p);
std::string
parser_name(digit_parser const &p);
std::string
parser_name(graph_parser const &p);
std::string
parser_name(lower_parser const &p);
std::string
parser_name(print_parser const &p);
std::string
parser_name(punct_parser const &p);
std::string
parser_name(blank_parser const &p);
std::string
parser_name(space_parser const &p);
std::string
parser_name(upper_parser const &p);
std::string
parser_name(xdigit_parser const &p);
std::string
parser_name(eol_parser const &p);
std::string
parser_name(end_parser const &p);
///////////////////////////////////////////////////////////////////////////////
// from rule.hpp
template<typename T0, typename T1, typename T2>
std::string
parser_name(rule<T0, T1, T2> const& p);
///////////////////////////////////////////////////////////////////////////////
// from subrule.hpp
template <typename FirstT, typename RestT>
std::string
parser_name(subrule_list<FirstT, RestT> const &p);
template <int ID, typename DefT, typename ContextT>
std::string
parser_name(subrule_parser<ID, DefT, ContextT> const &p);
template <int ID, typename ContextT>
std::string
parser_name(subrule<ID, ContextT> const &p);
///////////////////////////////////////////////////////////////////////////////
// from chset.hpp
///////////////////////////////////////////////////////////////////////////////
//
// Decide, if a node is to be traced or not
//
///////////////////////////////////////////////////////////////////////////////
template<
typename DerivedT, typename EmbedT,
typename T0, typename T1, typename T2
>
bool
trace_parser(impl::rule_base<DerivedT, EmbedT, T0, T1, T2>
const& p);
template <typename DerivedT, typename ContextT>
bool
trace_parser(grammar<DerivedT, ContextT> const& p);
template <int ID, typename ContextT>
bool
trace_parser(subrule<ID, ContextT> const& p);
template <typename ParserT, typename ActorTupleT>
struct init_closure_parser;
template <typename ParserT, typename ActorTupleT>
bool
trace_parser(init_closure_parser<ParserT, ActorTupleT> const& p);
///////////////////////////////////////////////////////////////////////////////
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} // namespace BOOST_SPIRIT_CLASSIC_NS
//////////////////////////////////
#include <boost/spirit/home/classic/debug/impl/parser_names.ipp>
#endif // defined(BOOST_SPIRIT_DEBUG)
#endif // !defined(BOOST_SPIRIT_PARSER_NAMES_HPP)
+37
View File
@@ -0,0 +1,37 @@
/*=============================================================================
Copyright (c) 2006 Tobias Schwinger
http://spirit.sourceforge.net/
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(BOOST_SPIRIT_DEBUG_TYPEOF_HPP)
#define BOOST_SPIRIT_DEBUG_TYPEOF_HPP
#include <boost/typeof/typeof.hpp>
#include <boost/spirit/home/classic/namespace.hpp>
#include <boost/spirit/home/classic/core/typeof.hpp>
namespace boost { namespace spirit {
BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
// debug_node.hpp
template<typename ContextT> struct parser_context_linker;
template<typename ScannerT> struct scanner_context_linker;
template<typename ContextT> struct closure_context_linker;
BOOST_SPIRIT_CLASSIC_NAMESPACE_END
}} // namespace BOOST_SPIRIT_CLASSIC_NS
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
// debug_node.hpp
BOOST_TYPEOF_REGISTER_TEMPLATE(BOOST_SPIRIT_CLASSIC_NS::parser_context_linker,1)
BOOST_TYPEOF_REGISTER_TEMPLATE(BOOST_SPIRIT_CLASSIC_NS::scanner_context_linker,1)
BOOST_TYPEOF_REGISTER_TEMPLATE(BOOST_SPIRIT_CLASSIC_NS::closure_context_linker,1)
#endif