/// <summary> /// Stops streaming transactions for the active account /// </summary> public override void StopTransactionStream() { if (_eventsSession != null) { _eventsSession.DataReceived -= OnEventReceived; _eventsSession.StopSession(); } }
private Task RunStreamingNotificationsTest() { EventsSession session = new EventsSession(_accountId); _eventReceived = new Semaphore(0, 100); session.DataReceived += OnEventReceived; session.StartSession(); Console.WriteLine("Starting event stream test"); return(Task.Run(() => { bool success = _eventReceived.WaitOne(10000); session.StopSession(); _results.Verify(success, "Streaming events successfully received"); } )); }
//--------------------------------------------------------------------------------------------------- #region Streaming tests protected virtual Task RunStreamingNotificationsTest() { EventsSession session = new EventsSession(_accountId); _eventReceived = new Semaphore(0, 100); session.DataReceived += OnEventReceived; session.StartSession(); _results.Add("Starting event stream test"); // returns the Run() task of the anonymous task return(Task.Run(() => { // should have received order/trade/position/transaction notification by now bool success = _eventReceived.WaitOne(10000); session.StopSession(); _results.Verify(success, "Streaming events successfully received"); } )); }
/// <summary> /// Disconnects the client from the broker's remote servers /// </summary> public override void Disconnect() { if (_eventsSession != null) { _eventsSession.DataReceived -= OnEventReceived; _eventsSession.StopSession(); } if (_ratesSession != null) { _ratesSession.DataReceived -= OnDataReceived; _ratesSession.StopSession(); } // request and wait for thread to stop _cancellationTokenSource.Cancel(); _connectionMonitorThread.Join(); _isConnected = false; }
/// <summary> /// Connects the client to the broker's remote servers /// </summary> public override void Connect() { if (IsConnected) return; // Load the list of instruments _oandaInstruments = GetInstruments().ToDictionary(x => x.instrument); // Register to the event session to receive events. _eventsSession = new EventsSession(this, _accountId); _eventsSession.DataReceived += OnEventReceived; _eventsSession.StartSession(); _isConnected = true; // create new thread to manage disconnections and reconnections _cancellationTokenSource = new CancellationTokenSource(); _connectionMonitorThread = new Thread(() => { var nextReconnectionAttemptUtcTime = DateTime.UtcNow; double nextReconnectionAttemptSeconds = 1; lock (_lockerConnectionMonitor) { _lastHeartbeatUtcTime = DateTime.UtcNow; } try { while (!_cancellationTokenSource.IsCancellationRequested) { TimeSpan elapsed; lock (_lockerConnectionMonitor) { elapsed = DateTime.UtcNow - _lastHeartbeatUtcTime; } if (!_connectionLost && elapsed > TimeSpan.FromSeconds(20)) { _connectionLost = true; nextReconnectionAttemptUtcTime = DateTime.UtcNow.AddSeconds(nextReconnectionAttemptSeconds); OnMessage(BrokerageMessageEvent.Disconnected("Connection with Oanda server lost. " + "This could be because of internet connectivity issues. ")); } else if (_connectionLost) { try { if (elapsed <= TimeSpan.FromSeconds(20)) { _connectionLost = false; nextReconnectionAttemptSeconds = 1; OnMessage(BrokerageMessageEvent.Reconnected("Connection with Oanda server restored.")); } else { if (DateTime.UtcNow > nextReconnectionAttemptUtcTime) { try { // check if we have a connection GetInstruments(); // restore events session if (_eventsSession != null) { _eventsSession.DataReceived -= OnEventReceived; _eventsSession.StopSession(); } _eventsSession = new EventsSession(this, _accountId); _eventsSession.DataReceived += OnEventReceived; _eventsSession.StartSession(); // restore rates session List<Symbol> symbolsToSubscribe; lock (_lockerSubscriptions) { symbolsToSubscribe = _subscribedSymbols.ToList(); } SubscribeSymbols(symbolsToSubscribe); } catch (Exception) { // double the interval between attempts (capped to 1 minute) nextReconnectionAttemptSeconds = Math.Min(nextReconnectionAttemptSeconds * 2, 60); nextReconnectionAttemptUtcTime = DateTime.UtcNow.AddSeconds(nextReconnectionAttemptSeconds); } } } } catch (Exception exception) { Log.Error(exception); } } Thread.Sleep(1000); } } catch (Exception exception) { Log.Error(exception); } }); _connectionMonitorThread.Start(); while (!_connectionMonitorThread.IsAlive) { Thread.Sleep(1); } }
/// <summary> /// Connects the client to the broker's remote servers /// </summary> public override void Connect() { if (IsConnected) { return; } // Load the list of instruments _oandaInstruments = GetInstruments().ToDictionary(x => x.instrument); // Register to the event session to receive events. _eventsSession = new EventsSession(this, _accountId); _eventsSession.DataReceived += OnEventReceived; _eventsSession.StartSession(); _isConnected = true; // create new thread to manage disconnections and reconnections _cancellationTokenSource = new CancellationTokenSource(); _connectionMonitorThread = new Thread(() => { var nextReconnectionAttemptUtcTime = DateTime.UtcNow; double nextReconnectionAttemptSeconds = 1; lock (_lockerConnectionMonitor) { _lastHeartbeatUtcTime = DateTime.UtcNow; } try { while (!_cancellationTokenSource.IsCancellationRequested) { TimeSpan elapsed; lock (_lockerConnectionMonitor) { elapsed = DateTime.UtcNow - _lastHeartbeatUtcTime; } if (!_connectionLost && elapsed > TimeSpan.FromSeconds(20)) { _connectionLost = true; nextReconnectionAttemptUtcTime = DateTime.UtcNow.AddSeconds(nextReconnectionAttemptSeconds); OnMessage(BrokerageMessageEvent.Disconnected("Connection with Oanda server lost. " + "This could be because of internet connectivity issues. ")); } else if (_connectionLost) { try { if (elapsed <= TimeSpan.FromSeconds(20)) { _connectionLost = false; nextReconnectionAttemptSeconds = 1; OnMessage(BrokerageMessageEvent.Reconnected("Connection with Oanda server restored.")); } else { if (DateTime.UtcNow > nextReconnectionAttemptUtcTime) { try { // check if we have a connection GetInstruments(); // restore events session if (_eventsSession != null) { _eventsSession.DataReceived -= OnEventReceived; _eventsSession.StopSession(); } _eventsSession = new EventsSession(this, _accountId); _eventsSession.DataReceived += OnEventReceived; _eventsSession.StartSession(); // restore rates session List <Symbol> symbolsToSubscribe; lock (_lockerSubscriptions) { symbolsToSubscribe = _subscribedSymbols.ToList(); } SubscribeSymbols(symbolsToSubscribe); } catch (Exception) { // double the interval between attempts (capped to 1 minute) nextReconnectionAttemptSeconds = Math.Min(nextReconnectionAttemptSeconds * 2, 60); nextReconnectionAttemptUtcTime = DateTime.UtcNow.AddSeconds(nextReconnectionAttemptSeconds); } } } } catch (Exception exception) { Log.Error(exception); } } Thread.Sleep(1000); } } catch (Exception exception) { Log.Error(exception); } }); _connectionMonitorThread.Start(); while (!_connectionMonitorThread.IsAlive) { Thread.Sleep(1); } }
static void Main(string[] args) { List <Instrument> instruments = null; var task = Task.Run(async() => instruments = await Rest.GetInstrumentsAsync(AccountId, null, new List <string>(_majors))); task.Wait(); var selectedMajors = instruments.Where(s => Array.Exists <string>(_majors, y => y == s.instrument)); RatesSession session = new RatesSession(AccountId, new List <Instrument>(selectedMajors)); _tickReceived = new Semaphore(0, 100); session.DataReceived += SessionOnDataReceived; session.StartSession(); Console.WriteLine("Starting rate stream test"); bool success = _tickReceived.WaitOne(10000); session.StopSession(); EventsSession eventSession = new EventsSession(AccountId); _eventReceived = new Semaphore(0, 100); eventSession.DataReceived += OnEventReceived; eventSession.StartSession(); Console.WriteLine("Starting event stream test"); Task.Run(() => { success = _eventReceived.WaitOne(10000); eventSession.StopSession(); } ); List <Price> prices; var task2 = Task.Run(async() => prices = await Rest.GetRatesAsync(instruments)); task2.Wait(); List <Position> positions = null; var task3 = Task.Run(async() => positions = await Rest.GetPositionsAsync(AccountId)); task3.Wait(); var request = new Dictionary <string, string> { { "instrument", TestInstrument }, { "units", "10000" }, { "side", "sell" }, { "type", "market" }, { "price", "1.0" } }; if (positions.Count == 0) { //Open a position PostOrderResponse response = null; var task4 = Task.Run(async() => response = await Rest.PostOrderAsync(AccountId, request)); task4.Wait(); if (response.tradeOpened != null && response.tradeOpened.id > 0) { Console.WriteLine("Post order success"); } } else { //Close all positions foreach (var position in positions) { DeletePositionResponse closePositionResponse = null; var task5 = Task.Run(async() => closePositionResponse = await Rest.DeletePositionAsync(AccountId, TestInstrument)); task5.Wait(); if (closePositionResponse.ids.Count > 0 && closePositionResponse.instrument == TestInstrument) { Console.WriteLine("Position closed"); } if (closePositionResponse.totalUnits > 0 && closePositionResponse.price > 0) { Console.WriteLine("Position close response seems valid"); } foreach (var id in closePositionResponse.ids) { Transaction transaction = null; var task6 = Task.Run(async() => transaction = await Rest.GetTransactionDetailsAsync(AccountId, id)); task6.Wait(); } } } Console.ReadLine(); }