/// <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); } }
public static void Main(string [] args) { if (args.Length == 0) { Console.WriteLine("Usage:"); Console.WriteLine("RhQuote SYMBOL1 [SYMBOL2 SYMBOL3 SYMBOL_N]"); Environment.Exit(1); } var rh = new RobinhoodClient(); if (!authenticate(rh)) { Console.WriteLine("Unable to authenticate user"); Environment.Exit(1); } try { var quotes = rh.DownloadQuote(args).Result; var history = rh.DownloadHistory(args, "5minute", "week").Result; Console.WriteLine(DateTime.Now); foreach (var q in quotes) { if (q == null) { continue; } Console.WriteLine("{0}\tCh: {1}%\tLTP: {2}\tBID: {3}\tASK: {4}", q.Symbol, q.ChangePercentage, q.LastTradePrice, q.BidPrice, q.AskPrice); } foreach (var h in history) { if (h == null) { continue; } Console.WriteLine("{0}\tInterval: {1}\tSpan: {2}\tBound: {3}", h.Symbol, h.Interval, h.Span, h.Bounds); foreach (var p in h.HistoricalInfo) { Console.WriteLine("{0}\tOpen: {1}\tClose: {2}\tHigh: {3}\tLow: {3}", p.BeginsAt, p.OpenPrice, p.ClosePrice, p.HighPrice, p.LowPrice); } } } catch { Console.WriteLine("None of the quotes entered were found."); } }