mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-07-28 02:57:56 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4491ef39c2 | |||
| 74a64b6fbd | |||
| 5f55fa68f1 | |||
| dc37543f83 | |||
| fe11646cd6 | |||
| 782115d644 | |||
| 6763dcdc26 | |||
| 1fc6ab77ed | |||
| 80e4886d4f | |||
| f3360cf6d6 | |||
| 6a9739ff1e | |||
| a3ded61946 | |||
| ad9589e444 | |||
| 8e996960fe | |||
| 4263f319c4 | |||
| 3eba06a73b | |||
| bd59c4052d | |||
| beacad1a10 | |||
| d728e10923 | |||
| c61c773fb9 | |||
| 05aa533e3b | |||
| 58acc52fa2 | |||
| 669e3604f3 | |||
| 7a7d1f33d9 | |||
| 9f4a247048 | |||
| fdd09f2170 | |||
| fdb9ebb5de | |||
| 33bff44b39 | |||
| 150995baea | |||
| 583aaa9627 | |||
| 9d2884b608 | |||
| a3ba4e7642 | |||
| 573db07ce7 | |||
| 7c1d2e53d4 | |||
| ee149feef1 | |||
| 04d2f2e189 | |||
| 6b3d54b9d5 | |||
| ba1754d59b | |||
| b89f00d310 | |||
| 19d9cb23d3 |
@@ -188,3 +188,6 @@ UpgradeLog*.htm
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# Python cache
|
||||
__pycache__/
|
||||
|
||||
+44
-50
@@ -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
@@ -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
@@ -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
@@ -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,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user