diff --git a/MTApiService/MTApiService.csproj b/MTApiService/MTApiService.csproj index 64c83838..b99a1f50 100755 --- a/MTApiService/MTApiService.csproj +++ b/MTApiService/MTApiService.csproj @@ -44,14 +44,15 @@ MtApiKey.snk - - ..\packages\log4net.2.0.5\lib\net40-full\log4net.dll - True + + ..\packages\log4net.2.0.12\lib\net40\log4net.dll + + diff --git a/MTApiService/packages.config b/MTApiService/packages.config index d67e57f9..0066004f 100644 --- a/MTApiService/packages.config +++ b/MTApiService/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MetaTraderApi_2017.sln b/MetaTraderApi_2017.sln index d8351e85..4010dd14 100644 --- a/MetaTraderApi_2017.sln +++ b/MetaTraderApi_2017.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30413.136 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApiClientUI", "TestClients\TestApiClientUI\TestApiClientUI.csproj", "{663CC515-EAAE-47D4-8933-5008C2DA1160}" EndProject @@ -47,6 +47,8 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "MtApiBootstrapper", "MtApiB {78B94552-DB17-40EC-B7C6-23D32DB85DC1} = {78B94552-DB17-40EC-B7C6-23D32DB85DC1} EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MtApiServiceNetCore", "MtApiServiceNetCore\MtApiServiceNetCore.csproj", "{7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -232,6 +234,22 @@ Global {8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x64.ActiveCfg = Release|x86 {8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x86.ActiveCfg = Release|x86 {8E63046B-56E5-4623-8808-558AD72A8F2B}.Release|x86.Build.0 = Release|x86 + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Debug|Win32.ActiveCfg = Debug|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Debug|Win32.Build.0 = Debug|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Debug|x64.ActiveCfg = Debug|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Debug|x64.Build.0 = Debug|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Debug|x86.ActiveCfg = Debug|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Debug|x86.Build.0 = Debug|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Release|Any CPU.Build.0 = Release|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Release|Win32.ActiveCfg = Release|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Release|Win32.Build.0 = Release|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Release|x64.ActiveCfg = Release|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Release|x64.Build.0 = Release|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Release|x86.ActiveCfg = Release|Any CPU + {7CAFAAE2-0C15-479A-B16D-C2FCE0A48E11}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -241,4 +259,7 @@ Global {38B9C657-BC2F-44F0-8824-54B31F2A64F5} = {B91FF338-E05D-4EF1-948B-A2376DB37ECA} {EB7C228D-9494-4985-845E-B8312450DF3D} = {B91FF338-E05D-4EF1-948B-A2376DB37ECA} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {23C8878C-16A5-47DF-9A57-73CCF847780D} + EndGlobalSection EndGlobal diff --git a/MtApi5/IMqlRates.cs b/MtApi5/IMqlRates.cs new file mode 100644 index 00000000..c9f1e94c --- /dev/null +++ b/MtApi5/IMqlRates.cs @@ -0,0 +1,18 @@ +// ReSharper disable InconsistentNaming +using System; + +namespace MtApi5 +{ + public interface IMqlRates + { + double close { get; set; } + double high { get; set; } + double low { get; set; } + long mt_time { get; set; } + double open { get; set; } + long real_volume { get; set; } + int spread { get; set; } + long tick_volume { get; set; } + DateTime time { get; } + } +} \ No newline at end of file diff --git a/MtApi5/IMqlTradeRequest.cs b/MtApi5/IMqlTradeRequest.cs new file mode 100644 index 00000000..237d1895 --- /dev/null +++ b/MtApi5/IMqlTradeRequest.cs @@ -0,0 +1,27 @@ +// ReSharper disable InconsistentNaming +using System; + +namespace MtApi5 +{ + public interface IMqlTradeRequest + { + ENUM_TRADE_REQUEST_ACTIONS Action { get; set; } + string Comment { get; set; } + ulong Deviation { get; set; } + DateTime Expiration { get; set; } + ulong Magic { get; set; } + int MtExpiration { get; } + ulong Order { get; set; } + ulong Position { get; set; } + ulong PositionBy { get; set; } + double Price { get; set; } + double Sl { get; set; } + double Stoplimit { get; set; } + string Symbol { get; set; } + double Tp { get; set; } + ENUM_ORDER_TYPE Type { get; set; } + ENUM_ORDER_TYPE_FILLING Type_filling { get; set; } + ENUM_ORDER_TYPE_TIME Type_time { get; set; } + double Volume { get; set; } + } +} \ No newline at end of file diff --git a/MtApi5/IMqlTradeResult.cs b/MtApi5/IMqlTradeResult.cs new file mode 100644 index 00000000..c334019a --- /dev/null +++ b/MtApi5/IMqlTradeResult.cs @@ -0,0 +1,17 @@ +// ReSharper disable InconsistentNaming + +namespace MtApi5 +{ + public interface IMqlTradeResult + { + double Ask { get; } + double Bid { get; } + string Comment { get; } + ulong Deal { get; } + ulong Order { get; } + double Price { get; } + uint Request_id { get; } + uint Retcode { get; } + double Volume { get; } + } +} \ No newline at end of file diff --git a/MtApi5/IMqlTradeTransaction.cs b/MtApi5/IMqlTradeTransaction.cs new file mode 100644 index 00000000..30aadbea --- /dev/null +++ b/MtApi5/IMqlTradeTransaction.cs @@ -0,0 +1,25 @@ +using System; + +namespace MtApi5 +{ + public interface IMqlTradeTransaction + { + ulong Deal { get; set; } + ENUM_DEAL_TYPE DealType { get; set; } + int MtTimeExpiration { get; } + ulong Order { get; set; } + ENUM_ORDER_STATE OrderState { get; set; } + ENUM_ORDER_TYPE OrderType { get; set; } + ulong Position { get; set; } + ulong PositionBy { get; set; } + double Price { get; set; } + double PriceSl { get; set; } + double PriceTp { get; set; } + double PriceTrigger { get; set; } + string Symbol { get; set; } + DateTime TimeExpiration { get; set; } + ENUM_ORDER_TYPE_TIME TimeType { get; set; } + ENUM_TRADE_TRANSACTION_TYPE Type { get; set; } + double Volume { get; set; } + } +} \ No newline at end of file diff --git a/MtApi5/IMt5Quote.cs b/MtApi5/IMt5Quote.cs new file mode 100644 index 00000000..0e542da0 --- /dev/null +++ b/MtApi5/IMt5Quote.cs @@ -0,0 +1,15 @@ +using System; + +namespace MtApi5 +{ + public interface IMt5Quote + { + double Ask { get; } + double Bid { get; } + int ExpertHandle { get; set; } + string Instrument { get; } + double Last { get; set; } + DateTime Time { get; set; } + ulong Volume { get; set; } + } +} \ No newline at end of file diff --git a/MtApi5/IMtApi5Client.cs b/MtApi5/IMtApi5Client.cs new file mode 100644 index 00000000..cd0e5293 --- /dev/null +++ b/MtApi5/IMtApi5Client.cs @@ -0,0 +1,243 @@ +// ReSharper disable InconsistentNaming +using System; +using System.Collections.Generic; + +namespace MtApi5 +{ + public interface IMtApi5Client + { + Mt5ConnectionState ConnectionState { get; } + int ExecutorHandle { get; set; } + + event EventHandler ConnectionStateChanged; + event EventHandler OnBookEvent; + event EventHandler OnLastTimeBar; + event EventHandler OnLockTicks; + event EventHandler OnTradeTransaction; + event EventHandler QuoteAdded; + event EventHandler QuoteRemoved; + event EventHandler QuoteUpdate; + event MtApi5Client.QuoteHandler QuoteUpdated; + + double AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE propertyId); + long AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER propertyId); + string AccountInfoString(ENUM_ACCOUNT_INFO_STRING propertyId); + void Alert(string message); + int Bars(string symbolName, ENUM_TIMEFRAMES timeframe); + int Bars(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime); + int BarsCalculated(int indicatorHandle); + void BeginConnect(int port); + void BeginConnect(string host, int port); + void BeginDisconnect(); + bool Buy(out MqlTradeResult result, double volume, string symbol = null, double price = 0, double sl = 0, double tp = 0, string comment = null); + bool ChartApplyTemplate(long chartId, string filename); + bool ChartClose(long chartId = 0); + long ChartFirst(); + double ChartGetDouble(long chartId, ENUM_CHART_PROPERTY_DOUBLE propId, int subWindow = 0); + long ChartGetInteger(long chartId, ENUM_CHART_PROPERTY_INTEGER propId, int subWindow = 0); + string ChartGetString(long chartId, ENUM_CHART_PROPERTY_STRING propId); + long ChartId(); + long ChartId(int expertHandle); + bool ChartIndicatorAdd(long chartId, int subWindow, int indicatorHandle); + bool ChartIndicatorDelete(long chartId, int subWindow, string indicatorShortname); + int ChartIndicatorGet(long chartId, int subWindow, string indicatorShortname); + string ChartIndicatorName(long chartId, int subWindow, int index); + int ChartIndicatorsTotal(long chartId, int subWindow); + bool ChartNavigate(long chartId, ENUM_CHART_POSITION position, int shift = 0); + long ChartNext(long chartId); + long ChartOpen(string symbol, ENUM_TIMEFRAMES period); + ENUM_TIMEFRAMES ChartPeriod(long chartId); + double ChartPriceOnDropped(); + void ChartRedraw(long chartId = 0); + bool ChartSaveTemplate(long chartId, string filename); + bool ChartScreenShot(long chartId, string filename, int width, int height, ENUM_ALIGN_MODE alignMode = ENUM_ALIGN_MODE.ALIGN_RIGHT); + bool ChartSetDouble(long chartId, ENUM_CHART_PROPERTY_DOUBLE propId, double value); + bool ChartSetInteger(long chartId, ENUM_CHART_PROPERTY_INTEGER propId, long value); + bool ChartSetString(long chartId, ENUM_CHART_PROPERTY_STRING propId, string value); + bool ChartSetSymbolPeriod(long chartId, string symbol, ENUM_TIMEFRAMES period); + string ChartSymbol(long chartId); + DateTime ChartTimeOnDropped(); + bool ChartTimePriceToXY(long chartId, int subWindow, DateTime? time, double price, out int x, out int y); + int ChartWindowFind(long chartId, string indicatorShortname); + int ChartWindowOnDropped(); + int ChartXOnDropped(); + bool ChartXYToTimePrice(long chartId, int x, int y, out int subWindow, out DateTime? time, out double price); + int ChartYOnDropped(); + int CopyBuffer(int indicatorHandle, int bufferNum, DateTime startTime, DateTime stopTime, out double[] buffer); + int CopyBuffer(int indicatorHandle, int bufferNum, DateTime startTime, int count, out double[] buffer); + int CopyBuffer(int indicatorHandle, int bufferNum, int startPos, int count, out double[] buffer); + int CopyClose(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out double[] closeArray); + int CopyClose(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out double[] closeArray); + int CopyClose(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out double[] closeArray); + int CopyHigh(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out double[] highArray); + int CopyHigh(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out double[] highArray); + int CopyHigh(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out double[] highArray); + int CopyLow(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out double[] lowArray); + int CopyLow(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out double[] lowArray); + int CopyLow(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out double[] lowArray); + int CopyOpen(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out double[] openArray); + int CopyOpen(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out double[] openArray); + int CopyOpen(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out double[] openArray); + int CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out MqlRates[] ratesArray); + int CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out MqlRates[] ratesArray); + int CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out MqlRates[] ratesArray); + int CopyRealVolume(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out long[] volumeArray); + int CopyRealVolume(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out long[] volumeArray); + int CopyRealVolume(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out long[] volumeArray); + int CopySpread(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out int[] spreadArray); + int CopySpread(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out int[] spreadArray); + int CopySpread(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out int[] spreadArray); + List CopyTicks(string symbolName, CopyTicksFlag flags = CopyTicksFlag.All, ulong from = 0, uint count = 0); + int CopyTickVolume(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out long[] volumeArray); + int CopyTickVolume(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out long[] volumeArray); + int CopyTickVolume(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out long[] volumeArray); + int CopyTime(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, DateTime stopTime, out DateTime[] timeArray); + int CopyTime(string symbolName, ENUM_TIMEFRAMES timeframe, DateTime startTime, int count, out DateTime[] timeArray); + int CopyTime(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, int count, out DateTime[] timeArray); + int GetLastError(); + IEnumerable GetQuotes(); + bool GlobalVariableCheck(string name); + bool GlobalVariableDel(string name); + double GlobalVariableGet(string name); + string GlobalVariableName(int index); + int GlobalVariablesDeleteAll(string prefixName = "", DateTime? limitData = null); + DateTime GlobalVariableSet(string name, double value); + bool GlobalVariableSetOnCondition(string name, double value, double checkValue); + void GlobalVariablesFlush(); + int GlobalVariablesTotal(); + bool GlobalVariableTemp(string name); + DateTime GlobalVariableTime(string name); + double HistoryDealGetDouble(ulong ticketNumber, ENUM_DEAL_PROPERTY_DOUBLE propertyId); + long HistoryDealGetInteger(ulong ticketNumber, ENUM_DEAL_PROPERTY_INTEGER propertyId); + string HistoryDealGetString(ulong ticketNumber, ENUM_DEAL_PROPERTY_STRING propertyId); + ulong HistoryDealGetTicket(int index); + bool HistoryDealSelect(ulong ticket); + int HistoryDealsTotal(); + double HistoryOrderGetDouble(ulong ticketNumber, ENUM_ORDER_PROPERTY_DOUBLE propertyId); + long HistoryOrderGetInteger(ulong ticketNumber, ENUM_ORDER_PROPERTY_INTEGER propertyId); + string HistoryOrderGetString(ulong ticketNumber, ENUM_ORDER_PROPERTY_STRING propertyId); + ulong HistoryOrderGetTicket(int index); + bool HistoryOrderSelect(ulong ticket); + int HistoryOrdersTotal(); + bool HistorySelect(DateTime fromDate, DateTime toDate); + bool HistorySelectByPosition(long positionId); + int iAC(string symbol, ENUM_TIMEFRAMES period); + int iAD(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME appliedVolume); + int iADX(string symbol, ENUM_TIMEFRAMES period, int adxPeriod); + int iADXWilder(string symbol, ENUM_TIMEFRAMES period, int adxPeriod); + int iAlligator(string symbol, ENUM_TIMEFRAMES period, int jawPeriod, int jawShift, int teethPeriod, int teethShift, int lipsPeriod, int lipsShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice); + int iAMA(string symbol, ENUM_TIMEFRAMES period, int amaPeriod, int fastMaPeriod, int slowMaPeriod, int amaShift, ENUM_APPLIED_PRICE appliedPrice); + int iAO(string symbol, ENUM_TIMEFRAMES period); + int iATR(string symbol, ENUM_TIMEFRAMES period, int maPeriod); + int iBands(string symbol, ENUM_TIMEFRAMES period, int bandsPeriod, int bandsShift, double deviation, ENUM_APPLIED_PRICE appliedPrice); + int iBearsPower(string symbol, ENUM_TIMEFRAMES period, int maPeriod); + int iBullsPower(string symbol, ENUM_TIMEFRAMES period, int maPeriod); + int iBWMFI(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME appliedVolume); + int iCCI(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_APPLIED_PRICE appliedPrice); + int iChaikin(string symbol, ENUM_TIMEFRAMES period, int fastMaPeriod, int slowMaPeriod, ENUM_MA_METHOD maMethod, ENUM_APPLIED_VOLUME appliedVolume); + int iCustom(string symbol, ENUM_TIMEFRAMES period, string name, bool[] parameters); + int iCustom(string symbol, ENUM_TIMEFRAMES period, string name, double[] parameters); + int iCustom(string symbol, ENUM_TIMEFRAMES period, string name, int[] parameters); + int iCustom(string symbol, ENUM_TIMEFRAMES period, string name, string[] parameters); + int iDEMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_APPLIED_PRICE appliedPrice); + int iDeMarker(string symbol, ENUM_TIMEFRAMES period, int maPeriod); + int iEnvelopes(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice, double deviation); + int iForce(string symbol, ENUM_TIMEFRAMES period); + int iForce(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_MA_METHOD maMethod, ENUM_APPLIED_VOLUME appliedVolume); + int iFrAMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_APPLIED_PRICE appliedPrice); + int iGator(string symbol, ENUM_TIMEFRAMES period, int jawPeriod, int jawShift, int teethPeriod, int teethShift, int lipsPeriod, int lipsShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice); + int iIchimoku(string symbol, ENUM_TIMEFRAMES period, int tenkanSen, int kijunSen, int senkouSpanB); + int iMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice); + int iMACD(string symbol, ENUM_TIMEFRAMES period, int fastEmaPeriod, int slowEmaPeriod, int signalPeriod, ENUM_APPLIED_PRICE appliedPrice); + int iMFI(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_APPLIED_VOLUME appliedVolume); + int iMomentum(string symbol, ENUM_TIMEFRAMES period, int momPeriod, ENUM_APPLIED_PRICE appliedPrice); + int IndicatorCreate(string symbol, ENUM_TIMEFRAMES period, ENUM_INDICATOR indicatorType, List parameters = null); + bool IndicatorRelease(int indicatorHandle); + int iOBV(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME appliedVolume); + int iOsMA(string symbol, ENUM_TIMEFRAMES period, int fastEmaPeriod, int slowEmaPeriod, int signalPeriod, ENUM_APPLIED_PRICE appliedPrice); + int iRSI(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_APPLIED_PRICE appliedPrice); + int iRVI(string symbol, ENUM_TIMEFRAMES period, int maPeriod); + int iSAR(string symbol, ENUM_TIMEFRAMES period, double step, double maximum); + int iStdDev(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice); + bool IsTesting(); + int iStochastic(string symbol, ENUM_TIMEFRAMES period, int Kperiod, int Dperiod, int slowing, ENUM_MA_METHOD maMethod, ENUM_STO_PRICE priceField); + int iTEMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShift, ENUM_APPLIED_PRICE appliedPrice); + int iTriX(string symbol, ENUM_TIMEFRAMES period, int maPeriod, ENUM_APPLIED_PRICE appliedPrice); + int iVIDyA(string symbol, ENUM_TIMEFRAMES period, int cmoPeriod, int emaPeriod, int maShift, ENUM_APPLIED_PRICE appliedPrice); + int iVolumes(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME appliedVolume); + int iWPR(string symbol, ENUM_TIMEFRAMES period, int calcPeriod); + bool MarketBookAdd(string symbol); + bool MarketBookGet(string symbol, out MqlBookInfo[] book); + bool MarketBookRelease(string symbol); + bool ObjectCreate(long chartId, string name, ENUM_OBJECT type, int nwin, DateTime time, double price, List> listOfCoordinates = null); + bool ObjectDelete(long chartId, string name); + int ObjectFind(long chartId, string name); + double ObjectGetDouble(long chartId, string name, ENUM_OBJECT_PROPERTY_DOUBLE propId); + long ObjectGetInteger(long chartId, string name, ENUM_OBJECT_PROPERTY_INTEGER propId); + string ObjectGetString(long chartId, string name, ENUM_OBJECT_PROPERTY_STRING propId); + DateTime ObjectGetTimeByValue(long chartId, string name, double value, int lineId); + double ObjectGetValueByTime(long chartId, string name, DateTime time, int lineId); + bool ObjectMove(long chartId, string name, int pointIndex, DateTime time, double price); + string ObjectName(long chartId, int pos, int subWindow = -1, int type = -1); + int ObjectsDeleteAll(long chartId, int subWindow = -1, int type = -1); + bool ObjectSetDouble(long chartId, string name, ENUM_OBJECT_PROPERTY_DOUBLE propId, double propValue); + bool ObjectSetInteger(long chartId, string name, ENUM_OBJECT_PROPERTY_INTEGER propId, long propValue); + bool ObjectSetString(long chartId, string name, ENUM_OBJECT_PROPERTY_STRING propId, string propValue); + int ObjectsTotal(long chartId, int subWindow = -1, int type = -1); + bool OrderCalcMargin(ENUM_ORDER_TYPE action, string symbol, double volume, double price, out double margin); + bool OrderCalcProfit(ENUM_ORDER_TYPE action, string symbol, double volume, double priceOpen, double priceClose, out double profit); + bool OrderCheck(MqlTradeRequest request, out MqlTradeCheckResult result); + bool OrderCloseAll(); + double OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE propertyId); + long OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER propertyId); + string OrderGetString(ENUM_ORDER_PROPERTY_STRING propertyId); + ulong OrderGetTicket(int index); + bool OrderSelect(ulong ticket); + bool OrderSend(MqlTradeRequest request, out MqlTradeResult result); + bool OrderSendAsync(MqlTradeRequest request, out MqlTradeResult result); + int OrdersTotal(); + bool PositionClose(ulong ticket, ulong deviation = ulong.MaxValue); + bool PositionClose(ulong ticket, out MqlTradeResult result); + bool PositionClose(ulong ticket, ulong deviation, out MqlTradeResult result); + int PositionCloseAll(); + bool PositionClosePartial(string symbol, double volume, ulong deviation = ulong.MaxValue); + bool PositionClosePartial(ulong ticket, double volume, ulong deviation = ulong.MaxValue); + double PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE propertyId); + long PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER propertyId); + string PositionGetString(ENUM_POSITION_PROPERTY_STRING propertyId); + string PositionGetSymbol(int index); + ulong PositionGetTicket(int index); + bool PositionModify(ulong ticket, double sl, double tp); + bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, string comment = ""); + bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, out MqlTradeResult result); + bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, string comment, out MqlTradeResult result); + bool PositionSelect(string symbol); + bool PositionSelectByTicket(ulong ticket); + int PositionsTotal(); + bool Print(string message); + void ResetLastError(); + bool Sell(out MqlTradeResult result, double volume, string symbol = null, double price = 0, double sl = 0, double tp = 0, string comment = null); + long SeriesInfoInteger(string symbolName, ENUM_TIMEFRAMES timeframe, ENUM_SERIES_INFO_INTEGER propId); + double SymbolInfoDouble(string symbolName, ENUM_SYMBOL_INFO_DOUBLE propId); + long SymbolInfoInteger(string symbolName, ENUM_SYMBOL_INFO_INTEGER propId); + bool SymbolInfoSessionQuote(string name, ENUM_DAY_OF_WEEK dayOfWeek, uint sessionIndex, out DateTime from, out DateTime to); + bool SymbolInfoSessionTrade(string name, ENUM_DAY_OF_WEEK dayOfWeek, uint sessionIndex, out DateTime from, out DateTime to); + string SymbolInfoString(string symbolName, ENUM_SYMBOL_INFO_STRING propId); + bool SymbolInfoString(string symbolName, ENUM_SYMBOL_INFO_STRING propId, out string value); + MqlTick SymbolInfoTick(string symbol); + bool SymbolInfoTick(string symbol, out MqlTick tick); + bool SymbolIsSynchronized(string symbolName); + string SymbolName(int pos, bool selected); + bool SymbolSelect(string symbolName, bool selected); + int SymbolsTotal(bool selected); + double TerminalInfoDouble(ENUM_TERMINAL_INFO_DOUBLE propertyId); + int TerminalInfoInteger(ENUM_TERMINAL_INFO_INTEGER propertyId); + string TerminalInfoString(ENUM_TERMINAL_INFO_STRING propertyId); + void TesterStop(); + DateTime TimeCurrent(); + DateTime TimeGMT(); + DateTime TimeLocal(); + DateTime TimeTradeServer(); + void UnlockTicks(); + } +} \ No newline at end of file diff --git a/MtApi5/MqlRates.cs b/MtApi5/MqlRates.cs index 8d8ee6e6..1852588a 100755 --- a/MtApi5/MqlRates.cs +++ b/MtApi5/MqlRates.cs @@ -3,7 +3,7 @@ namespace MtApi5 { - public class MqlRates + public class MqlRates : IMqlRates { public MqlRates(DateTime time, double open, double high, double low, double close, long tick_volume, int spread, long real_volume) { diff --git a/MtApi5/MqlTradeRequest.cs b/MtApi5/MqlTradeRequest.cs index a3f3d118..4b2fc0fa 100755 --- a/MtApi5/MqlTradeRequest.cs +++ b/MtApi5/MqlTradeRequest.cs @@ -4,7 +4,7 @@ namespace MtApi5 { - public class MqlTradeRequest + public class MqlTradeRequest : IMqlTradeRequest { public ENUM_TRADE_REQUEST_ACTIONS Action { get; set; } // Trade operation type public ulong Magic { get; set; } // Expert Advisor ID (magic number) @@ -24,7 +24,7 @@ public class MqlTradeRequest public DateTime Expiration // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type) { get { return Mt5TimeConverter.ConvertFromMtTime(MtExpiration); } - set { MtExpiration = Mt5TimeConverter.ConvertToMtTime(value); } + set { MtExpiration = Mt5TimeConverter.ConvertToMtTime(value); } } public string Comment { get; set; } // Order comment diff --git a/MtApi5/MqlTradeResult.cs b/MtApi5/MqlTradeResult.cs index 8e091708..574d1155 100755 --- a/MtApi5/MqlTradeResult.cs +++ b/MtApi5/MqlTradeResult.cs @@ -2,7 +2,7 @@ namespace MtApi5 { - public class MqlTradeResult + public class MqlTradeResult : IMqlTradeResult { public MqlTradeResult(uint retcode, ulong deal, ulong order, double volume, double price, double bid, double ask, string comment, uint request_id) { diff --git a/MtApi5/MqlTradeTransaction.cs b/MtApi5/MqlTradeTransaction.cs index 656f12fa..f5961569 100644 --- a/MtApi5/MqlTradeTransaction.cs +++ b/MtApi5/MqlTradeTransaction.cs @@ -3,7 +3,7 @@ namespace MtApi5 { - public class MqlTradeTransaction + public class MqlTradeTransaction : IMqlTradeTransaction { public ulong Deal { get; set; } // Deal ticket public ulong Order { get; set; } // Order ticket diff --git a/MtApi5/Mt5CommandType.cs b/MtApi5/Mt5CommandType.cs index c50d5521..0a5691a6 100755 --- a/MtApi5/Mt5CommandType.cs +++ b/MtApi5/Mt5CommandType.cs @@ -255,6 +255,8 @@ internal enum Mt5CommandType UnlockTicks = 159, PositionCloseAll = 160, - TesterStop = 161 + TesterStop = 161, + TesterDeposit = 162, + TesterWithdrawal = 163 } } diff --git a/MtApi5/Mt5Quote.cs b/MtApi5/Mt5Quote.cs index c3ec47c4..f7d14b3c 100755 --- a/MtApi5/Mt5Quote.cs +++ b/MtApi5/Mt5Quote.cs @@ -3,7 +3,7 @@ namespace MtApi5 { - public class Mt5Quote + public class Mt5Quote : IMt5Quote { public string Instrument { get; } public double Bid { get; } @@ -12,8 +12,8 @@ public class Mt5Quote public DateTime Time { get; set; } public double Last { get; set; } public ulong Volume { get; set; } -// public long TimeMsc { get; set; } -// public uint Flags { get; set; } + // public long TimeMsc { get; set; } + // public uint Flags { get; set; } internal Mt5Quote(string instrument, double bid, double ask) { @@ -23,7 +23,7 @@ internal Mt5Quote(string instrument, double bid, double ask) } internal Mt5Quote(MtQuote quote) - :this(quote.Instrument, quote.Bid, quote.Ask) + : this(quote.Instrument, quote.Bid, quote.Ask) { ExpertHandle = quote.ExpertHandle; } diff --git a/MtApi5/MtApi5.csproj b/MtApi5/MtApi5.csproj old mode 100755 new mode 100644 index 8596a9c9..c0cffb60 --- a/MtApi5/MtApi5.csproj +++ b/MtApi5/MtApi5.csproj @@ -1,123 +1,25 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {AC8B5010-DA75-477E-9CA5-547C649E12D8} + net5.0 Library - Properties - MtApi5 - MtApi5 - v4.0 - 512 + false - true - full - false ..\build\products\Debug\ - DEBUG;TRACE - prompt - 4 false + embedded - pdbonly - true ..\build\products\Release\ - TRACE - prompt - 4 + embedded - - ..\packages\Newtonsoft.Json.12.0.2\lib\net40\Newtonsoft.Json.dll - True - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - {DE76D5C7-B99C-4467-8408-78173BDD84E0} - MTApiService - + - - - - - \ No newline at end of file diff --git a/MtApi5/MtApi5Client.cs b/MtApi5/MtApi5Client.cs index a28348c0..0dbaec79 100755 --- a/MtApi5/MtApi5Client.cs +++ b/MtApi5/MtApi5Client.cs @@ -12,13 +12,13 @@ namespace MtApi5 { - public class MtApi5Client + public class MtApi5Client : IMtApi5Client { #region MT Constants - public const int SYMBOL_EXPIRATION_GTC = 1; - public const int SYMBOL_EXPIRATION_DAY = 2; - public const int SYMBOL_EXPIRATION_SPECIFIED = 4; - public const int SYMBOL_EXPIRATION_SPECIFIED_DAY = 8; + public const int SYMBOL_EXPIRATION_GTC = 1; + public const int SYMBOL_EXPIRATION_DAY = 2; + public const int SYMBOL_EXPIRATION_SPECIFIED = 4; + public const int SYMBOL_EXPIRATION_SPECIFIED_DAY = 8; public const int SYMBOL_FILLING_ALL_OR_NONE = 1; public const int SYMBOL_CANCEL_REMAIND = 1; @@ -42,7 +42,7 @@ public class MtApi5Client private int _executorHandle; private readonly Dictionary> _mtEventHandlers = new Dictionary>(); - + #endregion #region Public Methods @@ -596,7 +596,7 @@ public bool PositionClose(ulong ticket, ulong deviation = ulong.MaxValue) /// public bool PositionModify(ulong ticket, double sl, double tp) { - var commandParameters = new ArrayList { ticket, sl,tp }; + var commandParameters = new ArrayList { ticket, sl, tp }; return SendCommand(Mt5CommandType.PositionModify, commandParameters); } @@ -644,7 +644,7 @@ public bool PositionClose(ulong ticket, out MqlTradeResult result) /// true - successful check of the basic structures, otherwise - false. public bool PositionOpen(string symbol, ENUM_ORDER_TYPE orderType, double volume, double price, double sl, double tp, string comment = "") { - var commandParameters = new ArrayList { symbol, (int) orderType, volume, price, sl, tp, comment }; + var commandParameters = new ArrayList { symbol, (int)orderType, volume, price, sl, tp, comment }; return SendCommand(Mt5CommandType.PositionOpen, commandParameters); } @@ -936,7 +936,7 @@ public int CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, if (retVal != null) { ratesArray = new MqlRates[retVal.Length]; - for(var i = 0; i < retVal.Length; i++) + for (var i = 0; i < retVal.Length; i++) { ratesArray[i] = new MqlRates(retVal[i].time , retVal[i].open @@ -951,7 +951,7 @@ public int CopyRates(string symbolName, ENUM_TIMEFRAMES timeframe, int startPos, return ratesArray?.Length ?? 0; } - + /// ///Gets history data of MqlRates structure of a specified symbol-period in specified quantity into the ratesArray array. The elements ordering of the copied data is from present to the past, i.e., starting position of 0 means the current bar. /// @@ -1614,7 +1614,7 @@ public bool SymbolInfoString(string symbolName, ENUM_SYMBOL_INFO_STRING propId, /// ///Symbol name. /// Link to the structure of the MqlTick type, to which the current prices and time of the last price update will be placed. - public bool SymbolInfoTick(string symbol, out MqlTick tick) + public bool SymbolInfoTick(string symbol, out MqlTick tick) { tick = SendRequest(new SymbolInfoTickRequest { @@ -1652,7 +1652,7 @@ public bool SymbolInfoSessionQuote(string name, ENUM_DAY_OF_WEEK dayOfWeek, uint string strResult = SendCommand(Mt5CommandType.SymbolInfoSessionQuote, commandParameters); - return strResult.ParseResult(ParamSeparator, out from, out to); + return strResult.ParseResult(ParamSeparator, out from, out to); } /// @@ -1804,12 +1804,12 @@ public int ChartWindowFind(long chartId, string indicatorShortname) public bool ChartTimePriceToXY(long chartId, int subWindow, DateTime? time, double price, out int x, out int y) { var result = SendRequest(new ChartTimePriceToXyRequest - { - ChartId = chartId, - SubWindow = subWindow, - Time = time, - Price = price - }); + { + ChartId = chartId, + SubWindow = subWindow, + Time = time, + Price = price + }); x = result?.X ?? 0; y = result?.Y ?? 0; @@ -2241,6 +2241,28 @@ public void TesterStop() SendCommand(Mt5CommandType.TesterStop, null); } + /// + ///The special function that emulates depositing funds during a test. It can be used in some money management systems. + /// + ///Money to be deposited to an account in the deposit currency. + ///If successful, returns true, otherwise - false. + public bool TesterDeposit(double money) + { + var commandParameters = new ArrayList { money }; + return SendCommand(Mt5CommandType.TesterDeposit, commandParameters); + } + + /// + ///The special function to emulate the operation of money withdrawal in the process of testing. Can be used in some asset management systems. + /// + /// The sum of money that we need to withdraw (in the deposit currency). + ///If successful, returns true, otherwise - false. + public bool TesterWithdrawal(double money) + { + var commandParameters = new ArrayList { money }; + return SendCommand(Mt5CommandType.TesterWithdrawal, commandParameters); + } + #endregion // Common Functions #region Object Functions @@ -2259,7 +2281,7 @@ public bool ObjectCreate(long chartId, string name, ENUM_OBJECT type, int nwin, { //Count the additional coordinates int iAdditionalCoordinates = (listOfCoordinates != null) ? listOfCoordinates.Count() : 0; - if(iAdditionalCoordinates > 29) + if (iAdditionalCoordinates > 29) { throw new ArgumentOutOfRangeException("listOfCoordinates", "The maximum amount of coordinates in 30."); } @@ -2522,7 +2544,7 @@ public int iADXWilder(string symbol, ENUM_TIMEFRAMES period, int adxPeriod) ///The shift of the green line relative to the price chart. ///The method of averaging. Can be any of the ENUM_MA_METHOD values. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. - public int iAlligator(string symbol, ENUM_TIMEFRAMES period, int jawPeriod, int jawShift, int teethPeriod, + public int iAlligator(string symbol, ENUM_TIMEFRAMES period, int jawPeriod, int jawShift, int teethPeriod, int teethShift, int lipsPeriod, int lipsShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice) { var commandParameters = new ArrayList { symbol, (int)period, jawPeriod, jawShift, teethPeriod, teethShift, lipsPeriod, lipsShift, (int)maMethod, (int)appliedPrice }; @@ -2729,7 +2751,7 @@ public int iFrAMA(string symbol, ENUM_TIMEFRAMES period, int maPeriod, int maShi ///The shift of the green line relative to the price charts. It isn't directly connected with the visual shift of the indicator histogram. ///Smoothing type. Can be one of the values of ENUM_MA_METHOD. ///The price used. Can be any of the price constants ENUM_APPLIED_PRICE or a handle of another indicator. - public int iGator(string symbol, ENUM_TIMEFRAMES period, int jawPeriod, int jawShift, int teethPeriod, + public int iGator(string symbol, ENUM_TIMEFRAMES period, int jawPeriod, int jawShift, int teethPeriod, int teethShift, int lipsPeriod, int lipsShift, ENUM_MA_METHOD maMethod, ENUM_APPLIED_PRICE appliedPrice) { var commandParameters = new ArrayList { symbol, (int)period, jawPeriod, jawShift, teethPeriod, teethShift, lipsPeriod, lipsShift, (int)maMethod, (int)appliedPrice }; @@ -3372,7 +3394,7 @@ private void Connect(MtClient client) _client.ServerDisconnected += _client_ServerDisconnected; _client.ServerFailed += _client_ServerFailed; _client.MtEventReceived += _client_MtEventReceived; - message = string.IsNullOrEmpty(client.Host) ? $"Connected to localhost:{client.Port}" : $"Connected to { client.Host}:{client.Port}"; + message = string.IsNullOrEmpty(client.Host) ? $"Connected to localhost:{client.Port}" : $"Connected to {client.Host}:{client.Port}"; Log.Info(message); } @@ -3528,7 +3550,7 @@ private T SendCommand(Mt5CommandType commandType, ArrayList commandParameters } var responseValue = response.GetValue(); - return (T) responseValue; + return (T)responseValue; } private T SendRequest(RequestBase request) diff --git a/MtApi5/Properties/AssemblyInfo.cs b/MtApi5/Properties/AssemblyInfo.cs index 69c9076d..5eb5268c 100755 --- a/MtApi5/Properties/AssemblyInfo.cs +++ b/MtApi5/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.24")] -[assembly: AssemblyFileVersion("1.0.24")] +[assembly: AssemblyVersion("1.0.25")] +[assembly: AssemblyFileVersion("1.0.25")] diff --git a/MtApi5/packages.config b/MtApi5/packages.config index 66b711be..32637c2e 100755 --- a/MtApi5/packages.config +++ b/MtApi5/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/MtApiServiceNetCore/MtApiProxy.cs b/MtApiServiceNetCore/MtApiProxy.cs new file mode 100644 index 00000000..71a85858 --- /dev/null +++ b/MtApiServiceNetCore/MtApiProxy.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.ServiceModel; +using System.ServiceModel.Channels; + +namespace MTApiService +{ + internal class MtApiProxy : DuplexClientBase, IMtApi, IDisposable + { + public MtApiProxy(InstanceContext callbackContext, Binding binding, EndpointAddress remoteAddress) + : base(callbackContext, binding, remoteAddress) + { + InnerChannel.Faulted += InnerDuplexChannel_Faulted; + } + + #region IMtApi Members + + public bool Connect() + { + InnerChannel.Open(); + return Channel.Connect(); + } + + public void Disconnect() + { + Channel.Disconnect(); + } + + public MtResponse SendCommand(MtCommand command) + { + return Channel.SendCommand(command); + } + + public List GetQuotes() + { + return Channel.GetQuotes(); + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + try + { + Close(); + } + catch (CommunicationException) + { + Abort(); + } + catch (TimeoutException) + { + Abort(); + } + catch (Exception) + { + Abort(); + } + } + + #endregion + + #region Private Methods + private void InnerDuplexChannel_Faulted(object sender, EventArgs e) + { + Faulted?.Invoke(this, e); + } + + #endregion + + #region Events + public event EventHandler Faulted; + #endregion + } +} diff --git a/MtApiServiceNetCore/MtApiServiceNetCore.csproj b/MtApiServiceNetCore/MtApiServiceNetCore.csproj new file mode 100644 index 00000000..49eab33f --- /dev/null +++ b/MtApiServiceNetCore/MtApiServiceNetCore.csproj @@ -0,0 +1,41 @@ + + + net5.0 + Library + false + + + ..\build\products\Debug\ + embedded + + + ..\build\products\Release\ + + embedded + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MtApiServiceNetCore/MtClient.cs b/MtApiServiceNetCore/MtClient.cs new file mode 100644 index 00000000..b23489d3 --- /dev/null +++ b/MtApiServiceNetCore/MtClient.cs @@ -0,0 +1,294 @@ +using System; +using System.Collections; +using System.ServiceModel; +using System.Collections.Generic; +using log4net; +using System.Threading.Tasks; + +namespace MTApiService +{ + [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)] + public sealed class MtClient : IMtApiCallback, IDisposable + { + private const string ServiceName = "MtApiService"; + + public delegate void MtQuoteHandler(MtQuote quote); + public delegate void MtEventHandler(MtEvent e); + + #region Fields + private static readonly ILog Log = LogManager.GetLogger(typeof(MtClient)); + + private readonly MtApiProxy _proxy; + private Task lastQuoteTask; + private Task lastEventTask; + #endregion + + #region ctor + public MtClient(string host, int port) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentNullException(nameof(host), "host is null or empty"); + + if (port < 0 || port > 65536) + throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid"); + + Host = host; + Port = port; + + var urlService = $"net.tcp://{host}:{port}/{ServiceName}"; + + var bind = new NetTcpBinding(SecurityMode.None) + { + MaxReceivedMessageSize = 2147483647, + MaxBufferSize = 2147483647, + MaxBufferPoolSize = 2147483647, + SendTimeout = new TimeSpan(12, 0, 0), + ReceiveTimeout = new TimeSpan(12, 0, 0), + ReaderQuotas = + { + MaxArrayLength = 2147483647, + MaxBytesPerRead = 2147483647, + MaxDepth = 2147483647, + MaxStringContentLength = 2147483647, + MaxNameTableCharCount = 2147483647 + } + }; + + var quoteScheduler = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.AttachedToParent); + var eventScheduler = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.AttachedToParent); + lastQuoteTask = quoteScheduler.StartNew(() => { }); + lastEventTask = eventScheduler.StartNew(() => { }); + + _proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService)); + _proxy.Faulted += ProxyFaulted; + } + + public MtClient(int port) : this("localhost", port) + { + // piping is not supported yet: https://github.com/dotnet/wcf/issues/2535 + } + + #endregion + + #region Public Methods + /// Thrown when connection failed + public void Connect() + { + Log.Debug("Connect: begin."); + + if (_proxy.State != CommunicationState.Created) + { + Log.ErrorFormat("Connected: end. Client has invalid state {0}", _proxy.State); + return; + } + + bool coonected; + + try + { + coonected = _proxy.Connect(); + } + catch (Exception ex) + { + Log.ErrorFormat("Connect: Exception - {0}", ex.Message); + + throw new CommunicationException($"Connection failed to service. {ex.Message}"); + } + + if (coonected == false) + { + Log.Error("Connect: end. Connection failed."); + throw new CommunicationException("Connection failed"); + } + + Log.Debug("Connect: end."); + } + + public void Disconnect() + { + Log.Debug("Disconnect: begin."); + + try + { + _proxy.Disconnect(); + } + catch (Exception ex) + { + Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message); + } + + Log.Debug("Disconnect: end."); + } + + /// Thrown when connection failed + public MtResponse SendCommand(int commandType, ArrayList parameters, Dictionary namedParams, int expertHandle) + { + Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count); + + if (IsConnected == false) + { + Log.Error("SendCommand: Client is not connected."); + throw new CommunicationException("Client is not connected."); + } + + MtResponse result; + + try + { + result = _proxy.SendCommand(new MtCommand { + CommandType = commandType, + Parameters = parameters, + NamedParams = namedParams, + ExpertHandle = expertHandle}); + } + catch (Exception ex) + { + Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message); + + throw new CommunicationException("Service connection failed! " + ex.Message); + } + + Log.DebugFormat("SendCommand: end. result = {0}", result); + + return result; + } + + /// Thrown when connection failed + public List GetQuotes() + { + Log.Debug("GetQuotes: begin."); + + if (IsConnected == false) + { + Log.Warn("GetQuotes: end. Client is not connected."); + return null; + } + + List result; + + try + { + result = _proxy.GetQuotes(); + } + catch (Exception ex) + { + Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message); + + throw new CommunicationException($"Service connection failed! {ex.Message}"); + } + + Log.DebugFormat("GetQuotes: end. quotes count = {0}", result?.Count); + + return result; + } + + #endregion + + #region IMtApiCallback Members + + public void OnQuoteUpdate(MtQuote quote) + { + Log.DebugFormat("OnQuoteUpdate: begin. quote = {0}", quote); + + if (quote == null) return; + + if (QuoteUpdated != null) + { + lastQuoteTask = lastQuoteTask.ContinueWith((t) => QuoteUpdated.Invoke(quote)); + } + + Log.Debug("OnQuoteUpdate: end."); + } + + public void OnQuoteAdded(MtQuote quote) + { + Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote); + + if (QuoteAdded != null) + { + lastQuoteTask = lastQuoteTask.ContinueWith((t) => QuoteAdded.Invoke(quote)); + } + + Log.Debug("OnQuoteAdded: end."); + } + + public void OnQuoteRemoved(MtQuote quote) + { + Log.DebugFormat("OnQuoteRemoved: begin. quote = {0}", quote); + + if (QuoteRemoved != null) + { + lastQuoteTask = lastQuoteTask.ContinueWith((t) => QuoteRemoved.Invoke(quote)); + } + + Log.Debug("OnQuoteRemoved: end."); + } + + public void OnServerStopped() + { + Log.Debug("OnServerStopped: begin."); + + ServerDisconnected?.Invoke(this, EventArgs.Empty); + + Log.Debug("OnServerStopped: end."); + } + + + public void OnMtEvent(MtEvent e) + { + Log.DebugFormat("OnMtEvent: begin. event = {0}", e); + + if (MtEventReceived != null) + { + lastEventTask = lastEventTask.ContinueWith((t) => MtEventReceived.Invoke(e)); + } + + Log.Debug("OnMtEvent: end."); + } + + #endregion + + #region Properties + public string Host { get; private set; } + public int Port { get; private set; } + + private bool IsConnected => _proxy.State == CommunicationState.Opened; + + #endregion + + #region Private Methods + + private void ProxyFaulted(object sender, EventArgs e) + { + Log.Debug("ProxyFaulted: begin."); + + ServerFailed?.Invoke(this, EventArgs.Empty); + + Log.Debug("ProxyFaulted: end."); + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + Log.Debug("Dispose: begin."); + + _proxy.Dispose(); + + Log.Debug("Dispose: end."); + } + + #endregion + + #region Events + public event MtQuoteHandler QuoteAdded; + public event MtQuoteHandler QuoteRemoved; + public event MtQuoteHandler QuoteUpdated; + public event EventHandler ServerDisconnected; + public event EventHandler ServerFailed; + public event MtEventHandler MtEventReceived; + #endregion + } +} diff --git a/MtApiServiceNetCore/MtService.cs b/MtApiServiceNetCore/MtService.cs new file mode 100644 index 00000000..506fe9d4 --- /dev/null +++ b/MtApiServiceNetCore/MtService.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.ServiceModel; +using System.Threading; +using log4net; + +namespace MTApiService +{ + [ServiceContract(CallbackContract = typeof(IMtApiCallback), SessionMode = SessionMode.Required)] + public interface IMtApi + { + [OperationContract] + bool Connect(); + + [OperationContract(IsOneWay = true)] + void Disconnect(); + + [OperationContract] + MtResponse SendCommand(MtCommand command); + + [OperationContract] + List GetQuotes(); + } + + [ServiceContract] + public interface IMtApiCallback + { + [OperationContract(IsOneWay = true)] + void OnQuoteUpdate(MtQuote quote); + + [OperationContract(IsOneWay = true)] + void OnServerStopped(); + + [OperationContract(IsOneWay = true)] + void OnQuoteAdded(MtQuote quote); + + [OperationContract(IsOneWay = true)] + void OnQuoteRemoved(MtQuote quote); + + [OperationContract(IsOneWay = true)] + void OnMtEvent(MtEvent ntEvent); + } +} diff --git a/MtApiServiceNetCore/Properties/AssemblyInfo.cs b/MtApiServiceNetCore/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..3dc1eafc --- /dev/null +++ b/MtApiServiceNetCore/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MTApiService")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("DW")] +[assembly: AssemblyProduct("MTApiService")] +[assembly: AssemblyCopyright("Copyright © DW 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f1cc1516-9352-4ddd-811a-c5fc842b12d4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.32.0")] +[assembly: AssemblyFileVersion("1.0.32.0")] \ No newline at end of file diff --git a/TestClients/MtApi5TestClient/MainWindow.xaml b/TestClients/MtApi5TestClient/MainWindow.xaml index 0a7cdbb4..78729d34 100755 --- a/TestClients/MtApi5TestClient/MainWindow.xaml +++ b/TestClients/MtApi5TestClient/MainWindow.xaml @@ -594,6 +594,8 @@