private BrokerErrorCode RefreshEquityOrderBookToday() { DateTime EarliestValidMarketOpenDate = MarketUtils.GetMarketCurrentDate(); Dictionary <string, EquityOrderBookRecord> orders; return(GetEquityOrderBookToday(false, false, null, out orders)); }
public DerivativeSymbolTick GetTick(bool getSpread, out BrokerErrorCode code) { DerivativeSymbolQuote Q = null; DerivativeSymbolSpread S = null; DerivativeSymbolTick T = new DerivativeSymbolTick(); StringBuilder sb = new StringBuilder(); code = _broker.GetDerivativeQuote(Instrument.Symbol, Instrument.InstrumentType, Instrument.ExpiryDate, Instrument.StrikePrice, out Q); // Check for exchange closed or contract disabled code if (code == BrokerErrorCode.Success) { T.Q = Q; sb.Append(Q.ToTickString()); } if (getSpread) { code = _broker.GetDerivativeSpread(Instrument.Symbol, Instrument.InstrumentType, Instrument.ExpiryDate, Instrument.StrikePrice, out S); if (code == BrokerErrorCode.Success) { T.S = S; sb.Append(";" + S.ToString()); } } if (code.Equals(BrokerErrorCode.Success) && (_writeTicks || MarketUtils.IsTimeTodayAfter915(Q.QuoteTime))) { _writeTicks = true; _ticksw.WriteLine(sb.ToString()); } return(T); }
public void StartCapturingMarketTrend() { try { EquitySymbolQuote quote; errCode = myUpstoxWrapper.GetSnapQuote(exchStr, stockCode, out quote); myUpstoxWrapper.Upstox.QuotesReceivedEvent += new Upstox.QuotesReceivedEventEventHandler(QuoteReceived); var substatus = myUpstoxWrapper.Upstox.SubscribeQuotes(exchStr, stockCode); Trace(string.Format("SubscribeQuotes status={0}", substatus)); } catch (Exception ex) { Trace(string.Format("{0} Error: {1} \nStacktrace:{2}", stockCode, ex.Message, ex.StackTrace)); throw; } while (MarketUtils.IsMarketOpen()) { try { if (quote != null) { var changePct = (quote.LTP - quote.Close) / quote.Close; var prevmktTrendFactorForBuyMarkdown = mktTrendFactorForBuyMarkdown; if (changePct < -0.005) { mktTrendFactorForBuyMarkdown = 1.2; } else if (changePct < -0.01) { mktTrendFactorForBuyMarkdown = 1.5; } else if (changePct < -0.015) { mktTrendFactorForBuyMarkdown = 2; } else { mktTrendFactorForBuyMarkdown = 1; } if (prevmktTrendFactorForBuyMarkdown != mktTrendFactorForBuyMarkdown) { Trace(string.Format("MarketTrendForBuyMarkdown changed from {0} to {1}. Nifty changePct={2}", prevmktTrendFactorForBuyMarkdown, mktTrendFactorForBuyMarkdown, Math.Round(changePct, 5))); } } } catch (Exception ex) { Trace("Error:" + ex.Message + "\nStacktrace:" + ex.StackTrace); } Thread.Sleep(1000 * 15); } }
public void ConvertToDeliveryPreviousDaysExpiringOpenPositions() { if (!MarketUtils.IsTimeAfter2XMin(50)) { return; } BrokerErrorCode errCode = BrokerErrorCode.Unknown; // Get holding order matching this. check expiry date. if today then cancel holding order and convert it List <EquityPendingPositionForDelivery> pendingPositions; errCode = broker.GetOpenPositionsPendingForDelivery(stockCode, out pendingPositions); var positionsExpiringToday = pendingPositions.Where(p => p.ExpiryDate <= DateTime.Today.Date); var holdingsOrdersToRemove = new List <HoldingOrder>(); foreach (var position in positionsExpiringToday) { var holdingOrder = holdingsOrders.Where(h => h.Type == OrderPositionTypeEnum.OpenPendingDelivery && h.SettlementNumber == position.SettlementNumber && !string.IsNullOrEmpty(h.OrderRef) && h.Qty == position.BlockedQuantity && h.Qty > 0).FirstOrDefault(); var qtyToConvert = holdingOrder.Qty; // free up the blocked qty to go ahead with conversion errCode = CancelEquityOrder(string.Format("[Holding Conversion EOD] {0} {1}", holdingOrder.Type, holdingOrder.SettlementNumber), ref holdingOrder.OrderRef, EquityOrderType.DELIVERY, OrderDirection.SELL); if (errCode == BrokerErrorCode.Success) { // instead of removing the order mark the status as Cancelled and set Qty to 0 holdingOrder.Qty = 0; holdingOrder.Status = OrderStatus.CANCELLED; //holdingsOrdersToRemove.Add(holdingOrder); } int retryCount = 0; errCode = BrokerErrorCode.Unknown; while (errCode != BrokerErrorCode.Success && retryCount++ < 3) { // Just to ensure the qty is freed up and some time before retry Thread.Sleep(5000); // convert to delivery errCode = ConvertToDeliveryFromPendingForDelivery(stockCode, qtyToConvert, qtyToConvert, position.SettlementNumber, position.Exchange); if (errCode != BrokerErrorCode.Success) { // Conversion fails.. log the parameters Trace(string.Format("Previous ConversionToDelivery Failed: {5} {0} {1} qty expiring on {2} {3} {4}", stockCode, qtyToConvert, position.ExpiryDate.Date, position.SettlementNumber, position.Exchange, errCode)); } } } if (holdingsOrdersToRemove.Any()) { holdingsOrders.RemoveAll(h => holdingsOrdersToRemove.Contains(h)); UpdatePositionFile(); } }
public static BrokerErrorCode RefreshEquityStockStateToday(IBroker broker, EquityStockTradeStats stockInfo) { DateTime EarliestValidMarketOpenDate = MarketUtils.GetMarketCurrentDate(); if (stockInfo == null) { return(BrokerErrorCode.InValidArg); } return(stockInfo.EquityRefreshStockState(broker, EarliestValidMarketOpenDate, EarliestValidMarketOpenDate)); }
public static void hasExpired(Marketplace.Schemas.Services.SessionInfoResponse session, UIViewController controller) { accountViewController = controller; if (session.MultiSessionDetect) { AppSecurity.IsLogged = false; accountViewController.NavigationController.PopToRootViewController(true); MarketUtils.AlertView(controller, "Seguridad", "Se ha detectado otro inicio de sesión con el mismo usuario, se ha cerrado esta sesión."); return; } }
public DTick GetTickXMinutesOld(int minutes) { var time = GeneralUtils.RoundUp(DateTime.Now.AddMinutes(-minutes), TimeSpan.FromMinutes(1)); while (MarketUtils.IsTimeAfter915(time) && !AllTicks.ContainsKey(time) || AllTicks[time].Count == 0) { time = time.AddMinutes(-1); } if (AllTicks.ContainsKey(time)) { return(AllTicks[time][0]); } else { return(null); } }
public List <PriceHistoryDay> PriceHistory(int appId, string hashName) { var url = Urls.Market + $"/pricehistory/?appid={appId}&market_hash_name={Uri.EscapeDataString(hashName)}"; var resp = this.steam.Request(url, Method.GET, Urls.Market, null, true, proxy: this.Proxy); var respDes = JsonConvert.DeserializeObject <JPriceHistory>(resp.Data.Content); if (!respDes.Success) { throw new SteamException($"Cannot get price history for [{hashName}]"); } IEnumerable <dynamic> prices = Enumerable.ToList(respDes.Prices); var list = prices.Select( (g, index) => { var count = 0; if (g[2] != null && !int.TryParse(g[2].ToString(), out count)) { throw new SteamException($"Cannot parse items count in price history. Index: {index}"); } double price = 0; if (g[1] != null && !double.TryParse(g[1].ToString(), out price)) { throw new SteamException($"Cannot parse item price in price history. Index: {index}"); } return(new PriceHistoryItem { DateTime = MarketUtils.SteamTimeConvertor(g[0].ToString()), Count = count, Price = Math.Round(price, 2) }); }).GroupBy(x => x.DateTime.Date).Select( g => new PriceHistoryDay { Date = g.Key, History = g.Select(p => p).ToList() }).ToList(); return(list); }
public override void StockBuySell() { try { myUpstoxWrapper.Upstox.TradeUpdateEvent += new Upstox.TradeUpdateEventEventHandler(TradeUpdated); myUpstoxWrapper.Upstox.OrderUpdateEvent += new Upstox.OrderUpdateEventEventHandler(OrderUpdated); myUpstoxWrapper.Upstox.PositionUpdateEvent += new Upstox.PositionUpdateEventEventHandler(PositionUpdated); Init(AlgoType.AverageTheBuyThenSell); } catch (Exception ex) { Trace(string.Format("{0} Error: {1} \nStacktrace:{2}", stockCode, ex.Message, ex.StackTrace)); throw; } while (MarketUtils.IsMarketOpen()) { try { PlaceBuyOrderIfEligible(); HandleConversionAnytimeNew(); if (MarketUtils.IsTimeAfter3XMin(0)) { NearEODSquareOffAndCancelBuyOrder(); } if (MarketUtils.IsTimeAfter3XMin(29)) { CancelOpenOrders(); } } catch (Exception ex) { Trace("Error:" + ex.Message + "\nStacktrace:" + ex.StackTrace); } MainLoopPause(); } EODProcess(true); // EOD final update }
static void Main(string[] args) { BrokerErrorCode errCode = BrokerErrorCode.Unknown; // Check for Holiday today if (IsHolidayToday()) { Trace("Exchange Holiday today.. exiting."); return; } // Wait 2 seconds if contended – in case another instance // of the program is in the process of shutting down. if (!mutex.WaitOne(TimeSpan.FromSeconds(2), false)) { var message = "Another instance of the app is running. Only one instance for a userId is allowed! UserId: " + userId + ". Exiting.."; Trace(message); //Console.WriteLine("Press any key to exit.."); //Console.ReadKey(); return; } Trace(userId); MarketUtils.WaitUntilMarketOpen(); // Broker var broker = new IciciDirectBroker(userId, "AMIT1978", "08071986"); //var broker = new IciciDirectBroker(userId, "amit1978", "07111982"); broker.LogIn(); //// Separate Login thread in background //BrokingAccountThread loginThread = new BrokingAccountThread(); //Thread thread = new Thread(new ParameterizedThreadStart(LoginUtils.Background_LoginCheckerThread)); //BrokingAccountObject iciciAccObj = new BrokingAccountObject(broker); //loginThread.brokerAccountObj = iciciAccObj; //loginThread.thread = thread; //loginThread.thread.Name = "Main Login Thread of MUNISGcS"; //loginThread.thread.IsBackground = true; //loginThread.thread.Start(iciciAccObj); // ************ TESTING Code starts ****************** // //Trace("Testing starts"); //string ordertestref = ""; //double funds; //errCode = broker.GetFundsAvailable(out funds); //errCode = broker.AllocateFunds(FundAllocationCategory.IpoMf, funds); //errCode = broker.AllocateFunds(FundAllocationCategory.IpoMf, -4.67); //var str = string.Format("[Holding EOD] {0} {1}", OrderPositionTypeEnum.Btst, ""); //errCode = CancelEquityOrder(string.Format("[Holding EOD] {0} {1}", HoldingTypeEnum.Btst, ""), ref ordertestref, OrderDirection.SELL); //var newTrades = new Dictionary<string, EquityTradeBookRecord>(); //List<EquityDematHoldingRecord> holdings; //List<EquityBTSTTradeBookRecord> btstHoldings; //errCode = broker.GetBTSTListings("CAPFIR", out btstHoldings); //List<EquityPendingPositionForDelivery> pendingPositions; //errCode = broker.GetOpenPositionsPendingForDelivery("BAJFI", out pendingPositions); //errCode = broker.GetOpenPositionsPendingForDelivery("MOTSUM", out pendingPositions); //Dictionary<string, EquityOrderBookRecord> orders; //errCode = broker.GetEquityOrderBookToday(false, false, "MOTSUM", out orders); //errCode = broker.PlaceEquityMarginSquareOffOrder("BAJFI", 34, 34, "1733", OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.DELIVERY, "2017232", Exchange.NSE, out ordertestref); //errCode = broker.PlaceEquityMarginDeliveryFBSOrder("BAJFI", 5, "1733", OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.DELIVERY, Exchange.NSE, out ordertestref); //errCode = broker.GetDematAllocation("BAJFI", out holdings); //errCode = broker.GetDematAllocation("CAPFIR", out holdings); //errCode = broker.GetDematAllocation("CAPPOI", out holdings); //errCode = broker.ConvertToDeliveryFromMarginOpenPositions("BAJFI", 3, 1, "2017223", OrderDirection.BUY, Exchange.NSE); //errCode = broker.GetEquityTradeBookToday(true, "BAJFI", out newTrades); //errCode = broker.ConvertToDeliveryFromPendingForDelivery("CAPFIR", 4, 1, "2017217", Exchange.NSE); //errCode = broker.CancelEquityOrder("20171120N900017136", EquityOrderType.DELIVERY); //while (errCode != BrokerErrorCode.Success) //{ // errCode = broker.CancelAllOutstandingEquityOrders("BAJFI", out Dictionary<string, BrokerErrorCode> cancelledOrders); // errCode = broker.PlaceEquityDeliveryBTSTOrder("BAJFI", 1, "1831", OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.DELIVERY, Exchange.NSE, "2017221", out ordertestref); //} ////errCode = broker.PlaceEquityMarginDeliveryFBSOrder("BAJFI", 1, "1831", OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.DELIVERY, Exchange.NSE, out ordertestref); //Trace("Testing ends"); // ************ TESTING Code ends ****************** // // Ensure all funds are allocated double funds; errCode = BrokerErrorCode.Unknown; errCode = broker.GetFundsAvailable(out funds); funds -= 1000; funds = funds < 0 ? 0 : funds; if (funds > 0) { errCode = broker.AllocateFunds(FundAllocationCategory.Equity, funds); Trace(string.Format("Ensure free funds [{0}] are allocated to Equity: {1}", funds, errCode)); } // Read the config file List <TradeParams> stocksConfig = ReadTradingConfigFile(); var threads = new List <Thread>(stocksConfig.Count); foreach (var stockConfig in stocksConfig) { stockConfig.broker = broker; var t = new Thread(new AverageTheBuyThenSell(stockConfig).StockBuySell); threads.Add(t); } threads.ForEach(t => { t.Start(); Thread.Sleep(1000); }); threads.ForEach(t => t.Join()); // Send out the log in email and chat Trace("All stock threads completed. Emailing today's log file"); MessagingUtils.Init(); var log = GetLogContent(); MessagingUtils.SendAlertMessage("SimpleTrader log", log); Trace("Exiting.."); }
public MarketSearch Search( string query = "", int start = 0, int count = 10, bool searchInDescriptions = false, int appId = 0, EMarketSearchSortColumns sortColumn = EMarketSearchSortColumns.Name, ESort sort = ESort.Desc, IDictionary <string, string> custom = null) { var urlQuery = new Dictionary <string, string> { { "query", query }, { "start", start.ToString() }, { "count", count.ToString() }, { "search_descriptions", (searchInDescriptions ? 1 : 0).ToString() }, { "appid", appId.ToString() }, { "sort_column", MarketUtils.FirstCharacterToLower(sortColumn.ToString()) }, { "sort_dir", MarketUtils.FirstCharacterToLower(sort.ToString()) } }; if (custom != null && custom.Count > 0) { urlQuery = urlQuery.Concat(custom).ToDictionary(x => x.Key, x => x.Value); } var resp = this.steam.Request( Urls.Market + "/search/render/", Method.GET, Urls.Market, urlQuery, true, proxy: this.Proxy); var respDes = JsonConvert.DeserializeObject <JMarketSearch>(resp.Data.Content); if (!respDes.Success) { throw new SteamException("Failed Search"); } var marketSearch = new MarketSearch(); if (respDes.TotalCount <= 0) { return(marketSearch); } marketSearch.TotalCount = respDes.TotalCount; var html = respDes.ResultsHtml; var doc = new HtmlDocument(); doc.LoadHtml(html); var itemNodes = doc.DocumentNode.SelectNodes("//a[@class='market_listing_row_link']"); if (itemNodes == null || itemNodes.Count <= 0) { return(marketSearch); } var tempIndex = 0; foreach (var item in itemNodes) { tempIndex++; var nameNode = item.SelectSingleNode(".//span[@class='market_listing_item_name']"); if (nameNode == null) { throw new SteamException($"Cannot parse item name. Index [{tempIndex}]"); } var name = nameNode.InnerText; var gameNode = item.SelectSingleNode(".//span[@class='market_listing_game_name']"); if (gameNode == null) { throw new SteamException($"Cannot parse game name. Index [{tempIndex}]"); } var game = gameNode.InnerText; var imageUrlNode = item.SelectSingleNode(".//img[@class='market_listing_item_img']"); var imageUrl = imageUrlNode?.Attributes["srcset"]?.Value; var urlAttr = item.Attributes["href"]; if (urlAttr == null) { throw new SteamException($"Cannot find item url. Item [{name}], Index [{tempIndex}]"); } var url = urlAttr.Value; var quantityNode = item.SelectSingleNode(".//span[@class='market_listing_num_listings_qty']"); if (quantityNode == null) { throw new SteamException($"Cannot find quantity. Item [{name}], Index [{tempIndex}]"); } var quantityParse = int.TryParse( quantityNode.InnerText, NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var quantity); if (!quantityParse) { throw new SteamException($"Cannot parse quantity. Item [{name}], Index [{tempIndex}]"); } var minPriceNode = item.SelectSingleNode(".//span[@class='normal_price']"); if (minPriceNode == null) { throw new SteamException($"Cannot find item price. Item [{name}], Index [{tempIndex}]"); } var minPriceClean = minPriceNode.InnerText.Split(' ')[0]; var minPriceParse = double.TryParse( minPriceClean, NumberStyles.Currency, CultureInfo.GetCultureInfo("en-US"), out var minPrice); if (!minPriceParse) { throw new SteamException($"Cannot parse min. price. Item [{name}], Index [{tempIndex}]"); } marketSearch.Items.Add( new MarketSearchItem { ImageUrl = imageUrl, Name = name, Quantity = quantity, Game = game, Url = url, MinPrice = minPrice, HashName = MarketUtils.HashNameFromUrl(url), AppId = MarketUtils.AppIdFromUrl(url) }); } return(marketSearch); }
private MyListingsSalesItem ProcessSellListings(HtmlNode item, string currency) { var node = item.SelectSingleNode(".//span[@class='market_listing_price']"); var date = Regex.Match(item.InnerText, @"Listed: (.+)?\s").Groups[1].Value.Trim(); var priceString = node.InnerText.Replace("\r", string.Empty).Replace("\n", string.Empty) .Replace("\t", string.Empty).Replace(" ", string.Empty); if (priceString.Contains("Sold!")) { return(null); } var game = item.SelectSingleNode("//span[@class='market_listing_game_name']").InnerText; double price; try { var priceParse = priceString.Split('(')[0]; var currencySymbol = SteamCurrencies.Currencies[currency]; priceParse = priceParse.Replace(currencySymbol, string.Empty); var parseDouble = NumberUtils.TryParseDouble(priceParse, out price); if (parseDouble == false) { throw new SteamException($"Cannot parse order listing price - {priceString}"); } } catch (SteamException) { throw; } catch (Exception e) { throw new SteamException($"Cannot parse order listing price - {priceString} - {e.Message}"); } var saleIdMatch = Regex.Match(item.InnerHtml, "(?<=mylisting_)([0-9]*)(?=_name)"); if (!saleIdMatch.Success) { throw new SteamException("Cannot find sale listing ID"); } var saleIdParse = long.TryParse(saleIdMatch.Value, out var saleId); if (!saleIdParse) { throw new SteamException($"Cannot parse sale listing ID - {saleIdMatch.Value}"); } var imageUrl = item.SelectSingleNode($"//img[contains(@id, 'mylisting_{saleId}_image')]").Attributes["src"] .Value; imageUrl = Regex.Match(imageUrl, "image/(.*)/").Groups[1].Value; var urlNode = item.SelectSingleNode(".//a[@class='market_listing_item_name_link']"); if (urlNode == null) { throw new SteamException("Cannot find sale listing url"); } var url = urlNode.Attributes["href"].Value; var hashName = MarketUtils.HashNameFromUrl(url); var appId = MarketUtils.AppIdFromUrl(url); var nameNode = urlNode.InnerText; var result = new MyListingsSalesItem { AppId = appId, HashName = hashName, Name = nameNode, Date = date, SaleId = saleId, Price = price, Url = url, ImageUrl = imageUrl, Game = game }; return(result); }
private void GetPendingTransactionData( HtmlNode item, int tempIndex, MyListings myListings, ETransactionType type, string currency) { if (item == null) { return; } var node = item.SelectSingleNode(".//span[@class='market_listing_price']"); if (node == null) { throw new SteamException( $"Cannot parse order listing price and quantity node. Item index [{tempIndex}]"); } var date = Regex.Match(item.InnerText, @"Listed: (.+)?\s").Groups[1].Value.Trim(); var game = item.SelectSingleNode("//span[@class='market_listing_game_name']")?.InnerText; if (type == ETransactionType.Order) { var priceAndQuantityString = node.InnerText.Replace("\r", string.Empty).Replace("\n", string.Empty) .Replace("\t", string.Empty).Replace(" ", string.Empty); var priceAndQuantitySplit = priceAndQuantityString.Split('@'); double price; try { var priceParse = priceAndQuantitySplit[1].Replace(".", string.Empty); var currencySymbol = SteamCurrencies.Currencies[currency]; double.TryParse(priceParse.Replace(currencySymbol, string.Empty), out price); } catch (Exception) { throw new SteamException($"Cannot parse order listing price. Item index [{tempIndex}]"); } var quantityParse = int.TryParse(priceAndQuantitySplit[0], out var quantity); if (!quantityParse) { throw new SteamException($"Cannot parse order listing quantity. Item index [{tempIndex}]"); } var orderIdMatch = Regex.Match(item.InnerHtml, "(?<=mbuyorder_)([0-9]*)(?=_name)"); if (!orderIdMatch.Success) { throw new SteamException($"Cannot find order listing ID. Item index [{tempIndex}]"); } var orderIdParse = long.TryParse(orderIdMatch.Value, out var orderId); if (!orderIdParse) { throw new SteamException($"Cannot parse order listing ID. Item index [{tempIndex}]"); } var imageUrl = item.SelectSingleNode($"//img[contains(@id, 'mylisting_{orderId}_image')]") .Attributes["src"].Value; imageUrl = Regex.Match(imageUrl, "image/(.*)/").Groups[1].Value; var urlNode = item.SelectSingleNode(".//a[@class='market_listing_item_name_link']"); if (urlNode == null) { throw new SteamException($"Cannot find order listing url. Item index [{tempIndex}]"); } var url = urlNode.Attributes["href"].Value; var hashName = MarketUtils.HashNameFromUrl(url); var appId = MarketUtils.AppIdFromUrl(url); var nameNode = urlNode.InnerText; myListings.Orders.Add( new MyListingsOrdersItem { AppId = appId, HashName = hashName, Name = nameNode, Date = date, OrderId = orderId, Price = price, Quantity = quantity, Url = url, ImageUrl = imageUrl, Game = game }); } else { var priceString = node.InnerText.Replace("\r", string.Empty).Replace("\n", string.Empty) .Replace("\t", string.Empty).Replace(" ", string.Empty); double price; try { var priceParse = priceString.Split('(')[0]; var currencySymbol = SteamCurrencies.Currencies[currency]; double.TryParse(priceParse.Replace(currencySymbol, string.Empty), out price); } catch (Exception) { throw new SteamException($"Cannot parse order listing price. Item index [{tempIndex}]"); } var saleIdMatch = Regex.Match(item.InnerHtml, "(?<=mylisting_)([0-9]*)(?=_name)"); if (!saleIdMatch.Success) { throw new SteamException($"Cannot find sale listing ID. Item index [{tempIndex}]"); } var saleIdParse = long.TryParse(saleIdMatch.Value, out var saleId); if (!saleIdParse) { throw new SteamException($"Cannot parse sale listing ID. Item index [{tempIndex}]"); } var imageUrl = item.SelectSingleNode($"//img[contains(@id, 'mylisting_{saleId}_image')]") .Attributes["src"].Value.Replace("38fx38f", string.Empty).Replace( "https://steamcommunity-a.akamaihd.net/economy/image/", string.Empty); var urlNode = item.SelectSingleNode(".//a[@class='market_listing_item_name_link']"); if (urlNode == null) { throw new SteamException($"Cannot find sale listing url. Item index [{tempIndex}]"); } var url = urlNode.Attributes["href"].Value; var hashName = MarketUtils.HashNameFromUrl(url); var appId = MarketUtils.AppIdFromUrl(url); var nameNode = urlNode.InnerText; var result = new MyListingsSalesItem { AppId = appId, HashName = hashName, Name = nameNode, Date = date, SaleId = saleId, Price = price, Url = url, ImageUrl = imageUrl, Game = game }; var isConfirmation = item.InnerHtml.Contains("CancelMarketListingConfirmation"); if (isConfirmation == false) { myListings.Sales.Add(result); } else { myListings.ConfirmationSales.Add(result); } } }
// Try min profit squareoff first between 3 - 3.10 time. // From 3.10 to 3.15 time if squareoff of all positions is set to true and the ltp diff meets threshold for max loss pct, then do a market order squareoff public void TrySquareOffNearEOD(AlgoType algoType) { // if after 3 pm, then try to square off in at least no profit no loss if possible. either buy or sell is outstanding if (MarketUtils.IsTimeAfter3()) { var ordPriceType = OrderPriceType.LIMIT; var doUpdateOrders = false; // 3.10 - 3.15 pm time. market order type for forced square off given pct loss is within acceptable range // do it before 3.15, otherwise broker will try to squareoff on its own anytime between 3.15 - 3.30 if (MarketUtils.IsTimeAfter310() && !MarketUtils.IsTimeAfter315() && squareOffAllPositionsAtEOD && !isEODMinLossSquareOffMarketOrderUpdated) { var ltp = GetLTP(); ordPriceType = OrderPriceType.MARKET; var diff = Math.Abs((ltp - todayOutstandingPrice) / ltp); if (diff < pctMaxLossSquareOffPositions && todayOutstandingPrice > goodPrice) { Trace(string.Format("TrySquareOffNearEOD: max loss % {0} is within acceptable range of {1} and avg outstanding price {2} is greater than good price of {3}. Update squareoff at MARKET price type.", diff, pctMaxLossSquareOffPositions, todayOutstandingPrice, goodPrice)); doUpdateOrders = true; isEODMinLossSquareOffMarketOrderUpdated = true; } } // 3 - 3.10 pm time. try simple limit order with min profit price else if (!isEODMinProfitSquareOffLimitOrderUpdated) { Trace(string.Format("TrySquareOffNearEOD: Update squareoff LIMIT order with min profit % price or cancel outstanding orders")); ordPriceType = OrderPriceType.LIMIT; isEODMinProfitSquareOffLimitOrderUpdated = true; doUpdateOrders = true; } if (doUpdateOrders) { if (algoType == AlgoType.AverageTheBuyThenSell) { // just cancel the outstanding buy order if (!string.IsNullOrEmpty(todayOutstandingBuyOrderRef)) { // cancel existing buy order errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingBuyOrderRef, OrderDirection.BUY); } // bought qty needs square off. there is outstanding sell order, revise the price to try square off if (!string.IsNullOrEmpty(todayOutstandingSellOrderRef)) { // cancel existing sell order errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingSellOrderRef, OrderDirection.SELL); if (errCode == BrokerErrorCode.Success) { todayOutstandingSellOrderRef = ""; // place new sell order, update sell order ref Trace("Placing EOD squareoff updated order"); var sellPrice = GetSellPrice(todayOutstandingPrice, false, true); errCode = PlaceEquityOrder(stockCode, todayOutstandingQty, sellPrice.ToString(), ordPriceType, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, out todayOutstandingSellOrderRef); } } } else if (algoType == AlgoType.SimultaneousBuySell) { // if there is an outstanding order pair, just cancel both if (!string.IsNullOrEmpty(todayOutstandingBuyOrderRef) && !string.IsNullOrEmpty(todayOutstandingSellOrderRef)) { // cancel existing sell order errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingSellOrderRef, OrderDirection.SELL); // cancel existing buy order errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingBuyOrderRef, OrderDirection.BUY); } // bought qty needs square off. there is outstanding sell order, revise the price to try square off else if (string.IsNullOrEmpty(todayOutstandingBuyOrderRef) && !string.IsNullOrEmpty(todayOutstandingSellOrderRef)) { // cancel existing sell order errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingSellOrderRef, OrderDirection.SELL); if (errCode == BrokerErrorCode.Success) { todayOutstandingSellOrderRef = ""; // place new sell order, update sell order ref Trace("Placing EOD squareoff updated order"); var sellPrice = GetSellPrice(todayOutstandingPrice, false, true); errCode = PlaceEquityOrder(stockCode, ordQty, sellPrice.ToString(), ordPriceType, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, out todayOutstandingSellOrderRef); } } // sold qty needs square off. there is outstanding buy order, revise the price to try square off else if (string.IsNullOrEmpty(todayOutstandingSellOrderRef) && !string.IsNullOrEmpty(todayOutstandingBuyOrderRef)) { // cancel existing buy order errCode = CancelEquityOrder("(EOD squareoff) @ " + ordPriceType, ref todayOutstandingBuyOrderRef, OrderDirection.BUY); if (errCode == BrokerErrorCode.Success) { todayOutstandingBuyOrderRef = ""; // place new buy order, update buy order ref Trace("Placing EOD squareoff updated order"); var buyPrice = GetBuySquareOffPrice(todayOutstandingPrice); errCode = PlaceEquityOrder(stockCode, ordQty, buyPrice.ToString(), ordPriceType, OrderDirection.BUY, EquityOrderType.MARGIN, exchange, out todayOutstandingBuyOrderRef); } } } } } }
public BrokerErrorCode GetEquitySpread(string stockCode, out EquitySymbolSpread[] info) { BrokerErrorCode errorCode = BrokerErrorCode.Success; info = new EquitySymbolSpread[2]; string quoteData = null; int retryCount = 0; do { quoteData = HttpHelper.GetWebPageResponse( URL_ICICI_EQT_SPREAD + stockCode.ToUpper(), null, null, mCookieContainer); retryCount++; } while (quoteData == null && retryCount < 5); // web problems, slow connection, server down etc. if (string.IsNullOrEmpty(quoteData) || quoteData.IndexOf("entered is not valid") > -1) { return(BrokerErrorCode.NullResponse); } ParsedTable table = (ParsedTable)HtmlTableParser.ParseHtmlIntoTables(quoteData, true); // NSE price info info[0] = new EquitySymbolSpread(); info[0].Symbol = stockCode; info[0].Exchange = Exchange.NSE; string tempStr = ParsedTable.GetValue(table, new int[] { 0, 3, 0, 1 }); DateTime lastTradeTime = DateTime.Parse(tempStr); tempStr = ParsedTable.GetValue(table, new int[] { 0, 3, 1, 1 }); lastTradeTime += TimeSpan.Parse(tempStr); info[0].QuoteTime = lastTradeTime; info[0].TotalBidQty = MarketUtils.GetVolume(ParsedTable.GetValue(table, new int[] { 0, 5, 7, 1 })); info[0].TotalOfferQty = MarketUtils.GetVolume(ParsedTable.GetValue(table, new int[] { 0, 5, 8, 1 })); for (int i = 0; i < 5; i++) { info[0].BestBidQty[i] = MarketUtils.GetVolume(ParsedTable.GetValue(table, new int[] { 0, 5, i + 2, 0 })); info[0].BestBidPrice[i] = MarketUtils.GetPrice(ParsedTable.GetValue(table, new int[] { 0, 5, i + 2, 1 })); info[0].BestOfferQty[i] = MarketUtils.GetVolume(ParsedTable.GetValue(table, new int[] { 0, 5, i + 2, 2 })); info[0].BestOfferPrice[i] = MarketUtils.GetPrice(ParsedTable.GetValue(table, new int[] { 0, 5, i + 2, 3 })); } // BSE price info info[1] = new EquitySymbolSpread(); info[1].Symbol = stockCode; info[1].Exchange = Exchange.BSE; tempStr = ParsedTable.GetValue(table, new int[] { 0, 3, 0, 3 }); lastTradeTime = DateTime.Parse(tempStr); tempStr = ParsedTable.GetValue(table, new int[] { 0, 3, 1, 3 }); lastTradeTime += TimeSpan.Parse(tempStr); info[1].QuoteTime = lastTradeTime; info[1].TotalBidQty = MarketUtils.GetVolume(ParsedTable.GetValue(table, new int[] { 0, 5, 7, 3 })); info[1].TotalOfferQty = MarketUtils.GetVolume(ParsedTable.GetValue(table, new int[] { 0, 5, 8, 3 })); for (int i = 0; i < 5; i++) { info[1].BestBidQty[i] = MarketUtils.GetVolume(ParsedTable.GetValue(table, new int[] { 0, 5, i + 2, 4 })); info[1].BestBidPrice[i] = MarketUtils.GetPrice(ParsedTable.GetValue(table, new int[] { 0, 5, i + 2, 5 })); info[1].BestOfferQty[i] = MarketUtils.GetVolume(ParsedTable.GetValue(table, new int[] { 0, 5, i + 2, 6 })); info[1].BestOfferPrice[i] = MarketUtils.GetPrice(ParsedTable.GetValue(table, new int[] { 0, 5, i + 2, 7 })); } return(errorCode); }
private BrokerErrorCode CancelEquityOrder(string orderRef, bool refreshOrderBook) { // Login If needed BrokerErrorCode errorCode = CheckAndLogInIfNeeded(false); if (errorCode != BrokerErrorCode.Success) { return(errorCode); } if (refreshOrderBook) { // Make sure we have the latest order book data errorCode = RefreshEquityOrderBookToday(); if (errorCode != BrokerErrorCode.Success) { return(errorCode); } } EquityOrderBookRecord orderInfo; // Search for order in the Orders dictionary lock (lockObjectEquity) { if (mEquityOrderBook.ContainsKey(orderRef)) { orderInfo = mEquityOrderBook[orderRef]; } else { return(BrokerErrorCode.OrderDoesNotExist); } } if (orderInfo.Status != OrderStatus.ORDERED && orderInfo.Status != OrderStatus.PARTEXEC && orderInfo.Status != OrderStatus.REQUESTED) { if (orderInfo.Status == OrderStatus.QUEUED) { errorCode = BrokerErrorCode.OrderQueuedCannotCancel; } else if (orderInfo.Status == OrderStatus.EXECUTED) { errorCode = BrokerErrorCode.OrderExecutedCannotCancel; } else { errorCode = BrokerErrorCode.InValidOrderToCancel; } return(errorCode); } // Instead of getting it actually from order book // We simply assume current day only DateTime currentDate = MarketUtils.GetMarketCurrentDate(); string orderStatus = IciciConstants.OrderStatusString[(int)orderInfo.Status]; string zipCode = orderRef.Substring(8, 2); string postData = "Submit1=Yes&FML_PASS=1&NicValue=&m_pipeId=N9" + "&pgname=CanOrd&ismethodcall=0&mthname=" + "&m_status=" + orderStatus + "&m_nsestatus=C" + "&m_bsestatus=C" + "&FML_ORDR_REF=" + orderRef + // TODO: C for CASH , currently hardcoded. needs to be handled. // Get it in order book stock info somehow "&m_ProductType=C" + "&m_ordFlow=" + IciciConstants.OrderDirectionString[(int)orderInfo.Direction] + // order direction S/B "&m_exchCd=" + IciciConstants.ExchangeString[(int)orderInfo.Exchange] + // get exchange ""; string orderBookData = IciciGetWebPageResponse(URL_ICICI_EQT_CANCEL_ORDER, postData, URL_ICICI_REFERRER, mCookieContainer, out errorCode); if (errorCode.Equals(BrokerErrorCode.Success)) { string cancelConfirm = "Your order has been cancelled"; string cancelRequestSentToExchange = "Your request for order cancellation has been sent to the exchange"; // Either cancel confirm or cancellation request sent to exchange both are succes cases // Success if (orderBookData.Contains(cancelConfirm) || orderBookData.Contains(cancelRequestSentToExchange)) { // TODO: revist if any prob // Delete the orderRef from mEquityOrderBook // We ideally want it to remain in equity order book in cancelled state // but right now remove it rather than update // because let the GetEquityOrddrBook update it as per its protocol lock (lockObjectEquity) { mEquityOrderBook.Remove(orderRef); } return(BrokerErrorCode.Success); } } return(BrokerErrorCode.OrderCancelFailed); }
static void Main(string[] args) { BrokerErrorCode errCode = BrokerErrorCode.Unknown; var upstoxBroker = new MyUpstoxWrapper(apiKey, apiSecret, redirectUrl); #if DEBUG Trace("DEBUG MODE"); List <UpstoxTradeParams> stocksConfig1 = ReadTradingConfigFile(); errCode = upstoxBroker.Login1(); #else Trace("RELEASE MODE"); errCode = upstoxBroker.Login(); #endif // Check for Holiday today if (IsHolidayToday()) { Trace("Exchange Holiday today.. exiting."); return; } // Wait 2 seconds if contended – in case another instance // of the program is in the process of shutting down. if (!mutex.WaitOne(TimeSpan.FromSeconds(2), false)) { var message = "Another instance of the app is running. Only one instance for a userId is allowed! UserId: " + userId + ". Exiting.."; Trace(message); return; } Trace(userId); #if !DEBUG MarketUtils.WaitUntilMarketOpen(); #endif //Thread.Sleep(5000);// Let the rates etc update on server // Read the config file List <UpstoxTradeParams> stocksConfig = ReadTradingConfigFile(); var threads = new List <Thread>(stocksConfig.Count); var mktTrendConfig = new UpstoxMarketTrendParams(); var monthNow = DateTime.Now.Month + (DateTime.Now.Day > 20 ? 1 : 0); var yearNow = DateTime.Now.Year + (monthNow > 12 ? 1 : 0); if (monthNow > 12) { monthNow = 1; } var months = new[] { "DUMMY", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" }; var niftyFutCode = string.Format("NIFTY{0}{1}FUT", (yearNow - 2000), months[monthNow]); mktTrendConfig.stockCode = niftyFutCode; mktTrendConfig.exchangeStr = "NSE_FO"; mktTrendConfig.upstox = upstoxBroker; var mktTrend = new MarketTrend(mktTrendConfig); var mktThread = new Thread(mktTrend.StartCapturingMarketTrend); threads.Add(mktThread); foreach (var stockConfig in stocksConfig) { stockConfig.upstox = upstoxBroker; stockConfig.mktTrend = mktTrend; upstoxBroker.AddStock(stockConfig.stockCode); var t = new Thread(new UpstoxAverageTheBuyThenSell(stockConfig).StockBuySell); threads.Add(t); } threads.ForEach(t => { t.Start(); /*Thread.Sleep(200);*/ }); threads.ForEach(t => t.Join()); Trace("Update PnL files"); WritePnL(upstoxBroker, stocksConfig); // Send out the log in email and chat Trace("All stock threads completed. Emailing today's log file"); MessagingUtils.Init(); var log = GetLogContent(); MessagingUtils.SendAlertMessage("SimpleTrader log", log); Trace("Exiting.."); }
//////////////////////////////////// ////// EQUITY STOCK STATE ////// ////////////////////////////////// public static BrokerErrorCode EquityRefreshStockStateToday(IBroker broker, EquityStockTradeStats stockInfo) { DateTime EarliestValidMarketOpenDate = MarketUtils.GetMarketCurrentDate(); return(EquityRefreshStockState(broker, EarliestValidMarketOpenDate, EarliestValidMarketOpenDate, stockInfo)); }
public override void StockBuySell() { try { Init(AlgoType.AverageTheBuyThenSell); } catch (Exception ex) { Trace("Error:" + ex.Message + "\nStacktrace:" + ex.StackTrace); throw; } while (MarketUtils.IsMarketOpen()) { try { // Try to convert to delivery pending open positions (nearing expiry) from previous days ConvertToDeliveryPreviousDaysExpiringOpenPositions(); var holdingTradesRef = holdingsOrders.Select(h => h.OrderRef); { var newTrades = new Dictionary <string, EquityTradeBookRecord>(); // refresh trade book errCode = broker.GetEquityTradeBookToday(true, stockCode, out newTrades); foreach (var tradeKv in newTrades.OrderBy(t => t.Value.Direction).Reverse()) { var tradeRef = tradeKv.Key; var trade = tradeKv.Value; Trace(string.Format(tradeTraceFormat, stockCode, trade.Direction == OrderDirection.BUY ? "bought" : "sold", trade.NewQuantity, trade.Price, holdingTradesRef.Contains(tradeRef) ? "CASH" : "MARGIN")); // if any holding sell executed ProcessHoldingSellOrderExecution(newTrades); // if sell executed, then update today outstanding to 0 , because sell order always contains the total outstanding qty and now all of it got sold with this trade // but handle part executions using NewQuantity if (tradeRef == todayOutstandingSellOrderRef) { todayOutstandingQty -= trade.NewQuantity; if (todayOutstandingQty == 0) { todayOutstandingPrice = 0; todayOutstandingSellOrderRef = ""; } } // if buy executed, then place a corresponding updated sell order. assumption is that qty is completely executed. // part executed qty will get considered only for first part, for later ones there is no update because we wont get it in newTrades again if (tradeRef == todayOutstandingBuyOrderRef) { Dictionary <string, EquityOrderBookRecord> orders; errCode = broker.GetEquityOrderBookToday(false, false, stockCode, out orders); if (orders[todayOutstandingBuyOrderRef].Status == OrderStatus.EXECUTED) { Trace(string.Format("Fully executed newqty {0} todayoutstandingqty {1} todayoutstandingprice {2} sellorderref {3} buyorderef {4} buyorderstatus {5}", trade.NewQuantity, todayOutstandingQty, todayOutstandingPrice, todayOutstandingSellOrderRef, todayOutstandingBuyOrderRef, orders[todayOutstandingBuyOrderRef].Status)); todayOutstandingBuyOrderRef = ""; } else { Trace(string.Format("Partially executed newqty {0} todayoutstandingqty {1} todayoutstandingprice {2} sellorderref {3} buyorderef {4} buyorderstatus {5}", trade.NewQuantity, todayOutstandingQty, todayOutstandingPrice, todayOutstandingSellOrderRef, todayOutstandingBuyOrderRef, orders[todayOutstandingBuyOrderRef].Status)); } // update outstanding qty and outstanding price to place updated sell order todayOutstandingPrice = (todayOutstandingPrice * todayOutstandingQty) + (trade.NewQuantity * trade.Price); todayOutstandingQty += trade.NewQuantity; if (todayOutstandingQty == 0) { todayOutstandingPrice = 0; } else { todayOutstandingPrice /= todayOutstandingQty; } todayOutstandingPrice = Math.Round(todayOutstandingPrice, 2); if (todayOutstandingQty >= maxTodayOutstandingQtyAllowed) { Trace(string.Format("TodayOutstandingQty reached the max. todayOutstandingQty: {0} maxTodayOutstandingQtyAllowed: {1}", todayOutstandingQty, maxTodayOutstandingQtyAllowed)); } if ((todayOutstandingQty + holdingOutstandingQty) >= maxTotalOutstandingQtyAllowed) { Trace(string.Format("TotalOutstandingQty reached the max. todayOutstandingQty: {0} holdingOutstandingQty: {1} maxTotalOutstandingQtyAllowed: {2}", todayOutstandingQty, holdingOutstandingQty, maxTotalOutstandingQtyAllowed)); } settlementNumber = trade.SettlementNumber; lastBuyPrice = useAvgBuyPriceInsteadOfLastBuyPriceToCalculateBuyPriceForNewOrder ? todayOutstandingPrice : trade.Price; if (!string.IsNullOrEmpty(todayOutstandingSellOrderRef)) { // cancel existing sell order if it exists errCode = CancelEquityOrder("[Buy Executed]", ref todayOutstandingSellOrderRef, EquityOrderType.MARGIN, OrderDirection.SELL); } if (errCode == BrokerErrorCode.Success || string.IsNullOrEmpty(todayOutstandingSellOrderRef)) { // place new sell order if previous cancelled or it was first one, update sell order ref var sellPrice = GetSellPrice(todayOutstandingPrice, false, false); errCode = PlaceEquityOrder(stockCode, OrderPositionTypeEnum.Margin, todayOutstandingQty, todayOutstandingQty, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, "", out todayOutstandingSellOrderRef); } } } PlaceBuyOrderIfEligible(); } // Only relevant near EOD TrySquareOffNearEOD(AlgoType.AverageTheBuyThenSell); } catch (Exception ex) { Trace("Error:" + ex.Message + "\nStacktrace:" + ex.StackTrace); } if (MarketUtils.IsTimeAfter3XMin(28)) { CancelHoldingSellOrders(); ConvertToDeliveryAndUpdatePositionFile(); } PauseBetweenTradeBookCheck(); } // for safety call conversion once more if the conversion call in the above loop was missed due to Pause and loop's time check //CancelHoldingSellOrders(); ConvertToDeliveryAndUpdatePositionFile(true); // EOD final update }
public void TradeUpdated(object sender, TradeUpdateEventArgs args) { lock (lockRunEitherPlaceBuyOrTradeUpdated) { try { var trade = ConvertTradeUpdateArgsToTradeRecord(args); if (stockCode != trade.StockCode) { return; } var isSellExecutedFully = false; Trace(string.Format(tradeTraceFormat, stockCode, trade.Direction == OrderDirection.BUY ? "bought" : "sold", args.TradedQty, args.TradedPrice, holdingSellOrder.OrderId == trade.OrderId ? "DELIVERY" : "MARGIN", trade.OrderId, trade.TradeId, trade.DateTime, args.ExchTime, args.TimeStamp)); // if any holding sell executed if (trade.OrderId == holdingSellOrder.OrderId) { ProcessHoldingSellOrderExecution(trade.NewQuantity); } // if SELL executed, then update today outstanding with executed qty (handle part executions using NewQuantity) // If it is after 3.15 and broker did auto sq off, then broker's order ref is not with us and wont match with our sq off order. Our sqoff order will be cancelled by the broker if (trade.OrderId == outstandingSellOrder.OrderId || ((MarketUtils.IsTimeAfter315() && trade.EquityOrderType == EquityOrderType.MARGIN && trade.Direction == OrderDirection.SELL))) { if (!string.IsNullOrEmpty(outstandingSellOrder.OrderId) && trade.OrderId != outstandingSellOrder.OrderId) { // If broker initiated market squareoff then Cancel the known sell order to avoid extra execution errCode = CancelEquityOrder("[Broker SquareOff Executed]", ref outstandingSellOrder.OrderId, orderType, OrderDirection.SELL); } todayOutstandingQty -= trade.NewQuantity; if (todayOutstandingQty == 0) { todayOutstandingPrice = 0; outstandingSellOrder.OrderId = ""; todayOutstandingTradeCount = 0; isSellExecutedFully = true; } } // if BUY executed, then place a corresponding updated sell order. if (trade.OrderId == outstandingBuyOrder.OrderId) { currentBuyOrdExecutedQty += trade.NewQuantity; if (currentBuyOrdExecutedQty == currentBuyOrdQty) { Trace(string.Format("[Trade Execution] Fully executed NewQty={0} TotalQty={1}", trade.NewQuantity, currentBuyOrdQty)); outstandingBuyOrder.OrderId = ""; todayOutstandingTradeCount++; } else { Trace(string.Format("[Trade Execution] Partially executed NewQty={0} TotalQty={1}", trade.NewQuantity, currentBuyOrdQty)); } // update outstanding qty and outstanding price to place updated sell order todayOutstandingPrice = (todayOutstandingPrice * todayOutstandingQty) + (trade.NewQuantity * trade.Price); todayOutstandingQty += trade.NewQuantity; todayOutstandingPrice = todayOutstandingQty == 0 ? 0 : todayOutstandingPrice / todayOutstandingQty; UpdatePnLStats(); if (todayOutstandingQty >= maxTodayOutstandingQtyAllowed) { Trace(string.Format("[Trading Limits Hit] TodayOutstandingQty reached the max. todayOutstandingQty: {0} maxTodayPositionValueMultiple: {1}", todayOutstandingQty, maxTodayOutstandingQtyAllowed)); } if ((todayOutstandingQty + holdingOutstandingQty) >= maxTotalOutstandingQtyAllowed) { Trace(string.Format("[Trading Limits Hit] TotalOutstandingQty reached the max. todayOutstandingQty: {0} holdingOutstandingQty: {1} maxTotalPositionValueMultiple: {2}", todayOutstandingQty, holdingOutstandingQty, maxTotalOutstandingQtyAllowed)); } lastBuyPrice = trade.Price; var sellPrice = GetSellPrice(todayOutstandingPrice, false, false); if (!string.IsNullOrEmpty(outstandingSellOrder.OrderId)) { // modify existing sell order if it exists errCode = ModifyEquityOrder("NewBuy modify squareoff", stockCode, outstandingSellOrder.OrderId, OrderPriceType.LIMIT, todayOutstandingQty, sellPrice, out upstoxOrderStatus); // cancel existing sell order if it exists //errCode = CancelEquityOrder("[Buy Executed]", ref outstandingSellOrder.OrderId, orderType, OrderDirection.SELL); } if (string.IsNullOrEmpty(outstandingSellOrder.OrderId)) { // place new sell order if previous cancelled or it was first one, update sell order ref errCode = PlaceEquityOrder(exchStr, stockCode, OrderDirection.SELL, OrderPriceType.LIMIT, todayOutstandingQty, orderType, sellPrice, out outstandingSellOrder.OrderId, out upstoxOrderStatus); } } if (isSellExecutedFully) { // Cancel existing Buy order which might be an average seeking order, as the pricecalc might have changed if (!string.IsNullOrEmpty(outstandingBuyOrder.OrderId)) { // cancel existing buy order errCode = CancelEquityOrder("[Sell Executed Fully]", ref outstandingBuyOrder.OrderId, orderType, OrderDirection.BUY); } } } catch (Exception ex) { Trace("Error:" + ex.Message + "\nStacktrace:" + ex.StackTrace); } } }
public override void StockBuySell() { Init(AlgoType.SimultaneousBuySell); while (MarketUtils.IsMarketOpen()) { try { var newTrades = new Dictionary <string, EquityTradeBookRecord>(); // refresh trade book errCode = broker.GetEquityTradeBookToday(true, stockCode, out newTrades); if (newTrades.Count > 0) { var trade = newTrades.First().Value; Trace(string.Format(tradeTraceFormat, stockCode, trade.Direction == OrderDirection.BUY ? "bought" : "sold", trade.Quantity, trade.Price, newTrades.ContainsKey(holdingSellOrderRef) ? "CASH" : "MARGIN")); if (newTrades.ContainsKey(todayOutstandingBuyOrderRef)) { todayOutstandingQty += trade.Quantity; todayOutstandingPrice = trade.Price; todayOutstandingBuyOrderRef = ""; } else if (newTrades.ContainsKey(todayOutstandingSellOrderRef)) { todayOutstandingQty -= trade.Quantity; todayOutstandingPrice = trade.Price; todayOutstandingSellOrderRef = ""; } else if (newTrades.ContainsKey(holdingSellOrderRef)) { holdingOutstandingQty = 0; holdingOutstandingPrice = 0; holdingSellOrderRef = ""; UpdatePositionFile(holdingOutstandingQty, holdingOutstandingPrice, holdingSellOrderRef); } else { // upstox squared off the sell. verify it and cancel the buy order if (trade.Direction == OrderDirection.BUY) { CancelEquityOrder("Broker squared off the sell", todayOutstandingBuyOrderRef, trade.Direction); todayOutstandingQty += trade.Quantity; todayOutstandingPrice = trade.Price; todayOutstandingBuyOrderRef = ""; } } } // if order time is within range and today's buy order count is below max then only place pair if (IsOrderTimeWithinRange() && string.IsNullOrEmpty(todayOutstandingBuyOrderRef) && string.IsNullOrEmpty(todayOutstandingSellOrderRef) && buyOrderCount < maxBuyOrders && (todayOutstandingQty + holdingOutstandingQty) < maxAllowedOutstandingQty) { // no pair existing, place a pair order // place buy order, update buy order ref var buyPrice = GetBuyPrice(); errCode = PlaceEquityOrder(stockCode, ordQty, buyPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.BUY, EquityOrderType.MARGIN, Exchange.NSE, out todayOutstandingBuyOrderRef); // place new sell order, update sell order ref var sellPrice = GetSellPrice(buyPrice, false); errCode = PlaceEquityOrder(stockCode, ordQty, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.MARGIN, Exchange.NSE, out todayOutstandingSellOrderRef); } else if (MarketUtils.IsTimeAfter3() && (!string.IsNullOrEmpty(todayOutstandingBuyOrderRef) && !string.IsNullOrEmpty(todayOutstandingSellOrderRef))) { // if existing pair is unexecuted, then cancel the pair Trace("Cancelling the pair orders as no side is executed and its past 3 pm"); errCode = CancelEquityOrder("Unexecuted Pair cancellation", todayOutstandingBuyOrderRef, OrderDirection.BUY); if (errCode == BrokerErrorCode.Success) { todayOutstandingBuyOrderRef = ""; } errCode = CancelEquityOrder("Unexecuted Pair cancellation", todayOutstandingSellOrderRef, OrderDirection.SELL); if (errCode == BrokerErrorCode.Success) { todayOutstandingSellOrderRef = ""; } } TrySquareOffNearEOD(AlgoType.SimultaneousBuySell); } catch (Exception ex) { Trace("Error:" + ex.Message + "\nStacktrace:" + ex.StackTrace); } if (MarketUtils.IsTimeAfter325()) { ConvertToDeliveryAndUpdatePositionFile(); } PauseBetweenTradeBookCheck(); } ConvertToDeliveryAndUpdatePositionFile(); }
public Instrument(string symbol, InstrumentType type, DateTime expiry, int qty) : this(symbol, type, qty) { ExpiryDate = MarketUtils.GetExpiryExactDate(expiry); }
// Try min profit squareoff first between 3 - 3.10 time. // From 3.10 to 3.15 time if squareoff of all positions is set to true and the ltp diff meets threshold for max loss pct, then do a market order squareoff public void TrySquareOffNearEOD(AlgoType algoType) { // if after 3 pm, then try to square off in at least no profit no loss if possible. cancel the outstanding buys anyway if (MarketUtils.IsTimeAfter310()) { var ordPriceType = OrderPriceType.LIMIT; var doUpdateOrders = false; // 3.20 - 3.25 pm time. market order type for forced square off given pct loss is within acceptable range // do it before 3.15, otherwise broker will try to squareoff on its own anytime between 3.15 - 3.30 if (MarketUtils.IsTimeAfter320() && !MarketUtils.IsTimeAfter325() && squareOffAllPositionsAtEOD && !isEODMinLossSquareOffMarketOrderUpdated) { double ltp; var errCode = GetLTP(out ltp); if (errCode != BrokerErrorCode.Success) { return; } ordPriceType = OrderPriceType.MARKET; var diff = (ltp - todayOutstandingPrice) / ltp; Trace(string.Format("[Margin EOD]: diff {0} ltp {1} outstandingprice {2} pctMaxLossSquareOffPositions {3} goodPrice {4} ", diff, ltp, todayOutstandingPrice, pctMaxLossSquareOffPositions, goodPrice)); if ((Math.Abs(diff) < pctMaxLossSquareOffPositions || diff > 0) && todayOutstandingPrice > goodPrice) { Trace(string.Format("[Margin EOD]: max loss {0}% is less than {1}% and avg outstanding price {2} is greater than good price of {3}. LTP is {4}. Place squareoff @ MARKET.", diff, pctMaxLossSquareOffPositions, todayOutstandingPrice, goodPrice, ltp)); doUpdateOrders = true; isEODMinLossSquareOffMarketOrderUpdated = true; } } // 3.10 - 3.20 pm time. try simple limit order with min profit price. watch until 3.10 pm else if (!isEODMinProfitSquareOffLimitOrderUpdated) { Trace(string.Format("[Margin EOD]: MinProfit Squareoff and cancel outstanding buy orders")); ordPriceType = OrderPriceType.LIMIT; isEODMinProfitSquareOffLimitOrderUpdated = true; doUpdateOrders = true; } if (doUpdateOrders) { if (algoType == AlgoType.AverageTheBuyThenSell) { // just cancel the outstanding buy order if (!string.IsNullOrEmpty(todayOutstandingBuyOrderRef)) { // cancel existing buy order errCode = CancelEquityOrder("[Margin EOD]", ref todayOutstandingBuyOrderRef, EquityOrderType.MARGIN, OrderDirection.BUY); } // bought qty needs square off. there is outstanding sell order, revise the price to try square off if (!string.IsNullOrEmpty(todayOutstandingSellOrderRef)) { // cancel existing sell order errCode = CancelEquityOrder("[Margin EOD]", ref todayOutstandingSellOrderRef, EquityOrderType.MARGIN, OrderDirection.SELL); if (errCode == BrokerErrorCode.Success) { // place new sell order, update sell order ref var sellPrice = GetSellPrice(todayOutstandingPrice, false, true); errCode = PlaceEquityOrder(stockCode, OrderPositionTypeEnum.Margin, todayOutstandingQty, todayOutstandingQty, sellPrice.ToString(), ordPriceType, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, "", out todayOutstandingSellOrderRef); } } } } } }
// Stock trading lot(qty) for orders //private int mStockTradingLot; //protected int StockTradingLot //{ // get { lock (lockObjectProperties) { return mStockTradingLot; } } // set { lock (lockObjectProperties) { mStockTradingLot = value; } } //} public BrokerErrorCode RunCoreAlgo() { #region SimpleBuySellPairSquareAlgo bool bCancelPairOrder = false; string stockCode = stockInfo.StockCode; int stockExchange = stockInfo.MainExchange == Exchange.NSE ? 0 : 1; BrokerErrorCode errorCode = BrokerErrorCode.Unknown; int tryCnt = 0; while (errorCode != BrokerErrorCode.Success && tryCnt <= 5) { // refresh stock state (doesnt have price info) errorCode = EquityStockState.EquityRefreshStockStateToday(mBroker, stockInfo); if (errorCode == BrokerErrorCode.NotLoggedIn) { mBroker.LogOut(); errorCode = mBroker.CheckAndLogInIfNeeded(true); tryCnt++; } } string traceString = "RefreshEquityStockStateToday: " + errorCode.ToString(); FileTracing.TraceOut(traceString); if (errorCode.Equals(BrokerErrorCode.Success)) { // If no buy or sell order pending, i.e. the square-off pair orders have executed // then place a pair of fresh buy-sell orders if (!(stockInfo.IsAnyOutstandingBuyOrder() || stockInfo.IsAnyOutstandingSellOrder() )) { // Place buy-sell order pair // Get latest quote EquitySymbolQuote[] stockPrice; errorCode = mBroker.GetEquityQuote(stockCode, out stockPrice); if (!errorCode.Equals(BrokerErrorCode.Success)) { return(errorCode); } // Generate orders List <EquityOrderRecord> generatedOrders = new List <EquityOrderRecord>(); string BidPrice; string OfferPrice; // price decision // First orders, only if market not open and it is first order pair if ((stockInfo.NumTrades == 0) && !MarketUtils.IsMarketOpen()) { double closePrice = stockPrice[stockExchange].PreviousClosePriceDouble; if (algoParams.initBidPrice > 0) { BidPrice = algoParams.initBidPrice.ToString(); } else { decimal buy = (decimal)(closePrice - (2.0 / 100 * closePrice));//prevclose - 3% buy = decimal.Subtract(buy, 0.05M); buy = decimal.Round(buy, 1); BidPrice = buy.ToString(); } if (algoParams.initOfferPrice > 0) { OfferPrice = algoParams.initOfferPrice.ToString(); } else { decimal sell = (decimal)(closePrice + (2.0 / 100 * closePrice));//prevclose + 3% sell = decimal.Add(sell, 0.05M); sell = decimal.Round(sell, 1, MidpointRounding.AwayFromZero); OfferPrice = sell.ToString(); } } // Subsequent orders // TODO: May put time conditions or market volatility conditions here in else if else { double ltp = stockPrice[stockExchange].LastTradePriceDouble; decimal buy = (decimal)(ltp - ((double)(0.85 / 100) * ltp));//prevclose - 0.85% buy = decimal.Subtract(buy, 0.05M); buy = decimal.Round(buy, 1); BidPrice = buy.ToString(); decimal sell = (decimal)(ltp + ((double)(0.85 / 100) * ltp));//prevclose + 0.85% sell = decimal.Add(sell, 0.05M); sell = decimal.Round(sell, 1, MidpointRounding.AwayFromZero); OfferPrice = sell.ToString(); } // Buy generatedOrders.Add(new EquityOrderRecord(stockCode, algoParams.StockTradingLot, BidPrice, OrderPriceType.LIMIT, OrderDirection.BUY, stockInfo.MainExchange, EquityOrderType.DELIVERY, "0", "0")); if (!bGenerateASingleBuyOrderAtStart) { // Sell generatedOrders.Add(new EquityOrderRecord(stockCode, algoParams.StockTradingLot, OfferPrice, OrderPriceType.LIMIT, OrderDirection.SELL, stockInfo.MainExchange, EquityOrderType.DELIVERY, "0", "0")); } List <BrokerErrorCode> errorCodes = null; // Validate orders List <EquityOrderRecord> ordersToPlace = stockInfo.ReturnFilteredValidOrders(generatedOrders); // Place validated orders errorCodes = mBroker.PlaceMultipleEquityOrders(ordersToPlace, 5); traceString = "Stock: " + stockInfo.StockCode + " :PlaceMultipleEquityOrders: 2\n"; int o = 0; foreach (BrokerErrorCode errCodeEach in errorCodes) { EquityOrderRecord order = ordersToPlace[o++]; traceString = traceString + order.OrderDirection.ToString() + "-" + order.Quantity.ToString() + " at " + order.Price + ": " + errCodeEach.ToString() + "\n"; // Place Order failed if (!errCodeEach.Equals(BrokerErrorCode.Success)) { // Cancel both the orders bCancelPairOrder = true; } } FileTracing.TraceOut(traceString); // Even if any one of the orders failed to place, cancel the pair if (bCancelPairOrder) { errorCode = BrokerUtils.CancelStockOutstandingOrdersAndTrace(mBroker, stockCode); } } } return(errorCode); #endregion }
public override void StockBuySell() { Init(); // place buy order if eligible: if there is no pending buy order and if totaloutstanding qt is less than maxoutstanding if (string.IsNullOrEmpty(buyOrderRef) && todayOutstandingQty == 0 && (todayOutstandingQty + holdingOutstandingQty) < maxOutstandingQty) { // place buy order, update buy order ref var buyPrice = GetBuyPrice(); errCode = PlaceMarginOrder(stockCode, ordQty, buyPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.BUY, EquityOrderType.MARGIN, exchange, out buyOrderRef); } while (MarketUtils.IsMarketOpen()) { try { var newTrades = new Dictionary <string, EquityTradeBookRecord>(); // refresh trade book errCode = broker.GetEquityTradeBookToday(true, stockCode, out newTrades); if (newTrades.Count > 0) { var trade = newTrades.First().Value; Trace(string.Format(tradeTraceFormat, stockCode, trade.Direction == OrderDirection.BUY ? "bought" : "sold", trade.Quantity, trade.Price, newTrades.ContainsKey(holdingSellOrderRef) ? "CASH" : "MARGIN")); // if buy executed, then place a corresponding margin sell order if (newTrades.ContainsKey(buyOrderRef)) { // update outstanding qty and outstanding price to place updated sell order todayOutstandingQty = trade.Quantity; todayOutstandingPrice = trade.Price; settlementNumber = trade.SettlementNumber; // place new sell order, update sell order ref var sellPrice = GetSellPrice(todayOutstandingPrice, false); errCode = PlaceMarginOrder(stockCode, ordQty, sellPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.SELL, EquityOrderType.MARGIN, exchange, out sellOrderRef); } // if sell executed, then place a fresh buy order if (newTrades.ContainsKey(sellOrderRef)) { todayOutstandingQty = 0; todayOutstandingPrice = 0; if (string.IsNullOrEmpty(buyOrderRef)) { if (buyOrderCount >= maxBuyOrders) { break; } // place buy order, update buy order ref var buyPrice = GetBuyPrice(); errCode = PlaceMarginOrder(stockCode, ordQty, buyPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.BUY, EquityOrderType.MARGIN, exchange, out buyOrderRef); } } // if holding sell executed if (newTrades.ContainsKey(holdingSellOrderRef)) { holdingOutstandingQty = 0; holdingOutstandingPrice = 0; holdingSellOrderRef = ""; var positionStr = string.Format("{0} {1} {2}", todayOutstandingQty, todayOutstandingPrice, holdingSellOrderRef); File.WriteAllText(positionFile, positionStr); if (string.IsNullOrEmpty(buyOrderRef) && todayOutstandingQty == 0) { if (buyOrderCount >= maxBuyOrders) { break; } // place buy order if eligible: if there is no pending buy order and if totaloutstanding qt is less than maxoutstanding if ((todayOutstandingQty + holdingOutstandingQty) < maxOutstandingQty) { // place buy order, update buy order ref var buyPrice = GetBuyPrice(); errCode = PlaceMarginOrder(stockCode, ordQty, buyPrice.ToString(), OrderPriceType.LIMIT, OrderDirection.BUY, EquityOrderType.MARGIN, exchange, out buyOrderRef); } } } } TrySquareOffNearEOD(); } catch (Exception ex) { Trace("Error:" + ex.Message + "\nStacktrace:" + ex.StackTrace); } Thread.Sleep(1000 * 90); } // convert to delivery any open buy position ConvertToDeliveryAndUpdatePositionFile(); }
public BrokerErrorCode Prolog() { BrokerErrorCode errorCode = BrokerErrorCode.Success; string traceString = "Algo1_SimplePairedBuySellDelivery.Prolog :: ENTER"; FileTracing.TraceOut(traceString); if (algoParams.bCancelOutstandingOrdersAtStart) { errorCode = BrokerUtils.CancelStockOutstandingOrdersAndTrace(mBroker, stockCode); } if (!algoParams.bStartAFresh) { // Start from last run state and try to be in pair-execute state // There may be less than or equal to 1 lot of stock as long or short // Pick up the last trade from xml // TODO: } // Get latest quote EquitySymbolQuote[] stockPrice; errorCode = mBroker.GetEquityQuote(stockCode, out stockPrice); if (!errorCode.Equals(BrokerErrorCode.Success)) { return(errorCode); } int stockExchange = stockInfo.MainExchange == Exchange.NSE ? 0 : 1; double buyOrderValue = (stockPrice[stockExchange].LastTradePriceDouble * algoParams.StockTradingLot); buyOrderValue += stockInfo.EstimatedBrokerage(buyOrderValue); // Erroneous conditions get out, do later // TODO: right now assume stock abvailable is at least = stock trading lot // and assume limit is available //if(stockInfo.StockAvailableAtStart < // TODO: find better alternative to fit this variable if ((stockInfo.StockAvailableAtStart < algoParams.StockTradingLot) && (stockInfo.FundLimitAtStart >= 2 * buyOrderValue)) { // This means first buy the stock, then start trading it bGenerateASingleBuyOrderAtStart = true; } else if (stockInfo.StockAvailableAtStart < algoParams.StockTradingLot) { errorCode = BrokerErrorCode.InValidArg; } if (!bGenerateASingleBuyOrderAtStart && errorCode.Equals(BrokerErrorCode.Success)) { // There should be suficient stock to place a sell order to generate limit first // and then for the pair-orders // stockavailable should be at least twice the trading lot if ((stockInfo.FundLimitAtStart < buyOrderValue) && (stockInfo.StockAvailableAtStart >= 2 * algoParams.StockTradingLot)) { // Generate a sell order bGenerateASingleSellOrderAtStart = true; } else if (stockInfo.FundLimitAtStart < buyOrderValue) { errorCode = BrokerErrorCode.InValidArg; } } string price = "1"; bool bGenerateOrder = false; OrderDirection orderDirection = OrderDirection.BUY; // BUY order if (bGenerateASingleBuyOrderAtStart) { // price decision if (algoParams.initBidPrice > 0) { price = algoParams.initBidPrice.ToString(); } // First orders, only if market not open and it is first order pair else if (!MarketUtils.IsMarketOpen()) { double closePrice = stockPrice[stockExchange].PreviousClosePriceDouble; decimal buy = (decimal)(closePrice - ((double)(3.0 / 100) * closePrice));//prevclose - 3% buy = decimal.Subtract(buy, 0.05M); buy = decimal.Round(buy, 1); price = buy.ToString(); } // Subsequent orders // TODO: May put time conditions or market volatility conditions here in else if else { double ltp = stockPrice[stockExchange].LastTradePriceDouble; decimal buy = (decimal)(ltp - ((double)(0.65 / 100) * ltp));//prevclose - 0.65% buy = decimal.Subtract(buy, 0.05M); buy = decimal.Round(buy, 1); price = buy.ToString(); } orderDirection = OrderDirection.BUY; bGenerateASingleBuyOrderAtStart = false; bGenerateOrder = true; } // SELL order if (bGenerateASingleSellOrderAtStart) { // price decision if (algoParams.initOfferPrice > 0) { price = algoParams.initOfferPrice.ToString(); } // First orders, only if market not open and it is first order pair if (!MarketUtils.IsMarketOpen()) { double closePrice = stockPrice[stockExchange].PreviousClosePriceDouble; decimal sell = (decimal)(closePrice + (3.0 / 100 * closePrice));//prevclose + 3% sell = decimal.Add(sell, 0.05M); sell = decimal.Round(sell, 1, MidpointRounding.AwayFromZero); price = sell.ToString(); } // Subsequent orders // TODO: May put time conditions or market volatility conditions here in else if else { double ltp = stockPrice[stockExchange].LastTradePriceDouble; decimal sell = (decimal)(ltp + (0.65 / 100 * ltp));//prevclose + 0.65% sell = decimal.Add(sell, 0.05M); sell = decimal.Round(sell, 1, MidpointRounding.AwayFromZero); price = sell.ToString(); } orderDirection = OrderDirection.SELL; bGenerateASingleSellOrderAtStart = false; bGenerateOrder = true; } if (bGenerateOrder) { // Generate orders List <EquityOrderRecord> generatedOrders = new List <EquityOrderRecord> { new EquityOrderRecord(stockCode, algoParams.StockTradingLot, price, OrderPriceType.LIMIT, orderDirection, stockInfo.MainExchange, EquityOrderType.DELIVERY, "0", "0") }; List <BrokerErrorCode> errorCodes = null; // Validate orders List <EquityOrderRecord> ordersToPlace = stockInfo.ReturnFilteredValidOrders(generatedOrders); // Place validated orders errorCodes = mBroker.PlaceMultipleEquityOrders(ordersToPlace, 5); traceString = "Algo1_SimplePairedBuySellDelivery.Prolog\n" + "Stock: " + stockInfo.StockCode + " :PlaceMultipleEquityOrders: 1\n"; int o = 0; foreach (BrokerErrorCode errCodeEach in errorCodes) { EquityOrderRecord order = ordersToPlace[o++]; traceString = traceString + order.OrderDirection.ToString() + "-" + order.Quantity.ToString() + " at " + order.Price + ": " + errCodeEach.ToString() + "\n"; errorCode = errCodeEach; } FileTracing.TraceOut(traceString); } traceString = "Algo1_SimplePairedBuySellDelivery.Prolog :: EXIT"; FileTracing.TraceOut(traceString); return(errorCode); }