public override void Destroy() { Broker.Instance.UnsubscribePosition(PositionSubscription); PositionSubscription = null; base.Destroy(); }
public override void Initialize() { // Attempt to get a reference price either as the purchase price if there is a position in this stock, or the day's starting price otherwise DataAccessor.Accessor.GetStockInfo(StockSubscription.Symbol, (DataAccessor.StockInfo info) => { if (PositionSubscription.PositionInfo.Shares == 0) { this.RefPrice = info.PreviousClose; } }); PositionSubscription = Broker.Instance.SubscribeToPositionInfo(StockSubscription.Symbol); PositionSubscription.Notify += (Broker.PositionSubscription sub) => { if (sub.PositionInfo.Shares > 0) { this.RefPrice = sub.PositionInfo.AverageBuyPrice; } }; // Update the notification periodically StockSubscription.Notify += (DataAccessor.Subscription s) => { this.BeginInvoke((Action)(() => { PriceLabel.Text = string.Format("{0:c}", s.Price); PercentageLabel.Text = string.Format("{0}{1:P2}", (s.Price >= RefPrice) ? "+" : "-", (RefPrice != 0) ? Math.Abs((s.Price - RefPrice) / RefPrice) : 0); })); }; // Set the notification background color this.ParentLine.BackColor = GuiStyle.NOTIFICATION_COLOR; }
/// <summary> /// Ends the specified subscription /// </summary> /// <param name="subscription">The subscription to stop</param> public void UnsubscribePosition(Broker.PositionSubscription subscription) { if (RobinhoodThreadMutex.WaitOne(100)) { PositionSubscriptions.Remove(subscription); RobinhoodThreadMutex.ReleaseMutex(); } }
/// <summary> /// Returns information about a current position whenever there is a change /// </summary> /// <param name="symbol">The symbol to request the position for</param> /// <returns>The subscription instance</returns> public Broker.PositionSubscription SubscribeToPositionInfo(string symbol) { var subscription = new Broker.PositionSubscription(symbol); if (RobinhoodThreadMutex.WaitOne(100)) { PositionSubscriptions.Add(subscription); RobinhoodThreadMutex.ReleaseMutex(); } return(subscription); }
public override void Initialize() { PositionSubscription = Broker.Instance.SubscribeToPositionInfo(StockSubscription.Symbol); PositionSubscription.Notify += (Broker.PositionSubscription sub) => { if (sub.PositionInfo.Shares > 0) { this.RefPrice = sub.PositionInfo.AverageBuyPrice; } else { // Remove the position indication once there are no shares left ParentLine.ParentList.Remove(ParentLine); } }; StockSubscription.Notify += (DataAccessor.Subscription s) => { this.BeginInvoke((Action)(() => { PriceLabel.Text = string.Format("{0:c}", (s.Price * PositionSubscription.PositionInfo.Shares)); PercentageLabel.Text = string.Format("{0}{1:P2}", (s.Price >= RefPrice) ? "+" : "-", (RefPrice != 0) ? Math.Abs((s.Price - RefPrice) / RefPrice) : 0); })); }; }
/// <summary> /// The function executed as the Robinhood interface /// </summary> private void ThreadProcess() { while (Running) { // Process the history requests if (Client.isAuthenticated && (HistoryRequests.Count > 0) && ((DateTime.Now - HistoryRequests[0].RequestTime).TotalSeconds) > HISTORY_REQUEST_PROCESS_DELAY) { while ((HistoryRequests.Count > 0) && Running) { // Put together a single request RobinhoodThreadMutex.WaitOne(); DateTime start = HistoryRequests[0].Start; DateTime end = HistoryRequests[0].End; TimeSpan interval = getHistoryInterval(HistoryRequests[0].Interval, getHistoryTimeSpan(start, end)); List <string> symbols = new List <string>() { HistoryRequests[0].Symbol }; List <int> servicedIndices = new List <int>() { 0 }; for (int i = 1; i < HistoryRequests.Count; i++) { if (getHistoryInterval(HistoryRequests[i].Interval, getHistoryTimeSpan(HistoryRequests[i].Start, HistoryRequests[i].End)) == interval) { // Include this in the request symbols.Add(HistoryRequests[i].Symbol); servicedIndices.Add(i); start = ((start < HistoryRequests[i].Start) ? start : HistoryRequests[i].Start); end = ((end > HistoryRequests[i].End) ? end : HistoryRequests[i].End); } } RobinhoodThreadMutex.ReleaseMutex(); // Make the request if ((getHistoryTimeSpan(start, end) >= HISTORY_SPANS.ElementAt(HISTORY_SPANS.Count - 1).Key) || // If requesting too far back in history ((start.Date == end.Date) && ((end < EXTENDED_HOURS_OPEN) || (start >= EXTENDED_HOURS_CLOSE)))) // If requesting data outside of the available times { foreach (var s in servicedIndices) { HistoryRequests[s].Callback(null); } } else { var bounds = ((start.Date == end.Date) ? HISTORY_BOUNDS.EXTENDED : HISTORY_BOUNDS.REGULAR); // Can only get extended hours history for the current day var request = Client.DownloadHistory(symbols, HISTORY_INTERVALS[interval], HISTORY_SPANS[getHistoryTimeSpan(start, end)], bounds); request.Wait(); if (!request.IsCompleted || request.IsFaulted) { continue; } var history = request.Result; // Return the data to the reqesting sources int servicedCount = 0; foreach (var stock in history) { if (stock.HistoricalInfo.Count > 0) { // Put the data into a table DataTable dt = new DataTable(); dt.Columns.Add("Time", typeof(DateTime)); dt.Columns.Add("Price", typeof(float)); foreach (var p in stock.HistoricalInfo) { DateTime t = (interval < new TimeSpan(1, 0, 0, 0)) ? p.BeginsAt.ToLocalTime() : p.BeginsAt.AddHours(9.5); dt.Rows.Add(t, (float)p.OpenPrice); } // Add a final price dt.Rows.Add(stock.HistoricalInfo[stock.HistoricalInfo.Count - 1].BeginsAt.Add(interval).ToLocalTime(), stock.HistoricalInfo[stock.HistoricalInfo.Count - 1].ClosePrice); // Pass the table back to the caller if (!HistoryRequests[servicedIndices[servicedCount]].Symbol.Equals(stock.Symbol)) { //throw new Exception("Response does not match the request"); } HistoryRequests[servicedIndices[servicedCount]].Callback(dt); servicedCount++; } } } // Remove the processed requests from the queue RobinhoodThreadMutex.WaitOne(); for (int i = servicedIndices.Count - 1; i >= 0; i--) { HistoryRequests.RemoveAt(servicedIndices[i]); } RobinhoodThreadMutex.ReleaseMutex(); } } // Process the position subscriptions if (RobinhoodThreadMutex.WaitOne(0)) { for (int i = 0; Client.isAuthenticated && (i < PositionSubscriptions.Count); i++) { Broker.PositionSubscription sub = PositionSubscriptions[i]; var orderInfo = ActiveOrders.Find((a) => { return(a.Symbol.Equals(sub.PositionInfo.Symbol)); }); if (((DateTime.Now - sub.LastUpdated).TotalSeconds > 5) && (sub.Dirty || ((orderInfo != null) && (orderInfo.RefreshedAt != sub.LastUpdated)))) { sub.LastUpdated = DateTime.Now; GetPositionInfo(sub.PositionInfo.Symbol, (info) => { sub.PositionInfo = info; sub.LastUpdated = ((orderInfo != null) ? orderInfo.RefreshedAt : DateTime.Now); sub.Dirty = false; if (sub.Notify != null) { sub.Notify(sub); } }); } } RobinhoodThreadMutex.ReleaseMutex(); } // Update the active orders RefreshActiveOrders(); // Sleep so the thread doesn't run at 100% CPU System.Threading.Thread.Sleep(5); } }