private void UpdateMarketQuotes(MainForm mainForm) { //List<Stock> quotes = new List<Stock>(); if (mainForm.stocks.Count() == 0) { return; //quotes = mainForm.stocks.Union(quotes).ToList(); } List <Stock> marketStocks = Robinhood.GetQuote(mainForm.stocks.ToList()); foreach (Stock stock in marketStocks) { //relying on update recent order to add pending orders ThreadedBindingList <OrderSnapshot> pendingOrders = null; if (stock.PendingOrders != null) { lock (stock.PendingOrders) { pendingOrders = new ThreadedBindingList <OrderSnapshot>(AllPendingOrders.Where(o => o.InstrumentId == stock.InstrumentURL).ToList()); } } else { pendingOrders = new ThreadedBindingList <OrderSnapshot>(AllPendingOrders.Where(o => o.InstrumentId == stock.InstrumentURL).ToList()); } if (pendingOrders.Count > 0) { stock.PendingOrders = pendingOrders; } else { stock.PendingOrders = null; } mainForm.PositionsGrid.BeginInvoke((Action) delegate { lock (mainForm.stocks) { int index = mainForm.stocks.ToList() .FindIndex(s => s.Ticker == stock.Ticker); if (index >= 0) { mainForm.stocks[index] = stock; } } }); if (stock.NoOfShares > 0) { UpdateOwnedStock(mainForm, stock); } else { //don't own this stock stock.CostBasis = 0.00m; } } }
void StockUpdater(object parm) { HoldingForm form = (HoldingForm)parm; while (true) { try { if (stopThreads) { break; } stock = Robinhood.GetQuote(new List <Stock>() { stock }).First(); string quote = stock.Quote; form.labelQuote.Invoke((Action) delegate { form.labelQuote.Text = quote; form.labelQuote.ForeColor = form.stock.Color; }); form.labelAskPrice.Invoke((Action) delegate { form.labelAskPrice.Text = "$" + stock.AskPrice.ToString(); form.labelBidPrice.Text = "$" + stock.BidPrice.ToString(); }); /////////////////////////// if (stock.Entry.FollowPrice == PricePointControl.FollowPrice.AtAsk) { form.Entry.numericUpDownValue.Invoke((Action) delegate { form.Entry.numericUpDownValue.Value = stock.AskPrice; }); } if (stock.Entry.FollowPrice == PricePointControl.FollowPrice.AtLastTradedPrice) { form.Entry.numericUpDownValue.Invoke((Action) delegate { form.Entry.numericUpDownValue.Value = stock.LastTradePrice + 0.01m; }); } if (stock.Entry.FollowPrice == PricePointControl.FollowPrice.AtBid) { form.Entry.numericUpDownValue.Invoke((Action) delegate { form.Entry.numericUpDownValue.Value = stock.BidPrice; }); } ///////////////////////////////////////////// if (stock.StopLoss.FollowPrice == PricePointControl.FollowPrice.AtAsk) { form.Stop.numericUpDownValue.Invoke((Action) delegate { form.Stop.numericUpDownValue.Value = stock.AskPrice; }); } if (stock.StopLoss.FollowPrice == PricePointControl.FollowPrice.AtBid) { form.Stop.numericUpDownValue.Invoke((Action) delegate { form.Stop.numericUpDownValue.Value = stock.BidPrice; }); } if (stock.StopLoss.FollowPrice == PricePointControl.FollowPrice.AtLastTradedPrice) { form.Stop.numericUpDownValue.Invoke((Action) delegate { form.Stop.numericUpDownValue.Value = stock.LastTradePrice; }); } /////////////// if (stock.PriceTarget.FollowPrice == PricePointControl.FollowPrice.AtAsk) { form.PriceTarget.numericUpDownValue.Invoke((Action) delegate { form.PriceTarget.numericUpDownValue.Value = stock.AskPrice; }); } if (stock.PriceTarget.FollowPrice == PricePointControl.FollowPrice.AtLastTradedPrice) { form.PriceTarget.numericUpDownValue.Invoke((Action) delegate { form.PriceTarget.numericUpDownValue.Value = stock.LastTradePrice; }); } if (stock.PriceTarget.FollowPrice == PricePointControl.FollowPrice.AtBid) { form.PriceTarget.numericUpDownValue.Invoke((Action) delegate { form.PriceTarget.numericUpDownValue.Value = stock.BidPrice; }); } form.labelMarketValue.Invoke((Action) delegate { form.labelMarketValue.Text = "Market Value: $" + Math.Round(stock.LastTradePrice * form.NoOfShares.Value, 2).ToString(); }); form.bidAskRationLabel.Invoke((Action) delegate { bidAskRationLabel.Text = stock.BidAskSpread.ToString(); }); if (stock.NoOfShares > 0 && (stock.PendingOrders == null || !stock.PendingOrders.Any(o => o.Side == Side.Sell && o.Trigger == "stop"))) { Stop.Invoke((Action) delegate { if (Stop.placeOrderButton.BackColor == SystemColors.ControlLightLight) { Stop.placeOrderButton.BackColor = Color.IndianRed; Stop.placeOrderButton.ForeColor = Color.White; Stop.placeOrderButton.Text = "No Stop Order"; } else { Stop.placeOrderButton.BackColor = SystemColors.ControlLightLight; Stop.placeOrderButton.ForeColor = SystemColors.WindowText; Stop.placeOrderButton.Text = "Place Order"; } }); } else { Stop.Invoke((Action) delegate { Stop.placeOrderButton.BackColor = SystemColors.ButtonFace; Stop.placeOrderButton.ForeColor = SystemColors.WindowText; Stop.placeOrderButton.Text = "Place Order"; }); } this.BeginInvoke((Action) delegate { this.UpdatePendingOrder(); }); } catch (Exception e) { if (shown && form.IsHandleCreated) { form.labelQuote.Invoke((Action) delegate { form.labelQuote.Text = e.Message; form.labelQuote.ForeColor = Color.IndianRed; }); } } Thread.Sleep(form.refreshTime); } }
/// <summary> /// this thread updates all the quotes on the grids also downloads /// also download latest portfolio from RH /// </summary> /// <param name="form"></param> void MarketPerfomanceUpdater(object form) { MainForm mainForm = (MainForm)form; int i = 0; decimal lastprice = 0; while (true) { if (mainForm.formClosing) { break; } try { Stock[] quotes = new Stock[] { new Stock() { Ticker = mainForm.market.Ticker }, new Stock() { Ticker = mainForm.TVIX.Ticker }, new Stock() { Ticker = mainForm.nugt.Ticker } }; Account account = Robinhood.rh.DownloadAllAccounts().Result.First(); IList <Position> positions = Robinhood.rh.DownloadPositions(account.PositionsUrl.Uri.ToString()); foreach (Position position in positions) { Stock stock = mainForm.stocks.FirstOrDefault(s => s.InstrumentURL == position.InstrumentUrl.Uri.ToString()); if (stock == null) { if ((int)position.Quantity == 0) { continue; //skip stocks in RH watchlist } var q = Robinhood.rh.DownloadInstrument(position.InstrumentUrl.Uri.ToString()); stock = new Stock() { Ticker = q.Result.Symbol, NoOfShares = (int)position.Quantity, CostBasis = position.AverageBuyPrice }; mainForm.stocks.Add(stock); } else { stock.NoOfShares = (int)position.Quantity; if (stock.NoOfShares > 0) { stock.CostBasis = position.AverageBuyPrice; } else { stock.CostBasis = 0.00m; } } } if (mainForm.stocks.Count() > 0) { quotes = mainForm.stocks.Union(quotes).ToArray(); } List <Stock> marketStocks = Robinhood.GetQuote(quotes.ToList()); foreach (Stock stock in marketStocks) { if (stock.Ticker == market.Ticker) { mainForm.market = stock; } else if (stock.Ticker == TVIX.Ticker) { mainForm.TVIX = stock; } else if (stock.Ticker == nugt.Ticker) { mainForm.nugt = stock; } //relying on update recent order to add pending orders ThreadedBindingList <OrderSnapshot> pendingOrders = null; if (stock.PendingOrders != null) { lock (stock.PendingOrders) { pendingOrders = new ThreadedBindingList <OrderSnapshot>(AllPendingOrders.Where(o => o.InstrumentId == stock.InstrumentURL).ToList()); } } else { pendingOrders = new ThreadedBindingList <OrderSnapshot>(AllPendingOrders.Where(o => o.InstrumentId == stock.InstrumentURL).ToList()); } if (pendingOrders.Count > 0) { stock.PendingOrders = pendingOrders; } else { stock.PendingOrders = null; } mainForm.PositionsGrid.BeginInvoke((Action) delegate { lock (mainForm.stocks) { int index = mainForm.stocks.ToList() .FindIndex(s => s.Ticker == stock.Ticker); if (index >= 0) { mainForm.stocks[index] = stock; } } }); if (stock.NoOfShares > 0) { if (!mainForm.tabControlMain.TabPages[1].Text.Contains("Loading") && !trailStopping.Contains(stock.Ticker)) { //implementing trailing loss if (stock.StopLoss != null && stock.StopLoss.Execution == PricePointControl.Execution.Trailing && stock.StopLoss.TrailPrcntg > 0 && stock.NoOfShares > 0) { //PT reached sell if (stock.StopLoss.Price >= stock.LastTradePrice) { stock.StopLoss.Price = 0; //reset stop loss } decimal newVal = (stock.StopLoss.Price + (stock.StopLoss.Price * stock.StopLoss.TrailPrcntg / 100)); if (stock.LastTradePrice > newVal ) // within 2% of price target place limit sell { newVal = Math.Round(stock.LastTradePrice - (stock.LastTradePrice * stock.StopLoss.TrailPrcntg / 100), 2); if (stock.PendingOrders == null || (stock.PendingOrders != null && !stock.PendingOrders.Any(o => o.StopPrice <= newVal + 0.2m && o.StopPrice >= newVal - 0.2m))) { if (stock.NoOfShares < stock.StopLoss.NoOfShares) { stock.NoOfShares = stock.StopLoss.NoOfShares; } stock.StopLoss.Trigger = TriggerType.Stop; KeyValuePair <Stock, decimal> input = new KeyValuePair <Stock, decimal>(stock, newVal); lock (trailStopping) { trailStopping.Add(stock.Ticker); } ThreadPool.QueueUserWorkItem(TrailStopper, input); } } } //no stop loss place it if manage trade selected if (stock.ManageTrade && stock.NoOfShares > 0 && stock.StopLoss.Execution != PricePointControl.Execution.Trailing) { decimal newVal; decimal?currentStop = null; if (stock.PendingOrders != null && stock.PendingOrders.Count() > 0) { currentStop = (decimal)stock.PendingOrders.First().Price; } //if price has moved > 2% from cost newVal = Math.Round(stock.CostBasis + (stock.CostBasis * 2.10m / 100), 2); if (stock.LastTradePrice > newVal) { //price has moved 2% from cost move stop to break even newVal = Math.Round(stock.CostBasis + (stock.CostBasis * 2.00m / 100), 2); } else { //place stop loss at max newVal = Math.Round(stock.CostBasis - (stock.CostBasis * stock.MaxPrctgLoss / 100), 2); stock.StopLoss.StopOffset = 0.02m; stock.StopLoss.Trigger = TriggerType.Stop; //price has already moved at or below stop loss liquidate immiediately if (stock.LastTradePrice <= newVal) { newVal = stock.LastTradePrice; stock.StopLoss.Trigger = TriggerType.Immediate; } } if (currentStop == null || currentStop <= newVal - 0.03m || currentStop >= newVal + 0.03m) { stock.StopLoss.NoOfShares = stock.NoOfShares; stock.StopLoss.Price = newVal; //place adjusted stop loss KeyValuePair <Stock, decimal> input = new KeyValuePair <Stock, decimal>(stock, newVal); lock (trailStopping) { trailStopping.Add(stock.Ticker); } ThreadPool.QueueUserWorkItem(TrailStopper, input); } } } //Checking if Price target reached if (stock.PriceTarget != null && stock.NoOfShares > 0 && stock.PriceTarget.Price > 0 && stock.PriceTarget.NoOfShares > 0 && !priceTargeting.Contains(stock.Ticker)) { //PT reached sell if (stock.LastTradePrice + 0.02m >= stock.PriceTarget.Price) // within 2cent of price target place limit sell { KeyValuePair <Stock, decimal> input = new KeyValuePair <Stock, decimal>(stock, stock.PriceTarget.Price); lock (priceTargeting) { priceTargeting.Add(stock.Ticker); } ThreadPool.QueueUserWorkItem(PriceTargeter, input); } } } else { //don't own this stock stock.CostBasis = 0.00m; } } //Updating market tickers mainForm.BeginInvoke((MethodInvoker)(() => { mainForm.marketLabel.Text = market.Quote; mainForm.marketLabel.ForeColor = market.Color; })); mainForm.labelTVIX.BeginInvoke((Action) delegate { mainForm.labelTVIX.Text = TVIX.Quote; mainForm.labelTVIX.ForeColor = TVIX.Color; }); mainForm.nugtLabel.BeginInvoke((Action) delegate { mainForm.nugtLabel.Text = nugt.Quote; mainForm.nugtLabel.ForeColor = nugt.Color; }); //Updating account information mainForm.buyPowerLabel.Invoke((Action) delegate { mainForm.buyPowerLabel.Text = "Buying Power: $" + Math.Round(account.CashBalance.BuyingPower, 2).ToString(); }); mainForm.labelUnsettled.Invoke((Action) delegate { mainForm.labelUnsettled.Text = "Unsettled: $" + Math.Round(account.CashBalance.UnsettledFunds, 2).ToString(); }); mainForm.labelCash.Invoke((Action) delegate { mainForm.labelCash.Text = "Cash: $" + Math.Round(account.CashBalance.BuyingPower + account.CashBalance.UnsettledFunds + account.CashBalance.CashHeldForOrders, 2).ToString(); }); mainForm.buttonAddStock.Invoke((Action) delegate { mainForm.buttonAddStock.Enabled = true; }); if (mainForm.PositionsGrid.Enabled == false) { mainForm.PositionsGrid.Invoke((Action) delegate { mainForm.buttonAddStock.Enabled = true; }); } mainForm.PositionsGrid.Invoke((Action) delegate { UpdateGrids(); }); Thread.Sleep(refreshTime); } catch (AggregateException) { mainForm.BeginInvoke((MethodInvoker)(() => { mainForm.marketLabel.Text = "Could not reach Robinhood, Check network connection"; mainForm.marketLabel.ForeColor = Color.IndianRed; mainForm.marketLabel.BringToFront(); })); } catch (WebException e) { MessageBox.Show(e.ToString()); } catch (HttpException e) { MessageBox.Show(e.ToString()); } catch (Exception e) { MessageBox.Show(e.ToString()); logger.Error(e); } } }