Compare commits

..

220 Commits

Author SHA1 Message Date
Viacheslav Demydiuk 9eedf15e9e Issue #208: fixed issue with calling CheckOrders after starting TradeMonitor event MtApi has disconnected state 2020-10-22 22:26:17 +03:00
Viacheslav Demydiuk 373bfe4997 [MT4] Log improvements 2020-10-22 21:24:28 +03:00
Viacheslav Demydiuk 0cd8edb933 Updated LogConfigurator to avoid creation of many log files during several clients in one app session 2020-10-22 21:19:30 +03:00
Viacheslav Demydiuk a66f18c2b3 MTApiService version 1.0.33 2020-10-22 20:11:51 +03:00
Viacheslav Demydiuk 71964c3303 MtApi (MT4) version 1.0.42 2020-10-22 16:25:18 +03:00
Vyacheslav Demidyuk 4e7f8b93f4 Merge pull request #208 from mbochmann/dev
Changed design of monitors for better extensibility
2020-10-22 18:57:16 +03:00
Mitja Bochmann 5715e7e2b8 Update readme.md 2020-10-18 11:12:28 +02:00
Mitja 833ce1f192 Added ModifiedOrdersMonitor, added some more doc 2020-10-18 11:05:18 +02:00
m.bochmann 724162f29d Updated documentation of newly added classes 2020-10-13 15:52:55 +02:00
m.bochmann 739567d871 Bugfix in TimerTradeMonitor
SyncTrigger should only be set to true by default when the trigger will be initialized in the constructor.
2020-10-13 15:36:59 +02:00
m.bochmann a12ddba765 Changed design of monitors for better extensibility 2020-10-13 15:10:26 +02:00
Viacheslav Demydiuk 9a5acac2db Update readme: updated links 2020-10-13 15:19:26 +03:00
Viacheslav Demydiuk 7a776de8d3 Update readme: added link to telegram's chat 2020-10-13 15:18:03 +03:00
Viacheslav Demydiuk ce7953eee0 Issue #204: [MT5] Added function OrderSendAsync 2020-10-13 15:16:55 +03:00
Viacheslav Demydiuk 93aed4e44c Issue #202: [MT5] added Buy/Sell functions 2020-10-13 14:14:59 +03:00
Viacheslav Demydiuk 4c8c3b8766 MtApi [MT5] version 1.0.23 2020-09-04 12:10:26 +03:00
Viacheslav Demydiuk 73ebde8b6b Added link on Telegram's channel to readme 2020-08-30 12:28:54 +03:00
Viacheslav Demydiuk e33ba5b51f Issue #190: updated MtApi5.mq5 to version 1.7. Init string variable _erro 2020-08-28 18:54:33 +03:00
Viacheslav Demydiuk a0a4263e24 Issue #190: implemented function sendErrorResponse in Mt5Connector 2020-08-28 17:39:49 +03:00
Viacheslav Demydiuk 5d18dd4ad3 MTApiService version 1.0.32 2020-08-28 17:28:34 +03:00
Viacheslav Demydiuk 03ff1f9176 MtApi [MT5] version 1.0.22 2020-08-28 16:48:31 +03:00
Viacheslav Demydiuk f376b4e0e5 MtApi (MT4) version 1.0.41 2020-08-26 22:59:21 +03:00
Viacheslav Demydiuk fc54b5dd4a Updated test application (MT5) to perform testing functions iBullsPower, iBearsPower, BarsCalculated, CopyBuffer. 2020-08-26 21:06:26 +03:00
Viacheslav Demydiuk dd05804082 Issue #201: call iBullsPower instead iBearsPower in MQL 2020-08-26 17:53:31 +03:00
Viacheslav Demydiuk 4349eb3538 Issue #186: Implemented function PositionClosePartial 2020-08-24 22:43:20 +03:00
Vyacheslav Demidyuk e0daf9a82e Merge pull request #198 from KptKuck/dev
Add switchable Events / fix typo in AddLog()
2020-08-09 11:00:55 +03:00
Christian_X3 3997b6df74 add switchable Events
The function SendMtEvent requires a lot of computing time. To improve the speed of the tester, the events can now be switched off individually
2020-06-18 05:57:05 +02:00
Christian_X3 abfe1a281a fix typo in Addlog() 2020-06-18 05:03:21 +02:00
Viacheslav Demydiuk 93bfe8e56f removed redundant old projects from repo 2020-02-20 17:33:30 +02:00
Viacheslav Demydiuk bb27b4e50d #187: removed reference to Newtonsoft.Json in project TestApiClientUI 2020-02-20 17:29:06 +02:00
vdemydiuk 0f809cd60a MtApi [MT5] version 1.0.21 2019-11-11 12:52:28 +02:00
vdemydiuk f22a6c21f0 Updated gitignore file: added .vs folder 2019-11-07 15:45:19 +02:00
vdemydiuk 625753d83a Issue #142: removed old solution of VS 2015. Updated readme file related to VS 2017 2019-11-07 15:12:26 +02:00
vdemydiuk d621312a8b Merged fix of issue #175 from master 2019-11-06 11:59:41 +02:00
Vyacheslav Demidyuk a4df4bbf1e Merge pull request #177 from vlariono/master
#175 Fix null reference exception
2019-11-06 11:46:18 +02:00
vdemydiuk 43ef628c69 Issue #142: added support VS 2017 2019-11-05 17:03:58 +02:00
vdemydiuk 688149bd67 Merge branch 'master' into dev 2019-11-05 17:01:37 +02:00
Vyacheslav Demidyuk c33a5ed6f5 Merge pull request #174 from HengzheLi/fix-#173
#173 update IF checking
2019-11-05 15:39:28 +02:00
Vasily Larionov 828c1185b3 Position modify 2019-09-24 18:52:56 +03:00
Vasily Larionov 4b384d9da2 Fix null reference exception 2019-09-21 17:20:31 +03:00
hectorli 26de553443 #173 update IF checking 2019-08-27 22:15:59 +08:00
vdemydiuk ee81cfe012 Issue #143: Added function TesterStop [MT5] 2019-05-04 10:36:46 +03:00
vdemydiuk 5f4ae3cd9e Issue #74: Updated package Newtonsoft.Json from 8.0.3 to 12.0.2 2019-04-30 11:09:12 +03:00
vdemydiuk 13b8aa9644 Disable debug loging in MtApi.ex5 2019-04-30 11:07:47 +03:00
vdemydiuk e364b313c3 MtApi5: Set version 1.0.20 2019-04-26 13:07:34 +03:00
vdemydiuk 68f2a7ae07 Issue #147: added non-documented types of trade operations: balance, credit, rebate 2019-04-24 17:47:06 +03:00
vdemydiuk 42a1da3356 Issue #136: Added new properties to the ENUM_SYMBOL_INFO_DOUBLE enumeration: SYMBOL_VOLUME_REAL, SYMBOL_VOLUMEHIGH_REAL, SYMBOL_VOLUMELOW_REAL 2019-03-18 18:26:17 +02:00
vdemydiuk 44fab4dae1 Issue #136: Updated structures MqlTick, MqlBook with new field volume_real. Remove redundant code from MtApiService. 2019-03-18 17:31:54 +02:00
Vyacheslav Demidyuk d1387148df Merge pull request #148 from flognity/master
ObjectCreate can now take up to 30 anchor points
2019-03-18 16:11:48 +02:00
Florian Wilhelm bb4ac426cd Modified the ObjectCreate such that it can take up to 30 anchor points (maximum amount of anchor points in mql5). The MtApi5.mq5 has been updated to cope with the added parameters. The MtApi5.ex5 has been rebuilt. 2019-03-07 20:35:23 +01:00
vdemydiuk 34b4e33cc9 Issue #138: removed rudiment value POSITION_COMMISION from enum ENUM_POSITION_PROPERTY_DOUBLE 2019-02-20 13:12:29 +02:00
vdemydiuk f01ec01a5f Disable debug loging in MtApi.ex5 2018-06-06 15:11:56 +03:00
vdemydiuk 0c38d37559 Issue #107: Added function PositionCloseAll 2018-06-06 14:24:39 +03:00
vdemydiuk 897892dc89 Issue #122: Added event OnLockTicksEvent (MT5) 2018-06-06 12:46:24 +03:00
vdemydiuk 1a5882b75a Issue #122: Implemented UnlockTicks function in MtApi (MT5) 2018-06-05 19:19:35 +03:00
vdemydiuk 0f717f1cb7 Issue #119: Added out parameter MqlTradeResult to function PositionClose 2018-06-04 17:48:14 +03:00
vdemydiuk 5d78ad5067 Issue #120: set field 'Symbol' as optional in MqlTradeRequest (MT5) 2018-06-04 15:36:35 +03:00
vdemydiuk 6c45f28a05 Issue #121: Added original MtTime field to MqlRates (MT5) 2018-06-04 15:04:12 +03:00
vdemydiuk ca3c0e735f Issue #110: Implemented function for working with global variables (MT5) 2018-06-04 13:53:55 +03:00
vdemydiuk f71151104b Issue #111: Added enum value SYMBOL_VISIBLE 2018-05-08 19:07:52 +03:00
vdemydiuk 28816a75ac Issue #113: Changed extension of logging files to *.log 2018-05-08 16:44:57 +03:00
vdemydiuk 6023bffed6 Issue #106: Extended structure Mt5Quote with fields from MqlTick (volume, last, time) 2018-05-08 14:53:31 +03:00
vdemydiuk fd34f009cd Started version 1.0.19 (MT5) 2018-05-08 14:50:25 +03:00
Vyacheslav Demidyuk 1bb2b65cdf Merge pull request #115 from CVasquezG/master
Updated README
2018-04-02 16:27:58 +03:00
CVasquezG 37e8275465 Updated README
Changes made to the README file to be more formal.
I am doing this as a university assignment where I am required to improve documentation in the open source community.  I hope changes suggested in this commit are useful for your project.
2018-03-31 14:08:20 -07:00
vdemydiuk 52ca4fae1e MtApi5.ex5: Update version to 1.5. Disable debug logging 2018-03-27 11:25:22 +03:00
vdemydiuk 6b327e017a Removed unnecessary Windows Operations from MtApi5 code (MT5) 2018-03-27 11:11:33 +03:00
vdemydiuk 10a758bd93 Updated test application (MT5) to perform testing functions ChartIndicatorAdd, ChartIndicatorGet 2018-03-27 10:22:16 +03:00
vdemydiuk 4a9642b60c Issue #109: Fixed typo 'Magic' to 'Order' in MQL function JsonToMqlTradeRequest 2018-03-26 18:06:39 +03:00
vdemydiuk 6ba6496e46 Implemented functions ChartIndicatorAdd and ChartIndicatorGet 2018-03-24 21:45:35 +02:00
vdemydiuk 1ffbba5ee3 Updated test application (MT5) to perform testing functions ChartNavigate, ChartIndicatorDelete, ChartIndicatorName, ChartIndicatorsTotal, ChartWindowOnDropped, ChartPriceOnDropped, ChartTimeOnDropped, ChartXOnDropped, ChartYOnDropped, ChartSetSymbolPeriod, ChartScreenShot 2018-03-24 19:08:40 +02:00
vdemydiuk 8cdfd6fb91 Updated test application (MT5) to perform testing function ChartGetDouble and ChartGetInteger 2018-03-19 19:10:51 +02:00
vdemydiuk 7c3ddbabac Updated test application (MT5) to perform testing function ChartSetInteger and ChartSetString 2018-03-19 18:58:12 +02:00
vdemydiuk 83e0145a3a Updated test application (MT5) to perform testing function ChartPeriod and ChartSetDouble 2018-03-19 18:39:15 +02:00
vdemydiuk f17c7cd554 Updated test application (MT5) to perform testing function ChartWindowFind and ChartClose 2018-03-19 17:23:16 +02:00
vdemydiuk 4aefdd554b Updated test application (MT5) to perform testing function ChartId and ChartRedraw 2018-03-19 16:23:55 +02:00
vdemydiuk 820ed9a631 Refactored UI test client (MT5) 2018-03-19 15:10:09 +02:00
vdemydiuk 95c55e90be Added field ExpertHandle into class Mt5Quote 2018-03-19 15:09:02 +02:00
vdemydiuk 486a1979a6 Implemented functions ChartIndicatorName, ChartIndicatorsTotal, ChartWindowOnDropped, ChartPriceOnDropped, ChartTimeOnDropped, ChartXOnDropped, ChartYOnDropped, ChartSetSymbolPeriod, ChartScreenShot (MT5) 2018-03-15 17:44:53 +02:00
vdemydiuk faef5f7d18 Implemented function ChartIndicatorDelete (MT5) 2018-03-15 13:15:50 +02:00
vdemydiuk bd45c45fa1 Implemented function ChartNavigate (MT5) 2018-03-15 12:55:46 +02:00
vdemydiuk 29be184136 Implemented functions ChartGetDouble, ChartGetInteger (MT5) 2018-03-15 11:20:20 +02:00
vdemydiuk 9bfda95cf7 Implemented functions ChartSetDouble, ChartSetInteger, ChartSetString (MT5) 2018-03-14 19:53:53 +02:00
vdemydiuk 24b881d8a0 Implemented function ChartPeriod (MT5) 2018-03-14 19:16:29 +02:00
vdemydiuk 07dd83f890 Implemented functions ChartId, ChartRedraw, ChartWindowFind, ChartClose (MT5) 2018-03-14 18:10:44 +02:00
vdemydiuk 9afd30e463 Implemented function Alert (MT5) 2018-03-13 18:24:40 +02:00
vdemydiuk 16f454ca61 Implemented functions ChartTimePriceToXY, ChartXYToTimePrice (MT5) 2018-03-13 17:28:21 +02:00
vdemydiuk f3a3a582fd Issue #100: update test application for testing function SymbolInfoString (MT5) 2018-03-13 11:40:16 +02:00
vdemydiuk 93aaae86ed Issue #100: implemented second function SymbolInfoString (MT5) 2018-03-13 11:20:55 +02:00
Vyacheslav Demidyuk bce68fd168 Merge pull request #104 from Janderson/master
TerminalInfo Commands and ChartTemplate Commands
2018-03-13 10:54:16 +02:00
Janderson 0812229538 Chart Commands:
- ChartSaveTemplate Implemented
2018-03-12 23:08:04 -03:00
Janderson d0fa4af1d0 - Bug fix - when click in chartApplyTemplateButton, store template file in right place 2018-03-12 22:44:08 -03:00
Janderson 8eb4bcfabe Commands to handle with Terminal:
- TerminalInfoDoublePropertyId
- TerminalInfoIntegerPropertyId
- TerminalInfoStringPropertyId
2018-03-12 22:37:06 -03:00
Vyacheslav Demidyuk 9ea58354be Merge pull request #103 from Janderson/master
Missing function to mql5
2018-03-12 16:49:21 +02:00
Janderson FFerreira 02774d7328 Merge branch 'mt5_1_0_18' into master 2018-03-12 11:34:00 -03:00
Janderson FFerreira cbff71f8d0 - Correction of Test Client
- Missing codes in mtapi5.mq5
2018-03-12 11:17:12 -03:00
Janderson FFerreira 951a91976c - missing mql5 file 2018-03-11 19:56:28 -03:00
Janderson FFerreira 6a37826486 - Add some commands to handle with Chart to MT5 api
- Add some commands to handle with windows to MT5 api
2018-03-11 19:26:25 -03:00
vdemydiuk cab2de6d24 Issue #100: implemented functions GetLastError, ResetLastError() in MtApi (MT5) 2018-03-09 19:18:54 +02:00
vdemydiuk ec6c71607b Issue #96: Implemented function PositionGetTicket in MtApi (MT5) 2018-03-08 17:45:22 +02:00
vdemydiuk 0a39b69b15 Issue #95: Added default constructors to classes MqlBookInfo, MqlTradeCheckResult 2018-03-08 16:22:37 +02:00
vdemydiuk fe94ec21de Issue #102: fixed long type of result in function SeriesInfoInteger 2018-03-08 15:31:02 +02:00
vdemydiuk 34c78c73c0 Started version 1.0.18 (MT5) 2018-03-08 15:26:29 +02:00
vdemydiuk d7b8ef894c Issue #93: Fixed typo Cction (Action) in MtApi5.mq5 2018-03-02 13:22:40 +02:00
vdemydiuk 7f33cebce1 MtApi5: Set version 1.0.17 2018-03-02 12:21:54 +02:00
vdemydiuk 84740787d5 Issue #94: Added event handler OnBookEvent (MT5). 2018-03-02 11:43:03 +02:00
vdemydiuk ad6bad5187 Issue #93: Added event OnTradeTransaction. Udpated json.mqh to fix JSONNumber for correct serialization zero integer value". 2018-03-01 11:20:25 +02:00
vdemydiuk 0086b02bc8 Issue #92: Updated test application (MT5) to use functions IndicatorCreate and IndicatorRelease 2018-02-27 18:26:37 +02:00
vdemydiuk f7e06c1570 Issue #92: Added functions IndicatorCreate and IndicatorRelease 2018-02-27 09:49:26 +02:00
vdemydiuk c86a3a3752 Issue #91: Added MarketBookGetRequest to perform function MarketBookGet (MT5) 2018-02-21 14:43:25 +02:00
vdemydiuk be8a17c0fd Issue #88: Activate execute commands in tester mode (MT5) 2018-02-19 19:21:29 +02:00
vdemydiuk 5c6751de9b Issue #90: Added time functions: TimeCurrent, TimeTradeServer, TimeLocal, TimeGMT 2018-02-19 18:48:31 +02:00
vdemydiuk 83776f8b7a Minor refactoring to remote redundant code 2018-02-19 17:12:26 +02:00
vdemydiuk f1c1df1e00 Issue #89: Changed function OrderCheck to use json request/response 2018-02-19 17:02:19 +02:00
vdemydiuk d6640300f5 Issue #89: Changed function PositionOpen to use json request/response 2018-02-19 15:54:03 +02:00
vdemydiuk c9c188f697 Minor refactoring to remove code syle warnings 2018-02-19 13:37:43 +02:00
vdemydiuk 3a4f561836 Issue #87: Added event QuoteUpdate to MtApi5Client (MT5) for compatibility with MATLAB 2018-02-19 11:49:52 +02:00
vdemydiuk bdb30edee3 Issue #82: Responsed moved to Request folder 2018-02-19 11:27:07 +02:00
vdemydiuk 29f501b055 Issue #82: Refactored request responses (MtAp5). Added iCustom functions with string and boolean parameters. Added button iCustom in test application (MT5). 2018-02-19 11:07:37 +02:00
vdemydiuk 521d7ea2c0 Issue #82: Disabled debug mode in MtApi5.ex5. Updated test client to send order with values Expiration and Comment 2018-02-18 20:24:27 +02:00
DW 0e5bb40a6f Issue #82: Refactored MQL5 expert to use json in function OrderSend 2018-02-17 00:10:10 +02:00
vdemydiuk 14079dc3c1 Issue #82: Added stub class OrderSendRequest 2018-02-15 20:32:22 +02:00
vdemydiuk 3600a86971 MtApiService version 1.0.29. Added log wrapper class MtLog 2018-02-15 17:37:08 +02:00
vdemydiuk 83e62fbff7 Started version 1.0.16 (MT5) 2018-02-15 17:33:02 +02:00
vdemydiuk 5c96aeb2fd Issue #81: Added function TimeGMT into MtApi (MT4) 2018-02-13 19:02:08 +02:00
vdemydiuk a238e5eb36 Issue #80: Fixed wrong condition on fetch first parameter in function Execute_TerminalInfoString 2018-02-13 18:35:40 +02:00
vdemydiuk 11fd5b7527 Started version 1.0.40 (MT4) 2018-02-13 18:33:11 +02:00
vdemydiuk cbe75cfbf6 Issue #83: Added command button HistoryDealMethods to check functions related to the issue 2018-02-08 18:04:15 +02:00
vdemydiuk 9581431a9f Issue #84: Fixed bug in function HistoryOrderGetInteger, there was wrong return value type 2018-02-04 14:39:09 +02:00
vdemydiuk acf0c12531 MT5: started version 1.0.15 2018-02-04 14:02:41 +02:00
DW 1eccda9b2c Version MtApi4 1.0.39 2018-01-16 16:11:33 +02:00
DW fd4aac7c32 Issie #73: added wrapped function getBooleanValueW into MtApi.mq4. Issue #76: added precompiled value __DEBUG_LOG__ into MtApi.mq4 to disable logging in release verion 2018-01-16 16:06:21 +02:00
DW 36c90c8481 Updated test application (MT5): added test functions HistoryDealGetDouble, HistoryDealGetInteger, HistoryDealGetString 2018-01-11 15:28:57 +02:00
DW fefa451371 Issue #39: Added indicator functions on MQL side (MtApi MT5) 2018-01-10 19:13:31 +02:00
DW 1c57f88cb1 Issue #72: Fixed bug with serialization of parameters in functions HistoryDealGetInteger, HistoryDealGetString, HistoryDealGetDouble 2017-11-27 18:16:35 +02:00
DW 08ba45c65f Issue #39: Added indicator functions on C# side (MtApi MT5) 2017-11-27 18:09:54 +02:00
DW b8314e9ed7 MtApi5: add waiting incoming connection on MT5 side in backtesting mode 2017-11-15 18:16:23 +02:00
DW 9587b10c8c MtApi5 version 1.0.14 2017-11-15 18:15:34 +02:00
DW b838084ba2 Issue #14: Updated test application for using function PositionOpen with MqlTradeResult 2017-09-29 19:05:06 +03:00
DW cd24891022 Issue #14: Added function PositionOpen which returns MqlTradeResult 2017-09-29 18:27:36 +03:00
DW add69a4c03 Issue #41: Complete object functions on MQL side 2017-09-29 17:39:18 +03:00
DW 5a3407e47c Issue #41: Refactored MtApi5.mq5 - removed unnecessary variables 2017-09-29 15:48:46 +03:00
DW ce8cfbbb70 Issue #41: Refactored MtApi5.mq5 2017-09-29 15:34:35 +03:00
DW 8470bbd5cc Issue #41: Complete object functions in client side (MT5) 2017-09-27 18:36:26 +03:00
DW 5c7ae748a5 Issue #41: Added Object Properties enums: ENUM_OBJECT_PROPERTY_INTEGER, ENUM_OBJECT_PROPERTY_STRING, ENUM_BORDER_TYPE, ENUM_ALIGN_MODE 2017-09-27 17:45:09 +03:00
DW 7abb4d3b5e Issue #41: Partialy implemented object functions on client side 2017-09-27 15:38:54 +03:00
DW 486c42685a Issue #41: Added Object Types enum 2017-09-26 18:37:50 +03:00
DW f41ab37b6f Set version 1.0.13 of MtApi (MT5) 2017-09-26 17:27:06 +03:00
Vyacheslav Demidyuk 9e129fb6e2 Merge pull request #64 from Tr4Dr/master
Fixes for the OrderSend function [MT5]
2017-09-25 12:41:35 +03:00
Tr4Dr f7b00a8d88 Added null check to convertSystemString [MT5]
Whithout this fix, the OrderSend method crashing if we doesn't set the "request.Comment" property.
2017-09-18 14:55:03 +02:00
Tr4Dr a7cb14de25 Updated MqlTradeRequest [MT5] 2017-09-18 02:05:22 +02:00
Tr4Dr f50925c8d3 Changed wcslen to wcsnlen [MT5]
Maximum character length set to 1000 based on preinit() MQL5 function. This value must be kept synchronized with MQL side.
2017-09-17 22:35:26 +02:00
Tr4Dr e29a11de68 Changed type of '\0' literal to wchar_t [MT5] 2017-09-17 22:19:09 +02:00
Tr4Dr 12141775f3 Fixed type casting to __int64 [MT5]
long long type should be an alternative.
2017-09-17 22:05:56 +02:00
Tr4Dr b6d24b8aa9 Merge pull request #2 from vdemydiuk/master
Update from original
2017-09-16 22:01:19 +02:00
DW 7175fae18c Fixed WIX error: ICE Internal Error 100. API Returned: 1615. 2017-09-08 17:07:53 +03:00
DW 3c4d8d52ca Revert version mtapi (MT5) to 1.0.12 2017-09-08 16:30:39 +03:00
DW 6873363d41 Fixed build of MT5 test client 2017-09-08 16:07:41 +03:00
DW 947599327a MtApi5 version 1.0.13 2017-09-08 13:05:01 +03:00
DW 5645902a48 Merge branch 'master' into mt5_1_0_13 2017-09-08 12:45:31 +03:00
DW c82787473f Issue #16: Added Mt5Expert into MTApiService. Refactored MT5Connector 2017-09-08 12:44:14 +03:00
Vyacheslav Demidyuk c213fb709a Merge pull request #62 from Tr4Dr/master
Fixed the type of Deviation property in MqlTradeRequest (MT5)
2017-09-08 12:38:29 +03:00
Tr4Dr 2ac29dc871 Fixed the type of Deviation property in MqlTradeRequest (MT5) 2017-09-07 20:08:01 +02:00
DW 1f72b2b790 Refactored MTApiService and connectors projects 2017-09-07 17:46:25 +03:00
Vyacheslav Demidyuk 3a62ff56d7 Merge pull request #61 from Tr4Dr/master
Updated PositionClose function and a fixed warning (MT5)
2017-09-07 12:23:34 +03:00
Unknown d25fe529b4 Fixed warning in function CreateErrorResponse (MT5)
Declaration of 'message' hides global declaration in MtApi5.mq5
2017-09-07 00:21:12 +02:00
Unknown 15538e81f4 Updated PositionClose function (MT5)
Type of the ticket argument changed to ulong, added optional argument: deviation
2017-09-07 00:06:59 +02:00
Tr4Dr a33be3c764 Merge pull request #1 from vdemydiuk/master
Bringing fork up to date
2017-09-06 23:48:13 +02:00
DW 023fe8c7c9 Disable code to print event payload in MQL code (MT4) 2017-09-06 11:47:45 +03:00
DW b77516e324 Issue #59: Added event OnChartEvent into MtApi (MT4) 2017-09-05 18:34:26 +03:00
DW 4b48423c3f Issue #57: Added function PositionSelectByTicket into MQL code 2017-09-04 13:08:30 +03:00
DW 9800177b08 Issue #57: Added function PositionSelectByTicket into C# code 2017-08-29 17:40:23 +03:00
Vyacheslav Demidyuk a33d4a4594 Merge pull request #58 from Tr4Dr/master
Refactored and updated enumerations
2017-08-28 13:56:44 +03:00
Unknown 29722f362d Added Position and PositionBy properties to MqlTradeRequest 2017-08-25 15:32:24 +02:00
Unknown e072343fe1 Missing break after PositionGetSymbol 2017-08-25 15:12:41 +02:00
Unknown acb0c20ca8 Missing break after PositionGetDouble 2017-08-25 15:00:24 +02:00
Unknown 83543fee88 Refactored and updated enumerations 2017-08-25 01:31:57 +02:00
DW 3ce6b042de Added files into MtApi.proj 2017-08-21 15:56:21 +03:00
DW 9dd770e768 Fixed small errors in MQL part of chart operations 2017-08-21 15:42:10 +03:00
DW abb8b8afaa Added enums for chart properties. Fixed some mistakes in C# code of Chart Operations 2017-08-21 13:57:38 +03:00
DW 1d6569caa8 Issue #53: Complete add chart operation functions in expert (MQL part) 2017-08-18 18:56:00 +03:00
DW 441a3cb8de Merge with branch auth 2017-08-15 16:42:51 +03:00
DW 443f5c982c Issue #53: Complete chart operation functions into MtApi (client side) 2017-08-15 14:34:41 +03:00
DW 515a12ab15 Added function ChangeAccount 2017-08-12 01:31:36 +03:00
DW 84b00b605a Issue #53: Added some chart operation functions into MtApi (client side) 2017-08-11 23:33:30 +03:00
DW 10e267d031 Fixed bug in function iBarShift 2017-07-20 17:55:29 +03:00
DW abcd489367 Started version 1.0.37 2017-06-21 17:41:10 +03:00
DW d630e61e3c Issue #52: Updated functions OrderSend to use request stucture 2017-05-11 17:26:46 +03:00
DW 280bab7faf Started version 1.0.36 2017-05-11 10:44:30 +03:00
DW 26d270422b Revert version mtapi (MT4) to 1.0.35 2017-05-06 23:34:30 +03:00
DW 9cd2e3b18f Updated test application: added button on function UnlockTicks 2017-05-05 15:51:34 +03:00
DW 50013c0c29 Added command to UnlockTick in backtesting mode that will be locked on each candle. It allows to perform big tasks and send commands to MT4 in time of candle. 2017-05-05 14:16:15 +03:00
DW ca49d23017 Started version 1.0.36 2017-05-05 14:01:29 +03:00
DW 0346836d35 Issue #51: Add support localhost (127.0.0.1) host name 2017-05-05 13:57:43 +03:00
DW 2cc41df01a MtApi (MT4) version 1.0.34. Fixed issue #45 in MtApi.ex4 2017-02-22 17:17:00 +02:00
DW f05ade2cbf Set AppendToFile to True in LogConfigurator 2017-01-12 16:47:41 +02:00
DW d34524d77f Issue #44: Fixed MT5Connector project for using MtAdapter 2017-01-08 14:47:08 +02:00
DW d06cc67a5d MtApi MT5: started version 1.0.12 2017-01-08 14:45:03 +02:00
DW 5b76bf0547 Merge master fixed conflict. 2017-01-05 21:36:55 +02:00
DW 1c269f7339 Issue #32: Added function ObjectName into test client 2017-01-05 02:14:13 +02:00
DW 21fb790d8c Issue #32: Fixed small bugs in EA MtApi.mq4 2017-01-05 01:02:55 +02:00
DW 7c9a0aa8cc Issue #32: Implement object functions in EA MtApi.mq4 2017-01-03 21:29:41 +02:00
DW 18ddf3df1c Issue #32: Added c# implementations of most object functions in MtApi client 2016-12-30 17:16:48 +02:00
DW a8832b79ba Issue #32: Added function ObjectCreate in MtApi (MT4) 2016-12-27 17:41:11 +02:00
vdemydiuk 39146d68b2 Starting work on Object Functions 2016-12-26 17:49:06 +02:00
DW 5b03f01e9b Clear unnecessary witespaces in MtApi.mq4 2016-12-21 14:26:37 +02:00
vdemydiuk 8f5a1c8222 Refactored MtApi.mq4 2016-12-21 12:01:15 +02:00
vdemydiuk f5f13a13cc Issue #32: Added function ChartRedraw 2016-12-12 17:29:52 +02:00
vdemydiuk 9ef970cf1e Refactoring TestApiUiClient (Account Information tab) 2016-11-30 10:57:33 +02:00
vdemydiuk b5878ccb62 Refactoring TestApiUiClient (Check Status tab) 2016-11-29 19:08:53 +02:00
DW 4a7bb6f2cb MtApi (MT5) ver. 1.0.11.1 HotFix 2016-11-29 10:20:55 +02:00
vdemydiuk 5abfeebc90 Issue #32: Added function ChartId 2016-11-28 16:03:40 +02:00
vdemydiuk e333164552 Issue #32: Added ExecutorHandle property to determine which expert will be used for execution command 2016-11-28 14:45:33 +02:00
vdemydiuk 9a6968f618 Refactoring MtApi 2016-11-26 19:27:09 +02:00
DW d63a53b8a9 MtApi (MT4) version 1.0.32.1 (HotFix) 2016-11-25 16:06:11 +02:00
DW 7e821fcade Issue #38: Removed MemoryAppender in LogConfigurator (MtApiService) 2016-11-25 15:50:56 +02:00
DW 88e2d22abe Issue #38: Removed MemoryAppender in LogConfigurator (MtApiService) 2016-11-23 13:09:47 +02:00
DW fcfd741e5b Issue #37: Used ConcurrencyMode.Multiple for server and client side to avoid deadlocks and freezes of MtApiService 2016-11-23 10:51:50 +02:00
DW c722511c03 Refactored MtApiService (ver. 1.0.24): Added ExpertHandle to MtQuote and MtEvent. Added event QuoteUpdate to MtApiClient. 2016-11-18 15:47:55 +02:00
DW 39599436ab Started version 1.0.33 of MtApi MT4 2016-11-18 12:13:00 +02:00
177 changed files with 17672 additions and 6576 deletions
+3
View File
@@ -18,6 +18,9 @@ bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Roslyn cache directories
*.ide/
-30
View File
@@ -1,30 +0,0 @@
<Window x:Class="ConnectionsManager.AboutWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="About" Height="130" Width="300"
WindowStyle="ToolWindow"
WindowStartupLocation="CenterOwner">
<Window.Resources>
<BitmapImage x:Key="MtApiIcon" UriSource="pack://application:,,,/ConnectionsManager;component/favicon.ico"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="{StaticResource MtApiIcon}" Width="50" Height="50" HorizontalAlignment="Left" Margin="5"/>
<TextBlock Grid.Column="1" Text="Connection manager for MtApi" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<Button Grid.Row="1" Content="OK" Margin="5"
Width="70" IsDefault="True" IsCancel="True"
DockPanel.Dock="Bottom"
VerticalAlignment="Center"/>
</Grid>
</Window>
-28
View File
@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace ConnectionsManager
{
/// <summary>
/// Interaction logic for AboutWindow.xaml
/// </summary>
public partial class AboutWindow : Window
{
public AboutWindow(Window owner)
{
InitializeComponent();
this.Owner = owner;
}
}
}
-43
View File
@@ -1,43 +0,0 @@
<Window x:Class="ConnectionsManager.AddProfileDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Add new connection profile" Height="180" Width="300"
WindowStyle="ToolWindow"
WindowStartupLocation="CenterOwner">
<Grid x:Name="_MainLayout">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Profile name" Margin="5"/>
<TextBox Grid.Row="0" Grid.Column="1" Margin="5"
Text="{Binding Path=ProfileName, UpdateSourceTrigger=PropertyChanged}"
TextChanged="TextBox_TextChanged"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Host" Margin="5"/>
<ComboBox Grid.Row="1" Grid.Column="1" Margin="5"
ItemsSource="{Binding HostList}"
SelectedItem="{Binding Host}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Port" Margin="5"/>
<TextBox Grid.Row="2" Grid.Column="1" Margin="5"
Text="{Binding Path=Port, UpdateSourceTrigger=PropertyChanged}"
PreviewTextInput="TextBox_PreviewTextInput"
TextChanged="TextBox_TextChanged"/>
<StackPanel Grid.Row="3" Grid.ColumnSpan="2" Margin="0,10,0,0"
Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<Button Content="OK" Width="70" Margin="4" IsDefault="True" Command="{Binding OkCommand}"/>
<Button Content="Cancel" Width="70" Margin="4" IsCancel="True"/>
</StackPanel>
</Grid>
</Window>
@@ -1,97 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using System.Net;
namespace ConnectionsManager
{
/// <summary>
/// Interaction logic for AddProfileDialog.xaml
/// </summary>
public partial class AddProfileDialog : Window
{
// private const string PIPE_SERVER_NAME = "localhost(pipe)";
private const string LOCALHOST_NAME = "localhost";
public string ProfileName { get; set; }
public static readonly DependencyProperty HostProperty = DependencyProperty.Register("Host", typeof(string), typeof(AddProfileDialog));
public string Host
{
get { return (string)this.GetValue(HostProperty); }
set { this.SetValue(HostProperty, value); }
}
public string Port { get; set; }
public DelegateCommand OkCommand { get; set; }
public List<string> HostList { get; set; }
public AddProfileDialog(Window owner)
{
InitializeComponent();
this.Owner = owner;
OkCommand = new DelegateCommand(ExecuteOk, CanExecuteOk);
_MainLayout.DataContext = this;
Loaded += (sender, e) => MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName());
HostList = new List<string>();
HostList.Add(string.Empty);
HostList.Add(LOCALHOST_NAME);
if (ips != null)
{
foreach (IPAddress ipAddress in ips.AddressList)
{
HostList.Add(ipAddress.ToString());
}
}
Host = HostList.First();
}
private bool CanExecuteOk(object o)
{
return string.IsNullOrEmpty(ProfileName) == false
&& string.IsNullOrEmpty(Port) == false;
}
private void ExecuteOk(object o)
{
this.DialogResult = true;
Close();
}
private static bool IsTextAllowed(string text)
{
Regex regex = new Regex("[^0-9]+");
return !regex.IsMatch(text);
}
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = !IsTextAllowed(e.Text);
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
OkCommand.RaiseCanExecuteChanged();
}
}
}
-8
View File
@@ -1,8 +0,0 @@
<Application x:Class="ConnectionsManager.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
-16
View File
@@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
namespace ConnectionsManager
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
@@ -1,168 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C8751BA1-6A85-468C-87BD-758F37B8C0DD}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ConnectionsManager</RootNamespace>
<AssemblyName>ConnectionsManager</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisLogFile>bin\Debug\ConnectionsManager.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<CodeAnalysisLogFile>bin\Release\ConnectionsManager.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="AboutWindow.xaml.cs">
<DependentUpon>AboutWindow.xaml</DependentUpon>
</Compile>
<Compile Include="AddProfileDialog.xaml.cs">
<DependentUpon>AddProfileDialog.xaml</DependentUpon>
</Compile>
<Compile Include="DelegateCommand.cs" />
<Compile Include="ViewModel.cs" />
<Page Include="AboutWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="AddProfileDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MTApiService\MTApiService.csproj">
<Project>{DE76D5C7-B99C-4467-8408-78173BDD84E0}</Project>
<Name>MTApiService</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="favicon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy $(TargetPath) $(SolutionDir)Release\</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-51
View File
@@ -1,51 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace ConnectionsManager
{
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
}
-35
View File
@@ -1,35 +0,0 @@
<Window x:Class="ConnectionsManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MtApi Connections Manager" Height="300" Width="440"
Loaded="Window_Loaded">
<Grid x:Name="_MainLayout">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Menu>
<MenuItem Header="Edit">
<MenuItem Header="Add Profile..." Command="{Binding AddProfileCommand}"/>
<MenuItem Header="Delete Profile" Command="{Binding DeleteProfileCommand}"/>
</MenuItem>
<MenuItem Header="Help">
<MenuItem Header="About" Command="{Binding ShowAboutCommand}"/>
</MenuItem>
</Menu>
<ListView Grid.Row="1"
ItemsSource="{Binding ConnectionProfiles}"
SelectionMode="Single"
SelectedItem="{Binding SelectedProfile}">
<ListView.View>
<GridView>
<GridViewColumn Width="140" Header="Profile" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Width="180" Header="Host" DisplayMemberBinding="{Binding Host}" />
<GridViewColumn Width="80" Header="Port" DisplayMemberBinding="{Binding Port}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
-37
View File
@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ConnectionsManager
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ViewModel _vm;
public MainWindow()
{
InitializeComponent();
_vm = new ViewModel();
_MainLayout.DataContext = _vm;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_vm.Initialize();
}
}
}
@@ -1,55 +0,0 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 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("ConnectionsManager")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ConnectionsManager")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[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)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// 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.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
-63
View File
@@ -1,63 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18034
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ConnectionsManager.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ConnectionsManager.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
@@ -1,117 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
-26
View File
@@ -1,26 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18034
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ConnectionsManager.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
@@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
-114
View File
@@ -1,114 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using MTApiService;
using System.ComponentModel;
using System.Windows;
namespace ConnectionsManager
{
class ViewModel : INotifyPropertyChanged
{
#region Properties
private ObservableCollection<MtConnectionProfile> _ConnectionProfiles = new ObservableCollection<MtConnectionProfile>();
public ObservableCollection<MtConnectionProfile> ConnectionProfiles
{
get { return _ConnectionProfiles; }
}
public DelegateCommand AddProfileCommand { get; private set; }
public DelegateCommand DeleteProfileCommand { get; private set; }
public DelegateCommand ShowAboutCommand { get; private set; }
private MtConnectionProfile _SelectedProfile;
public MtConnectionProfile SelectedProfile
{
get { return _SelectedProfile; }
set
{
_SelectedProfile = value;
OnPropertyChanged("SelectedProfile");
DeleteProfileCommand.RaiseCanExecuteChanged();
}
}
#endregion
#region Public Methods
public ViewModel()
{
AddProfileCommand = new DelegateCommand(ExecuteAddProfile);
DeleteProfileCommand = new DelegateCommand(ExecuteDeleteProfile, CanExecuteDeleteProfile);
ShowAboutCommand = new DelegateCommand(ExecuteShowAbout);
}
public void Initialize()
{
var profiles = MtRegistryManager.LoadConnectionProfiles();
if (profiles != null)
{
foreach(var prof in profiles)
{
ConnectionProfiles.Add(prof);
}
}
}
#endregion
#region Private Methods
private void ExecuteAddProfile(object o)
{
var dlg = new AddProfileDialog(App.Current.MainWindow);
var result = dlg.ShowDialog();
if (result == true)
{
var profile = new MtConnectionProfile(dlg.ProfileName);
profile.Host = dlg.Host;
profile.Port = int.Parse(dlg.Port);
MtRegistryManager.AddConnectionProfile(profile);
ConnectionProfiles.Add(profile);
}
}
private bool CanExecuteDeleteProfile(object o)
{
return SelectedProfile != null;
}
private void ExecuteDeleteProfile(object o)
{
var result = MessageBox.Show("Do you want to delete connection profile '" + SelectedProfile.Name + "' ?"
, "Question", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
MtRegistryManager.RemoveConnectionProfile(SelectedProfile.Name);
ConnectionProfiles.Remove(SelectedProfile);
}
}
private void ExecuteShowAbout(object o)
{
var dlg = new AboutWindow(App.Current.MainWindow);
dlg.ShowDialog();
}
#endregion
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Fields
#endregion
}
}
-3
View File
@@ -1,3 +0,0 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 894 B

-61
View File
@@ -1,61 +0,0 @@
using System;
using System.Security.Cryptography;
using System.Text;
using System.Security;
namespace Licensing
{
public class DigitalSignatureHelper
{
public static String GeneratePrivateKey()
{
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
return dsa.ToXmlString(true);
}
public static String GetPublicKey(String privateKey)
{
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
dsa.FromXmlString(privateKey);
return dsa.ToXmlString(false);
}
public static string CreateSignature(string inputData, String privateKey)
{
// create the crypto-service provider:
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
// setup the dsa from the private key:
dsa.FromXmlString(privateKey);
byte[] data = UTF8Encoding.ASCII.GetBytes(inputData);
// get the signature:
byte[] signature = dsa.SignData(data);
return Convert.ToBase64String(signature);
}
public static bool VerifySignature(string inputData, string signature, string publicKey)
{
// create the crypto-service provider:
DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
// setup the provider from the public key:
dsa.FromXmlString(publicKey);
// get the license terms data:
//byte[] data = Convert.FromBase64String(inputData);
byte[] data = UTF8Encoding.ASCII.GetBytes(inputData);
// get the signature data:
byte[] signatureData = Convert.FromBase64String(signature);
// verify that the license-terms match the signature data
if (dsa.VerifyData(data, signatureData) == false)
throw new SecurityException("Signature Not Verified!");
return true;
}
}
}
-77
View File
@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{21FA6E21-EE5D-4A84-B0ED-E1D8876B41FB}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Licensing</RootNamespace>
<AssemblyName>Licensing</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DigitalSignatureHelper.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MTApiService\MTApiService.csproj">
<Project>{DE76D5C7-B99C-4467-8408-78173BDD84E0}</Project>
<Name>MTApiService</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-326
View File
@@ -1,326 +0,0 @@
namespace Licensing
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBoxPublicKey = new System.Windows.Forms.TextBox();
this.buttonGenerateKey = new System.Windows.Forms.Button();
this.buttonLoadKey = new System.Windows.Forms.Button();
this.buttonSaveKey = new System.Windows.Forms.Button();
this.textBoxPrivateKey = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.textBoxAccountName = new System.Windows.Forms.TextBox();
this.textBoxAccountNumber = new System.Windows.Forms.TextBox();
this.buttonSign = new System.Windows.Forms.Button();
this.textBoxSignature = new System.Windows.Forms.TextBox();
this.buttonGetPublicKey = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.clipboardCopyBtn = new System.Windows.Forms.Button();
this.buttonExportPublicKey = new System.Windows.Forms.Button();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.label3 = new System.Windows.Forms.Label();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.saveToRegBtn = new System.Windows.Forms.Button();
this.buttonVerify = new System.Windows.Forms.Button();
this.buttonExportSignature = new System.Windows.Forms.Button();
this.readRegBtn = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.groupBox4.SuspendLayout();
this.SuspendLayout();
//
// textBoxPublicKey
//
this.textBoxPublicKey.Location = new System.Drawing.Point(6, 19);
this.textBoxPublicKey.Name = "textBoxPublicKey";
this.textBoxPublicKey.ReadOnly = true;
this.textBoxPublicKey.Size = new System.Drawing.Size(620, 20);
this.textBoxPublicKey.TabIndex = 0;
//
// buttonGenerateKey
//
this.buttonGenerateKey.Location = new System.Drawing.Point(6, 45);
this.buttonGenerateKey.Name = "buttonGenerateKey";
this.buttonGenerateKey.Size = new System.Drawing.Size(75, 23);
this.buttonGenerateKey.TabIndex = 2;
this.buttonGenerateKey.Text = "Generate";
this.buttonGenerateKey.UseVisualStyleBackColor = true;
this.buttonGenerateKey.Click += new System.EventHandler(this.buttonGenerateKey_Click);
//
// buttonLoadKey
//
this.buttonLoadKey.Location = new System.Drawing.Point(168, 45);
this.buttonLoadKey.Name = "buttonLoadKey";
this.buttonLoadKey.Size = new System.Drawing.Size(75, 23);
this.buttonLoadKey.TabIndex = 3;
this.buttonLoadKey.Text = "Load";
this.buttonLoadKey.UseVisualStyleBackColor = true;
this.buttonLoadKey.Click += new System.EventHandler(this.buttonLoadKey_Click);
//
// buttonSaveKey
//
this.buttonSaveKey.Location = new System.Drawing.Point(87, 45);
this.buttonSaveKey.Name = "buttonSaveKey";
this.buttonSaveKey.Size = new System.Drawing.Size(75, 23);
this.buttonSaveKey.TabIndex = 4;
this.buttonSaveKey.Text = "Save";
this.buttonSaveKey.UseVisualStyleBackColor = true;
this.buttonSaveKey.Click += new System.EventHandler(this.buttonSaveKey_Click);
//
// textBoxPrivateKey
//
this.textBoxPrivateKey.Location = new System.Drawing.Point(6, 19);
this.textBoxPrivateKey.Name = "textBoxPrivateKey";
this.textBoxPrivateKey.ReadOnly = true;
this.textBoxPrivateKey.Size = new System.Drawing.Size(620, 20);
this.textBoxPrivateKey.TabIndex = 0;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(8, 48);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(47, 13);
this.label4.TabIndex = 6;
this.label4.Text = "Number:";
//
// textBoxAccountName
//
this.textBoxAccountName.Location = new System.Drawing.Point(67, 19);
this.textBoxAccountName.Name = "textBoxAccountName";
this.textBoxAccountName.Size = new System.Drawing.Size(559, 20);
this.textBoxAccountName.TabIndex = 7;
//
// textBoxAccountNumber
//
this.textBoxAccountNumber.Location = new System.Drawing.Point(67, 45);
this.textBoxAccountNumber.Name = "textBoxAccountNumber";
this.textBoxAccountNumber.Size = new System.Drawing.Size(559, 20);
this.textBoxAccountNumber.TabIndex = 7;
//
// buttonSign
//
this.buttonSign.Location = new System.Drawing.Point(10, 45);
this.buttonSign.Name = "buttonSign";
this.buttonSign.Size = new System.Drawing.Size(75, 23);
this.buttonSign.TabIndex = 8;
this.buttonSign.Text = "Sign";
this.buttonSign.UseVisualStyleBackColor = true;
this.buttonSign.Click += new System.EventHandler(this.buttonSign_Click);
//
// textBoxSignature
//
this.textBoxSignature.Location = new System.Drawing.Point(10, 19);
this.textBoxSignature.Name = "textBoxSignature";
this.textBoxSignature.Size = new System.Drawing.Size(615, 20);
this.textBoxSignature.TabIndex = 10;
//
// buttonGetPublicKey
//
this.buttonGetPublicKey.Location = new System.Drawing.Point(6, 45);
this.buttonGetPublicKey.Name = "buttonGetPublicKey";
this.buttonGetPublicKey.Size = new System.Drawing.Size(75, 23);
this.buttonGetPublicKey.TabIndex = 11;
this.buttonGetPublicKey.Text = "Get Key";
this.buttonGetPublicKey.UseVisualStyleBackColor = true;
this.buttonGetPublicKey.Click += new System.EventHandler(this.buttonGetPublicKey_Click);
//
// groupBox1
//
this.groupBox1.Controls.Add(this.textBoxPrivateKey);
this.groupBox1.Controls.Add(this.buttonGenerateKey);
this.groupBox1.Controls.Add(this.buttonLoadKey);
this.groupBox1.Controls.Add(this.buttonSaveKey);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(632, 78);
this.groupBox1.TabIndex = 12;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Private Key";
//
// groupBox2
//
this.groupBox2.Controls.Add(this.clipboardCopyBtn);
this.groupBox2.Controls.Add(this.buttonExportPublicKey);
this.groupBox2.Controls.Add(this.textBoxPublicKey);
this.groupBox2.Controls.Add(this.buttonGetPublicKey);
this.groupBox2.Location = new System.Drawing.Point(12, 96);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(632, 77);
this.groupBox2.TabIndex = 13;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Public Key";
//
// clipboardCopyBtn
//
this.clipboardCopyBtn.Location = new System.Drawing.Point(169, 46);
this.clipboardCopyBtn.Name = "clipboardCopyBtn";
this.clipboardCopyBtn.Size = new System.Drawing.Size(113, 23);
this.clipboardCopyBtn.TabIndex = 13;
this.clipboardCopyBtn.Text = "Copy to Clipboard";
this.clipboardCopyBtn.UseVisualStyleBackColor = true;
this.clipboardCopyBtn.Click += new System.EventHandler(this.clipboardCopyBtn_Click);
//
// buttonExportPublicKey
//
this.buttonExportPublicKey.Location = new System.Drawing.Point(88, 46);
this.buttonExportPublicKey.Name = "buttonExportPublicKey";
this.buttonExportPublicKey.Size = new System.Drawing.Size(75, 23);
this.buttonExportPublicKey.TabIndex = 12;
this.buttonExportPublicKey.Text = "Export";
this.buttonExportPublicKey.UseVisualStyleBackColor = true;
this.buttonExportPublicKey.Click += new System.EventHandler(this.buttonExportPublicKey_Click);
//
// groupBox3
//
this.groupBox3.Controls.Add(this.textBoxAccountName);
this.groupBox3.Controls.Add(this.label3);
this.groupBox3.Controls.Add(this.textBoxAccountNumber);
this.groupBox3.Controls.Add(this.label4);
this.groupBox3.Location = new System.Drawing.Point(12, 180);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(635, 81);
this.groupBox3.TabIndex = 14;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Account";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(8, 22);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(38, 13);
this.label3.TabIndex = 5;
this.label3.Text = "Name:";
//
// groupBox4
//
this.groupBox4.Controls.Add(this.readRegBtn);
this.groupBox4.Controls.Add(this.saveToRegBtn);
this.groupBox4.Controls.Add(this.buttonVerify);
this.groupBox4.Controls.Add(this.buttonExportSignature);
this.groupBox4.Controls.Add(this.textBoxSignature);
this.groupBox4.Controls.Add(this.buttonSign);
this.groupBox4.Location = new System.Drawing.Point(13, 268);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(631, 76);
this.groupBox4.TabIndex = 15;
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Signature";
//
// saveToRegBtn
//
this.saveToRegBtn.Location = new System.Drawing.Point(172, 45);
this.saveToRegBtn.Name = "saveToRegBtn";
this.saveToRegBtn.Size = new System.Drawing.Size(101, 23);
this.saveToRegBtn.TabIndex = 13;
this.saveToRegBtn.Text = "Save To Reg";
this.saveToRegBtn.UseVisualStyleBackColor = true;
this.saveToRegBtn.Click += new System.EventHandler(this.saveToRegBtn_Click);
//
// buttonVerify
//
this.buttonVerify.Location = new System.Drawing.Point(550, 45);
this.buttonVerify.Name = "buttonVerify";
this.buttonVerify.Size = new System.Drawing.Size(75, 23);
this.buttonVerify.TabIndex = 12;
this.buttonVerify.Text = "Verify";
this.buttonVerify.UseVisualStyleBackColor = true;
this.buttonVerify.Click += new System.EventHandler(this.buttonVerify_Click);
//
// buttonExportSignature
//
this.buttonExportSignature.Location = new System.Drawing.Point(91, 45);
this.buttonExportSignature.Name = "buttonExportSignature";
this.buttonExportSignature.Size = new System.Drawing.Size(75, 23);
this.buttonExportSignature.TabIndex = 11;
this.buttonExportSignature.Text = "Export";
this.buttonExportSignature.UseVisualStyleBackColor = true;
this.buttonExportSignature.Click += new System.EventHandler(this.buttonExportSignature_Click);
//
// readRegBtn
//
this.readRegBtn.Location = new System.Drawing.Point(279, 45);
this.readRegBtn.Name = "readRegBtn";
this.readRegBtn.Size = new System.Drawing.Size(132, 23);
this.readRegBtn.TabIndex = 14;
this.readRegBtn.Text = "Read from Registry";
this.readRegBtn.UseVisualStyleBackColor = true;
this.readRegBtn.Click += new System.EventHandler(this.readRegBtn_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(659, 351);
this.Controls.Add(this.groupBox4);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Name = "MainForm";
this.Text = "Liccensing";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.groupBox4.ResumeLayout(false);
this.groupBox4.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TextBox textBoxPublicKey;
private System.Windows.Forms.Button buttonGenerateKey;
private System.Windows.Forms.Button buttonLoadKey;
private System.Windows.Forms.Button buttonSaveKey;
private System.Windows.Forms.TextBox textBoxPrivateKey;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox textBoxAccountName;
private System.Windows.Forms.TextBox textBoxAccountNumber;
private System.Windows.Forms.Button buttonSign;
private System.Windows.Forms.TextBox textBoxSignature;
private System.Windows.Forms.Button buttonGetPublicKey;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button buttonExportPublicKey;
private System.Windows.Forms.GroupBox groupBox4;
private System.Windows.Forms.Button buttonExportSignature;
private System.Windows.Forms.Button buttonVerify;
private System.Windows.Forms.Button clipboardCopyBtn;
private System.Windows.Forms.Button saveToRegBtn;
private System.Windows.Forms.Button readRegBtn;
}
}
-352
View File
@@ -1,352 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using MTApiService;
namespace Licensing
{
public partial class MainForm : Form
{
private bool mIsSaved = true;
public MainForm()
{
InitializeComponent();
}
private void buttonGenerateKey_Click(object sender, EventArgs e)
{
textBoxPrivateKey.Text = DigitalSignatureHelper.GeneratePrivateKey();
mIsSaved = false;
}
private void buttonGetPublicKey_Click(object sender, EventArgs e)
{
string privateKey = textBoxPrivateKey.Text;
if (string.IsNullOrEmpty(privateKey) == false)
{
textBoxPublicKey.Text = DigitalSignatureHelper.GetPublicKey(privateKey);
}
else
{
MessageBox.Show("Private Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void buttonSaveKey_Click(object sender, EventArgs e)
{
string privateKey = textBoxPrivateKey.Text;
if (string.IsNullOrEmpty(privateKey) == false)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "MetaTraderApi Key Files (*.mtk)|*.mtk";
dlg.Title = "Save MetaTraderApi Key File";
if (dlg.ShowDialog() == DialogResult.OK)
{
try
{
using (TextWriter file = new StreamWriter(dlg.FileName, true))
{
file.WriteLine(privateKey);
}
mIsSaved = true;
}
catch (Exception ex)
{
var errorMsg = string.Format("Saving failed!\n{0}", ex.Message);
MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
else
{
MessageBox.Show("Private Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void buttonLoadKey_Click(object sender, EventArgs e)
{
if (mIsSaved == false)
{
if (MessageBox.Show("Private Key is not saved. Continue?", "Private Key", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
return;
}
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "MetaTraderApi Key Files (*.mtk)|*.mtk";
dlg.Title = "Load MetaTraderApi Key File";
if (dlg.ShowDialog() == DialogResult.OK)
{
textBoxPrivateKey.Text = string.Empty;
textBoxPublicKey.Text = string.Empty;
try
{
using (TextReader file = new StreamReader(dlg.FileName))
{
textBoxPrivateKey.Text = file.ReadLine();
}
mIsSaved = true;
}
catch (Exception ex)
{
var errorMsg = string.Format("Saving failed!\n{0}", ex.Message);
MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void buttonSign_Click(object sender, EventArgs e)
{
string privateKey = textBoxPrivateKey.Text;
if (string.IsNullOrEmpty(privateKey) == false)
{
string accountName = textBoxAccountName.Text;
string accountNumber = textBoxAccountNumber.Text;
if (string.IsNullOrEmpty(accountName) == false)
{
if (string.IsNullOrEmpty(accountNumber) == false)
{
string inputData = accountName + accountNumber;
textBoxSignature.Text = DigitalSignatureHelper.CreateSignature(inputData, privateKey);
}
else
{
MessageBox.Show("AccountNumber is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
MessageBox.Show("AccountName is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
MessageBox.Show("Private Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void buttonExportPublicKey_Click(object sender, EventArgs e)
{
string publicKey = textBoxPublicKey.Text;
if (string.IsNullOrEmpty(publicKey) == false)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "MetaTraderApi Key Files (*.mtk)|*.mtk";
dlg.Title = "Export MetaTraderApi Key File";
if (dlg.ShowDialog() == DialogResult.OK)
{
try
{
using (TextWriter file = new StreamWriter(dlg.FileName, true))
{
file.WriteLine(publicKey);
}
mIsSaved = true;
}
catch (Exception ex)
{
var errorMsg = string.Format("Export failed!\n{0}", ex.Message);
MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
else
{
MessageBox.Show("Public Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void buttonExportSignature_Click(object sender, EventArgs e)
{
string signature = textBoxSignature.Text;
if (string.IsNullOrEmpty(signature) == false)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "MetaTraderApi Key (*.mta)|*.mta";
dlg.Title = "Export MetaTraderApi Key";
if (dlg.ShowDialog() == DialogResult.OK)
{
try
{
using (TextWriter file = new StreamWriter(dlg.FileName))
{
file.WriteLine(signature);
}
mIsSaved = true;
}
catch (Exception ex)
{
var errorMsg = string.Format("Export failed!\n{0}", ex.Message);
MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
else
{
MessageBox.Show("Signature is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void buttonVerify_Click(object sender, EventArgs e)
{
string publicKey = textBoxPublicKey.Text;
if (string.IsNullOrEmpty(publicKey) == false)
{
string signature = textBoxSignature.Text;
if (string.IsNullOrEmpty(signature) == false)
{
string accountName = textBoxAccountName.Text;
string accountNumber = textBoxAccountNumber.Text;
if (string.IsNullOrEmpty(accountName) == false)
{
if (string.IsNullOrEmpty(accountNumber) == false)
{
string inputData = accountName + accountNumber;
var verifyResult = false;
try
{
verifyResult = DigitalSignatureHelper.VerifySignature(inputData, signature, publicKey);
}
catch (SecurityException ex)
{
MessageBox.Show(ex.Message, "Verify", MessageBoxButtons.OK, MessageBoxIcon.Warning);
verifyResult = false;
}
catch (Exception ex)
{
string errorMsg = string.Format("Verify process failed!\n{0}", ex.Message);
MessageBox.Show(errorMsg, "Verify", MessageBoxButtons.OK, MessageBoxIcon.Error);
verifyResult = false;
}
if (verifyResult == true)
{
MessageBox.Show("Signature good", "Verify", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
else
{
MessageBox.Show("AccountNumber is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
MessageBox.Show("AccountName is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
MessageBox.Show("Signature is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
MessageBox.Show("Public Key is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
private void clipboardCopyBtn_Click(object sender, EventArgs e)
{
Clipboard.SetText(textBoxPublicKey.Text);
}
private void saveToRegBtn_Click(object sender, EventArgs e)
{
string signature = textBoxSignature.Text;
string accountName = textBoxAccountName.Text;
string accountNumber = textBoxAccountNumber.Text;
if (string.IsNullOrEmpty(signature))
{
MessageBox.Show("Signature is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (string.IsNullOrEmpty(accountName))
{
MessageBox.Show("AccountName is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (string.IsNullOrEmpty(accountNumber))
{
MessageBox.Show("AccountNumber is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "Registry files (*.reg)|*.reg";
dlg.Title = "Registry files";
if (dlg.ShowDialog() == DialogResult.OK)
{
string key = MtRegistryManager.SaveSignatureKey(accountName, accountNumber, signature);
bool exported = MtRegistryManager.ExportKey(key, dlg.FileName);
if (exported)
{
MessageBox.Show("Export successed.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.None);
}
else
{
MessageBox.Show("Export failed!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void readRegBtn_Click(object sender, EventArgs e)
{
string accountName = textBoxAccountName.Text;
string accountNumber = textBoxAccountNumber.Text;
if (string.IsNullOrEmpty(accountName))
{
MessageBox.Show("AccountName is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (string.IsNullOrEmpty(accountNumber))
{
MessageBox.Show("AccountNumber is empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
string signature = MtRegistryManager.ReadSignatureKey(accountName, accountNumber);
textBoxSignature.Text = signature;
}
}
}
-120
View File
@@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
-21
View File
@@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Licensing
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
-36
View File
@@ -1,36 +0,0 @@
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("Licensing")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("DW")]
[assembly: AssemblyProduct("Licensing")]
[assembly: AssemblyCopyright("Copyright © DW 2012")]
[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("2c3df81b-2285-44ff-a152-0111e25d9b1a")]
// 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.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+1 -3
View File
@@ -35,6 +35,4 @@ using namespace System::Security::Permissions;
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
[assembly:CLSCompliantAttribute(true)];
+153 -377
View File
@@ -6,14 +6,15 @@
#include "MT5Handler.h"
#include "Windows.h"
#include < vcclr.h >
#include <vcclr.h>
#include <functional>
using namespace System;
using namespace MTApiService;
using namespace System::Runtime::InteropServices;
using namespace System::Reflection;
using namespace System::Text;
using namespace System::Collections::Generic;
using namespace System::Collections::Generic;
using namespace System::Diagnostics;
using namespace System::Security::Cryptography;
using namespace System::Security;
@@ -30,297 +31,166 @@ public struct CMqlRates
int spread; // Spread
__int64 real_volume; // Trade volume
};
public struct CMqlTick
{
__int64 time; // Time of the last prices update
double bid; // Current Bid price
double ask; // Current Ask price
double last; // Price of the last deal (Last)
unsigned __int64 volume; // Volume for the current Last price
};
public struct CMqlBookInfo
{
int type; // Order type from ENUM_BOOK_TYPE enumeration
double price; // Price
__int64 volume; // Volume
};
#pragma pack(pop)
void convertSystemString(wchar_t* dest, String^ src)
{
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
memcpy(dest, wch, wcslen(wch) * sizeof(wchar_t));
dest[wcslen(wch)] = '\0';
if (src != nullptr) {
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
memcpy(dest, wch, wcsnlen(wch, 1000) * sizeof(wchar_t));
dest[wcsnlen(wch, 1000)] = L'\0';
}
else
{
dest[0] = L'\0';
}
}
bool VerifySignature(System::String^ inputData, System::String^ signature, System::String^ publicKey)
{
bool verifyResult = false;
#define _DLLAPI extern "C" __declspec(dllexport)
template <typename T> T Execute(std::function<T()> func, wchar_t* err, T default_value)
{
T result = default_value;
try
{
DSACryptoServiceProvider^ dsa = gcnew DSACryptoServiceProvider();
dsa->FromXmlString(publicKey);
array<System::Byte>^ data = UTF8Encoding::ASCII->GetBytes(inputData);
array<System::Byte>^ signatureData = Convert::FromBase64String(signature);
verifyResult = dsa->VerifyData(data, signatureData);
}
catch(Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:VerifySignature(): failed. " + e->Message);
verifyResult = false;
}
return verifyResult;
}
bool g_IsVerified = true;
void _stdcall verify(int isDemo, wchar_t* accountName, long accountNumber)
{
if (isDemo != 0)
{
g_IsVerified = true;
return;
}
System::String^ signature = MtRegistryManager::ReadSignatureKey(gcnew String(accountName), accountNumber.ToString());
Resources::ResourceManager^ rm = gcnew Resources::ResourceManager(L"MT5Connector.cl", Assembly::GetExecutingAssembly());
System::String^ inputData = gcnew System::String(accountName);
inputData += accountNumber.ToString();
System::String^ publicKey = rm->GetString(L"cl");
g_IsVerified = VerifySignature(inputData, gcnew System::String(signature), publicKey);
}
int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
if (g_IsVerified == false)
{
System::String^ errorVerified = "Verification is failed!\nPlease contact with support.";
convertSystemString(err, errorVerified);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): not verified");
return 0;
}
try
{
MT5Handler^ mtHander = gcnew MT5Handler();
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHander);
result = func();
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:initExpert(): " + e->Message);
return 0;
}
return 1;
return result;
}
int _stdcall deinitExpert(int expertHandle, wchar_t* err)
_DLLAPI int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, int isTestMode, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:deinitExpert(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, &port, symbol, &bid, &ask, &isTestMode]() {
bool isTesting = (isTestMode != 0) ? true : false;
auto expert = gcnew Mt5Expert(expertHandle, gcnew String(symbol), bid, ask, gcnew MT5Handler(), isTesting);
MtAdapter::GetInstance()->AddExpert(port, expert);
return 1;
}, err, 0);
}
int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
_DLLAPI int _stdcall deinitExpert(int expertHandle, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MT5Connector:updateQuote(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle]() {
MtAdapter::GetInstance()->RemoveExpert(expertHandle);
return 1;
}, err, 0);
}
int _stdcall sendIntResponse(int expertHandle, int response)
_DLLAPI int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, symbol, &bid, &ask]() {
MtAdapter::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
return 1;
}, err, 0);
}
int _stdcall sendLongResponse(int expertHandle, __int64 response)
_DLLAPI bool _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &eventType, payload]() {
MtAdapter::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
return true;
}, err, false);
}
int _stdcall sendULongResponse(int expertHandle, unsigned __int64 response)
_DLLAPI int _stdcall sendIntResponse(int expertHandle, int response, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseULong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
return 1;
}, err, 0);
}
int _stdcall sendBooleanResponse(int expertHandle, int response)
_DLLAPI int _stdcall sendLongResponse(int expertHandle, __int64 response, wchar_t* err)
{
try
{
return Execute<int>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
return 1;
}, err, 0);
}
_DLLAPI int _stdcall sendULongResponse(int expertHandle, unsigned __int64 response, wchar_t* err)
{
return Execute<int>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseULong(response));
return 1;
}, err, 0);
}
_DLLAPI int _stdcall sendBooleanResponse(int expertHandle, int response, wchar_t* err)
{
return Execute<int>([&expertHandle, &response]() {
bool value = (response != 0) ? true : false;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendBooleanResponse(): " + e->Message);
return 0;
}
return 1;
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
return 1;
}, err, 0);
}
int _stdcall sendDoubleResponse(int expertHandle, double response)
_DLLAPI int _stdcall sendDoubleResponse(int expertHandle, double response, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
return 1;
}, err, 0);
}
int _stdcall sendStringResponse(int expertHandle, wchar_t* response)
_DLLAPI int _stdcall sendStringResponse(int expertHandle, wchar_t* response, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendStringResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
return 1;
}, err, 0);
}
int _stdcall sendVoidResponse(int expertHandle)
_DLLAPI int _stdcall sendVoidResponse(int expertHandle, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendVoidResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseObject(nullptr));
return 1;
}, err, 0);
}
int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size)
_DLLAPI int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size, wchar_t* err)
{
try
{
return Execute<int>([&expertHandle, values, &size]() {
array<double>^ list = gcnew array<double>(size);
for(int i = 0; i < size; i++)
{
for (int i = 0; i < size; i++)
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendDoubleArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
return 1;
}, err, 0);
}
int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size)
_DLLAPI int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size, wchar_t* err)
{
try
{
return Execute<int>([&expertHandle, values, &size]() {
array<int>^ list = gcnew array<int>(size);
for(int i = 0; i < size; i++)
{
for (int i = 0; i < size; i++)
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendIntArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
return 1;
}, err, 0);
}
int _stdcall sendLongArrayResponse(int expertHandle, __int64* values, int size)
_DLLAPI int _stdcall sendLongArrayResponse(int expertHandle, __int64* values, int size, wchar_t* err)
{
try
{
return Execute<int>([&expertHandle, values, &size]() {
array<System::Int64>^ list = gcnew array<System::Int64>(size);
for(int i = 0; i < size; i++)
{
for (int i = 0; i < size; i++)
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLongArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendLongArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLongArray(list));
return 1;
}, err, 0);
}
int _stdcall sendMqlRatesArrayResponse(int expertHandle, CMqlRates values[], int size)
_DLLAPI int _stdcall sendMqlRatesArrayResponse(int expertHandle, CMqlRates values[], int size, wchar_t* err)
{
try
{
return Execute<int>([&expertHandle, values, &size]() {
array<MtMqlRates^>^ list = gcnew array<MtMqlRates^>(size);
for(int i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
MtMqlRates^ rates = gcnew MtMqlRates();
rates->time = values[i].time;
@@ -331,180 +201,86 @@ int _stdcall sendMqlRatesArrayResponse(int expertHandle, CMqlRates values[], int
rates->tick_volume = values[i].tick_volume;
rates->spread = values[i].spread;
rates->real_volume = values[i].real_volume;
list[i] = rates;
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlRatesArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlRatesArray(list));
return 1;
}, err, 0);
}
int _stdcall sendMqlTickResponse(int expertHandle, CMqlTick* response, int size)
_DLLAPI bool _stdcall sendErrorResponse(int expertHandle, int code, wchar_t* message, wchar_t* err)
{
try
{
MtMqlTick^ mtResponse = gcnew MtMqlTick();
mtResponse->time = response->time;
mtResponse->bid = response->bid;
mtResponse->ask = response->ask;
mtResponse->last = response->last;
mtResponse->volume = response->volume;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlTick(mtResponse));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlTickResponse(): " + e->Message);
return 0;
}
return 1;
}
int _stdcall sendMqlBookInfoArrayResponse(int expertHandle, CMqlBookInfo values[], int size)
{
try
{
array<MtMqlBookInfo^>^ list = gcnew array<MtMqlBookInfo^>(size);
for(int i = 0; i < size; i++)
{
MtMqlBookInfo^ info = gcnew MtMqlBookInfo();
info->type = values[i].type;
info->price = values[i].price;
info->volume = values[i].volume;
list[i] = info;
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseMqlBookInfoArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:sendMqlRatesArrayResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &code, message]() {
MtResponseString^ res = gcnew MtResponseString(gcnew String(message));
res->ErrorCode = code;
MtAdapter::GetInstance()->SendResponse(expertHandle, res);
return true;
}, err, false);
}
//----------- get values -------------------------------
int _stdcall getCommandType(int expertHandle, int* res)
_DLLAPI int _stdcall getCommandType(int expertHandle, int* res, wchar_t* err)
{
try
{
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getCommandType(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, res]() {
*res = MtAdapter::GetInstance()->GetCommandType(expertHandle);
return 1;
}, err, 0);
}
int _stdcall getIntValue(int expertHandle, int paramIndex, int* res)
_DLLAPI int _stdcall getIntValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{
try
{
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getIntValue(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, &paramIndex, res]() {
*res = (int)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return 1;
}, err, 0);
}
int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res)
_DLLAPI int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res, wchar_t* err)
{
try
{
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getDoubleValue(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, &paramIndex, res]() {
*res = (double)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return 1;
}, err, 0);
}
int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
_DLLAPI int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res, wchar_t* err)
{
try
{
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getStringValue(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, &paramIndex, res]() {
convertSystemString(res, (String^)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
return 1;
}, err, 0);
}
int _stdcall getULongValue(int expertHandle, int paramIndex, unsigned __int64* res)
_DLLAPI int _stdcall getULongValue(int expertHandle, int paramIndex, unsigned __int64* res, wchar_t* err)
{
try
{
*res = (unsigned long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getULongValue(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, &paramIndex, res]() {
*res = (unsigned __int64)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return 1;
}, err, 0);
}
int _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res)
_DLLAPI int _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res, wchar_t* err)
{
try
{
*res = (long)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getLongValue(): " + e->Message);
return 0;
}
return 1;
return Execute<int>([&expertHandle, &paramIndex, res]() {
*res = (__int64)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return 1;
}, err, 0);
}
int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res)
_DLLAPI int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{
try
{
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return Execute<int>([&expertHandle, &paramIndex, res]() {
bool val = (bool)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = val == true ? 1 : 0;
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getBooleanValue(): " + e->Message);
return 0;
}
return 1;
return 1;
}, err, 0);
}
int _stdcall getUIntValue(int expertHandle, int paramIndex, unsigned int* res)
_DLLAPI int _stdcall getUIntValue(int expertHandle, int paramIndex, unsigned int* res, wchar_t* err)
{
try
{
*res = (unsigned int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getUIntValue(): " + e->Message);
return 0;
}
return 1;
}
return Execute<int>([&expertHandle, &paramIndex, res]() {
*res = (unsigned int)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return 1;
}, err, 0);
}
-27
View File
@@ -1,27 +0,0 @@
LIBRARY MT5Connector
EXPORTS initExpert
deinitExpert
updateQuote
sendIntResponse
sendBooleanResponse
sendDoubleResponse
sendStringResponse
sendVoidResponse
sendDoubleArrayResponse
sendIntArrayResponse
sendLongArrayResponse
sendMqlRatesArrayResponse
sendLongResponse
sendULongResponse
sendMqlTickResponse
sendMqlBookInfoArrayResponse
getCommandType
getIntValue
getUIntValue
getDoubleValue
getStringValue
getLongValue
getULongValue
getBooleanValue
verify
+6 -10
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -23,6 +23,7 @@
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>MT5Connector</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -30,28 +31,28 @@
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -95,7 +96,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib</AdditionalDependencies>
<ModuleDefinitionFile>.\MT5Connector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -108,7 +108,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MT5Connector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -120,7 +119,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MT5Connector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -132,7 +130,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MT5Connector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -157,7 +154,6 @@
</ItemGroup>
<ItemGroup>
<None Include="app.ico" />
<None Include="MT5Connector.def" />
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
@@ -44,9 +44,6 @@
<None Include="app.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="MT5Connector.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc">
+2 -3
View File
@@ -1,8 +1,7 @@
namespace MTApiService
{
public interface ICommandManager
internal interface ICommandManager
{
void EnqueueCommandTask(MtCommandTask task);
MtCommandTask DequeueCommandTask();
MtCommandTask SendCommand(MtCommand task);
}
}
+1 -6
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MTApiService
namespace MTApiService
{
public interface IMetaTraderHandler
{
+9
View File
@@ -0,0 +1,9 @@
namespace MTApiService
{
internal interface ITaskExecutor
{
void Execute(MtCommandTask task);
int Handle { get; }
}
}
+89 -13
View File
@@ -8,28 +8,93 @@ using log4net.Repository.Hierarchy;
namespace MTApiService
{
public class MtLog
{
#region ctor
internal MtLog(Type type)
{
_log = LogManager.GetLogger(type);
}
#endregion
#region Public
public void Debug(object message)
{
_log.Debug(message);
}
public void Error(object message)
{
_log.Error(message);
}
public void Fatal(object message)
{
_log.Fatal(message);
}
public void Info(object message)
{
_log.Info(message);
}
public void Warn(object message)
{
_log.Warn(message);
}
#endregion
#region Private
private readonly ILog _log;
#endregion
}
public enum LogLevel
{
Off,
Debug,
Info
}
public class LogConfigurator
{
private const string LogFileNameExtension = "txt";
private const string LogFileNameExtension = "log";
public static void Setup(string profileName)
{
#if (DEBUG)
const LogLevel logLevel = LogLevel.Debug;
#else
const LogLevel logLevel = LogLevel.Info;
#endif
Setup(profileName, logLevel);
}
public static void Setup(string profileName, LogLevel logLevel)
{
if (string.IsNullOrEmpty(profileName))
throw new ArgumentNullException();
var hierarchy = (Hierarchy) LogManager.GetRepository();
//check if logger is already configurated to avoid creation many empty logs files
if (hierarchy.Configured)
return;
var patternLayout = new PatternLayout
{
ConversionPattern = "%date [%thread] %-5level %logger - %message%newline"
};
patternLayout.ActivateOptions();
string filename = $"{DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss")}-{Process.GetCurrentProcess().Id}.{LogFileNameExtension}";
var filename = $"{DateTime.Now:yyyy-dd-M--HH-mm-ss}-{Process.GetCurrentProcess().Id}.{LogFileNameExtension}";
var roller = new RollingFileAppender
{
AppendToFile = false,
AppendToFile = true,
File = $@"{System.IO.Path.GetTempPath()}{profileName}\Logs\{filename}",
Layout = patternLayout,
PreserveLogFileNameExtension = true,
@@ -40,17 +105,28 @@ namespace MTApiService
};
roller.ActivateOptions();
hierarchy.Root.AddAppender(roller);
var memory = new MemoryAppender();
memory.ActivateOptions();
hierarchy.Root.AddAppender(memory);
#if (DEBUG)
hierarchy.Root.Level = Level.Debug;
#else
hierarchy.Root.Level = Level.Info;
#endif
hierarchy.Root.Level = ConvertLogLevel(logLevel);
hierarchy.Configured = true;
}
public static MtLog GetLogger(Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
return new MtLog(type);
}
private static Level ConvertLogLevel(LogLevel logLevel)
{
switch (logLevel)
{
case LogLevel.Debug: return Level.Debug;
case LogLevel.Info: return Level.Info;
case LogLevel.Off: return Level.Off;
default:
throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null);
}
}
}
}
+4 -4
View File
@@ -62,7 +62,9 @@
<ItemGroup>
<Compile Include="ICommandManager.cs" />
<Compile Include="IMetaTraderHandler.cs" />
<Compile Include="ITaskExecutor.cs" />
<Compile Include="LogConfigurator.cs" />
<Compile Include="Mt5Expert.cs" />
<Compile Include="MtCommandEventArgs.cs" />
<Compile Include="IDisposableChannel.cs" />
<Compile Include="IMtApiServer.cs" />
@@ -70,19 +72,17 @@
<Compile Include="MtClient.cs" />
<Compile Include="MtCommandTask.cs" />
<Compile Include="MtEvent.cs" />
<Compile Include="MtMqlBookInfo.cs" />
<Compile Include="MtMqlRates.cs" />
<Compile Include="MtMqlTick.cs" />
<Compile Include="MtMqlTradeRequest.cs" />
<Compile Include="MtRegistryManager.cs" />
<Compile Include="MtConnectionProfile.cs" />
<Compile Include="MtExecutorManager.cs" />
<Compile Include="MtExpert.cs" />
<Compile Include="MtInstrument.cs" />
<Compile Include="MtQuote.cs" />
<Compile Include="MtResponse.cs" />
<Compile Include="MtServer.cs" />
<Compile Include="MtCommand.cs" />
<Compile Include="MtServerInstance.cs" />
<Compile Include="MtAdapter.cs" />
<Compile Include="MtService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
+77
View File
@@ -0,0 +1,77 @@
using log4net;
namespace MTApiService
{
public class Mt5Expert : MtExpert
{
private static readonly ILog Log = LogManager.GetLogger(typeof(Mt5Expert));
private const int StopExpertInterval = 2000; // 2 sec for testing mode
private System.Timers.Timer _stopTimer;
public Mt5Expert(int handle, string symbol, double bid, double ask, IMetaTraderHandler mtHandler, bool isTestMode) :
base(handle, symbol, bid, ask, mtHandler)
{
IsTestMode = isTestMode;
}
public bool IsTestMode { get; }
public override int GetCommandType()
{
Log.Debug("GetCommandType: called.");
if (IsTestMode)
{
ResetTestModeTimer();
}
return base.GetCommandType();
}
public override void SendEvent(MtEvent mtEvent)
{
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
if (IsTestMode)
{
if (_stopTimer == null)
{
_stopTimer = new System.Timers.Timer
{
Interval = StopExpertInterval,
AutoReset = false
};
_stopTimer.Elapsed += _stopTimer_Elapsed;
}
}
base.SendEvent(mtEvent);
Log.Debug("SendEvent: end.");
}
private void _stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Log.Debug("_stopTimer_Elapsed: begin.");
Log.Warn("Mt5Expert has received new tick during 2 sec in testing mode. The possible cause: user has stopped the tester manually in MetaTrader 5.");
Deinit();
_stopTimer.Elapsed -= _stopTimer_Elapsed;
_stopTimer = null;
Log.Debug("_stopTimer_Elapsed: end.");
}
private void ResetTestModeTimer()
{
if (_stopTimer == null)
return;
//reset timer
_stopTimer.Stop();
_stopTimer.Start();
}
}
}
+90 -23
View File
@@ -4,13 +4,13 @@ using log4net;
namespace MTApiService
{
public class MtServerInstance
public class MtAdapter
{
#region Fields
private const string LogProfileName = "MtApiService";
private static readonly ILog Log = LogManager.GetLogger(typeof(MtServerInstance));
private static readonly MtServerInstance Instance = new MtServerInstance();
private static readonly ILog Log = LogManager.GetLogger(typeof(MtAdapter));
private static readonly MtAdapter Instance = new MtAdapter();
private readonly Dictionary<int, MtServer> _servers = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> _experts = new Dictionary<int, MtExpert>();
@@ -18,16 +18,16 @@ namespace MTApiService
#region Init Instance
private MtServerInstance()
private MtAdapter()
{
LogConfigurator.Setup(LogProfileName);
}
static MtServerInstance()
static MtAdapter()
{
}
public static MtServerInstance GetInstance()
public static MtAdapter GetInstance()
{
return Instance;
}
@@ -36,12 +36,12 @@ namespace MTApiService
#region Public Methods
public void InitExpert(int expertHandle, int port, string symbol, double bid, double ask, IMetaTraderHandler mtHandler)
public void AddExpert(int port, MtExpert expert)
{
if (mtHandler == null)
throw new ArgumentNullException(nameof(mtHandler));
if (expert == null)
throw new ArgumentNullException(nameof(expert));
Log.InfoFormat("InitExpert: begin. symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
Log.InfoFormat("AddExpert: begin. expert = {0}", expert);
MtServer server;
lock (_servers)
@@ -60,21 +60,20 @@ namespace MTApiService
}
}
var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler);
lock (_experts)
{
_experts[expert.Handle] = expert;
}
server.AddExpert(expert);
expert.Deinited += ExpertOnDeinited;
Log.Info("InitExpert: end");
Log.Info("AddExpert: end");
}
public void DeinitExpert(int expertHandle)
public void RemoveExpert(int expertHandle)
{
Log.InfoFormat("DeinitExpert: begin. expertHandle = {0}", expertHandle);
Log.InfoFormat("RemoveExpert: begin. expertHandle = {0}", expertHandle);
MtExpert expert = null;
@@ -83,7 +82,6 @@ namespace MTApiService
if (_experts.ContainsKey(expertHandle))
{
expert = _experts[expertHandle];
_experts.Remove(expertHandle);
}
}
@@ -93,15 +91,15 @@ namespace MTApiService
}
else
{
Log.WarnFormat("DeinitExpert: expert with id {0} has not been found.", expertHandle);
Log.WarnFormat("RemoveExpert: expert with id {0} has not been found.", expertHandle);
}
Log.Info("DeinitExpert: end");
Log.Info("RemoveExpert: end");
}
public void SendQuote(int expertHandle, string symbol, double bid, double ask)
{
Log.DebugFormat("SendQuote: begin. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
Log.DebugFormat("UpdateQuote: begin. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
MtExpert expert;
lock (_experts)
@@ -111,14 +109,14 @@ namespace MTApiService
if (expert != null)
{
expert.Quote = new MtQuote(symbol, bid, ask);
expert.UpdateQuote(new MtQuote { Instrument = symbol, Bid = bid, Ask = ask, ExpertHandle = expertHandle });
}
else
{
Log.WarnFormat("SendQuote: expert with id {0} has not been found.", expertHandle);
Log.WarnFormat("UpdateQuote: expert with id {0} has not been found.", expertHandle);
}
Log.Debug("SendQuote: end");
Log.Debug("UpdateQuote: end");
}
public void SendEvent(int expertHandle, int eventType, string payload)
@@ -133,7 +131,7 @@ namespace MTApiService
if (expert != null)
{
expert.SendEvent(new MtEvent(eventType, payload));
expert.SendEvent(new MtEvent { EventType = eventType, Payload = payload, ExpertHandle = expertHandle });
}
else
{
@@ -208,6 +206,50 @@ namespace MTApiService
return retval;
}
public object GetNamedParameter(int expertHandle, string name)
{
Log.DebugFormat("GetNamedParameter: begin. expertHandle = {0}, name = {1}", expertHandle, name);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("GetNamedParameter: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetNamedParameter(name);
Log.DebugFormat("GetNamedParameter: end. retval = {0}", retval);
return retval;
}
public bool ContainsNamedParameter(int expertHandle, string name)
{
Log.DebugFormat("ContainsNamedParameter: begin. expertHandle = {0}, name = {1}", expertHandle, name);
MtExpert expert;
lock (_experts)
{
expert = _experts[expertHandle];
}
if (expert == null)
{
Log.WarnFormat("ContainsNamedParameter: expert with id {0} has not been found.", expertHandle);
}
bool retval = expert != null ? expert.ContainsNamedParameter(name) : false;
Log.DebugFormat("ContainsNamedParameter: end. retval = {0}", retval);
return retval;
}
#endregion
#region Private Methods
@@ -228,6 +270,31 @@ namespace MTApiService
}
}
}
private void ExpertOnDeinited(object sender, EventArgs eventArgs)
{
Log.Debug("ExpertOnDeinited: begin.");
var expert = sender as MtExpert;
if (expert == null)
{
Log.Warn("expert_Deinited: end. Expert is not defined.");
return;
}
lock (_experts)
{
if (_experts.ContainsKey(expert.Handle))
{
_experts.Remove(expert.Handle);
}
}
Log.DebugFormat("ExpertOnDeinited: removed expert {0}", expert.Handle);
Log.Debug("ExpertOnDeinited: end.");
}
#endregion
}
}
+1 -1
View File
@@ -11,13 +11,13 @@ namespace MTApiService
: base(callbackContext, binding, remoteAddress)
{
InnerDuplexChannel.Faulted += InnerDuplexChannel_Faulted;
InnerDuplexChannel.Open();
}
#region IMtApi Members
public bool Connect()
{
InnerDuplexChannel.Open();
return Channel.Connect();
}
+42 -90
View File
@@ -6,38 +6,33 @@ using log4net;
namespace MTApiService
{
[CallbackBehavior(UseSynchronizationContext = false)]
public class MtClient: IMtApiCallback, IDisposable
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public 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 MtApiProxy _proxy;
private bool _isConnected;
private readonly MtApiProxy _proxy;
#endregion
#region Public Methods
public void Open(string host, int port)
#region ctor
public MtClient(string host, int port)
{
Log.DebugFormat("Open: begin. host = {0}, port = {1}", host, 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");
var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
Host = host;
Port = port;
if (_proxy != null)
{
Log.Warn("Open: end. _proxy is not null.");
return;
}
var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
var bind = new NetTcpBinding(SecurityMode.None)
{
@@ -55,28 +50,19 @@ namespace MTApiService
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted;
Log.Debug("Open: end.");
}
public void Open(int port)
public MtClient(int port)
{
Log.DebugFormat("Open: begin. port = {0}", port);
if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
Port = port;
if (_proxy != null)
{
Log.Warn("Open: end. _proxy is not null.");
return;
}
var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{
@@ -94,61 +80,40 @@ namespace MTApiService
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted;
Log.Debug("Open: end.");
}
public void Close()
{
Log.Debug("Close: begin.");
if (_proxy != null)
{
_proxy.Faulted -= ProxyFaulted;
_proxy.Dispose();
_proxy = null;
}
_isConnected = false;
Log.Debug("Close: end.");
}
#endregion
#region Public Methods
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public void Connect()
{
Log.Debug("Connect: begin.");
if (_proxy == null)
if (_proxy.State != CommunicationState.Created)
{
Log.Error("Connect: _proxy is not defined.");
throw new CommunicationException("Connection failed to service. Proxy is not defined (needs to call Open)");
}
if (_isConnected)
{
Log.Warn("Connected: end. Client is already connected.");
Log.ErrorFormat("Connected: end. Client has invalid state {0}", _proxy.State);
return;
}
bool coonected;
try
{
_isConnected = _proxy.Connect();
coonected = _proxy.Connect();
}
catch (Exception ex)
{
Log.ErrorFormat("Connect: Exception - {0}", ex.Message);
Close();
throw new CommunicationException($"Connection failed to service. {ex.Message}");
}
if (_isConnected == false)
if (coonected == false)
{
Log.Error("Connect: end. Connection failed.");
throw new CommunicationException("Connection failed");
@@ -163,72 +128,60 @@ namespace MTApiService
try
{
_isConnected = false;
_proxy?.Disconnect();
_proxy.Disconnect();
}
catch (Exception ex)
{
Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message);
Close();
}
Log.Debug("Disconnect: end.");
}
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public MtResponse SendCommand(int commandType, ArrayList parameters)
public MtResponse SendCommand(int commandType, ArrayList parameters, Dictionary<string, object> namedParams, int expertHandle)
{
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
MtResponse result;
if (_isConnected == false)
if (IsConnected == false)
{
Log.Error("SendCommand: Client is not connected.");
throw new CommunicationException("Client is not connected.");
}
if (_proxy == null)
{
Log.Error("SendCommand: Proxy is not defined.");
throw new CommunicationException("Proxy is not defined.");
}
MtResponse result;
try
{
result = _proxy.SendCommand(new MtCommand(commandType, parameters));
result = _proxy.SendCommand(new MtCommand {
CommandType = commandType,
Parameters = parameters,
NamedParams = namedParams,
ExpertHandle = expertHandle});
}
catch (Exception ex)
{
Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message);
Close();
throw new CommunicationException("Service connection failed! " + ex.Message);
}
Log.DebugFormat("SendCommand: end. result = {0}", result);
return result;
}
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public IEnumerable<MtQuote> GetQuotes()
public List<MtQuote> GetQuotes()
{
Log.Debug("GetQuotes: begin.");
if (_isConnected == false)
if (IsConnected == false)
{
Log.Warn("GetQuotes: end. Client is not connected.");
return null;
}
if (_proxy == null)
{
Log.Warn("GetQuotes: end. _proxy is not defined.");
return null;
}
List<MtQuote> result;
try
@@ -239,8 +192,6 @@ namespace MTApiService
{
Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message);
Close();
throw new CommunicationException($"Service connection failed! {ex.Message}");
}
@@ -286,18 +237,17 @@ namespace MTApiService
{
Log.Debug("OnServerStopped: begin.");
Close();
ServerDisconnected?.Invoke(this, EventArgs.Empty);
Log.Debug("OnServerStopped: end.");
}
public void OnMtEvent(MtEvent mtEvent)
public void OnMtEvent(MtEvent e)
{
Log.DebugFormat("OnMtEvent: begin. event = {0}", mtEvent);
Log.DebugFormat("OnMtEvent: begin. event = {0}", e);
MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent));
MtEventReceived?.Invoke(e);
Log.Debug("OnMtEvent: end.");
}
@@ -305,7 +255,10 @@ namespace MTApiService
#endregion
#region Properties
public bool IsConnected => _proxy.State == CommunicationState.Opened && _isConnected;
public string Host { get; private set; }
public int Port { get; private set; }
private bool IsConnected => _proxy.State == CommunicationState.Opened;
#endregion
@@ -315,7 +268,6 @@ namespace MTApiService
{
Log.Debug("ProxyFaulted: begin.");
Close();
ServerFailed?.Invoke(this, EventArgs.Empty);
Log.Debug("ProxyFaulted: end.");
@@ -329,7 +281,7 @@ namespace MTApiService
{
Log.Debug("Dispose: begin.");
Close();
_proxy.Dispose();
Log.Debug("Dispose: end.");
}
@@ -342,7 +294,7 @@ namespace MTApiService
public event MtQuoteHandler QuoteUpdated;
public event EventHandler ServerDisconnected;
public event EventHandler ServerFailed;
public event EventHandler<MtEventArgs> MtEventReceived;
public event MtEventHandler MtEventReceived;
#endregion
}
}
+9 -8
View File
@@ -1,26 +1,27 @@
using System.Runtime.Serialization;
using System.Collections;
using System.Collections.Generic;
namespace MTApiService
{
[DataContract]
public class MtCommand
{
public MtCommand(int commandType, ArrayList parameters)
{
CommandType = commandType;
Parameters = parameters;
}
[DataMember]
public int CommandType { get; set; }
[DataMember]
public int CommandType { get; private set; }
public ArrayList Parameters { get; set; }
[DataMember]
public ArrayList Parameters { get; private set; }
public Dictionary<string, object> NamedParams { get; set; }
[DataMember]
public int ExpertHandle { get; set; }
public override string ToString()
{
return $"CommandType = {CommandType}";
return $"CommandType = {CommandType}; ExpertHandle = {ExpertHandle}";
}
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ namespace MTApiService
Command = command;
}
public MtCommand Command { get; private set; }
public MtCommand Command { get; }
public MtResponse WaitResult(int time)
{
+5 -18
View File
@@ -7,30 +7,17 @@ namespace MTApiService
public class MtEvent
{
[DataMember]
public int EventType { get; private set; }
public int EventType { get; internal set; }
[DataMember]
public string Payload { get; private set; }
public string Payload { get; internal set; }
public MtEvent(int eventType, string payload)
{
EventType = eventType;
Payload = payload;
}
[DataMember]
public int ExpertHandle { get; internal set; }
public override string ToString()
{
return "MtEvent = " + EventType + ", Payload = " + Payload;
return $"EventType = {EventType}; Payload = {Payload}; ExpertHandle = {ExpertHandle}";
}
}
public class MtEventArgs: EventArgs
{
public MtEventArgs(MtEvent e)
{
Event = e;
}
public MtEvent Event { get; private set; }
}
}
+55 -111
View File
@@ -4,14 +4,13 @@ using log4net;
namespace MTApiService
{
internal class MtCommandExecutorManager : ICommandManager
internal class MtExecutorManager : ICommandManager
{
#region Private Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtCommandExecutorManager));
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExecutorManager));
private readonly List<ITaskExecutor> _executorList = new List<ITaskExecutor>();
private readonly Dictionary<int, ITaskExecutor> _executorMap = new Dictionary<int, ITaskExecutor>();
private readonly object _locker = new object();
#endregion
@@ -23,149 +22,94 @@ namespace MTApiService
lock (_locker)
{
_commandExecutors.Clear();
_commandTasks.Clear();
_executorList.Clear();
_executorMap.Clear();
}
Log.Debug("Stop: end.");
}
public void AddCommandExecutor(MtExpert commandExecutor)
public void AddExecutor(ITaskExecutor executor)
{
if (commandExecutor == null)
throw new ArgumentNullException(nameof(commandExecutor));
if (executor == null)
throw new ArgumentNullException(nameof(executor));
Log.DebugFormat("AddCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
Log.DebugFormat("AddExecutor: begin. executor = {0}", executor);
var notify = false;
lock (_locker)
{
if (_commandExecutors.Contains(commandExecutor))
if (_executorList.Contains(executor))
{
Log.Warn("AddCommandExecutor: end. Command executor already exist.");
Log.Warn("AddExecutor: end. Executor already exist.");
return;
}
_commandExecutors.Add(commandExecutor);
if (_commandTasks.Count > 0)
{
notify = true;
}
}
commandExecutor.CommandExecuted += CommandExecutor_CommandExecuted;
commandExecutor.CommandManager = this;
if (notify)
{
NotifyCommandReady();
_executorList.Add(executor);
_executorMap[executor.Handle] = executor;
}
Log.Debug("AddCommandExecutor: end.");
}
public void RemoveCommandExecutor(MtExpert commandExecutor)
public void RemoveExecutor(ITaskExecutor executor)
{
if (commandExecutor == null)
throw new ArgumentNullException(nameof(commandExecutor));
if (executor == null)
throw new ArgumentNullException(nameof(executor));
Log.DebugFormat("RemoveCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
Log.DebugFormat("RemoveExecutor: begin. executor = {0}", executor);
var notify = false;
lock (_locker)
{
if (_commandExecutors.Contains(commandExecutor) == false)
if (_executorList.Contains(executor) == false)
{
Log.Warn("RemoveCommandExecutor: end. Command executor is not exist in collection.");
Log.Warn("RemoveExecutor: end. Executor is not exist in collection.");
return;
}
_commandExecutors.Remove(commandExecutor);
if (_commandTasks.Count > 0)
_executorList.Remove(executor);
_executorMap.Remove(executor.Handle);
}
Log.Debug("RemoveExecutor: end.");
}
public MtCommandTask SendCommand(MtCommand command)
{
if (command == null)
throw new ArgumentNullException(nameof(command));
var task = new MtCommandTask(command);
Log.DebugFormat("SendTask: begin. command = {0}", command);
ITaskExecutor executor;
lock (_locker)
{
if (_executorMap.ContainsKey(command.ExpertHandle))
{
notify = true;
executor = _executorMap[command.ExpertHandle];
}
else
{
executor = _executorList.Count > 0 ? _executorList[0] : null;
}
}
commandExecutor.CommandExecuted -= CommandExecutor_CommandExecuted;
commandExecutor.CommandManager = null;
if (notify)
if (executor == null)
{
NotifyCommandReady();
Log.Error("SendTask: Executor is null!");
}
else
{
executor.Execute(task);
}
Log.Debug("RemoveCommandExecutor: end.");
Log.Debug("SendTask: end.");
return task;
}
public void EnqueueCommandTask(MtCommandTask task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
Log.DebugFormat("EnqueueCommandTask: begin. task = {0}", task);
lock (_locker)
{
_commandTasks.Enqueue(task);
}
NotifyCommandReady();
Log.Debug("EnqueueCommandTask: end.");
}
public MtCommandTask DequeueCommandTask()
{
Log.Debug("DequeueCommandTask: called.");
lock (_locker)
{
return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null;
}
}
#endregion
#region Private Methods
private void NotifyCommandReady()
{
Log.Debug("NotifyCommandReady: begin.");
var commandExecutors = new List<MtExpert>();
lock (_locker)
{
commandExecutors.AddRange(_commandExecutors);
}
foreach (var executor in commandExecutors)
{
executor.NotifyCommandReady();
}
Log.DebugFormat("NotifyCommandReady: end. Notified executor count = {0}", commandExecutors.Count);
}
private void CommandExecutor_CommandExecuted(object sender, EventArgs e)
{
Log.Debug("CommandExecutor_CommandExecuted: begin.");
var notify = false;
lock (_locker)
{
if (_commandTasks.Count > 0)
{
notify = true;
}
}
if (notify)
{
NotifyCommandReady();
}
Log.Debug("CommandExecutor_CommandExecuted: end.");
}
#endregion
}
}
+107 -80
View File
@@ -1,37 +1,38 @@
using System;
using log4net;
using System.Collections.Generic;
namespace MTApiService
{
public class MtExpert
public class MtExpert: ITaskExecutor
{
public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote);
public delegate void MtEventHandler(MtExpert expert, MtEvent e);
#region Private Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExpert));
private readonly IMetaTraderHandler _mtHadler;
private MtCommandTask _commandTask;
private ICommandManager _commandManager;
private MtCommandTask _currentTask;
private readonly Queue<MtCommandTask> _taskQueue = new Queue<MtCommandTask>();
private readonly object _locker = new object();
#endregion
#region Public Methods
public MtExpert(int handle, MtQuote quote, IMetaTraderHandler mtHandler)
public MtExpert(int handle, string symbol, double bid, double ask, IMetaTraderHandler mtHandler)
{
if (mtHandler == null)
throw new ArgumentNullException(nameof(mtHandler));
Quote = quote;
_quote = new MtQuote { ExpertHandle = handle, Instrument = symbol, Bid = bid, Ask = ask};
Handle = handle;
_mtHadler = mtHandler;
}
public void Deinit()
public virtual void Deinit()
{
Log.Debug("Deinit: begin.");
IsEnable = false;
FireOnDeinited();
Log.Debug("Deinit: end.");
@@ -41,31 +42,26 @@ namespace MTApiService
{
Log.DebugFormat("SendResponse: begin. response = {0}", response);
_commandTask.SetResult(response);
_commandTask = null;
FireOnCommandExecuted();
_currentTask.SetResult(response);
_currentTask = null;
Log.Debug("SendResponse: end.");
}
public int GetCommandType()
public virtual int GetCommandType()
{
Log.Debug("GetCommandType: called.");
var commandManager = CommandManager;
if (commandManager != null)
{
_commandTask = commandManager.DequeueCommandTask();
}
_currentTask = DequeueTask();
return _commandTask?.Command?.CommandType ?? 0;
return _currentTask?.Command?.CommandType ?? 0;
}
public object GetCommandParameter(int index)
{
Log.DebugFormat("GetCommandType: called. index = {0}", index);
Log.DebugFormat("GetCommandParameter: called. index = {0}", index);
var command = _commandTask?.Command;
var command = _currentTask?.Command;
if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count)
{
return command.Parameters[index];
@@ -74,7 +70,47 @@ namespace MTApiService
return null;
}
public void SendEvent(MtEvent mtEvent)
public object GetNamedParameter(string name)
{
Log.DebugFormat("GetNamedParameter: called. name = {0}", name);
var command = _currentTask?.Command;
if (command == null)
{
Log.Warn("GetNamedParameter: command is not defined in task.");
return null;
}
if (command.NamedParams == null)
{
Log.Warn("GetNamedParameter: NamedParams is not defined in command.");
return null;
}
return command.NamedParams[name];
}
public bool ContainsNamedParameter(string name)
{
Log.DebugFormat("ContainsNamedParameter: called. name = {0}", name);
var command = _currentTask?.Command;
if (command == null)
{
Log.Warn("ContainsNamedParameter: command is not defined in task.");
return false;
}
if (command.NamedParams == null)
{
Log.Warn("ContainsNamedParameter: NamedParams is not defined in command.");
return false;
}
return command.NamedParams.ContainsKey(name);
}
public virtual void SendEvent(MtEvent mtEvent)
{
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
@@ -83,14 +119,38 @@ namespace MTApiService
Log.Debug("SendEvent: end.");
}
public void UpdateQuote(MtQuote quote)
{
Log.DebugFormat("UpdateQuote: begin. quote = {0}", quote);
Quote = quote;
Log.Debug("UpdateQuote: end.");
}
public override string ToString()
{
return $"ExpertHandle = {Handle}";
return $"ExpertHandle = {Handle}, Quote = {Quote}";
}
#endregion
#region ITaskExecutor
public void Execute(MtCommandTask task)
{
lock (_taskQueue)
{
_taskQueue.Enqueue(task);
}
NotifyCommandReady();
}
#endregion
#region Properties
private MtQuote _quote;
public MtQuote Quote
{
@@ -101,7 +161,7 @@ namespace MTApiService
return _quote;
}
}
set
private set
{
lock (_locker)
{
@@ -113,61 +173,34 @@ namespace MTApiService
}
public int Handle { get; }
private bool _isEnable = true;
public bool IsEnable
{
get
{
lock (_locker)
{
return _isEnable;
}
}
private set
{
lock (_locker)
{
_isEnable = value;
}
}
}
public ICommandManager CommandManager
{
private get
{
lock (_locker)
{
return _commandManager;
}
}
set
{
lock (_locker)
{
_commandManager = value;
}
}
}
#endregion
#region IMtCommandExecutor
public void NotifyCommandReady()
{
Log.Debug("NotifyCommandReady: begin.");
SendTickToMetaTrader();
Log.Debug("NotifyCommandReady: end.");
}
#endregion
#region Private Methods
private void SendTickToMetaTrader()
private MtCommandTask DequeueTask()
{
Log.Debug("DequeueTask: called.");
MtCommandTask task;
int count;
lock (_locker)
{
count = _taskQueue.Count;
task = _taskQueue.Count > 0 ? _taskQueue.Dequeue() : null;
}
Log.DebugFormat("DequeueTask: end. left task count = {0}.", count);
return task;
}
private void NotifyCommandReady()
{
Log.Debug("NotifyCommandReady: begin.");
_mtHadler.SendTickToMetaTrader(Handle);
Log.Debug("NotifyCommandReady: end.");
}
private void FireOnQuoteChanged(MtQuote quote)
@@ -180,22 +213,16 @@ namespace MTApiService
Deinited?.Invoke(this, EventArgs.Empty);
}
private void FireOnCommandExecuted()
{
CommandExecuted?.Invoke(this, EventArgs.Empty);
}
private void FireOnMtEvent(MtEvent mtEvent)
{
OnMtEvent?.Invoke(this, new MtEventArgs(mtEvent));
OnMtEvent?.Invoke(this, mtEvent);
}
#endregion
#region Events
public event EventHandler Deinited;
public event MtQuoteHandler QuoteChanged;
public event EventHandler CommandExecuted;
public event EventHandler<MtEventArgs> OnMtEvent;
public event MtEventHandler OnMtEvent;
#endregion
}
}
-29
View File
@@ -1,29 +0,0 @@
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtQuote
{
[DataMember]
public string Instrument { get; private set; }
[DataMember]
public double Bid { get; private set; }
[DataMember]
public double Ask { get; private set; }
public MtQuote(string instrument, double bid, double ask)
{
Instrument = instrument;
Bid = bid;
Ask = ask;
}
public override string ToString()
{
return "Instrument = " + Instrument + ", Bid = " + Bid + ", Ask = " + Ask;
}
}
}
-17
View File
@@ -1,17 +0,0 @@
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtMqlBookInfo
{
[DataMember]
public int type { get; set; }
[DataMember]
public double price { get; set; }
[DataMember]
public long volume { get; set; }
}
}
-23
View File
@@ -1,23 +0,0 @@
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtMqlTick
{
[DataMember]
public long time { get; set; } // Time of the last prices update
[DataMember]
public double bid { get; set; } // Current Bid price
[DataMember]
public double ask { get; set; } // Current Ask price
[DataMember]
public double last { get; set; } // Price of the last deal (Last)
[DataMember]
public ulong volume { get; set; } // Volume for the current Last price
}
}
+7 -3
View File
@@ -9,9 +9,9 @@ namespace MTApiService
[DataMember]
public int Action { get; set; }
[DataMember]
public uint Magic { get; set; }
public ulong Magic { get; set; }
[DataMember]
public uint Order { get; set; }
public ulong Order { get; set; }
[DataMember]
public string Symbol { get; set; }
[DataMember]
@@ -25,7 +25,7 @@ namespace MTApiService
[DataMember]
public double Tp { get; set; }
[DataMember]
public uint Deviation { get; set; }
public ulong Deviation { get; set; }
[DataMember]
public int Type { get; set; }
[DataMember]
@@ -36,5 +36,9 @@ namespace MTApiService
public DateTime Expiration { get; set; }
[DataMember]
public string Comment { get; set; }
[DataMember]
public ulong Position { get; set; }
[DataMember]
public ulong PositionBy { get; set; }
}
}
+25
View File
@@ -0,0 +1,25 @@
using System.Runtime.Serialization;
namespace MTApiService
{
[DataContract]
public class MtQuote
{
[DataMember]
public string Instrument { get; internal set; }
[DataMember]
public double Bid { get; internal set; }
[DataMember]
public double Ask { get; internal set; }
[DataMember]
public int ExpertHandle { get; internal set; }
public override string ToString()
{
return $"Instrument = {Instrument}; Bid = {Bid}; Ask = {Ask}; ExpertHandle = {ExpertHandle}";
}
}
}
+26 -43
View File
@@ -12,16 +12,38 @@ namespace MTApiService
{
static IEnumerable<Type> GetKnownTypes()
{
return new Type[] { typeof(MtResponseInt), typeof(MtResponseDouble),
return new Type[] { typeof(MtResponseObject),
typeof(MtResponseInt), typeof(MtResponseDouble),
typeof(MtResponseString), typeof(MtResponseBool),
typeof(MtResponseLong), typeof(MtResponseULong),
typeof(MtResponseDoubleArray), typeof(MtResponseIntArray),
typeof(MtResponseLongArray), typeof(MtResponseMqlTick),
typeof(MtResponseArrayList), typeof(MtResponseMqlRatesArray),
typeof(MtResponseMqlBookInfoArray)};
typeof(MtResponseLongArray),
typeof(MtResponseArrayList), typeof(MtResponseMqlRatesArray)};
}
public abstract object GetValue();
[DataMember]
public int ErrorCode { get; set; }
}
[DataContract]
public class MtResponseObject : MtResponse
{
public MtResponseObject(object value)
{
Value = value;
}
[DataMember]
public object Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value?.ToString() ?? string.Empty;
}
}
[DataContract]
@@ -232,43 +254,4 @@ namespace MTApiService
return Value.ToString();
}
}
[DataContract]
public class MtResponseMqlTick : MtResponse
{
public MtResponseMqlTick(MtMqlTick value)
{
Value = value;
}
[DataMember]
public MtMqlTick Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
[DataContract]
public class MtResponseMqlBookInfoArray : MtResponse
{
public MtResponseMqlBookInfoArray(MtMqlBookInfo[] value)
{
Value = value;
}
[DataMember]
public MtMqlBookInfo[] Value { get; private set; }
public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
}
}
+29 -17
View File
@@ -21,7 +21,7 @@ namespace MTApiService
private readonly MtService _service;
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
private readonly MtExecutorManager _executorManager = new MtExecutorManager();
private readonly List<MtExpert> _experts = new List<MtExpert>();
#endregion
@@ -62,21 +62,24 @@ namespace MTApiService
}
//init local pipe host
var localUrl = CreateConnectionAddress(null, port, true);
var localServiceHost = CreateServiceHost(localUrl, true);
var localPipeUrl = CreateConnectionAddress(null, port, true);
var localPipeServiceHost = CreateServiceHost(localPipeUrl, true);
if (localPipeServiceHost != null)
{
_hosts.Add(localPipeServiceHost);
}
//init localhost
var localUrl = CreateConnectionAddress("localhost", port, false);
var localServiceHost = CreateServiceHost(localUrl, false);
if (localServiceHost != null)
{
_hosts.Add(localServiceHost);
}
//init network hosts
var dnsHostName = Dns.GetHostName();
var ips = Dns.GetHostEntry(dnsHostName);
if (ips == null)
{
Log.WarnFormat("InitHosts: end. Dns.GetHostEntry has returned null for DNS Host Name {0}", dnsHostName);
return false;
}
foreach (var ipAddress in ips.AddressList)
{
@@ -149,7 +152,7 @@ namespace MTApiService
_experts.Add(expert);
}
_executorManager.AddCommandExecutor(expert);
_executorManager.AddExecutor(expert);
_service.OnQuoteAdded(expert.Quote);
@@ -170,11 +173,20 @@ namespace MTApiService
return null;
}
var task = new MtCommandTask(command);
_executorManager.EnqueueCommandTask(task);
var task = _executorManager.SendCommand(command);
//wait for execute command in MetaTrader
var response = task.WaitResult(WaitResponseTime);
MtResponse response = null;
try
{
response = task.WaitResult(WaitResponseTime);
}
catch (Exception ex)
{
Log.WarnFormat("SendCommand: Exception - {0}", ex.Message);
}
Log.DebugFormat("SendCommand: end. response = {0}", response);
return response;
}
@@ -371,7 +383,7 @@ namespace MTApiService
expertsCount = _experts.Count;
}
_executorManager.RemoveCommandExecutor(expert);
_executorManager.RemoveExecutor(expert);
expert.Deinited -= expert_Deinited;
expert.QuoteChanged -= expert_QuoteChanged;
@@ -398,11 +410,11 @@ namespace MTApiService
Log.Debug("expert_QuoteChanged: end.");
}
private void Expert_OnMtEvent(object sender, MtEventArgs e)
private void Expert_OnMtEvent(MtExpert expert, MtEvent e)
{
Log.DebugFormat("Expert_OnMtEvent: begin. event = {0}", e.Event);
Log.DebugFormat("Expert_OnMtEvent: begin. expert = {0}, event = {1}", expert, e);
_service.OnMtEvent(e.Event);
_service.OnMtEvent(e);
Log.Debug("Expert_OnMtEvent: end.");
}
+7 -7
View File
@@ -66,7 +66,7 @@ namespace MTApiService
if (callback == null)
{
Log.Warn("Connect: end. Callback is not definded.");
Log.Warn("Connect: end. Callback is not defined.");
return false;
}
@@ -158,7 +158,7 @@ namespace MTApiService
public void QuoteUpdate(MtQuote quote)
{
Log.Debug("QuoteUpdate: begin.");
Log.DebugFormat("QuoteUpdate: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteUpdate(quote));
@@ -167,7 +167,7 @@ namespace MTApiService
public void OnQuoteAdded(MtQuote quote)
{
Log.Debug("OnQuoteAdded: begin.");
Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteAdded(quote));
@@ -176,18 +176,18 @@ namespace MTApiService
public void OnQuoteRemoved(MtQuote quote)
{
Log.Debug("OnQuoteRemoved: begin.");
Log.DebugFormat("OnQuoteRemoved: begin. quote = {0}", quote);
ExecuteCallbackAction(a => a.OnQuoteRemoved(quote));
Log.Debug("OnQuoteRemoved: end.");
}
public void OnMtEvent(MtEvent mtEvent)
public void OnMtEvent(MtEvent e)
{
Log.Debug("OnMtEvent: begin.");
Log.DebugFormat("OnMtEvent: begin.quote = {0}", e);
ExecuteCallbackAction(a => a.OnMtEvent(mtEvent));
ExecuteCallbackAction(a => a.OnMtEvent(e));
Log.Debug("OnMtEvent: end.");
}
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 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.23.0")]
[assembly: AssemblyFileVersion("1.0.23.0")]
[assembly: AssemblyVersion("1.0.33.0")]
[assembly: AssemblyFileVersion("1.0.33.0")]
+175 -196
View File
@@ -4,7 +4,8 @@
#include "MT4Handler.h"
#include "Windows.h"
#include < vcclr.h >
#include <vcclr.h>
#include <functional>
using namespace System;
using namespace MTApiService;
@@ -17,6 +18,8 @@ using namespace System::IO;
using namespace System::Collections::Generic;
using namespace System::Diagnostics;
#define _DLLAPI extern "C" __declspec(dllexport)
void convertSystemString(wchar_t* dest, String^ src)
{
pin_ptr<const wchar_t> wch = PtrToStringChars(src);
@@ -24,264 +27,240 @@ void convertSystemString(wchar_t* dest, String^ src)
dest[wcslen(wch)] = '\0';
}
int _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
template <typename T> T Execute(std::function<T()> func, wchar_t* err, T default_value)
{
T result = default_value;
try
{
MT4Handler^ mtHandler = gcnew MT4Handler();
MtServerInstance::GetInstance()->InitExpert(expertHandle, port, gcnew String(symbol), bid, ask, mtHandler);
result = func();
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:initExpert(): " + e->Message);
return 0;
}
return 1;
return result;
}
int _stdcall deinitExpert(int expertHandle, wchar_t* err)
_DLLAPI bool _stdcall initExpert(int expertHandle, int port, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->DeinitExpert(expertHandle);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:deinitExpert(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &port, symbol, &bid, &ask]() {
auto expert = gcnew MtExpert(expertHandle, gcnew String(symbol), bid, ask, gcnew MT4Handler());
MtAdapter::GetInstance()->AddExpert(port, expert);
return true;
}, err, false);
}
int _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
_DLLAPI bool _stdcall deinitExpert(int expertHandle, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:updateQuote(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle]() {
MtAdapter::GetInstance()->RemoveExpert(expertHandle);
return true;
}, err, false);
}
_DLLAPI bool _stdcall updateQuote(int expertHandle, wchar_t* symbol, double bid, double ask, wchar_t* err)
{
return Execute<bool>([&expertHandle, symbol, &bid, &ask]() {
MtAdapter::GetInstance()->SendQuote(expertHandle, gcnew String(symbol), bid, ask);
return true;
}, err, false);
}
int _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
_DLLAPI bool _stdcall sendEvent(int expertHandle, int eventType, wchar_t* payload, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
}
catch (Exception^ e)
{
convertSystemString(err, e->Message);
Debug::WriteLine("[ERROR] MTConnector:updateTimeBar(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &eventType, payload]() {
MtAdapter::GetInstance()->SendEvent(expertHandle, eventType, gcnew String(payload));
return true;
}, err, false);
}
int _stdcall sendIntResponse(int expertHandle, int response)
_DLLAPI bool _stdcall sendIntResponse(int expertHandle, int response, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendIntResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseInt(response));
return true;
}, err, false);
}
int _stdcall sendBooleanResponse(int expertHandle, int response)
_DLLAPI bool _stdcall sendBooleanResponse(int expertHandle, bool response, wchar_t* err)
{
try
{
bool value = (response != 0) ? true : false;
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(value));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendBooleanResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseBool(response));
return true;
}, err, false);
}
int _stdcall sendDoubleResponse(int expertHandle, double response)
_DLLAPI bool _stdcall sendDoubleResponse(int expertHandle, double response, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendDoubleResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDouble(response));
return true;
}, err, false);
}
int _stdcall sendStringResponse(int expertHandle, wchar_t* response)
_DLLAPI bool _stdcall sendStringResponse(int expertHandle, wchar_t* response, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendStringResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseString(gcnew String(response)));
return true;
}, err, false);
}
int _stdcall sendVoidResponse(int expertHandle)
_DLLAPI bool _stdcall sendErrorResponse(int expertHandle, int code, wchar_t* message, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, nullptr);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendVoidResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &code, message]() {
MtResponseString^ res = gcnew MtResponseString(gcnew String(message));
res->ErrorCode = code;
MtAdapter::GetInstance()->SendResponse(expertHandle, res);
return true;
}, err, false);
}
int _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size)
_DLLAPI bool _stdcall sendVoidResponse(int expertHandle, wchar_t* err)
{
try
{
return Execute<bool>([&expertHandle]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseObject(nullptr));
return true;
}, err, false);
}
_DLLAPI bool _stdcall sendDoubleArrayResponse(int expertHandle, double* values, int size, wchar_t* err)
{
return Execute<bool>([&expertHandle, values, &size]() {
array<double>^ list = gcnew array<double>(size);
for(int i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendDoubleArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseDoubleArray(list));
return true;
}, err, false);
}
int _stdcall sendIntArrayResponse(int expertHandle, int* values, int size)
_DLLAPI bool _stdcall sendIntArrayResponse(int expertHandle, int* values, int size, wchar_t* err)
{
try
{
return Execute<bool>([&expertHandle, values, &size]() {
array<int>^ list = gcnew array<int>(size);
for(int i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
list[i] = values[i];
}
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendIntArrayResponse(): " + e->Message);
return 0;
}
return 1;
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseIntArray(list));
return true;
}, err, false);
}
int _stdcall sendLongResponse(int expertHandle, __int64 response)
_DLLAPI bool _stdcall sendLongResponse(int expertHandle, __int64 response, wchar_t* err)
{
try
{
MtServerInstance::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:sendLongResponse(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &response]() {
MtAdapter::GetInstance()->SendResponse(expertHandle, gcnew MtResponseLong(response));
return true;
}, err, false);
}
int _stdcall getCommandType(int expertHandle, int* res)
_DLLAPI bool _stdcall getCommandType(int expertHandle, int* res, wchar_t* err)
{
try
{
*res = MtServerInstance::GetInstance()->GetCommandType(expertHandle);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getCommandType(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, res]() {
*res = MtAdapter::GetInstance()->GetCommandType(expertHandle);
return true;
}, err, false);
}
int _stdcall getIntValue(int expertHandle, int paramIndex, int* res)
_DLLAPI bool _stdcall getIntValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{
try
{
*res = (int)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getIntValue(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (int)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
int _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res)
// --- index parameters
_DLLAPI bool _stdcall getDoubleValue(int expertHandle, int paramIndex, double* res, wchar_t* err)
{
try
{
*res = (double)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getDoubleValue(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (double)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
int _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res)
_DLLAPI bool _stdcall getStringValue(int expertHandle, int paramIndex, wchar_t* res, wchar_t* err)
{
try
{
convertSystemString(res, (String^)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MTConnector:getStringValue(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &paramIndex, res]() {
convertSystemString(res, (String^)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex));
return true;
}, err, false);
}
int _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res)
_DLLAPI bool _stdcall getBooleanValue(int expertHandle, int paramIndex, int* res, wchar_t* err)
{
try
{
bool val = (bool)MtServerInstance::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
*res = val == true ? 1 : 0;
}
catch (Exception^ e)
{
Debug::WriteLine("[ERROR] MT5Connector:getBooleanValue(): " + e->Message);
return 0;
}
return 1;
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (bool)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getLongValue(int expertHandle, int paramIndex, __int64* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, &paramIndex, res]() {
*res = (__int64)MtAdapter::GetInstance()->GetCommandParameter(expertHandle, paramIndex);
return true;
}, err, false);
}
// --- named parameters
_DLLAPI bool _stdcall containsNamedValue(int expertHandle, wchar_t* paramName)
{
wchar_t err[1000];
return Execute<bool>([&expertHandle, paramName]() {
return MtAdapter::GetInstance()->ContainsNamedParameter(expertHandle, gcnew String(paramName));
}, err, false);
}
_DLLAPI bool _stdcall getNamedIntValue(int expertHandle, wchar_t* paramName, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (int)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedDoubleValue(int expertHandle, wchar_t* paramName, double* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (double)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedStringValue(int expertHandle, wchar_t* paramName, wchar_t* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
convertSystemString(res, (String^)obj);
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedBooleanValue(int expertHandle, wchar_t* paramName, int* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
*res = (bool)obj;
return true;
}, err, false);
}
_DLLAPI bool _stdcall getNamedLongValue(int expertHandle, wchar_t* paramName, __int64* res, wchar_t* err)
{
return Execute<bool>([&expertHandle, paramName, res]() {
System::Object^ obj = MtAdapter::GetInstance()->GetNamedParameter(expertHandle, gcnew String(paramName));
if (obj != nullptr)
*res = (__int64)obj;
return true;
}, err, false);
}
-19
View File
@@ -1,19 +0,0 @@
LIBRARY MTConnector
EXPORTS initExpert
deinitExpert
updateQuote
sendEvent
sendIntResponse
sendBooleanResponse
sendDoubleResponse
sendStringResponse
sendVoidResponse
sendDoubleArrayResponse
sendIntArrayResponse
sendLongResponse
getCommandType
getIntValue
getDoubleValue
getStringValue
getBooleanValue
+6 -10
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -24,6 +24,7 @@
<Keyword>ManagedCProj</Keyword>
<RootNamespace>MTConnector</RootNamespace>
<ProjectName>MTConnector</ProjectName>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -31,28 +32,28 @@
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -96,7 +97,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -109,7 +109,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -121,7 +120,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -133,7 +131,6 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\MTConnector.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -154,7 +151,6 @@
</ItemGroup>
<ItemGroup>
<None Include="app.ico" />
<None Include="MTConnector.def" />
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
-3
View File
@@ -44,9 +44,6 @@
<None Include="app.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="MTConnector.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc">
+24
View File
@@ -0,0 +1,24 @@
using System;
namespace MtApi
{
public class ChartEventArgs : EventArgs
{
internal ChartEventArgs(int expertHandle, MtChartEvent chartEvent)
{
ExpertHandle = expertHandle;
ChartId = chartEvent.ChartId;
EventId = chartEvent.EventId;
Lparam = chartEvent.Lparam;
Dparam = chartEvent.Dparam;
Sparam = chartEvent.Sparam;
}
public int ExpertHandle { get; }
public long ChartId { get; }
public int EventId { get; }
public long Lparam { get; }
public double Dparam { get; }
public string Sparam { get; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi
{
public enum EnumAlignMode
{
ALIGN_LEFT = 1,
ALIGN_CENTER = 2,
ALIGN_RIGHT = 0
}
}
+18
View File
@@ -0,0 +1,18 @@
namespace MtApi
{
public enum EnumChartEvent
{
CHARTEVENT_KEYDOWN = 0,
CHARTEVENT_MOUSE_MOVE = 10,
CHARTEVENT_OBJECT_CREATE = 7,
CHARTEVENT_OBJECT_CHANGE = 8,
CHARTEVENT_OBJECT_DELETE = 6,
CHARTEVENT_CLICK = 4,
CHARTEVENT_OBJECT_CLICK = 1,
CHARTEVENT_OBJECT_DRAG = 2,
CHARTEVENT_OBJECT_ENDEDIT = 3,
CHARTEVENT_CHART_CHANGE = 9,
CHARTEVENT_CUSTOM = 1000,
CHARTEVENT_CUSTOM_LAST = 66534
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace MtApi
{
public enum EnumChartPropertyDouble
{
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
}
}
+55
View File
@@ -0,0 +1,55 @@
namespace MtApi
{
public enum EnumChartPropertyInteger
{
CHART_BRING_TO_TOP = 35,
CHART_MOUSE_SCROLL = 42,
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_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_IS_OFFLINE = 112
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace MtApi
{
public enum EnumChartPropertyString
{
CHART_COMMENT = 20
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace MtApi
{
enum EnumColorFormat
{
COLOR_FORMAT_XRGB_NOALPHA = 0, //The component of the alpha channel is ignored
COLOR_FORMAT_ARGB_RAW = 1, //Color components are not handled by the terminal (must be correctly set by the user)
COLOR_FORMAT_ARGB_NORMALIZE = 2 //Color components are handled by the terminal
}
}
+46
View File
@@ -0,0 +1,46 @@
namespace MtApi
{
public enum EnumObject
{
OBJ_VLINE = 0, //Vertical Line
OBJ_HLINE = 1, //Horizontal Line
OBJ_TREND = 2, //Trend Line
BJ_TRENDBYANGLE = 3, //Trend Line By Angle
OBJ_CYCLES = 20, //Cycle Lines
OBJ_CHANNEL = 5, //Equidistant Channel
OBJ_STDDEVCHANNEL = 6, //Standard Deviation Channel
OBJ_REGRESSION = 4, //Linear Regression Channel
OBJ_PITCHFORK = 19, //Andrews’ Pitchfork
OBJ_GANNLINE = 7, //Gann Line
OBJ_GANNFAN = 8, //Gann Fan
OBJ_GANNGRID = 9, //Gann Grid
OBJ_FIBO = 10, //Fibonacci Retracement
OBJ_FIBOTIMES = 11, //Fibonacci Time Zones
OBJ_FIBOFAN = 12, //Fibonacci Fan
OBJ_FIBOARC = 13, //Fibonacci Arcs
OBJ_FIBOCHANNEL = 15, //Fibonacci Channel
OBJ_EXPANSION = 14, //Fibonacci Expansion
OBJ_RECTANGLE = 16, //Rectangle
OBJ_TRIANGLE = 17, //Triangle
OBJ_ELLIPSE = 18, //Ellipse
OBJ_ARROW_THUMB_UP = 29, //Thumbs Up
OBJ_ARROW_THUMB_DOWN = 30, //Thumbs Down
OBJ_ARROW_UP = 31, //Arrow Up
OBJ_ARROW_DOWN = 32, //Arrow Down
OBJ_ARROW_STOP = 33, //Stop Sign
OBJ_ARROW_CHECK = 34, //Check Sign
OBJ_ARROW_LEFT_PRICE = 35, //Left Price Label
OBJ_ARROW_RIGHT_PRICE = 36, //Right Price Label
OBJ_ARROW_BUY = 37, //Buy Sign
OBJ_ARROW_SELL = 38, //Sell Sign
OBJ_ARROW = 22, //Arrow
OBJ_TEXT = 21, //Text
OBJ_LABEL = 23, //Label
OBJ_BUTTON = 25, //Button
OBJ_BITMAP = 26, //Bitmap
OBJ_BITMAP_LABEL = 24, //Bitmap Label
OBJ_EDIT = 27, //Edit
OBJ_EVENT = 42, //The "Event" object corresponding to an event in the economic calendar
OBJ_RECTANGLE_LABEL = 28 //The "Rectangle label" object for creating and designing the custom graphical interface.
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace MtApi
{
public enum EnumObjectPropertyDouble
{
OBJPROP_PRICE = 20, // Price coordinate
OBJPROP_LEVELVALUE = 204, // Level value
OBJPROP_SCALE = 12, // Scale (properties of Gann objects, Fibonacci Arcs and Ellipse)
OBJPROP_ANGLE = 13, // Angle. For the objects with no angle specified, created from a program, the value is equal to EMPTY_VALUE
OBJPROP_DEVIATION = 16, // Deviation for the Standard Deviation Channel
}
}
+40
View File
@@ -0,0 +1,40 @@
namespace MtApi
{
public enum EnumObjectPropertyInteger
{
OBJPROP_COLOR = 6,
OBJPROP_STYLE = 7,
OBJPROP_WIDTH = 8,
OBJPROP_BACK = 9,
OBJPROP_ZORDER = 207,
OBJPROP_HIDDEN = 208,
OBJPROP_SELECTED = 17,
OBJPROP_READONLY = 1028,
OBJPROP_TYPE = 18,
OBJPROP_TIME = 19,
OBJPROP_SELECTABLE = 1000,
OBJPROP_CREATETIME = 998,
OBJPROP_LEVELS = 200,
OBJPROP_LEVELCOLOR = 201,
OBJPROP_LEVELSTYLE = 202,
OBJPROP_LEVELWIDTH = 203,
OBJPROP_ALIGN = 1036,
OBJPROP_FONTSIZE = 100,
OBJPROP_RAY_RIGHT = 1004,
OBJPROP_ELLIPSE = 11,
OBJPROP_ARROWCODE = 14,
OBJPROP_TIMEFRAMES = 15,
OBJPROP_ANCHOR = 1011,
OBJPROP_XDISTANCE = 102,
OBJPROP_YDISTANCE = 103,
OBJPROP_STATE = 1018,
OBJPROP_XSIZE = 1019,
OBJPROP_YSIZE = 1020,
OBJPROP_XOFFSET = 1033,
OBJPROP_YOFFSET = 1034,
OBJPROP_BGCOLOR = 1025,
OBJPROP_CORNER = 101,
OBJPROP_BORDER_TYPE = 1029,
OBJPROP_BORDER_COLOR = 1035
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace MtApi
{
public enum EnumObjectPropertyString
{
OBJPROP_NAME = 1037,
OBJPROP_TEXT = 999,
OBJPROP_TOOLTIP = 206,
OBJPROP_LEVELTEXT = 205,
OBJPROP_FONT = 1001,
OBJPROP_BMPFILE = 1017,
OBJPROP_SYMBOL = 1021
}
}
-42
View File
@@ -1,42 +0,0 @@
using System;
using System.Threading.Tasks;
namespace MtApi
{
static class ExtensionMethods
{
#region Event Methods
public static Task FireEventAsync(this MtApiQuoteHandler evenHandler, object sender, string symbol, double bid, double ask)
{
return Task.Factory.StartNew(() =>
{
evenHandler?.Invoke(sender, symbol, bid, ask);
});
}
public static Task FireEventAsync(this EventHandler eventHandler, object sender)
{
return Task.Factory.StartNew(() =>
{
eventHandler?.Invoke(sender, EventArgs.Empty);
});
}
public static Task FireEventAsync<T>(this EventHandler<T> eventHandler, object sender, T e)
where T : EventArgs
{
return Task.Factory.StartNew(() =>
{
eventHandler?.Invoke(sender, e);
});
}
#endregion
public static MtQuote Convert(this MTApiService.MtQuote quote)
{
return (quote != null) ? new MtQuote(quote.Instrument, quote.Bid, quote.Ask) : null;
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using System;
namespace MtApi
{
[Flags]
public enum FlagFontStyle
{
//Flags for specifying font style
FONT_ITALIC = -2147483648,
FONT_UNDERLINE = 1073741824,
FONT_STRIKEOUT = 536870912,
//Flags for specifying font width
FW_DONTCARE = 0,
FW_THIN = 1,
FW_EXTRALIGHT = 2,
FW_ULTRALIGHT = 3,
FW_LIGHT = 4,
FW_NORMAL = 5,
FW_REGULAR = 6,
FW_MEDIUM = 7,
FW_SEMIBOLD = 8,
FW_DEMIBOLD = 9,
FW_BOLD = 10,
FW_EXTRABOLD = 11,
FW_ULTRABOLD = 12,
FW_HEAVY = 13,
FW_BLACK = 14
}
}
@@ -10,8 +10,13 @@ namespace MtApi.Monitors
Opened = opened;
Closed = closed;
}
/// <summary>
/// Contains all newly opened orders since the last time the monitor checked the open orders.
/// </summary>
public List<MtOrder> Opened { get; private set; }
/// <summary>
/// Contains all newly closed orders since the last time the monitor checked the open orders.
/// </summary>
public List<MtOrder> Closed { get; private set; }
}
}
+113
View File
@@ -0,0 +1,113 @@
using System;
using MtApi.Monitors.Triggers;
namespace MtApi.Monitors
{
public abstract class MtMonitorBase
{
#region Fields
private volatile bool _isStarted = false;
private bool _syncTrigger;
#endregion
#region Properties
/// <summary>
/// ApiClient
/// </summary>
protected MtApiClient ApiClient { get; }
/// <summary>
/// Returns true if the <see cref="ApiClient"/> is connected.
/// </summary>
public bool IsMtConnected => ApiClient.ConnectionState == MtConnectionState.Connected;
/// <summary>
/// Returns the trigger which will be used to raise the monitoring call.
/// </summary>
public IMonitorTrigger MonitorTrigger { get; }
/// <summary>
/// Returns true if the Monitor is started.
/// </summary>
public bool IsStarted { get => _isStarted; }
/// <summary>
/// If true, the <see cref="MonitorTrigger"/> will be stopped or started automatically when <see cref="Start"/> or <see cref="Stop"/> will be called.
/// <para>CAUTION: If you use the MonitorTrigger for different Monitors, this will stop all monitors if you call stop and <see cref="SyncTrigger"/> is <c>true</c>.</para>
/// </summary>
public bool SyncTrigger { get => _syncTrigger; set => _syncTrigger = value; }
#endregion
#region ctor
/// <summary>
/// Default constructor for Monitors
/// </summary>
/// <param name="apiClient">The apiClient which will be used to work with.</param>
/// <param name="monitorTrigger">The trigger which lead this Monitor to do his work.</param>
/// <param name="syncTrigger">See property <see cref="SyncTrigger"/>.</param>
public MtMonitorBase(MtApiClient apiClient, IMonitorTrigger monitorTrigger, bool syncTrigger = false)
{
ApiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
MonitorTrigger = monitorTrigger ?? throw new ArgumentNullException(nameof(monitorTrigger));
SyncTrigger = syncTrigger;
}
#endregion
#region Methods
/// <summary>
/// Let the monitor listen to the <see cref="MonitorTrigger"/>.
/// </summary>
public virtual void Start()
{
if (!_isStarted)
{
ApiClient.ConnectionStateChanged += ApiClientConnectionStateChanged;
MonitorTrigger.Raised += MonitorTriggerRaised;
_isStarted = true;
OnStart();
if (SyncTrigger)
MonitorTrigger.Start();
}
}
/// <summary>
/// Let the monitor stop listening to the <see cref="MonitorTrigger"/>.
/// </summary>
public virtual void Stop()
{
if (_isStarted)
{
MonitorTrigger.Raised -= MonitorTriggerRaised;
ApiClient.ConnectionStateChanged -= ApiClientConnectionStateChanged;
_isStarted = false;
OnStop();
if (SyncTrigger)
MonitorTrigger.Stop();
}
}
private void MonitorTriggerRaised(object sender, EventArgs e) => OnTriggerRaised();
private void ApiClientConnectionStateChanged(object sender, MtConnectionEventArgs e)
{
if (e.Status == MtConnectionState.Connected)
OnMtConnected();
else if (e.Status == MtConnectionState.Failed || e.Status == MtConnectionState.Disconnected)
OnMtDisconnected();
}
/// <summary>
/// Will be called when <see cref="Start"/> will be called.
/// </summary>
protected virtual void OnStart() { }
/// <summary>
/// Will be called when <see cref="Stop"/> will be called.
/// </summary>
protected virtual void OnStop() { }
/// <summary>
/// Will be called when the <see cref="ApiClient"/> is successfully connected.
/// </summary>
protected virtual void OnMtConnected() { }
/// <summary>
/// Will be called when <see cref="ApiClient"/> is disconnected.
/// </summary>
protected virtual void OnMtDisconnected() { }
/// <summary>
/// Will be called when the <see cref="MonitorTrigger"/> raised.
/// </summary>
protected abstract void OnTriggerRaised();
#endregion
}
}
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi.Monitors
{
public class ModifiedOrdersEventArgs : EventArgs
{
/// <summary>
/// Returns a list of all modified orders
/// </summary>
public List<MtModifiedOrder> ModifiedOrders { get; }
public ModifiedOrdersEventArgs(List<MtModifiedOrder> modifiedOrders)
{
ModifiedOrders = modifiedOrders;
}
}
}
@@ -0,0 +1,68 @@
using MtApi.Monitors.Triggers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi.Monitors
{
public class ModifiedOrdersMonitor : MtMonitorBase
{
#region Fields
private List<MtOrder> _lastOrders = null;
#endregion
#region Properties
/// <summary>
/// Define on which types of modification this monitor should raise <see cref="OrdersModified"/>
/// </summary>
public OrderModifiedTypes OrderModifiedTypes { get; set; }
#endregion
#region Events
/// <summary>
/// Will be raised when this monitor detects changes on open orders
/// </summary>
public event EventHandler<ModifiedOrdersEventArgs> OrdersModified;
#endregion
#region ctor
public ModifiedOrdersMonitor(MtApiClient apiClient, IMonitorTrigger monitorTrigger, OrderModifiedTypes orderModifiedTypes = OrderModifiedTypes.All, bool syncTrigger = false)
: base(apiClient, monitorTrigger, syncTrigger)
{
_lastOrders = GetOrders();
OrderModifiedTypes = orderModifiedTypes;
}
#endregion
/// <summary>
/// Requests all current open orders
/// </summary>
/// <returns></returns>
private List<MtOrder> GetOrders() => IsMtConnected ? ApiClient.GetOrders(OrderSelectSource.MODE_TRADES) : null;
protected override void OnTriggerRaised()
{
if(_lastOrders == null)
{
_lastOrders = GetOrders();
return;
}
List<MtOrder> currentOrders = GetOrders();
OrderModifiedTypes omt = OrderModifiedTypes;
var mtModifiedOrders = currentOrders
.Select(co => new MtModifiedOrder(_lastOrders.FirstOrDefault(x => x.Ticket == co.Ticket), co))
.ToList();
List<MtModifiedOrder> modifiedOrders = new List<MtModifiedOrder>();
modifiedOrders.AddRange(GetMtModifiedOrdersWithModType(mtModifiedOrders, omt, OrderModifiedTypes.TakeProfit)); //If the takeprofit were changed between both calls
modifiedOrders.AddRange(GetMtModifiedOrdersWithModType(mtModifiedOrders, omt, OrderModifiedTypes.StopLoss)); //If the stoploss were changed between both calls
modifiedOrders.AddRange(GetMtModifiedOrdersWithModType(mtModifiedOrders, omt, OrderModifiedTypes.Operation)); //If an order changed from limit / stop order to an open order
if (modifiedOrders.Count > 0)
OrdersModified?.Invoke(this, new ModifiedOrdersEventArgs(modifiedOrders));
_lastOrders = currentOrders;
}
private static IEnumerable<MtModifiedOrder> GetMtModifiedOrdersWithModType(IEnumerable<MtModifiedOrder> orders, OrderModifiedTypes globalSearchFlag, OrderModifiedTypes modifiedType)
=> globalSearchFlag.HasFlag(modifiedType) ? orders.Where(o => o.ModifyType.HasFlag(modifiedType)) : new List<MtModifiedOrder>();
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi.Monitors
{
public class MtModifiedOrder
{
/// <summary>
/// The order in its old state (before the changes)
/// </summary>
public MtOrder OldOrder { get; }
/// <summary>
/// The order in its new state (after the changes)
/// </summary>
public MtOrder NewOrder { get; }
/// <summary>
/// The changes found by this instance
/// </summary>
public OrderModifiedTypes ModifyType { get; private set; }
/// <summary>
/// Initializes an instance and compare the order in its old and new state
/// </summary>
/// <param name="oldOrder">The order in its old state (before the changes)</param>
/// <param name="newOrder">The order in its new state (after the changes)</param>
public MtModifiedOrder(MtOrder oldOrder, MtOrder newOrder)
{
if (oldOrder != null && newOrder != null && oldOrder.Ticket != newOrder.Ticket)
throw new ArgumentException(nameof(oldOrder) + " and " + nameof(newOrder) + " need to have the same ticket id");
OldOrder = oldOrder;
NewOrder = newOrder;
ModifyType = OrderModifiedTypes.None;
Compare();
}
private void Compare()
{
if(NewOrder != null && OldOrder != null)
{
if (OldOrder.StopLoss != NewOrder.StopLoss)
ModifyType |= OrderModifiedTypes.StopLoss;
if (OldOrder.TakeProfit != NewOrder.TakeProfit)
ModifyType |= OrderModifiedTypes.TakeProfit;
if (OldOrder.Operation != NewOrder.Operation)
ModifyType |= OrderModifiedTypes.Operation;
}
}
}
}
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi.Monitors
{
[Flags]
public enum OrderModifiedTypes
{
None = 0x0,
TakeProfit = 1 << 0,
StopLoss = 1 << 1,
Operation = 1 << 2,
All = 7
}
}
+11 -49
View File
@@ -1,56 +1,18 @@

using MtApi.Monitors.Triggers;
namespace MtApi.Monitors
{
public class TimeframeTradeMonitor : TradeMonitor
{
#region Fields
private volatile bool _isStarted;
#endregion
#region ctor
public TimeframeTradeMonitor(MtApiClient apiClient)
: base(apiClient)
/// <summary>
/// Constructor for initializing a new instance with a trigger instance of <see cref="NewBarTrigger"/>.
/// <para>SyncTrigger is set to true by default</para>
/// </summary>
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
public TimeframeTradeMonitor(MtApiClient apiClient)
: base(apiClient, new NewBarTrigger(apiClient))
{
apiClient.OnLastTimeBar += ApiClient_OnLastTimeBar;
SyncTrigger = true; //Sync-Trigger set to true, to have the same behavior as before
}
#endregion
#region Public Methods
//
// Summary:
// Gets a value indicating whether the TimeframeTradeMonitor should raise checking orders
//
// Returns:
// true if PositionMonitor should check orders
// otherwise, false.
public override bool IsStarted => _isStarted;
#endregion
#region Protected Methods
protected override void OnMtConnected() {}
protected override void OnMtDisconnected() {}
protected override void OnStart()
{
_isStarted = true;
}
protected override void OnStop()
{
_isStarted = false;
}
#endregion
#region Private Methods
private void ApiClient_OnLastTimeBar(object sender, TimeBarArgs e)
{
if (_isStarted)
{
Check();
}
}
#endregion
}
}
}
+28 -71
View File
@@ -1,90 +1,47 @@
using System.Timers;
using System;
using MtApi.Monitors.Triggers;
namespace MtApi.Monitors
{
public class TimerTradeMonitor : TradeMonitor
{
#region Fields
private readonly Timer _timer = new Timer();
private readonly TimeElapsedTrigger _timeElapsedTrigger;
#endregion
#region ctor
public TimerTradeMonitor(MtApiClient apiClient)
: base(apiClient)
{
_timer.Interval = 10000; //default interval 10 sec
_timer.Elapsed += _timer_Elapsed;
}
#endregion
#region Public Methods
//
// Summary:
// Gets or sets the interval, expressed in milliseconds, at which to check orders
//
// Returns:
// The time, in milliseconds, between checking events. The value
// must be greater than zero, and less than or equal to System.Int32.MaxValue.
// The default is 10000 milliseconds.
//
// Exceptions:
// T:System.ArgumentException:
// The interval is less than or equal to zero.-or-The interval is greater than System.Int32.MaxValue,
// and the PositionMonitor is currently started.
#region Properties
/// <summary>
/// Interval for raising the trigger
/// </summary>
public double Interval
{
get { return _timer.Interval; }
set { _timer.Interval = value; }
}
//
// Summary:
// Gets a value indicating whether the PositionMonitor should raise checking orders
//
// Returns:
// true if TimerTradeMonitor should check orders
// otherwise, false.
public override bool IsStarted
{
get { return _timer.Enabled; }
get => _timeElapsedTrigger.Interval.TotalMilliseconds;
set => _timeElapsedTrigger.Interval = TimeSpan.FromMilliseconds(value);
}
#endregion
#region Protected Methods
protected override void OnStart()
#region ctors
/// <summary>
/// Constructor for initializing a new instance with a default <see cref="Interval"/> of 10 seconds.
/// <para>SyncTrigger is set to true by default</para>
/// </summary>
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
public TimerTradeMonitor(MtApiClient apiClient)
: this(apiClient, new TimeElapsedTrigger(TimeSpan.FromSeconds(10)))
{
if (IsMtConnected)
{
_timer.Start();
}
SyncTrigger = true; //Sync-Trigger set to true, to have the same behavior as before
}
protected override void OnStop()
/// <summary>
/// Constructor for initializing a new instance with a custom instance of <see cref="TimeElapsedTrigger"/>.
/// <para>SyncTrigger is set to false by default</para>
/// </summary>
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
/// <param name="timeElapsedTrigger">The custom instance of <see cref="TimeElapsedTrigger"/> which will be used to trigger this instance of <see cref="TradeMonitor"/>.</param>
public TimerTradeMonitor(MtApiClient apiClient, TimeElapsedTrigger timeElapsedTrigger)
: base(apiClient, timeElapsedTrigger)
{
_timer.Stop();
}
protected override void OnMtConnected()
{
_timer.Start();
}
protected override void OnMtDisconnected()
{
_timer.Stop();
}
#endregion
#region Private Methods
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_timer.Elapsed -= _timer_Elapsed; //unregister from events to prevent rise condition during work with orders
Check();
_timer.Elapsed += _timer_Elapsed; //register again
_timeElapsedTrigger = timeElapsedTrigger;
}
#endregion
}
}
}
+44 -116
View File
@@ -1,63 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MtApi.Monitors.Triggers;
namespace MtApi.Monitors
{
public abstract class TradeMonitor
public class TradeMonitor : MtMonitorBase
{
#region Fields
private readonly MtApiClient _apiClient;
private List<MtOrder> _prevOrders;
private readonly object _locker = new object();
#endregion
#region ctor
protected TradeMonitor(MtApiClient apiClient)
{
if (apiClient == null)
throw new ArgumentNullException(nameof(apiClient));
_apiClient = apiClient;
}
#endregion
#region Public Methods
//
// Summary:
// Gets a value indicating whether the TradeMonitor should raise checking orders
//
// Returns:
// true if TradeMonitor should check orders
// otherwise, false.
public abstract bool IsStarted { get; }
//
// Summary:
// Start checking orders.
//
public void Start()
{
_apiClient.ConnectionStateChanged += _apiClient_ConnectionStateChanged;
if (IsMtConnected)
{
InitialCheck();
}
OnStart();
}
//
// Summary:
// Stop checking orders.
//
public void Stop()
{
_apiClient.ConnectionStateChanged -= _apiClient_ConnectionStateChanged;
OnStop();
}
#endregion
#region Events
//
// Summary:
@@ -65,17 +20,34 @@ namespace MtApi.Monitors
public event EventHandler<AvailabilityOrdersEventArgs> AvailabilityOrdersChanged;
#endregion
#region Protected Methods
#region ctor
/// <summary>
/// Constructor for initializing an instance of <see cref="TradeMonitor"/>.
/// </summary>
/// <param name="apiClient">The <see cref="MtApiClient"/> which will be used to communicate with MetaTrader.</param>
/// <param name="monitorTrigger">The custom instance of <see cref="IMonitorTrigger"/> which will be used to trigger this instance of <see cref="TradeMonitor"/>.</param>
public TradeMonitor(MtApiClient apiClient, IMonitorTrigger monitorTrigger) : base(apiClient, monitorTrigger) { }
#endregion
protected abstract void OnStart();
protected abstract void OnStop();
protected override void OnMtConnected()
{
InitialCheck();
base.OnMtConnected();
}
protected override void OnStart()
{
if (IsMtConnected)
InitialCheck();
base.OnStart();
}
protected abstract void OnMtConnected();
protected abstract void OnMtDisconnected();
public bool IsMtConnected => _apiClient.ConnectionState == MtConnectionState.Connected;
protected void Check()
protected override void OnTriggerRaised()
{
if (IsMtConnected)
Check();
}
private void Check()
{
try
{
@@ -90,92 +62,48 @@ namespace MtApi.Monitors
//TODO: write error to log
}
}
#endregion
private void InitialCheck()
{
lock (_locker)
_prevOrders = null;
#region Private Methods
Task.Factory.StartNew(Check);
}
private void CheckOrders()
{
var openedOrders = new List<MtOrder>();
var closedOrders = new List<MtOrder>();
List<MtOrder> prevOrders;
// get current orders from MetaTrader
var tradesOrders = _apiClient.GetOrders(OrderSelectSource.MODE_TRADES);
var tradesOrders = ApiClient.GetOrders(OrderSelectSource.MODE_TRADES);
List<MtOrder> prevOrders;
lock(_locker)
{
lock (_locker)
prevOrders = _prevOrders;
}
if (prevOrders != null) //skip checking on first load orders
{
//check open orders
foreach (var order in tradesOrders)
{
if (prevOrders.Find(a => a.Ticket == order.Ticket) == null)
{
openedOrders.Add(order);
}
}
openedOrders = tradesOrders.Where(to => prevOrders.Find(a => a.Ticket == to.Ticket) == null).ToList();
//check closed orders
var closeOrdersTemp = new List<MtOrder>();
foreach (var order in prevOrders)
{
if (tradesOrders.Find(a => a.Ticket == order.Ticket) == null)
{
closeOrdersTemp.Add(order);
}
}
var closeOrdersTemp = prevOrders.Where(po => tradesOrders.Find(a => a.Ticket == po.Ticket) == null).ToList();
if (closeOrdersTemp.Count > 0)
{
//get closed orders from history with actual values
var historyOrders = _apiClient.GetOrders(OrderSelectSource.MODE_HISTORY);
foreach (var order in closeOrdersTemp)
{
var closedOrder = historyOrders.Find(a => a.Ticket == order.Ticket);
if (closedOrder != null)
{
closedOrders.Add(closedOrder);
}
}
var historyOrders = ApiClient.GetOrders(OrderSelectSource.MODE_HISTORY);
closedOrders = closeOrdersTemp.Where(cot => historyOrders.Find(a => a.Ticket == cot.Ticket) != null).ToList();
}
}
lock(_locker)
{
lock (_locker)
_prevOrders = tradesOrders;
}
if (openedOrders.Count > 0 || closedOrders.Count > 0)
{
AvailabilityOrdersChanged?.Invoke(this, new AvailabilityOrdersEventArgs(openedOrders, closedOrders));
}
}
private void _apiClient_ConnectionStateChanged(object sender, MtConnectionEventArgs e)
{
if (e.Status == MtConnectionState.Connected)
{
InitialCheck();
OnMtConnected();
}
else if (e.Status == MtConnectionState.Failed || e.Status == MtConnectionState.Disconnected)
{
OnMtDisconnected();
}
}
private void InitialCheck()
{
lock (_locker)
{
_prevOrders = null;
}
Task.Factory.StartNew(Check);
}
#endregion
}
}
}
@@ -0,0 +1,27 @@
using System;
namespace MtApi.Monitors.Triggers
{
/// <summary>
/// Interface for triggers which can be used to trigger a <see cref="MtMonitorBase"/>.
/// </summary>
public interface IMonitorTrigger
{
/// <summary>
/// Event will be called if the trigger raised.
/// </summary>
event EventHandler Raised;
/// <summary>
/// Returns whether the trigger is started
/// </summary>
bool IsStarted { get; }
/// <summary>
/// Stops the trigger and prevents further calls of the <see cref="Raised"/> event.
/// </summary>
void Stop();
/// <summary>
/// Starts the trigger.
/// </summary>
void Start();
}
}
+68
View File
@@ -0,0 +1,68 @@
using System;
namespace MtApi.Monitors.Triggers
{
/// <summary>
/// Raises the <see cref="Raised"/> event if a bar is closed and a new one started.
/// </summary>
public class NewBarTrigger : IMonitorTrigger
{
#region Fields
private volatile bool _isStarted;
private readonly MtApiClient _apiClient;
#endregion
#region Properties
/// <summary>
/// Returns true if the trigger is started, otherwise false
/// </summary>
public bool IsStarted => _isStarted;
#endregion
#region Events
/// <summary>
/// Event will be called if the trigger raised.
/// </summary>
public event EventHandler Raised;
#endregion
#region ctor
public NewBarTrigger(MtApiClient apiClient)
{
_apiClient = apiClient;
_apiClient.OnLastTimeBar += _apiClient_OnLastTimeBar;
}
#endregion
#region Public methods
/// <summary>
/// Starts the trigger
/// </summary>
public void Start() => SetIsStarted(true);
/// <summary>
/// Stops the trigger
/// </summary>
public void Stop() => SetIsStarted(false);
#endregion
#region Private methods
private void _apiClient_OnLastTimeBar(object sender, TimeBarArgs e)
{
if (_isStarted)
Raised?.Invoke(this, EventArgs.Empty);
}
private void SetIsStarted(bool value)
{
if (value != _isStarted)
{
_isStarted = value;
if (value)
_apiClient.OnLastTimeBar += _apiClient_OnLastTimeBar;
else
_apiClient.OnLastTimeBar -= _apiClient_OnLastTimeBar;
}
}
#endregion
}
}
@@ -0,0 +1,74 @@
using System;
using System.Timers;
namespace MtApi.Monitors.Triggers
{
public class TimeElapsedTrigger : IMonitorTrigger
{
#region Fields
readonly Timer _timer;
#endregion
#region Properties
/// <summary>
/// Interval for raising the trigger
/// </summary>
public TimeSpan Interval
{
get => TimeSpan.FromMilliseconds(_timer.Interval);
set => _timer.Interval = value.TotalMilliseconds;
}
/// <summary>
/// Returns true if the trigger is started, otherwise false
/// </summary>
public bool IsStarted => _timer.Enabled;
/// <summary>
/// If true, the trigger will raise continuosly after elapsed <see cref="Interval"/>, otherwise the trigger will raise only once after elapsed <see cref="Interval"/>.
/// </summary>
public bool AutoReset { get => _timer.AutoReset; set => _timer.AutoReset = value; }
#endregion
#region Events
/// <summary>
/// Returns true if the trigger is started, otherwise false
/// </summary>
public event EventHandler Raised;
#endregion
#region ctor
/// <summary>
/// Constructor for initializing TimeElapsedTrigger
/// </summary>
/// <param name="time">Defines the interval for raising the event.</param>
/// <param name="autoReset">If true, the trigger will raise continuosly after elapsed <see cref="Interval"/>, otherwise the trigger will raise only once after elapsed <see cref="Interval"/>.</param>
public TimeElapsedTrigger(TimeSpan time, bool autoReset = true)
{
_timer = new Timer(time.TotalMilliseconds);
_timer.Elapsed += _timer_Elapsed;
AutoReset = autoReset;
}
#endregion
#region Public methods
/// <summary>
/// Starts the trigger
/// </summary>
public void Start() => _timer.Start();
/// <summary>
/// Stops the trigger
/// </summary>
public void Stop() => _timer.Stop();
#endregion
#region private methods
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
_timer.Elapsed -= _timer_Elapsed;
Raised?.Invoke(this, EventArgs.Empty);
_timer.Elapsed += _timer_Elapsed;
}
#endregion
}
}
+66
View File
@@ -0,0 +1,66 @@
## Monitors
Monitors can be used to monitor different changes on Mt4 structs.
## MtMonitorBase
This is the base class for monitoring extensions. If inherited `MtMonitorBase` needs an instance of `MtApiClient` and `IMonitorTrigger`.
`SyncTrigger` (which can be set in the constructor or as Property) can be used to define whether the trigger should be started and stopped as well if `Start()` or `Stop()` will be called on an instance of a child class of `MtMonitorBase`.
Keep in mind: If an `IMonitorTrigger` will be used for several monitors, `SyncTrigger` set to `true` would cause that all monitors related to this trigger would stop:
```
var fooTrigger = new FooTrigger();
var fooMonitor = new FooMonitor(apiClient, fooTrigger, true);
var barMonitor = new FooMonitor(apiClient, fooTrigger, false);
fooTrigger.Start();
barMonitor.Start();
fooMonitor.Start();
fooMonitor.Stop(); //Because of SyncTrigger = true in the constructor of FooMonitor, fooTrigger.Stop() were triggered as well. Therefore barMonitor will not get any further triggers.
```
## IMonitorTrigger
An `IMonitorTrigger` is for defining when the monitor should check whether his conditions are met for invoking his event.
There are already two `IMonitorTrigger`s which can be used:
### NewBarTrigger
Triggers when a new bar starts
### TimeElapsedTrigger
Triggers when a defined time elapsed
## Default monitors:
There are already two different monitors defined. You can extend them or define new ones by inheriting from `MtMonitorBase`.
### TradeMonitor
Can be used to get updates on new opened trades or closed trades.
## ModifiedOrdersMonitor
Can be used to get updates on modified trades (takeprofit, stoploss, operation).
`OrderModifiedTypes` defines which modifications should be monitored:
1. `None` would cause no monitoring. But please use `Start()` and `Stop()` instead.
2. `TakeProfit` would cause observing whether the TakeProfit were changed.
3. `StopLoss` would cause observing whether the StopLoss were changed.
4. `Operation` would cause observing trades which changed from a stop / limit order to an open order.
5. `All` would cause observing all above defined.
Because `OrderModifiedTypes` is defined with the Flag-Attribute, you can combine the above monitoring types with a pipe: `OrderModifiedTypes.TakeProfit | OrderModifiedTypes.StopLoss`.
### Example
```
var orderModifyMonitor = new ModifiedOrdersMonitor(
_apiClient,
new MtApi.Monitors.Triggers.TimeElapsedTrigger(TimeSpan.FromSeconds(1)),
OrderModifiedTypes.All,
true
);
orderModifyMonitor.OrdersModified += OrderModifyMonitor_OrdersModified;
orderModifyMonitor.Start();
private void OrderModifyMonitor_OrdersModified(object sender, ModifiedOrdersEventArgs e)
{
//Receives the event
}
```
+20 -1
View File
@@ -58,16 +58,35 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ChartEventArgs.cs" />
<Compile Include="ChartPeriod.cs" />
<Compile Include="EnumAlignMode.cs" />
<Compile Include="EnumChartPropertyDouble.cs" />
<Compile Include="EnumChartPropertyInteger.cs" />
<Compile Include="EnumChartPropertyString.cs" />
<Compile Include="EnumColorFormat.cs" />
<Compile Include="EnumObject.cs" />
<Compile Include="EnumObjectPropertyDouble.cs" />
<Compile Include="EnumObjectPropertyInteger.cs" />
<Compile Include="EnumObjectPropertyString.cs" />
<Compile Include="EnumSeriesInfoInteger.cs" />
<Compile Include="EnumSymbolInfoDouble.cs" />
<Compile Include="EnumSymbolInfoInteger.cs" />
<Compile Include="EnumTerminalInfoDouble.cs" />
<Compile Include="EnumTerminalInfoInteger.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="FlagFontStyle.cs" />
<Compile Include="Monitors\AvailabilityOrdersEventArgs.cs" />
<Compile Include="Monitors\OrderModification\ModifiedOrdersEventArgs.cs" />
<Compile Include="Monitors\OrderModification\ModifiedOrdersMonitor.cs" />
<Compile Include="Monitors\OrderModification\MtModifiedOrder.cs" />
<Compile Include="Monitors\MtMonitorBase.cs" />
<Compile Include="Monitors\OrderModification\OrderModifiedTypes.cs" />
<Compile Include="Monitors\Triggers\IMonitorTrigger.cs" />
<Compile Include="Monitors\Triggers\NewBarTrigger.cs" />
<Compile Include="Monitors\Triggers\TimeElapsedTrigger.cs" />
<Compile Include="MqlRates.cs" />
<Compile Include="MqlTick.cs" />
<Compile Include="MtChartEvent.cs" />
<Compile Include="MtConnectionEventArgs.cs" />
<Compile Include="MtConnectionException.cs" />
<Compile Include="MtConnectionState.cs" />
+1382 -122
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -13,9 +13,9 @@ namespace MtApi
return Color.FromArgb((byte)(color), (byte)(color >> 8), (byte)(color >> 16));
}
public static int ConvertToMtColor(Color color)
public static int ConvertToMtColor(Color? color)
{
return color == Color.Empty ? 0xffffff : (Color.FromArgb(color.B, color.G, color.R).ToArgb() & 0xffffff);
return color == null || color == Color.Empty ? 0xffffff : (Color.FromArgb(color.Value.B, color.Value.G, color.Value.R).ToArgb() & 0xffffff);
}
}
}
+3 -3
View File
@@ -13,13 +13,13 @@ namespace MtApi
return new DateTime(tmpTime.Ticks + (time * 0x989680L));
}
public static int ConvertToMtTime(DateTime time)
public static int ConvertToMtTime(DateTime? time)
{
int result = 0;
if (time != DateTime.MinValue)
if (time != null && time != DateTime.MinValue)
{
DateTime tmpTime = new DateTime(1970, 1, 1);
result = (int)((time.Ticks - tmpTime.Ticks) / 0x989680L);
result = (int)((time.Value.Ticks - tmpTime.Ticks) / 0x989680L);
}
return result;
}
+11
View File
@@ -0,0 +1,11 @@
namespace MtApi
{
internal class MtChartEvent
{
public long ChartId { get; set; }
public int EventId { get; set; }
public long Lparam { get; set; }
public double Dparam { get; set; }
public string Sparam { get; set; }
}
}
Executable → Regular
+86 -9
View File
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
namespace MtApi
{
enum MtCommandType
{
@@ -116,6 +111,7 @@ namespace MtApi
TimeSeconds = 86,
TimeYear = 87,
Year = 88,
TimeGMT = 281,
//Global Variables
GlobalVariableCheck = 89,
@@ -140,8 +136,8 @@ namespace MtApi
iBullsPower = 106,
iCCI = 107,
iCCIOnArray = 108,
iCustom = 109,
iCustom_d = 10109,
//iCustom = 109,
//iCustom_d = 10109,
iDeMarker = 110,
iEnvelopes = 111,
iEnvelopesOnArray = 112,
@@ -201,6 +197,87 @@ namespace MtApi
SymbolsTotal = 200,
SymbolName = 201,
SymbolSelect = 202,
SymbolInfoInteger = 203
SymbolInfoInteger = 203,
//Object Functions
ObjectCreate = 208,
ObjectName = 209,
ObjectDelete = 210,
ObjectsDeleteAll = 211,
ObjectFind = 212,
ObjectGetTimeByValue = 213,
ObjectGetValueByTime = 214,
ObjectMove = 215,
ObjectsTotal = 216,
ObjectGetDouble = 217,
ObjectGetInteger = 218,
ObjectGetString = 219,
ObjectSetDouble = 220,
ObjectSetInteger = 221,
ObjectSetString = 222,
TextSetFont = 223,
TextOut = 224,
TextGetSize = 225,
ObjectDescription = 226,
ObjectGet = 227,
ObjectGetFiboDescription = 228,
ObjectGetShiftByValue = 229,
ObjectGetValueByShift = 230,
ObjectSet = 231,
ObjectSetFiboDescription = 232,
ObjectSetText = 233,
ObjectType = 234,
UnlockTicks = 235,
//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,
WindowBarsPerChart = 264,
WindowExpertName = 265,
WindowFind = 266,
WindowFirstVisibleBar = 267,
WindowHandle = 268,
WindowIsVisible = 269,
WindowOnDropped = 270,
WindowPriceMax = 271,
WindowPriceMin = 272,
WindowPriceOnDropped = 273,
WindowRedraw = 274,
WindowScreenShot = 275,
WindowTimeOnDropped = 276,
WindowsTotal = 277,
WindowXOnDropped = 278,
WindowYOnDropped = 279,
ChangeAccount = 280
}
}
+1 -4
View File
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
{
public class MtConnectionEventArgs: EventArgs
{
public MtConnectionState Status { get; private set; }
public String ConnectionMessage { get; private set; }
public string ConnectionMessage { get; private set; }
public MtConnectionEventArgs(MtConnectionState status, string message)
{
+2 -1
View File
@@ -2,6 +2,7 @@
{
public enum MtEventTypes
{
LastTimeBar = 1
LastTimeBar = 1,
ChartEvent = 2
}
}
+9
View File
@@ -5,6 +5,7 @@
public string Instrument { get; private set; }
public double Bid { get; private set; }
public double Ask { get; private set; }
public int ExpertHandle { get; private set; }
public MtQuote(string instrument, double bid, double ask)
{
@@ -12,5 +13,13 @@
Bid = bid;
Ask = ask;
}
internal MtQuote(MTApiService.MtQuote quote)
{
Instrument = quote.Instrument;
Bid = quote.Bid;
Ask = quote.Ask;
ExpertHandle = quote.ExpertHandle;
}
}
}
-3
View File
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MtApi
{
+2 -11
View File
@@ -11,16 +11,7 @@ namespace MtApi
public double Close { get; set; }
public double High { get; set; }
public double Low { get; set; }
public DateTime OpenTime
{
get { return MtApiTimeConverter.ConvertFromMtTime(MtOpenTime); }
}
public DateTime CloseTime
{
get { return MtApiTimeConverter.ConvertFromMtTime(MtCloseTime); }
}
public DateTime OpenTime => MtApiTimeConverter.ConvertFromMtTime(MtOpenTime);
public DateTime CloseTime => MtApiTimeConverter.ConvertFromMtTime(MtCloseTime);
}
}
+3 -1
View File
@@ -1,4 +1,6 @@
namespace MtApi
// ReSharper disable InconsistentNaming
namespace MtApi
{
public enum ENUM_TERMINAL_INFO_STRING
{
Executable → Regular
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 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")]
[assembly: AssemblyVersion("1.0.42.0")]
[assembly: AssemblyFileVersion("1.0.42.0")]
+8 -5
View File
@@ -1,18 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MtApi
{
public class TimeBarArgs: EventArgs
{
internal TimeBarArgs(int expertHandle, MtTimeBar timeBar)
: this(timeBar)
{
ExpertHandle = expertHandle;
}
public TimeBarArgs(MtTimeBar timeBar)
{
TimeBar = timeBar;
}
public MtTimeBar TimeBar { get; private set; }
public int ExpertHandle { get; }
public MtTimeBar TimeBar { get; }
}
}
+4 -1
View File
@@ -7,6 +7,9 @@
OP_BUYLIMIT = 2,
OP_SELLLIMIT = 3,
OP_BUYSTOP = 4,
OP_SELLSTOP = 5
OP_SELLSTOP = 5,
OP_BALANCE = 6,
OP_CREDIT = 7,
OP_REBATE = 8
}
}

Some files were not shown because too many files have changed in this diff Show More