From 6d422b2f4a7eab298b0295ea14a5b93172ae2435 Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Fri, 9 Jan 2026 14:38:16 +0530 Subject: [PATCH 1/9] using class instead of struct --- KiteConnect/Structures.cs | 90 +++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/KiteConnect/Structures.cs b/KiteConnect/Structures.cs index 33a84e1..5b9035e 100644 --- a/KiteConnect/Structures.cs +++ b/KiteConnect/Structures.cs @@ -9,7 +9,7 @@ namespace KiteConnect /// /// Tick data structure /// - public struct Tick + public class Tick { public string Mode { get; set; } public UInt32 InstrumentToken { get; set; } @@ -40,7 +40,7 @@ public struct Tick /// /// Market depth item structure /// - public struct DepthItem + public class DepthItem { public DepthItem(Dictionary data) { @@ -57,7 +57,7 @@ public DepthItem(Dictionary data) /// /// Historical structure /// - public struct Historical + public class Historical { public Historical(ArrayList data) { @@ -82,7 +82,7 @@ public Historical(ArrayList data) /// /// Holding structure /// - public struct Holding + public class Holding { public Holding(Dictionary data) { @@ -140,7 +140,7 @@ public Holding(Dictionary data) /// /// MTF Holding structure /// - public struct MTFHolding + public class MTFHolding { public MTFHolding(Dictionary data) { @@ -168,7 +168,7 @@ public MTFHolding(Dictionary data) /// /// AuctionInstrument structure /// - public struct AuctionInstrument + public class AuctionInstrument { public AuctionInstrument(Dictionary data) { @@ -230,7 +230,7 @@ public AuctionInstrument(Dictionary data) /// /// Available margin structure /// - public struct AvailableMargin + public class AvailableMargin { public AvailableMargin(Dictionary data) { @@ -256,7 +256,7 @@ public AvailableMargin(Dictionary data) /// /// Utilised margin structure /// - public struct UtilisedMargin + public class UtilisedMargin { public UtilisedMargin(Dictionary data) { @@ -293,7 +293,7 @@ public UtilisedMargin(Dictionary data) /// /// UserMargin structure /// - public struct UserMargin + public class UserMargin { public UserMargin(Dictionary data) { @@ -319,7 +319,7 @@ public UserMargin(Dictionary data) /// /// User margins response structure /// - public struct UserMarginsResponse + public class UserMarginsResponse { public UserMarginsResponse(Dictionary data) { @@ -340,7 +340,7 @@ public UserMarginsResponse(Dictionary data) /// /// OrderMarginParams structure /// - public struct OrderMarginParams + public class OrderMarginParams { /// /// Exchange in which instrument is listed (Constants.Exchange.NSE, Constants.Exchange.BSE, etc.) @@ -391,7 +391,7 @@ public struct OrderMarginParams /// /// OrderMargin structure /// - public struct OrderMargin + public class OrderMargin { public OrderMargin(Dictionary data) { @@ -439,7 +439,7 @@ public OrderMargin(Dictionary data) /// /// ContractNoteParams structure /// - public struct ContractNoteParams + public class ContractNoteParams { /// /// Order ID that is received in the orderbook @@ -490,7 +490,7 @@ public struct ContractNoteParams /// /// ContractNote structure /// - public struct ContractNote + public class ContractNote { public ContractNote(Dictionary data) { @@ -511,7 +511,7 @@ public ContractNote(Dictionary data) throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); } } - + /// /// Exchange in which instrument is listed (Constants.Exchange.NSE, Constants.Exchange.BSE, etc.) /// @@ -561,7 +561,7 @@ public ContractNote(Dictionary data) /// /// OrderCharges structure /// - public struct OrderCharges + public class OrderCharges { public OrderCharges(Dictionary data) { @@ -595,7 +595,7 @@ public OrderCharges(Dictionary data) /// /// OrderChargesGST structure /// - public struct OrderChargesGST + public class OrderChargesGST { public OrderChargesGST(Dictionary data) { @@ -621,7 +621,7 @@ public OrderChargesGST(Dictionary data) /// /// BasketMargin structure /// - public struct BasketMargin + public class BasketMargin { public BasketMargin(Dictionary data) { @@ -650,7 +650,7 @@ public BasketMargin(Dictionary data) /// /// OrderMarginPNL structure /// - public struct OrderMarginPNL + public class OrderMarginPNL { public OrderMarginPNL(Dictionary data) { @@ -672,7 +672,7 @@ public OrderMarginPNL(Dictionary data) /// /// Position structure /// - public struct Position + public class Position { public Position(Dictionary data) { @@ -749,7 +749,7 @@ public Position(Dictionary data) /// /// Position response structure /// - public struct PositionResponse + public class PositionResponse { public PositionResponse(Dictionary data) { @@ -769,7 +769,7 @@ public PositionResponse(Dictionary data) /// /// Order structure /// - public struct Order + public class Order { public Order(Dictionary data) { @@ -864,7 +864,7 @@ public Order(Dictionary data) /// /// GTTOrder structure /// - public struct GTT + public class GTT { public GTT(Dictionary data) { @@ -904,7 +904,7 @@ public GTT(Dictionary data) /// /// GTTMeta structure /// - public struct GTTMeta + public class GTTMeta { public GTTMeta(Dictionary data) { @@ -924,7 +924,7 @@ public GTTMeta(Dictionary data) /// /// GTTCondition structure /// - public struct GTTCondition + public class GTTCondition { public GTTCondition(Dictionary data) { @@ -956,7 +956,7 @@ public GTTCondition(Dictionary data) /// /// GTTOrder structure /// - public struct GTTOrder + public class GTTOrder { public GTTOrder(Dictionary data) { @@ -967,7 +967,7 @@ public GTTOrder(Dictionary data) OrderType = data["order_type"]; Quantity = Convert.ToInt32(data["quantity"]); Price = data["price"]; - Result = data["result"] == null ? null : new Nullable(new GTTResult(data["result"])); + Result = data["result"] == null ? null : new GTTResult(data["result"]); } catch (Exception e) { @@ -986,13 +986,13 @@ public GTTOrder(Dictionary data) /// /// GTTResult structure /// - public struct GTTResult + public class GTTResult { public GTTResult(Dictionary data) { try { - OrderResult = data["order_result"] == null ? null : new Nullable(new GTTOrderResult(data["order_result"])); + OrderResult = data["order_result"] == null ? null : new GTTOrderResult(data["order_result"]); Timestamp = data["timestamp"]; TriggeredAtPrice = data["triggered_at"]; } @@ -1010,7 +1010,7 @@ public GTTResult(Dictionary data) /// /// GTTOrderResult structure /// - public struct GTTOrderResult + public class GTTOrderResult { public GTTOrderResult(Dictionary data) { @@ -1032,7 +1032,7 @@ public GTTOrderResult(Dictionary data) /// /// GTTParams structure /// - public struct GTTParams + public class GTTParams { public string TradingSymbol { get; set; } public string Exchange { get; set; } @@ -1046,7 +1046,7 @@ public struct GTTParams /// /// GTTOrderParams structure /// - public struct GTTOrderParams + public class GTTOrderParams { public decimal Quantity { get; set; } public decimal Price { get; set; } @@ -1061,7 +1061,7 @@ public struct GTTOrderParams /// /// Instrument structure /// - public struct Instrument + public class Instrument { public Instrument(Dictionary data) { @@ -1105,7 +1105,7 @@ public Instrument(Dictionary data) /// /// Trade structure /// - public struct Trade + public class Trade { public Trade(Dictionary data) { @@ -1148,7 +1148,7 @@ public Trade(Dictionary data) /// /// Trigger range structure /// - public struct TrigerRange + public class TrigerRange { public TrigerRange(Dictionary data) { @@ -1174,7 +1174,7 @@ public TrigerRange(Dictionary data) /// /// User structure /// - public struct User + public class User { public User(Dictionary data) { @@ -1220,7 +1220,7 @@ public User(Dictionary data) public string Email { get; } } - public struct TokenSet + public class TokenSet { public TokenSet(Dictionary data) { @@ -1243,7 +1243,7 @@ public TokenSet(Dictionary data) /// /// User structure /// - public struct Profile + public class Profile { public Profile(Dictionary data) { @@ -1281,7 +1281,7 @@ public Profile(Dictionary data) /// /// Quote structure /// - public struct Quote + public class Quote { public Quote(Dictionary data) { @@ -1391,7 +1391,7 @@ public Quote(Dictionary data) /// /// OHLC Quote structure /// - public struct OHLC + public class OHLC { public OHLC(Dictionary data) { @@ -1422,7 +1422,7 @@ public OHLC(Dictionary data) /// /// LTP Quote structure /// - public struct LTP + public class LTP { public LTP(Dictionary data) { @@ -1444,7 +1444,7 @@ public LTP(Dictionary data) /// /// Mutual funds holdings structure /// - public struct MFHolding + public class MFHolding { public MFHolding(Dictionary data) { @@ -1477,7 +1477,7 @@ public MFHolding(Dictionary data) /// /// Mutual funds instrument structure /// - public struct MFInstrument + public class MFInstrument { public MFInstrument(Dictionary data) { @@ -1534,7 +1534,7 @@ public MFInstrument(Dictionary data) /// /// Mutual funds order structure /// - public struct MFOrder + public class MFOrder { public MFOrder(Dictionary data) { @@ -1591,7 +1591,7 @@ public MFOrder(Dictionary data) /// /// Mutual funds SIP structure /// - public struct MFSIP + public class MFSIP { public MFSIP(Dictionary data) { From ac388555be2f955c6e1b393c62266566f9413d92 Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Fri, 9 Jan 2026 14:39:03 +0530 Subject: [PATCH 2/9] using string, uint and ulong instead of String, UInt32 and UInt64 --- KiteConnect/Kite.cs | 26 +++++++------- KiteConnect/Structures.cs | 66 ++++++++++++++++++------------------ KiteConnect/Ticker.cs | 38 ++++++++++----------- KiteConnect/Utils.cs | 14 ++++---- KiteConnectSample/Program.cs | 4 +-- 5 files changed, 74 insertions(+), 74 deletions(-) diff --git a/KiteConnect/Kite.cs b/KiteConnect/Kite.cs index aa9b648..09e0d22 100644 --- a/KiteConnect/Kite.cs +++ b/KiteConnect/Kite.cs @@ -46,7 +46,7 @@ public Kite(string APIKey, string AccessToken = null, string Root = null, bool D { _accessToken = AccessToken; _apiKey = APIKey; - if (!String.IsNullOrEmpty(Root)) this._root = Root; + if (!string.IsNullOrEmpty(Root)) this._root = Root; _enableLogging = Debug; _timeout = Timeout; @@ -105,7 +105,7 @@ public void SetAccessToken(string AccessToken) /// Login url to authenticate the user. public string GetLoginURL() { - return String.Format("{0}?api_key={1}&v=3", _login, _apiKey); + return string.Format("{0}?api_key={1}&v=3", _login, _apiKey); } /// @@ -435,7 +435,7 @@ public Dictionary ModifyOrder( string ProductString = Product; if ((ProductString == "bo" || ProductString == "co") && VarietyString != ProductString) - throw new Exception(String.Format("Invalid variety. It should be: {0}", ProductString)); + throw new Exception(string.Format("Invalid variety. It should be: {0}", ProductString)); Utils.AddIfNotNull(param, "order_id", OrderId); Utils.AddIfNotNull(param, "parent_order_id", ParentOrderId); @@ -528,7 +528,7 @@ public List GetOrderHistory(string OrderId) public List GetOrderTrades(string OrderId = null) { Dictionary tradesdata; - if (!String.IsNullOrEmpty(OrderId)) + if (!string.IsNullOrEmpty(OrderId)) { var param = new Dictionary(); param.Add("order_id", OrderId); @@ -633,7 +633,7 @@ public List GetInstruments(string Exchange = null) List> instrumentsData; - if (String.IsNullOrEmpty(Exchange)) + if (string.IsNullOrEmpty(Exchange)) instrumentsData = Get(Routes.Market.AllInstruments, param); else { @@ -932,7 +932,7 @@ public List GetMFOrders() /// /// The Mutual funds order. /// Order id. - public MFOrder GetMFOrders(String OrderId) + public MFOrder GetMFOrders(string OrderId) { var param = new Dictionary(); param.Add("order_id", OrderId); @@ -975,7 +975,7 @@ public Dictionary PlaceMFOrder( /// /// JSON response as nested string dictionary. /// Unique order id. - public Dictionary CancelMFOrder(String OrderId) + public Dictionary CancelMFOrder(string OrderId) { var param = new Dictionary(); @@ -1008,7 +1008,7 @@ public List GetMFSIPs() /// /// The Mutual funds SIP. /// SIP id. - public MFSIP GetMFSIPs(String SIPID) + public MFSIP GetMFSIPs(string SIPID) { var param = new Dictionary(); param.Add("sip_id", SIPID); @@ -1086,7 +1086,7 @@ public Dictionary ModifyMFSIP( /// /// JSON response as nested string dictionary. /// SIP id. - public Dictionary CancelMFSIP(String SIPId) + public Dictionary CancelMFSIP(string SIPId) { var param = new Dictionary(); @@ -1181,7 +1181,7 @@ private void AddExtraHeaders(ref HttpRequestMessage Req) { foreach (var header in Req.Headers) { - Console.WriteLine("DEBUG: " + header.Key + ": " + String.Join(",", header.Value.ToArray())); + Console.WriteLine("DEBUG: " + header.Key + ": " + string.Join(",", header.Value.ToArray())); } } } @@ -1222,14 +1222,14 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict string url = route; if (QueryParams.Count > 0) { - url += "?" + String.Join("&", QueryParams.Select(x => Utils.BuildParam(x.Key, x.Value))); + url += "?" + string.Join("&", QueryParams.Select(x => Utils.BuildParam(x.Key, x.Value))); } string requestBody = ""; if (json) requestBody = Utils.JsonSerialize(Params); else - requestBody = String.Join("&", (Params as Dictionary).Select(x => Utils.BuildParam(x.Key, x.Value))); + requestBody = string.Join("&", (Params as Dictionary).Select(x => Utils.BuildParam(x.Key, x.Value))); request.RequestUri = new Uri(url); request.Method = new HttpMethod(Method); @@ -1255,7 +1255,7 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict // build final url if (allParams.Count > 0) { - url += "?" + String.Join("&", allParams.Select(x => Utils.BuildParam(x.Key, x.Value))); + url += "?" + string.Join("&", allParams.Select(x => Utils.BuildParam(x.Key, x.Value))); } request.RequestUri = new Uri(url); diff --git a/KiteConnect/Structures.cs b/KiteConnect/Structures.cs index 5b9035e..d0a2b87 100644 --- a/KiteConnect/Structures.cs +++ b/KiteConnect/Structures.cs @@ -12,14 +12,14 @@ namespace KiteConnect public class Tick { public string Mode { get; set; } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public bool Tradable { get; set; } public decimal LastPrice { get; set; } - public UInt32 LastQuantity { get; set; } + public uint LastQuantity { get; set; } public decimal AveragePrice { get; set; } - public UInt32 Volume { get; set; } - public UInt32 BuyQuantity { get; set; } - public UInt32 SellQuantity { get; set; } + public uint Volume { get; set; } + public uint BuyQuantity { get; set; } + public uint SellQuantity { get; set; } public decimal Open { get; set; } public decimal High { get; set; } public decimal Low { get; set; } @@ -31,9 +31,9 @@ public class Tick // KiteConnect 3 Fields public DateTime? LastTradeTime { get; set; } - public UInt32 OI { get; set; } - public UInt32 OIDayHigh { get; set; } - public UInt32 OIDayLow { get; set; } + public uint OI { get; set; } + public uint OIDayHigh { get; set; } + public uint OIDayLow { get; set; } public DateTime? Timestamp { get; set; } } @@ -49,9 +49,9 @@ public DepthItem(Dictionary data) Orders = Convert.ToUInt32(data["orders"]); } - public UInt32 Quantity { get; set; } + public uint Quantity { get; set; } public decimal Price { get; set; } - public UInt32 Orders { get; set; } + public uint Orders { get; set; } } /// @@ -75,8 +75,8 @@ public Historical(ArrayList data) public decimal High { get; } public decimal Low { get; } public decimal Close { get; } - public UInt64 Volume { get; } - public UInt64 OI { get; } + public ulong Volume { get; } + public ulong OI { get; } } /// @@ -126,7 +126,7 @@ public Holding(Dictionary data) public string TradingSymbol { get; set; } public string CollateralType { get; set; } public decimal T1Quantity { get; set; } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public string ISIN { get; set; } public decimal RealisedQuantity { get; set; } public decimal Quantity { get; set; } @@ -205,7 +205,7 @@ public AuctionInstrument(Dictionary data) public string TradingSymbol { get; set; } public string Exchange { get; set; } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public string ISIN { get; set; } public string Product { get; set; } public decimal Price { get; set; } @@ -735,7 +735,7 @@ public Position(Dictionary data) public decimal BuyPrice { get; } public decimal SellPrice { get; } public decimal M2M { get; } - public UInt32 InstrumentToken { get; } + public uint InstrumentToken { get; } public decimal ClosePrice { get; } public decimal Quantity { get; } public decimal DayBuyQuantity { get; } @@ -837,7 +837,7 @@ public Order(Dictionary data) public string ExchangeOrderId { get; set; } public DateTime? ExchangeTimestamp { get; set; } public decimal FilledQuantity { get; set; } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public string OrderId { get; set; } public DateTime? OrderTimestamp { get; set; } public string OrderType { get; set; } @@ -946,7 +946,7 @@ public GTTCondition(Dictionary data) } } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public string Exchange { get; set; } public string TradingSymbol { get; set; } public List TriggerValues { get; set; } @@ -1036,7 +1036,7 @@ public class GTTParams { public string TradingSymbol { get; set; } public string Exchange { get; set; } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public string TriggerType { get; set; } public decimal LastPrice { get; set; } public List Orders { get; set; } @@ -1088,8 +1088,8 @@ public Instrument(Dictionary data) } - public UInt32 InstrumentToken { get; set; } - public UInt32 ExchangeToken { get; set; } + public uint InstrumentToken { get; set; } + public uint ExchangeToken { get; set; } public string TradingSymbol { get; set; } public string Name { get; set; } public decimal LastPrice { get; set; } @@ -1099,7 +1099,7 @@ public Instrument(Dictionary data) public string Segment { get; set; } public string Exchange { get; set; } public decimal Strike { get; set; } - public UInt32 LotSize { get; set; } + public uint LotSize { get; set; } } /// @@ -1136,7 +1136,7 @@ public Trade(Dictionary data) public string ExchangeOrderId { get; } public string Tradingsymbol { get; } public string Exchange { get; } - public UInt32 InstrumentToken { get; } + public uint InstrumentToken { get; } public string TransactionType { get; } public string Product { get; } public decimal AveragePrice { get; } @@ -1165,7 +1165,7 @@ public TrigerRange(Dictionary data) } } - public UInt32 InstrumentToken { get; } + public uint InstrumentToken { get; } public decimal Lower { get; } public decimal Upper { get; } public decimal Percentage { get; } @@ -1362,13 +1362,13 @@ public Quote(Dictionary data) } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public decimal LastPrice { get; set; } - public UInt32 LastQuantity { get; set; } + public uint LastQuantity { get; set; } public decimal AveragePrice { get; set; } - public UInt32 Volume { get; set; } - public UInt32 BuyQuantity { get; set; } - public UInt32 SellQuantity { get; set; } + public uint Volume { get; set; } + public uint BuyQuantity { get; set; } + public uint SellQuantity { get; set; } public decimal Open { get; set; } public decimal High { get; set; } public decimal Low { get; set; } @@ -1382,9 +1382,9 @@ public Quote(Dictionary data) // KiteConnect 3 Fields public DateTime? LastTradeTime { get; set; } - public UInt32 OI { get; set; } - public UInt32 OIDayHigh { get; set; } - public UInt32 OIDayLow { get; set; } + public uint OI { get; set; } + public uint OIDayHigh { get; set; } + public uint OIDayLow { get; set; } public DateTime? Timestamp { get; set; } } @@ -1411,7 +1411,7 @@ public OHLC(Dictionary data) } } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public decimal LastPrice { get; } public decimal Open { get; } public decimal Close { get; } @@ -1437,7 +1437,7 @@ public LTP(Dictionary data) } } - public UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public decimal LastPrice { get; } } diff --git a/KiteConnect/Ticker.cs b/KiteConnect/Ticker.cs index 6f0d0ad..2111da2 100644 --- a/KiteConnect/Ticker.cs +++ b/KiteConnect/Ticker.cs @@ -35,7 +35,7 @@ public class Ticker private IWebSocket _ws; // Dictionary that keeps instrument_token -> mode data - private Dictionary _subscribedTokens; + private Dictionary _subscribedTokens; // Delegates for callbacks @@ -133,14 +133,14 @@ public Ticker(string APIKey, string AccessToken, string Root = null, bool Reconn _debug = Debug; _apiKey = APIKey; _accessToken = AccessToken; - _subscribedTokens = new Dictionary(); + _subscribedTokens = new Dictionary(); _interval = ReconnectInterval; _timerTick = ReconnectInterval; _retries = ReconnectTries; - if (!String.IsNullOrEmpty(Root)) + if (!string.IsNullOrEmpty(Root)) _root = Root; _isReconnect = Reconnect; - _socketUrl = _root + String.Format("?api_key={0}&access_token={1}", _apiKey, _accessToken); + _socketUrl = _root + string.Format("?api_key={0}&access_token={1}", _apiKey, _accessToken); // initialize websocket if (CustomWebSocket != null) @@ -189,9 +189,9 @@ private ushort ReadShort(byte[] b, ref int offset) /// /// Reads 4 byte int32 from byte stream /// - private UInt32 ReadInt(byte[] b, ref int offset) + private uint ReadInt(byte[] b, ref int offset) { - UInt32 data = (UInt32)BitConverter.ToUInt32(new byte[] { b[offset + 3], b[offset + 2], b[offset + 1], b[offset + 0] }, 0); + uint data = (uint)BitConverter.ToUInt32(new byte[] { b[offset + 3], b[offset + 2], b[offset + 1], b[offset + 0] }, 0); offset += 4; return data; } @@ -496,16 +496,16 @@ private void Reconnect() /// Subscribe to a list of instrument_tokens. /// /// List of instrument instrument_tokens to subscribe - public void Subscribe(UInt32[] Tokens) + public void Subscribe(uint[] Tokens) { if (Tokens.Length == 0) return; - string msg = "{\"a\":\"subscribe\",\"v\":[" + String.Join(",", Tokens) + "]}"; + string msg = "{\"a\":\"subscribe\",\"v\":[" + string.Join(",", Tokens) + "]}"; if (_debug) Console.WriteLine(msg.Length); if (IsConnected) _ws.Send(msg); - foreach (UInt32 token in Tokens) + foreach (uint token in Tokens) if (!_subscribedTokens.ContainsKey(token)) _subscribedTokens.Add(token, "quote"); } @@ -514,16 +514,16 @@ public void Subscribe(UInt32[] Tokens) /// Unsubscribe the given list of instrument_tokens. /// /// List of instrument instrument_tokens to unsubscribe - public void UnSubscribe(UInt32[] Tokens) + public void UnSubscribe(uint[] Tokens) { if (Tokens.Length == 0) return; - string msg = "{\"a\":\"unsubscribe\",\"v\":[" + String.Join(",", Tokens) + "]}"; + string msg = "{\"a\":\"unsubscribe\",\"v\":[" + string.Join(",", Tokens) + "]}"; if (_debug) Console.WriteLine(msg); if (IsConnected) _ws.Send(msg); - foreach (UInt32 token in Tokens) + foreach (uint token in Tokens) if (_subscribedTokens.ContainsKey(token)) _subscribedTokens.Remove(token); } @@ -533,16 +533,16 @@ public void UnSubscribe(UInt32[] Tokens) /// /// List of instrument tokens on which the mode should be applied /// Mode to set. It can be one of the following: ltp, quote, full. - public void SetMode(UInt32[] Tokens, string Mode) + public void SetMode(uint[] Tokens, string Mode) { if (Tokens.Length == 0) return; - string msg = "{\"a\":\"mode\",\"v\":[\"" + Mode + "\", [" + String.Join(",", Tokens) + "]]}"; + string msg = "{\"a\":\"mode\",\"v\":[\"" + Mode + "\", [" + string.Join(",", Tokens) + "]]}"; if (_debug) Console.WriteLine(msg); if (IsConnected) _ws.Send(msg); - foreach (UInt32 token in Tokens) + foreach (uint token in Tokens) if (_subscribedTokens.ContainsKey(token)) _subscribedTokens[token] = Mode; } @@ -553,11 +553,11 @@ public void SetMode(UInt32[] Tokens, string Mode) public void ReSubscribe() { if (_debug) Console.WriteLine("Resubscribing"); - UInt32[] all_tokens = _subscribedTokens.Keys.ToArray(); + uint[] all_tokens = _subscribedTokens.Keys.ToArray(); - UInt32[] ltp_tokens = all_tokens.Where(key => _subscribedTokens[key] == "ltp").ToArray(); - UInt32[] quote_tokens = all_tokens.Where(key => _subscribedTokens[key] == "quote").ToArray(); - UInt32[] full_tokens = all_tokens.Where(key => _subscribedTokens[key] == "full").ToArray(); + uint[] ltp_tokens = all_tokens.Where(key => _subscribedTokens[key] == "ltp").ToArray(); + uint[] quote_tokens = all_tokens.Where(key => _subscribedTokens[key] == "quote").ToArray(); + uint[] full_tokens = all_tokens.Where(key => _subscribedTokens[key] == "full").ToArray(); UnSubscribe(all_tokens); Subscribe(all_tokens); diff --git a/KiteConnect/Utils.cs b/KiteConnect/Utils.cs index 0ce0345..69faaa2 100644 --- a/KiteConnect/Utils.cs +++ b/KiteConnect/Utils.cs @@ -22,7 +22,7 @@ public class Utils /// Date object/ public static DateTime? StringToDate(string DateString) { - if (String.IsNullOrEmpty(DateString)) + if (string.IsNullOrEmpty(DateString)) return null; try @@ -53,7 +53,7 @@ public static string JsonSerialize(object obj) MatchCollection mc = Regex.Matches(json, @"\\/Date\((\d*?)\)\\/"); foreach (Match m in mc) { - UInt64 unix = UInt64.Parse(m.Groups[1].Value) / 1000; + ulong unix = ulong.Parse(m.Groups[1].Value) / 1000; json = json.Replace(m.Groups[0].Value, UnixToDateTime(unix).ToString()); } return json; @@ -94,7 +94,7 @@ public static dynamic ElementToDict(JsonElement obj) else if (obj.ValueKind == JsonValueKind.Object) { var map = obj.EnumerateObject().ToList(); - var newMap = new Dictionary(); + var newMap = new Dictionary(); for (int i = 0; i < map.Count; i++) { newMap.Add(map[i].Name, ElementToDict(map[i].Value)); @@ -122,7 +122,7 @@ public static dynamic ElementToDict(JsonElement obj) /// /// Input string. /// Decimal value - public static decimal StringToDecimal(String value) + public static decimal StringToDecimal(string value) { return decimal.Parse(value, NumberStyles.Any, CultureInfo.InvariantCulture); } @@ -180,7 +180,7 @@ public static MemoryStream StreamFromString(string value) /// Value of the parameter public static void AddIfNotNull(Dictionary Params, string Key, string Value) { - if (!String.IsNullOrEmpty(Value)) + if (!string.IsNullOrEmpty(Value)) Params.Add(Key, Value); } @@ -215,7 +215,7 @@ public static string BuildParam(string Key, dynamic Value) else { string[] values = (string[])Value; - return String.Join("&", values.Select(x => HttpUtility.UrlEncode(Key) + "=" + HttpUtility.UrlEncode(x))); + return string.Join("&", values.Select(x => HttpUtility.UrlEncode(Key) + "=" + HttpUtility.UrlEncode(x))); } } @@ -224,7 +224,7 @@ public static string BuildParam(string Key, dynamic Value) /// /// Unix timestamp in seconds. /// DateTime object. - public static DateTime UnixToDateTime(UInt64 unixTimeStamp) + public static DateTime UnixToDateTime(ulong unixTimeStamp) { // Unix timestamp is seconds past epoch DateTime dateTime = new DateTime(1970, 1, 1, 5, 30, 0, 0, DateTimeKind.Unspecified); diff --git a/KiteConnectSample/Program.cs b/KiteConnectSample/Program.cs index b41a43c..541607a 100644 --- a/KiteConnectSample/Program.cs +++ b/KiteConnectSample/Program.cs @@ -479,8 +479,8 @@ private static void initTicker() ticker.Connect(); // Subscribing to NIFTY50 and setting mode to LTP - ticker.Subscribe(Tokens: new UInt32[] { 256265 }); - ticker.SetMode(Tokens: new UInt32[] { 256265 }, Mode: Constants.TickerMode.LTP); + ticker.Subscribe(Tokens: new uint[] { 256265 }); + ticker.SetMode(Tokens: new uint[] { 256265 }, Mode: Constants.TickerMode.LTP); } private static void OnTokenExpire() From c8ee6d111bd183f1412cc4c5cdc2add7f4d46623 Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Fri, 9 Jan 2026 14:39:39 +0530 Subject: [PATCH 3/9] added setters --- KiteConnect/Structures.cs | 294 +++++++++++++++++++------------------- 1 file changed, 147 insertions(+), 147 deletions(-) diff --git a/KiteConnect/Structures.cs b/KiteConnect/Structures.cs index d0a2b87..967e601 100644 --- a/KiteConnect/Structures.cs +++ b/KiteConnect/Structures.cs @@ -70,13 +70,13 @@ public Historical(ArrayList data) OI = data.Count > 6 ? Convert.ToUInt64(data[6]) : 0; } - public DateTime TimeStamp { get; } - public decimal Open { get; } - public decimal High { get; } - public decimal Low { get; } - public decimal Close { get; } - public ulong Volume { get; } - public ulong OI { get; } + public DateTime TimeStamp { get; set; } + public decimal Open { get; set; } + public decimal High { get; set; } + public decimal Low { get; set; } + public decimal Close { get; set; } + public ulong Volume { get; set; } + public ulong OI { get; set; } } /// @@ -715,35 +715,35 @@ public Position(Dictionary data) } - public string Product { get; } - public decimal OvernightQuantity { get; } - public string Exchange { get; } - public decimal SellValue { get; } - public decimal BuyM2M { get; } - public decimal LastPrice { get; } - public string TradingSymbol { get; } - public decimal Realised { get; } - public decimal PNL { get; } - public decimal Multiplier { get; } - public decimal SellQuantity { get; } - public decimal SellM2M { get; } - public decimal BuyValue { get; } - public decimal BuyQuantity { get; } - public decimal AveragePrice { get; } - public decimal Unrealised { get; } - public decimal Value { get; } - public decimal BuyPrice { get; } - public decimal SellPrice { get; } - public decimal M2M { get; } - public uint InstrumentToken { get; } - public decimal ClosePrice { get; } - public decimal Quantity { get; } - public decimal DayBuyQuantity { get; } - public decimal DayBuyPrice { get; } - public decimal DayBuyValue { get; } - public decimal DaySellQuantity { get; } - public decimal DaySellPrice { get; } - public decimal DaySellValue { get; } + public string Product { get; set; } + public decimal OvernightQuantity { get; set; } + public string Exchange { get; set; } + public decimal SellValue { get; set; } + public decimal BuyM2M { get; set; } + public decimal LastPrice { get; set; } + public string TradingSymbol { get; set; } + public decimal Realised { get; set; } + public decimal PNL { get; set; } + public decimal Multiplier { get; set; } + public decimal SellQuantity { get; set; } + public decimal SellM2M { get; set; } + public decimal BuyValue { get; set; } + public decimal BuyQuantity { get; set; } + public decimal AveragePrice { get; set; } + public decimal Unrealised { get; set; } + public decimal Value { get; set; } + public decimal BuyPrice { get; set; } + public decimal SellPrice { get; set; } + public decimal M2M { get; set; } + public uint InstrumentToken { get; set; } + public decimal ClosePrice { get; set; } + public decimal Quantity { get; set; } + public decimal DayBuyQuantity { get; set; } + public decimal DayBuyPrice { get; set; } + public decimal DayBuyValue { get; set; } + public decimal DaySellQuantity { get; set; } + public decimal DaySellPrice { get; set; } + public decimal DaySellValue { get; set; } } /// @@ -762,8 +762,8 @@ public PositionResponse(Dictionary data) Net.Add(new Position(item)); } - public List Day { get; } - public List Net { get; } + public List Day { get; set; } + public List Net { get; set; } } /// @@ -1131,18 +1131,18 @@ public Trade(Dictionary data) } - public string TradeId { get; } - public string OrderId { get; } - public string ExchangeOrderId { get; } - public string Tradingsymbol { get; } - public string Exchange { get; } - public uint InstrumentToken { get; } - public string TransactionType { get; } - public string Product { get; } - public decimal AveragePrice { get; } - public decimal Quantity { get; } - public DateTime? FillTimestamp { get; } - public DateTime? ExchangeTimestamp { get; } + public string TradeId { get; set; } + public string OrderId { get; set; } + public string ExchangeOrderId { get; set; } + public string Tradingsymbol { get; set; } + public string Exchange { get; set; } + public uint InstrumentToken { get; set; } + public string TransactionType { get; set; } + public string Product { get; set; } + public decimal AveragePrice { get; set; } + public decimal Quantity { get; set; } + public DateTime? FillTimestamp { get; set; } + public DateTime? ExchangeTimestamp { get; set; } } /// @@ -1165,10 +1165,10 @@ public TrigerRange(Dictionary data) } } - public uint InstrumentToken { get; } - public decimal Lower { get; } - public decimal Upper { get; } - public decimal Percentage { get; } + public uint InstrumentToken { get; set; } + public decimal Lower { get; set; } + public decimal Upper { get; set; } + public decimal Percentage { get; set; } } /// @@ -1203,21 +1203,21 @@ public User(Dictionary data) } - public string APIKey { get; } - public string[] Products { get; } - public string UserName { get; } - public string UserShortName { get; } - public string AvatarURL { get; } - public string Broker { get; } - public string AccessToken { get; } - public string PublicToken { get; } - public string RefreshToken { get; } - public string UserType { get; } - public string UserId { get; } - public DateTime? LoginTime { get; } - public string[] Exchanges { get; } - public string[] OrderTypes { get; } - public string Email { get; } + public string APIKey { get; set; } + public string[] Products { get; set; } + public string UserName { get; set; } + public string UserShortName { get; set; } + public string AvatarURL { get; set; } + public string Broker { get; set; } + public string AccessToken { get; set; } + public string PublicToken { get; set; } + public string RefreshToken { get; set; } + public string UserType { get; set; } + public string UserId { get; set; } + public DateTime? LoginTime { get; set; } + public string[] Exchanges { get; set; } + public string[] OrderTypes { get; set; } + public string Email { get; set; } } public class TokenSet @@ -1235,9 +1235,9 @@ public TokenSet(Dictionary data) throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); } } - public string UserId { get; } - public string AccessToken { get; } - public string RefreshToken { get; } + public string UserId { get; set; } + public string AccessToken { get; set; } + public string RefreshToken { get; set; } } /// @@ -1267,15 +1267,15 @@ public Profile(Dictionary data) } - public string[] Products { get; } - public string UserName { get; } - public string UserShortName { get; } - public string AvatarURL { get; } - public string Broker { get; } - public string UserType { get; } - public string[] Exchanges { get; } - public string[] OrderTypes { get; } - public string Email { get; } + public string[] Products { get; set; } + public string UserName { get; set; } + public string UserShortName { get; set; } + public string AvatarURL { get; set; } + public string Broker { get; set; } + public string UserType { get; set; } + public string[] Exchanges { get; set; } + public string[] OrderTypes { get; set; } + public string Email { get; set; } } /// @@ -1412,11 +1412,11 @@ public OHLC(Dictionary data) } public uint InstrumentToken { get; set; } - public decimal LastPrice { get; } - public decimal Open { get; } - public decimal Close { get; } - public decimal High { get; } - public decimal Low { get; } + public decimal LastPrice { get; set; } + public decimal Open { get; set; } + public decimal Close { get; set; } + public decimal High { get; set; } + public decimal Low { get; set; } } /// @@ -1438,7 +1438,7 @@ public LTP(Dictionary data) } public uint InstrumentToken { get; set; } - public decimal LastPrice { get; } + public decimal LastPrice { get; set; } } /// @@ -1465,13 +1465,13 @@ public MFHolding(Dictionary data) } - public decimal Quantity { get; } - public string Fund { get; } - public string Folio { get; } - public decimal AveragePrice { get; } - public string TradingSymbol { get; } - public decimal LastPrice { get; } - public decimal PNL { get; } + public decimal Quantity { get; set; } + public string Fund { get; set; } + public string Folio { get; set; } + public decimal AveragePrice { get; set; } + public string TradingSymbol { get; set; } + public decimal LastPrice { get; set; } + public decimal PNL { get; set; } } /// @@ -1510,25 +1510,25 @@ public MFInstrument(Dictionary data) } - public string TradingSymbol { get; } - public string AMC { get; } - public string Name { get; } - - public bool PurchaseAllowed { get; } - public bool RedemtpionAllowed { get; } - - public decimal MinimumPurchaseAmount { get; } - public decimal PurchaseAmountMultiplier { get; } - public decimal MinimumAdditionalPurchaseAmount { get; } - public decimal MinimumRedemptionQuantity { get; } - public decimal RedemptionQuantityMultiplier { get; } - public decimal LastPrice { get; } - - public string DividendType { get; } - public string SchemeType { get; } - public string Plan { get; } - public string SettlementType { get; } - public DateTime? LastPriceDate { get; } + public string TradingSymbol { get; set; } + public string AMC { get; set; } + public string Name { get; set; } + + public bool PurchaseAllowed { get; set; } + public bool RedemtpionAllowed { get; set; } + + public decimal MinimumPurchaseAmount { get; set; } + public decimal PurchaseAmountMultiplier { get; set; } + public decimal MinimumAdditionalPurchaseAmount { get; set; } + public decimal MinimumRedemptionQuantity { get; set; } + public decimal RedemptionQuantityMultiplier { get; set; } + public decimal LastPrice { get; set; } + + public string DividendType { get; set; } + public string SchemeType { get; set; } + public string Plan { get; set; } + public string SettlementType { get; set; } + public DateTime? LastPriceDate { get; set; } } /// @@ -1567,25 +1567,25 @@ public MFOrder(Dictionary data) } - public string StatusMessage { get; } - public string PurchaseType { get; } - public string PlacedBy { get; } - public decimal Amount { get; } - public decimal Quantity { get; } - public string SettlementId { get; } - public DateTime? OrderTimestamp { get; } - public decimal AveragePrice { get; } - public string TransactionType { get; } - public string ExchangeOrderId { get; } - public DateTime? ExchangeTimestamp { get; } - public string Fund { get; } - public string Variety { get; } - public string Folio { get; } - public string Tradingsymbol { get; } - public string Tag { get; } - public string OrderId { get; } - public string Status { get; } - public decimal LastPrice { get; } + public string StatusMessage { get; set; } + public string PurchaseType { get; set; } + public string PlacedBy { get; set; } + public decimal Amount { get; set; } + public decimal Quantity { get; set; } + public string SettlementId { get; set; } + public DateTime? OrderTimestamp { get; set; } + public decimal AveragePrice { get; set; } + public string TransactionType { get; set; } + public string ExchangeOrderId { get; set; } + public DateTime? ExchangeTimestamp { get; set; } + public string Fund { get; set; } + public string Variety { get; set; } + public string Folio { get; set; } + public string Tradingsymbol { get; set; } + public string Tag { get; set; } + public string OrderId { get; set; } + public string Status { get; set; } + public decimal LastPrice { get; set; } } /// @@ -1619,21 +1619,21 @@ public MFSIP(Dictionary data) } } - public string DividendType { get; } - public int PendingInstalments { get; } - public DateTime? Created { get; } - public DateTime? LastInstalment { get; } - public string TransactionType { get; } - public string Frequency { get; } - public int InstalmentDate { get; } - public string Fund { get; } - public string SIPId { get; } - public string Tradingsymbol { get; } - public string Tag { get; } - public decimal InstalmentAmount { get; } - public int Instalments { get; } - public string Status { get; } - public string OrderId { get; } + public string DividendType { get; set; } + public int PendingInstalments { get; set; } + public DateTime? Created { get; set; } + public DateTime? LastInstalment { get; set; } + public string TransactionType { get; set; } + public string Frequency { get; set; } + public int InstalmentDate { get; set; } + public string Fund { get; set; } + public string SIPId { get; set; } + public string Tradingsymbol { get; set; } + public string Tag { get; set; } + public decimal InstalmentAmount { get; set; } + public int Instalments { get; set; } + public string Status { get; set; } + public string OrderId { get; set; } } } From e45c6ab4e0fcfef44a4a4dd4e1e605036c1bde61 Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Fri, 9 Jan 2026 14:40:15 +0530 Subject: [PATCH 4/9] updated .net target framework and nuget packages --- KiteConnect/KiteConnect.csproj | 8 ++++---- KiteConnectSample/KiteConnectSample.csproj | 2 +- KiteConnectTest/KiteConnectTest.csproj | 15 ++++++++++----- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/KiteConnect/KiteConnect.csproj b/KiteConnect/KiteConnect.csproj index 6be6aa7..40da354 100644 --- a/KiteConnect/KiteConnect.csproj +++ b/KiteConnect/KiteConnect.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 Ajin Asokan Zerodha Technology Pvt. Ltd. Tech.Zerodha.KiteConnect @@ -23,13 +23,13 @@ - + - + - + diff --git a/KiteConnectSample/KiteConnectSample.csproj b/KiteConnectSample/KiteConnectSample.csproj index 027bae7..659bac9 100644 --- a/KiteConnectSample/KiteConnectSample.csproj +++ b/KiteConnectSample/KiteConnectSample.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 diff --git a/KiteConnectTest/KiteConnectTest.csproj b/KiteConnectTest/KiteConnectTest.csproj index 2cca2c2..8974727 100644 --- a/KiteConnectTest/KiteConnectTest.csproj +++ b/KiteConnectTest/KiteConnectTest.csproj @@ -1,16 +1,21 @@ - net6.0 + net8.0 false - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + From 2d44f477df7f43852a0225cbee1d0f88a6216740 Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Tue, 3 Feb 2026 19:39:11 +0530 Subject: [PATCH 5/9] compile time error for not awaiting task/method --- KiteConnect/KiteConnect.csproj | 8 ++++++++ KiteConnectSample/KiteConnectSample.csproj | 8 ++++++++ KiteConnectTest/KiteConnectTest.csproj | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/KiteConnect/KiteConnect.csproj b/KiteConnect/KiteConnect.csproj index 40da354..9507747 100644 --- a/KiteConnect/KiteConnect.csproj +++ b/KiteConnect/KiteConnect.csproj @@ -22,6 +22,14 @@ true + + $(WarningsAsErrors);NU1605;CS4014 + + + + $(WarningsAsErrors);NU1605;CS4014 + + diff --git a/KiteConnectSample/KiteConnectSample.csproj b/KiteConnectSample/KiteConnectSample.csproj index 659bac9..40c6608 100644 --- a/KiteConnectSample/KiteConnectSample.csproj +++ b/KiteConnectSample/KiteConnectSample.csproj @@ -5,6 +5,14 @@ net8.0 + + $(WarningsAsErrors);NU1605;CS4014 + + + + $(WarningsAsErrors);NU1605;CS4014 + + diff --git a/KiteConnectTest/KiteConnectTest.csproj b/KiteConnectTest/KiteConnectTest.csproj index 8974727..8831e9f 100644 --- a/KiteConnectTest/KiteConnectTest.csproj +++ b/KiteConnectTest/KiteConnectTest.csproj @@ -6,6 +6,14 @@ false + + $(WarningsAsErrors);NU1605;CS4014 + + + + $(WarningsAsErrors);NU1605;CS4014 + + From db78435a69ebf3c0262f561ea0bd8a447465dbfa Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Fri, 9 Jan 2026 14:41:41 +0530 Subject: [PATCH 6/9] refactored code for profile & margins request --- KiteConnect/Kite.cs | 71 +++++++++++++++++----- KiteConnect/Structures.cs | 111 +++++++++-------------------------- KiteConnectSample/Program.cs | 9 +-- KiteConnectTest/KiteTest.cs | 34 ++++++----- 4 files changed, 108 insertions(+), 117 deletions(-) diff --git a/KiteConnect/Kite.cs b/KiteConnect/Kite.cs index 09e0d22..2821880 100644 --- a/KiteConnect/Kite.cs +++ b/KiteConnect/Kite.cs @@ -1,12 +1,17 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Collections; -using System.Reflection; +using System.Net; using System.Net.Http; -using System.Text; +using System.Net.Http.Json; using System.Net.Mime; -using System.Net; +using System.Reflection; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; namespace KiteConnect { @@ -15,6 +20,7 @@ namespace KiteConnect /// public class Kite { + private static readonly JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, Converters = { new JsonStringEnumConverter() } }; // Default root API endpoint. It's possible to // override this by passing the `Root` parameter during initialisation. private string _root = "https://api.kite.trade"; @@ -186,11 +192,9 @@ public TokenSet RenewAccessToken(string RefreshToken, string AppSecret) /// Gets currently logged in user details /// /// User profile - public Profile GetProfile() + public Task GetProfileAsync(CancellationToken cancellationToken = default) { - var profileData = Get(Routes.User.Profile); - - return new Profile(profileData); + return GetAsync("/user/profile", cancellationToken); } /// @@ -310,22 +314,22 @@ public BasketMargin GetBasketMargins(List OrderMarginParams, /// /// Get account balance and cash margin details for all segments. /// + /// /// User margin response with both equity and commodity margins. - public UserMarginsResponse GetMargins() + public Task GetMarginsAsync(CancellationToken cancellationToken = default) { - var marginsData = Get(Routes.User.Margins); - return new UserMarginsResponse(marginsData["data"]); + return GetAsync("/user/margins", cancellationToken); } /// /// Get account balance and cash margin details for a particular segment. /// /// Trading segment (eg: equity or commodity) + /// /// Margins for specified segment. - public UserMargin GetMargins(string Segment) + public Task GetMarginsAsync(string Segment, CancellationToken cancellationToken = default) { - var userMarginData = Get(Routes.User.SegmentMargins, new Dictionary { { "segment", Segment } }); - return new UserMargin(userMarginData["data"]); + return GetAsync($"/user/margins/{Segment}", cancellationToken); } /// @@ -1311,6 +1315,45 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict } + private async Task GetAsync(string path, CancellationToken cancellationToken) + { + string url = _root + path; + var httpResponse = await httpClient.GetAsync(url, cancellationToken); + if (httpResponse.IsSuccessStatusCode) + { + var response = await httpResponse.Content.ReadFromJsonAsync>(jsonSerializerOptions, cancellationToken); + if (response.Status == ResponseStatus.Success) + return response.Data; + else + throw new KiteException($"Expected sucess status, got {response.Status}.", httpResponse.StatusCode); + } + else + { + await ThrowErrorAsync(httpResponse, cancellationToken); + throw new KiteException("Something went wrong.", httpResponse.StatusCode); + } + } + + private async Task ThrowErrorAsync(HttpResponseMessage httpResponse, CancellationToken cancellationToken) + { + var response = await httpResponse.Content.ReadFromJsonAsync(jsonSerializerOptions, cancellationToken); + switch (response.ErrorType) + { + case "GeneralException": throw new GeneralException(response.Message, httpResponse.StatusCode); + case "TokenException": + { + _sessionHook?.Invoke(); + throw new TokenException(response.Message, httpResponse.StatusCode); + } + case "PermissionException": throw new PermissionException(response.Message, httpResponse.StatusCode); + case "OrderException": throw new OrderException(response.Message, httpResponse.StatusCode); + case "InputException": throw new InputException(response.Message, httpResponse.StatusCode); + case "DataException": throw new DataException(response.Message, httpResponse.StatusCode); + case "NetworkException": throw new NetworkException(response.Message, httpResponse.StatusCode); + default: throw new GeneralException(response.Message, httpResponse.StatusCode); + } + } + #endregion } diff --git a/KiteConnect/Structures.cs b/KiteConnect/Structures.cs index 967e601..b092d86 100644 --- a/KiteConnect/Structures.cs +++ b/KiteConnect/Structures.cs @@ -3,9 +3,29 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Text.Json.Serialization; namespace KiteConnect { + internal enum ResponseStatus + { + Success, + Error, + } + + internal class SucessResponse + { + public ResponseStatus Status { get; set; } + public T Data { get; set; } + } + + internal class ErrorResponse + { + public ResponseStatus Status { get; set; } + public string Message { get; set; } + public string ErrorType { get; set; } + } + /// /// Tick data structure /// @@ -232,21 +252,7 @@ public AuctionInstrument(Dictionary data) /// public class AvailableMargin { - public AvailableMargin(Dictionary data) - { - try - { - AdHocMargin = data["adhoc_margin"]; - Cash = data["cash"]; - Collateral = data["collateral"]; - IntradayPayin = data["intraday_payin"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - + [JsonPropertyName("adhoc_margin")] public decimal AdHocMargin { get; set; } public decimal Cash { get; set; } public decimal Collateral { get; set; } @@ -258,29 +264,13 @@ public AvailableMargin(Dictionary data) /// public class UtilisedMargin { - public UtilisedMargin(Dictionary data) - { - try - { - Debits = Utils.GetValueOrDefault(data, "debits", 0m); - Exposure = Utils.GetValueOrDefault(data, "exposure", 0m); - M2MRealised = Utils.GetValueOrDefault(data, "m2m_realised", 0m); - M2MUnrealised = Utils.GetValueOrDefault(data, "m2m_unrealised", 0m); - OptionPremium = Utils.GetValueOrDefault(data, "option_premium", 0m); - Payout = Utils.GetValueOrDefault(data, "payout", 0m); - Span = Utils.GetValueOrDefault(data, "span", 0m); - HoldingSales = Utils.GetValueOrDefault(data, "holding_sales", 0m); - Turnover = Utils.GetValueOrDefault(data, "turnover", 0m); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public decimal Debits { get; set; } public decimal Exposure { get; set; } + + [JsonPropertyName("m2m_realised")] public decimal M2MRealised { get; set; } + + [JsonPropertyName("m2m_unrealised")] public decimal M2MUnrealised { get; set; } public decimal OptionPremium { get; set; } public decimal Payout { get; set; } @@ -295,21 +285,6 @@ public UtilisedMargin(Dictionary data) /// public class UserMargin { - public UserMargin(Dictionary data) - { - try - { - Enabled = data["enabled"]; - Net = data["net"]; - Available = new AvailableMargin(data["available"]); - Utilised = new UtilisedMargin(data["utilised"]); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public bool Enabled { get; set; } public decimal Net { get; set; } public AvailableMargin Available { get; set; } @@ -321,18 +296,6 @@ public UserMargin(Dictionary data) /// public class UserMarginsResponse { - public UserMarginsResponse(Dictionary data) - { - try - { - Equity = new UserMargin(data["equity"]); - Commodity = new UserMargin(data["commodity"]); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } public UserMargin Equity { get; set; } public UserMargin Commodity { get; set; } } @@ -1245,30 +1208,10 @@ public TokenSet(Dictionary data) /// public class Profile { - public Profile(Dictionary data) - { - try - { - Products = (string[])data["data"]["products"].ToArray(typeof(string)); - UserName = data["data"]["user_name"]; - UserShortName = data["data"]["user_shortname"]; - AvatarURL = data["data"]["avatar_url"]; - Broker = data["data"]["broker"]; - UserType = data["data"]["user_type"]; - Exchanges = (string[])data["data"]["exchanges"].ToArray(typeof(string)); - OrderTypes = (string[])data["data"]["order_types"].ToArray(typeof(string)); - Email = data["data"]["email"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - - public string[] Products { get; set; } public string UserName { get; set; } + + [JsonPropertyName("user_shortname")] public string UserShortName { get; set; } public string AvatarURL { get; set; } public string Broker { get; set; } diff --git a/KiteConnectSample/Program.cs b/KiteConnectSample/Program.cs index 541607a..ed54c71 100644 --- a/KiteConnectSample/Program.cs +++ b/KiteConnectSample/Program.cs @@ -1,6 +1,7 @@ using System; using KiteConnect; using System.Collections.Generic; +using System.Threading.Tasks; namespace KiteConnectSample { @@ -19,7 +20,7 @@ class Program static string MyPublicToken = "abcdefghijklmnopqrstuvwxyz"; static string MyAccessToken = "abcdefghijklmnopqrstuvwxyz"; - static void Main(string[] args) + static async Task Main(string[] args) { kite = new Kite(MyAPIKey, Debug: true); @@ -322,8 +323,8 @@ static void Main(string[] args) // Margins - UserMargin commodityMargins = kite.GetMargins(Constants.Margin.Commodity); - UserMargin equityMargins = kite.GetMargins(Constants.Margin.Equity); + UserMargin commodityMargins = await kite.GetMarginsAsync(Constants.Margin.Commodity); + UserMargin equityMargins = await kite.GetMarginsAsync(Constants.Margin.Equity); // Order margins @@ -365,7 +366,7 @@ static void Main(string[] args) contractNoteParam.Product = Constants.Product.MIS; List contractNotes = kite.GetVirtualContractNote(new List() { contractNoteParam }); Console.WriteLine(Utils.JsonSerialize(contractNotes)); - + // Historical Data With Dates List historical = kite.GetHistoricalData( diff --git a/KiteConnectTest/KiteTest.cs b/KiteConnectTest/KiteTest.cs index 9f75487..a14cba7 100644 --- a/KiteConnectTest/KiteTest.cs +++ b/KiteConnectTest/KiteTest.cs @@ -1,16 +1,20 @@ -using System; +using KiteConnect; using Microsoft.VisualStudio.TestTools.UnitTesting; -using KiteConnect; -using System.Net; +using System; using System.Collections.Generic; using System.IO; using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; namespace KiteConnectTest { [TestClass] public class KiteTest { + private static readonly JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, Converters = { new JsonStringEnumConverter() } }; + MockServer ms; [TestInitialize] @@ -30,7 +34,7 @@ public void TestSetAccessToken() { Kite kite = new Kite("apikey"); kite.SetAccessToken("access_token"); - Assert.ThrowsException(() => kite.GetPositions()); + Assert.Throws(() => kite.GetPositions()); } @@ -41,16 +45,16 @@ public void TestError() ms.SetStatusCode(403); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080", Debug: true); - Assert.ThrowsException(() => kite.GetProfile()); + Assert.ThrowsAsync(async () => await kite.GetProfileAsync()); } [TestMethod] - public void TestProfile() + public async Task TestProfile() { string json = File.ReadAllText(@"responses/profile.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - Profile profile = kite.GetProfile(); + Profile profile = await kite.GetProfileAsync(); Console.WriteLine(profile.Email); Assert.AreEqual(profile.Email, "xxxyyy@gmail.com"); } @@ -88,24 +92,24 @@ public void TestAuctionInstruments() } [TestMethod] - public void TestMargins() + public async Task TestMargins() { string json = File.ReadAllText(@"responses/margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - UserMarginsResponse margins = kite.GetMargins(); + UserMarginsResponse margins = await kite.GetMarginsAsync(); Assert.AreEqual(margins.Equity.Net, (decimal)1697.7); Assert.AreEqual(margins.Commodity.Net, (decimal)-8676.296); } [TestMethod] - public void TestMarginsNoTurnover() + public async Task TestMarginsNoTurnover() { string json = File.ReadAllText(@"responses/margins_noturnover.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - UserMarginsResponse margins = kite.GetMargins(); + UserMarginsResponse margins = await kite.GetMarginsAsync(); Assert.AreEqual(margins.Equity.Utilised.Turnover, (decimal)0); Assert.AreEqual(margins.Commodity.Utilised.Turnover, (decimal)0); @@ -230,23 +234,23 @@ public void TestBasketMarginsCompact() } [TestMethod] - public void TestEquityMargins() + public async Task TestEquityMargins() { string json = File.ReadAllText(@"responses/equity_margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - UserMargin margin = kite.GetMargins("equity"); + UserMargin margin = await kite.GetMarginsAsync("equity"); Assert.AreEqual(margin.Net, (decimal)1812.3535); } [TestMethod] - public void TestCommodityMargins() + public async Task TestCommodityMargins() { string json = File.ReadAllText(@"responses/equity_margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - UserMargin margin = kite.GetMargins("commodity"); + UserMargin margin = await kite.GetMarginsAsync("commodity"); Assert.AreEqual(margin.Net, (decimal)1812.3535); } From 74c170db444b799bdc69f21274c17ea9cba9931c Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Thu, 29 Jan 2026 11:02:30 +0530 Subject: [PATCH 7/9] refactoring order and gtt endpoints --- KiteConnect/CustomDateTimeConverter.cs | 24 ++ KiteConnect/Kite.cs | 414 +++++++++++++------------ KiteConnect/ParametersBuilder.cs | 57 ++++ KiteConnect/Routes.cs | 13 - KiteConnect/Structures.cs | 315 +++---------------- KiteConnect/Ticker.cs | 15 +- KiteConnectSample/Program.cs | 54 ++-- KiteConnectTest/KiteTest.cs | 32 +- KiteConnectTest/responses/trades.json | 2 +- 9 files changed, 379 insertions(+), 547 deletions(-) create mode 100644 KiteConnect/CustomDateTimeConverter.cs create mode 100644 KiteConnect/ParametersBuilder.cs diff --git a/KiteConnect/CustomDateTimeConverter.cs b/KiteConnect/CustomDateTimeConverter.cs new file mode 100644 index 0000000..8f17fc1 --- /dev/null +++ b/KiteConnect/CustomDateTimeConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace KiteConnect +{ + internal class CustomDateTimeConverter : JsonConverter + { + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + if (value.Length == 10) + return DateTime.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture); + else + return DateTime.ParseExact(value, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } +} diff --git a/KiteConnect/Kite.cs b/KiteConnect/Kite.cs index 2821880..4942ce5 100644 --- a/KiteConnect/Kite.cs +++ b/KiteConnect/Kite.cs @@ -12,6 +12,7 @@ using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; +using System.Web; namespace KiteConnect { @@ -20,7 +21,7 @@ namespace KiteConnect /// public class Kite { - private static readonly JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, Converters = { new JsonStringEnumConverter() } }; + internal static readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, Converters = { new JsonStringEnumConverter(), new CustomDateTimeConverter() } }; // Default root API endpoint. It's possible to // override this by passing the `Root` parameter during initialisation. private string _root = "https://api.kite.trade"; @@ -123,20 +124,16 @@ public string GetLoginURL() /// Token obtained from the GET paramers after a successful login redirect. /// API secret issued with the API key. /// User structure with tokens and profile data - public User GenerateSession(string RequestToken, string AppSecret) + public Task GenerateSessionAsync(string RequestToken, string AppSecret) { string checksum = Utils.SHA256Hash(_apiKey + RequestToken + AppSecret); - var param = new Dictionary - { - {"api_key", _apiKey}, - {"request_token", RequestToken}, - {"checksum", checksum} - }; - - var userData = Post(Routes.API.Token, param); + var formDataBuilder = new ParametersBuilder() + .Add("api_key", _apiKey) + .Add("request_token", RequestToken) + .Add("checksum", checksum); - return new User(userData); + return PostAsync("/session/token", formData: formDataBuilder.Build()); } /// @@ -144,14 +141,13 @@ public User GenerateSession(string RequestToken, string AppSecret) /// /// Access token to invalidate. Default is the active access token. /// Json response in the form of nested string dictionary. - public Dictionary InvalidateAccessToken(string AccessToken = null) + public Task InvalidateAccessTokenAsync(string AccessToken = null) { - var param = new Dictionary(); - - Utils.AddIfNotNull(param, "api_key", _apiKey); - Utils.AddIfNotNull(param, "access_token", AccessToken); + var queryParametersBuilder = new ParametersBuilder() + .AddIfNotNull("api_key", _apiKey) + .AddIfNotNull("access_token", AccessToken); - return Delete(Routes.API.Token, param); + return DeleteAsync("/session/token", queryParameters: queryParametersBuilder.Build()); } /// @@ -159,14 +155,13 @@ public Dictionary InvalidateAccessToken(string AccessToken = nu /// /// RefreshToken to invalidate /// Json response in the form of nested string dictionary. - public Dictionary InvalidateRefreshToken(string RefreshToken) + public Task InvalidateRefreshTokenAsync(string RefreshToken) { - var param = new Dictionary(); - - Utils.AddIfNotNull(param, "api_key", _apiKey); - Utils.AddIfNotNull(param, "refresh_token", RefreshToken); + var queryParametersBuilder = new ParametersBuilder() + .AddIfNotNull("api_key", _apiKey) + .AddIfNotNull("refresh_token", RefreshToken); - return Delete(Routes.API.Token, param); + return DeleteAsync("/session/token", queryParameters: queryParametersBuilder.Build()); } /// @@ -175,17 +170,15 @@ public Dictionary InvalidateRefreshToken(string RefreshToken) /// RefreshToken to renew the AccessToken. /// API secret issued with the API key. /// TokenRenewResponse that contains new AccessToken and RefreshToken. - public TokenSet RenewAccessToken(string RefreshToken, string AppSecret) + public Task RenewAccessTokenAsync(string RefreshToken, string AppSecret) { - var param = new Dictionary(); - string checksum = Utils.SHA256Hash(_apiKey + RefreshToken + AppSecret); + var formDataBuilder = new ParametersBuilder() + .AddIfNotNull("api_key", _apiKey) + .AddIfNotNull("refresh_token", RefreshToken) + .AddIfNotNull("checksum", checksum); - Utils.AddIfNotNull(param, "api_key", _apiKey); - Utils.AddIfNotNull(param, "refresh_token", RefreshToken); - Utils.AddIfNotNull(param, "checksum", checksum); - - return new TokenSet(Post(Routes.API.Refresh, param)); + return PostAsync("/session/refresh_token", formData: formDataBuilder.Build()); } /// @@ -194,7 +187,7 @@ public TokenSet RenewAccessToken(string RefreshToken, string AppSecret) /// User profile public Task GetProfileAsync(CancellationToken cancellationToken = default) { - return GetAsync("/user/profile", cancellationToken); + return GetAsync("/user/profile", cancellationToken: cancellationToken); } /// @@ -318,18 +311,18 @@ public BasketMargin GetBasketMargins(List OrderMarginParams, /// User margin response with both equity and commodity margins. public Task GetMarginsAsync(CancellationToken cancellationToken = default) { - return GetAsync("/user/margins", cancellationToken); + return GetAsync("/user/margins", cancellationToken: cancellationToken); } /// /// Get account balance and cash margin details for a particular segment. /// - /// Trading segment (eg: equity or commodity) + /// Trading segment (eg: equity or commodity) /// /// Margins for specified segment. - public Task GetMarginsAsync(string Segment, CancellationToken cancellationToken = default) + public Task GetMarginsAsync(string segment, CancellationToken cancellationToken = default) { - return GetAsync($"/user/margins/{Segment}", cancellationToken); + return GetAsync($"/user/margins/{segment}", cancellationToken: cancellationToken); } /// @@ -354,7 +347,7 @@ public Task GetMarginsAsync(string Segment, CancellationToken cancel /// Total number of legs for iceberg order type (number of legs per Iceberg should be between 2 and 10) /// Split quantity for each iceberg leg order (Quantity/IcebergLegs) /// Json response in the form of nested string dictionary. - public Dictionary PlaceOrder( + public Task PlaceOrderAsync( string Exchange, string TradingSymbol, string TransactionType, @@ -376,29 +369,28 @@ public Dictionary PlaceOrder( string AuctionNumber = null ) { - var param = new Dictionary(); - - Utils.AddIfNotNull(param, "exchange", Exchange); - Utils.AddIfNotNull(param, "tradingsymbol", TradingSymbol); - Utils.AddIfNotNull(param, "transaction_type", TransactionType); - Utils.AddIfNotNull(param, "quantity", Quantity.ToString()); - Utils.AddIfNotNull(param, "price", Price.ToString()); - Utils.AddIfNotNull(param, "product", Product); - Utils.AddIfNotNull(param, "order_type", OrderType); - Utils.AddIfNotNull(param, "validity", Validity); - Utils.AddIfNotNull(param, "disclosed_quantity", DisclosedQuantity.ToString()); - Utils.AddIfNotNull(param, "trigger_price", TriggerPrice.ToString()); - Utils.AddIfNotNull(param, "squareoff", SquareOffValue.ToString()); - Utils.AddIfNotNull(param, "stoploss", StoplossValue.ToString()); - Utils.AddIfNotNull(param, "trailing_stoploss", TrailingStoploss.ToString()); - Utils.AddIfNotNull(param, "variety", Variety); - Utils.AddIfNotNull(param, "tag", Tag); - Utils.AddIfNotNull(param, "validity_ttl", ValidityTTL.ToString()); - Utils.AddIfNotNull(param, "iceberg_legs", IcebergLegs.ToString()); - Utils.AddIfNotNull(param, "iceberg_quantity", IcebergQuantity.ToString()); - Utils.AddIfNotNull(param, "auction_number", AuctionNumber); - - return Post(Routes.Order.Place, param); + var formDataBuilder = new ParametersBuilder() + .AddIfNotNull("exchange", Exchange) + .AddIfNotNull("tradingsymbol", TradingSymbol) + .AddIfNotNull("transaction_type", TransactionType) + .Add("quantity", Quantity) + .AddIfNotNull("price", Price) + .AddIfNotNull("product", Product) + .AddIfNotNull("order_type", OrderType) + .AddIfNotNull("validity", Validity) + .AddIfNotNull("disclosed_quantity", DisclosedQuantity) + .AddIfNotNull("trigger_price", TriggerPrice) + .AddIfNotNull("squareoff", SquareOffValue) + .AddIfNotNull("stoploss", StoplossValue) + .AddIfNotNull("trailing_stoploss", TrailingStoploss) + .AddIfNotNull("variety", Variety) + .AddIfNotNull("tag", Tag) + .AddIfNotNull("validity_ttl", ValidityTTL) + .AddIfNotNull("iceberg_legs", IcebergLegs) + .AddIfNotNull("iceberg_quantity", IcebergQuantity) + .AddIfNotNull("auction_number", AuctionNumber); + + return PostAsync($"/orders/{Variety}", formData: formDataBuilder.Build()); } /// @@ -418,7 +410,7 @@ public Dictionary PlaceOrder( /// For SL, SL-M etc. /// You can place orders of varieties; regular orders, after market orders, cover orders etc. /// Json response in the form of nested string dictionary. - public Dictionary ModifyOrder( + public Task ModifyOrder( string OrderId, string ParentOrderId = null, string Exchange = null, @@ -433,7 +425,7 @@ public Dictionary ModifyOrder( decimal? TriggerPrice = null, string Variety = Constants.Variety.Regular) { - var param = new Dictionary(); + var formDataBuilder = new ParametersBuilder(); string VarietyString = Variety; string ProductString = Product; @@ -441,31 +433,31 @@ public Dictionary ModifyOrder( if ((ProductString == "bo" || ProductString == "co") && VarietyString != ProductString) throw new Exception(string.Format("Invalid variety. It should be: {0}", ProductString)); - Utils.AddIfNotNull(param, "order_id", OrderId); - Utils.AddIfNotNull(param, "parent_order_id", ParentOrderId); - Utils.AddIfNotNull(param, "trigger_price", TriggerPrice.ToString()); - Utils.AddIfNotNull(param, "variety", Variety); + formDataBuilder.AddIfNotNull("order_id", OrderId) + .AddIfNotNull("parent_order_id", ParentOrderId) + .AddIfNotNull("trigger_price", TriggerPrice) + .AddIfNotNull("variety", Variety); if (VarietyString == "bo" && ProductString == "bo") { - Utils.AddIfNotNull(param, "quantity", Quantity.ToString()); - Utils.AddIfNotNull(param, "price", Price.ToString()); - Utils.AddIfNotNull(param, "disclosed_quantity", DisclosedQuantity.ToString()); + formDataBuilder.AddIfNotNull("quantity", Quantity) + .AddIfNotNull("price", Price) + .AddIfNotNull("disclosed_quantity", DisclosedQuantity); } else if (VarietyString != "co" && ProductString != "co") { - Utils.AddIfNotNull(param, "exchange", Exchange); - Utils.AddIfNotNull(param, "tradingsymbol", TradingSymbol); - Utils.AddIfNotNull(param, "transaction_type", TransactionType); - Utils.AddIfNotNull(param, "quantity", Quantity.ToString()); - Utils.AddIfNotNull(param, "price", Price.ToString()); - Utils.AddIfNotNull(param, "product", Product); - Utils.AddIfNotNull(param, "order_type", OrderType); - Utils.AddIfNotNull(param, "validity", Validity); - Utils.AddIfNotNull(param, "disclosed_quantity", DisclosedQuantity.ToString()); + formDataBuilder.AddIfNotNull("exchange", Exchange) + .AddIfNotNull("tradingsymbol", TradingSymbol) + .AddIfNotNull("transaction_type", TransactionType) + .AddIfNotNull("quantity", Quantity) + .AddIfNotNull("price", Price) + .AddIfNotNull("product", Product) + .AddIfNotNull("order_type", OrderType) + .AddIfNotNull("validity", Validity) + .AddIfNotNull("disclosed_quantity", DisclosedQuantity); } - return Put(Routes.Order.Modify, param); + return PutAsync($"/orders/{Variety}/{OrderId}", formData: formDataBuilder.Build()); } /// @@ -475,31 +467,21 @@ public Dictionary ModifyOrder( /// You can place orders of varieties; regular orders, after market orders, cover orders etc. /// Id of the parent order (obtained from the /orders call) as BO is a multi-legged order /// Json response in the form of nested string dictionary. - public Dictionary CancelOrder(string OrderId, string Variety = Constants.Variety.Regular, string ParentOrderId = null) + public Task CancelOrderAsync(string OrderId, string Variety = Constants.Variety.Regular, string ParentOrderId = null) { - var param = new Dictionary(); + var queryParametersBuilder = new ParametersBuilder() + .AddIfNotNull("parent_order_id", ParentOrderId);//TODO undocumented parameter - Utils.AddIfNotNull(param, "order_id", OrderId); - Utils.AddIfNotNull(param, "parent_order_id", ParentOrderId); - Utils.AddIfNotNull(param, "variety", Variety); - - return Delete(Routes.Order.Cancel, param); + return DeleteAsync($"/orders/{Variety}/{OrderId}", queryParameters: queryParametersBuilder.Build()); } /// /// Gets the collection of orders from the orderbook. /// /// List of orders. - public List GetOrders() + public Task> GetOrdersAsync() { - var ordersData = Get(Routes.Order.AllOrders); - - List orders = new List(); - - foreach (Dictionary item in ordersData["data"]) - orders.Add(new Order(item)); - - return orders; + return GetAsync>("/orders"); } /// @@ -507,19 +489,9 @@ public List GetOrders() /// /// Unique order id /// List of order objects. - public List GetOrderHistory(string OrderId) + public Task> GetOrderHistoryAsync(string OrderId) { - var param = new Dictionary(); - param.Add("order_id", OrderId); - - var orderData = Get(Routes.Order.History, param); - - List orderhistory = new List(); - - foreach (Dictionary item in orderData["data"]) - orderhistory.Add(new Order(item)); - - return orderhistory; + return GetAsync>($"/orders/{OrderId}"); } /// @@ -529,34 +501,21 @@ public List GetOrderHistory(string OrderId) /// /// is the ID of the order (optional) whose trades are to be retrieved. If no `OrderId` is specified, all trades for the day are returned. /// List of trades of given order. - public List GetOrderTrades(string OrderId = null) + public Task> GetOrderTradesAsync(string OrderId = null) { - Dictionary tradesdata; if (!string.IsNullOrEmpty(OrderId)) - { - var param = new Dictionary(); - param.Add("order_id", OrderId); - tradesdata = Get(Routes.Order.Trades, param); - } + return GetAsync>($"/orders/{OrderId}/trades"); else - tradesdata = Get(Routes.Order.AllTrades); - - List trades = new List(); - - foreach (Dictionary item in tradesdata["data"]) - trades.Add(new Trade(item)); - - return trades; + return GetAsync>("/trades"); } /// /// Retrieve the list of positions. /// /// Day and net positions. - public PositionResponse GetPositions() + public Task GetPositionsAsync() { - var positionsdata = Get(Routes.Portfolio.Positions); - return new PositionResponse(positionsdata["data"]); + return GetAsync("/portfolio/positions"); } /// @@ -772,16 +731,9 @@ public Dictionary GetTriggerRange(string[] InstrumentId, st /// Retrieve the list of GTTs. /// /// List of GTTs. - public List GetGTTs() + public Task> GetGTTsAsync() { - var gttsdata = Get(Routes.GTT.AllGTTs); - - List gtts = new List(); - - foreach (Dictionary item in gttsdata["data"]) - gtts.Add(new GTT(item)); - - return gtts; + return GetAsync>("/gtt/triggers"); } @@ -790,14 +742,9 @@ public List GetGTTs() /// /// Id of the GTT /// GTT info - public GTT GetGTT(int GTTId) + public Task GetGTTAsync(int GTTId) { - var param = new Dictionary(); - param.Add("id", GTTId.ToString()); - - var gttdata = Get(Routes.GTT.Info, param); - - return new GTT(gttdata["data"]); + return GetAsync($"/gtt/triggers/{GTTId}"); } /// @@ -805,35 +752,39 @@ public GTT GetGTT(int GTTId) /// /// Contains the parameters for the GTT order /// Json response in the form of nested string dictionary. - public Dictionary PlaceGTT(GTTParams gttParams) + public Task PlaceGTTAsync(GTTParams gttParams) { - var condition = new Dictionary(); - condition.Add("exchange", gttParams.Exchange); - condition.Add("tradingsymbol", gttParams.TradingSymbol); - condition.Add("trigger_values", gttParams.TriggerPrices); - condition.Add("last_price", gttParams.LastPrice); - condition.Add("instrument_token", gttParams.InstrumentToken); - - var ordersParam = new List>(); + var condition = new Dictionary + { + { "exchange", gttParams.Exchange }, + { "tradingsymbol", gttParams.TradingSymbol }, + { "trigger_values", gttParams.TriggerPrices }, + { "last_price", gttParams.LastPrice }, + { "instrument_token", gttParams.InstrumentToken } //TODO undocumented + }; + + var ordersParam = new List>(); foreach (var o in gttParams.Orders) { - var order = new Dictionary(); - order["exchange"] = gttParams.Exchange; - order["tradingsymbol"] = gttParams.TradingSymbol; - order["transaction_type"] = o.TransactionType; - order["quantity"] = o.Quantity; - order["price"] = o.Price; - order["order_type"] = o.OrderType; - order["product"] = o.Product; + var order = new Dictionary() + { + { "exchange", gttParams.Exchange }, + { "tradingsymbol", gttParams.TradingSymbol }, + { "transaction_type", o.TransactionType }, + { "quantity", o.Quantity }, + { "price", o.Price }, + { "order_type", o.OrderType }, + { "product", o.Product }, + }; ordersParam.Add(order); } - var parms = new Dictionary(); - parms.Add("condition", Utils.JsonSerialize(condition)); - parms.Add("orders", Utils.JsonSerialize(ordersParam)); - parms.Add("type", gttParams.TriggerType); + var formDataBuilder = new ParametersBuilder() + .Add("condition", JsonSerializer.Serialize(condition, JsonSerializerOptions)) + .Add("orders", JsonSerializer.Serialize(ordersParam, JsonSerializerOptions)) + .Add("type", gttParams.TriggerType); - return Post(Routes.GTT.Place, parms); + return PostAsync("/gtt/triggers", formData: formDataBuilder.Build()); } /// @@ -842,36 +793,39 @@ public Dictionary PlaceGTT(GTTParams gttParams) /// Id of the GTT to be modified /// Contains the parameters for the GTT order /// Json response in the form of nested string dictionary. - public Dictionary ModifyGTT(int GTTId, GTTParams gttParams) + public Task ModifyGTTAsync(int GTTId, GTTParams gttParams) { - var condition = new Dictionary(); - condition.Add("exchange", gttParams.Exchange); - condition.Add("tradingsymbol", gttParams.TradingSymbol); - condition.Add("trigger_values", gttParams.TriggerPrices); - condition.Add("last_price", gttParams.LastPrice); - condition.Add("instrument_token", gttParams.InstrumentToken); - - var ordersParam = new List>(); + var condition = new Dictionary + { + { "exchange", gttParams.Exchange }, + { "tradingsymbol", gttParams.TradingSymbol }, + { "trigger_values", gttParams.TriggerPrices }, + { "last_price", gttParams.LastPrice }, + { "instrument_token", gttParams.InstrumentToken } //TODO undocumented + }; + + var ordersParam = new List>(); foreach (var o in gttParams.Orders) { - var order = new Dictionary(); - order["exchange"] = gttParams.Exchange; - order["tradingsymbol"] = gttParams.TradingSymbol; - order["transaction_type"] = o.TransactionType; - order["quantity"] = o.Quantity; - order["price"] = o.Price; - order["order_type"] = o.OrderType; - order["product"] = o.Product; + var order = new Dictionary() + { + { "exchange", gttParams.Exchange }, + { "tradingsymbol", gttParams.TradingSymbol }, + { "transaction_type", o.TransactionType }, + { "quantity", o.Quantity }, + { "price", o.Price }, + { "order_type", o.OrderType }, + { "product", o.Product }, + }; ordersParam.Add(order); } - var parms = new Dictionary(); - parms.Add("condition", Utils.JsonSerialize(condition)); - parms.Add("orders", Utils.JsonSerialize(ordersParam)); - parms.Add("type", gttParams.TriggerType); - parms.Add("id", GTTId.ToString()); + var formDataBuilder = new ParametersBuilder() + .Add("condition", JsonSerializer.Serialize(condition, JsonSerializerOptions)) + .Add("orders", JsonSerializer.Serialize(ordersParam, JsonSerializerOptions)) + .Add("type", gttParams.TriggerType); - return Put(Routes.GTT.Modify, parms); + return PutAsync($"/gtt/triggers/{GTTId}", formDataBuilder.Build()); } /// @@ -879,12 +833,9 @@ public Dictionary ModifyGTT(int GTTId, GTTParams gttParams) /// /// Id of the GTT to be modified /// Json response in the form of nested string dictionary. - public Dictionary CancelGTT(int GTTId) + public Task CancelGTT(int GTTId) { - var parms = new Dictionary(); - parms.Add("id", GTTId.ToString()); - - return Delete(Routes.GTT.Delete, parms); + return DeleteAsync($"/gtt/triggers/{GTTId}"); } #endregion GTT @@ -1169,21 +1120,21 @@ private dynamic Delete(string Route, dynamic Params = null) /// /// Adds extra headers to request /// - /// Request object to add headers - private void AddExtraHeaders(ref HttpRequestMessage Req) + /// Request object to add headers + private void AddExtraHeaders(HttpRequestMessage request) { var KiteAssembly = Assembly.GetAssembly(typeof(Kite)); if (KiteAssembly != null) { - Req.Headers.UserAgent.TryParseAdd("KiteConnect.Net/" + KiteAssembly.GetName().Version); + request.Headers.UserAgent.TryParseAdd("KiteConnect.Net/" + KiteAssembly.GetName().Version); } - Req.Headers.Add("X-Kite-Version", "3"); - Req.Headers.Add("Authorization", "token " + _apiKey + ":" + _accessToken); + request.Headers.Add("X-Kite-Version", "3"); + request.Headers.Add("Authorization", "token " + _apiKey + ":" + _accessToken); if (_enableLogging) { - foreach (var header in Req.Headers) + foreach (var header in request.Headers) { Console.WriteLine("DEBUG: " + header.Key + ": " + string.Join(",", header.Value.ToArray())); } @@ -1237,7 +1188,7 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict request.RequestUri = new Uri(url); request.Method = new HttpMethod(Method); - AddExtraHeaders(ref request); + AddExtraHeaders(request); if (_enableLogging) Console.WriteLine("DEBUG: " + Method + " " + url + "\n" + requestBody); @@ -1265,7 +1216,7 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict request.RequestUri = new Uri(url); request.Method = new HttpMethod(Method); if (_enableLogging) Console.WriteLine("DEBUG: " + Method + " " + url); - AddExtraHeaders(ref request); + AddExtraHeaders(request); } HttpResponseMessage response = httpClient.Send(request); @@ -1315,13 +1266,68 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict } - private async Task GetAsync(string path, CancellationToken cancellationToken) + private Task GetAsync(string path, IReadOnlyCollection> queryParameters = null, CancellationToken cancellationToken = default) + { + string url = BuildUrl(_root, path, queryParameters); + return SendRequestAsync(HttpMethod.Get, url, cancellationToken: cancellationToken); + } + + private Task PostAsync(string path, IReadOnlyCollection> queryParameters = null, IReadOnlyCollection> formData = default, CancellationToken cancellationToken = default) + { + string url = BuildUrl(_root, path, queryParameters); + HttpContent content = null; + if (formData != null && formData.Count > 0) + content = new FormUrlEncodedContent(formData); + return SendRequestAsync(HttpMethod.Post, url, content, cancellationToken); + } + + private Task PutAsync(string path, IReadOnlyCollection> queryParameters = null, IReadOnlyCollection> formData = default, CancellationToken cancellationToken = default) + { + string url = BuildUrl(_root, path, queryParameters); + HttpContent content = null; + if (formData != null && formData.Count > 0) + content = new FormUrlEncodedContent(formData); + return SendRequestAsync(HttpMethod.Put, url, content, cancellationToken); + } + + private Task DeleteAsync(string path, IReadOnlyCollection> queryParameters = null, CancellationToken cancellationToken = default) + { + string url = BuildUrl(_root, path, queryParameters); + return SendRequestAsync(HttpMethod.Delete, url, cancellationToken: cancellationToken); + } + + private async Task SendRequestAsync(HttpMethod httpMethod, string url, HttpContent content = null, CancellationToken cancellationToken = default) + { + using var httpRequestMessage = new HttpRequestMessage(httpMethod, url); + AddExtraHeaders(httpRequestMessage); + if (content != null) + httpRequestMessage.Content = content; + using var httpResponse = await httpClient.SendAsync(httpRequestMessage); + return await ParseResponseAsync(httpResponse, cancellationToken); + } + + private static string BuildUrl(string baseUrl, string path, IReadOnlyCollection> queryParameters) + { + string url = baseUrl + path; + if (queryParameters != null && queryParameters.Count > 0) + { + var uriBuilder = new UriBuilder(url); + var existingQueryParamters = HttpUtility.ParseQueryString(url.Contains('?') ? uriBuilder.Query : string.Empty); + foreach (var item in queryParameters) + { + existingQueryParamters.Add(item.Key, item.Value); + } + uriBuilder.Query = existingQueryParamters.ToString(); + url = uriBuilder.Uri.ToString(); + } + return url; + } + + private async Task ParseResponseAsync(HttpResponseMessage httpResponse, CancellationToken cancellationToken) { - string url = _root + path; - var httpResponse = await httpClient.GetAsync(url, cancellationToken); if (httpResponse.IsSuccessStatusCode) { - var response = await httpResponse.Content.ReadFromJsonAsync>(jsonSerializerOptions, cancellationToken); + var response = await httpResponse.Content.ReadFromJsonAsync>(JsonSerializerOptions, cancellationToken); if (response.Status == ResponseStatus.Success) return response.Data; else @@ -1336,7 +1342,7 @@ private async Task GetAsync(string path, CancellationToken cancellationTok private async Task ThrowErrorAsync(HttpResponseMessage httpResponse, CancellationToken cancellationToken) { - var response = await httpResponse.Content.ReadFromJsonAsync(jsonSerializerOptions, cancellationToken); + var response = await httpResponse.Content.ReadFromJsonAsync(JsonSerializerOptions, cancellationToken); switch (response.ErrorType) { case "GeneralException": throw new GeneralException(response.Message, httpResponse.StatusCode); diff --git a/KiteConnect/ParametersBuilder.cs b/KiteConnect/ParametersBuilder.cs new file mode 100644 index 0000000..24f08fe --- /dev/null +++ b/KiteConnect/ParametersBuilder.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; + +namespace KiteConnect +{ + internal readonly struct ParametersBuilder + { + private readonly List> _parameters; + public ParametersBuilder() + { + _parameters = new List>(); + } + + public ParametersBuilder Add(string key, string value) + { + _parameters.Add(new KeyValuePair(key, value)); + return this; + } + + public ParametersBuilder AddIfNotNull(string key, string value) + { + if (value != null) + _parameters.Add(new KeyValuePair(key, value)); + return this; + } + + public ParametersBuilder Add(string key, int value) + { + _parameters.Add(new KeyValuePair(key, value.ToString())); + return this; + } + + public ParametersBuilder Add(string key, decimal value) + { + _parameters.Add(new KeyValuePair(key, value.ToString())); + return this; + } + + public ParametersBuilder AddIfNotNull(string key, int? value) + { + if (value != null) + _parameters.Add(new KeyValuePair(key, value.ToString())); + return this; + } + + public ParametersBuilder AddIfNotNull(string key, decimal? value) + { + if (value != null) + _parameters.Add(new KeyValuePair(key, value.ToString())); + return this; + } + + public IReadOnlyCollection> Build() + { + return _parameters; + } + } +} diff --git a/KiteConnect/Routes.cs b/KiteConnect/Routes.cs index ae07305..b446b51 100644 --- a/KiteConnect/Routes.cs +++ b/KiteConnect/Routes.cs @@ -4,12 +4,6 @@ public static class Routes { public const string Parameters = "/parameters"; - public static class API - { - public const string Token = "/session/token"; - public const string Refresh = "/session/refresh_token"; - } - public static class Instrument { public const string Margins = "/margins/{segment}"; @@ -33,13 +27,6 @@ public static class Basket public const string Margins = "/margins/basket"; } - public static class User - { - public const string Profile = "/user/profile"; - public const string Margins = "/user/margins"; - public const string SegmentMargins = "/user/margins/{segment}"; - } - public static class GTT { public const string AllGTTs = "/gtt/triggers"; diff --git a/KiteConnect/Structures.cs b/KiteConnect/Structures.cs index b092d86..cc4d042 100644 --- a/KiteConnect/Structures.cs +++ b/KiteConnect/Structures.cs @@ -1,8 +1,8 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Net; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; namespace KiteConnect @@ -26,6 +26,16 @@ internal class ErrorResponse public string ErrorType { get; set; } } + internal class WebsocketMessage + { + public string Type { get; set; } + } + + internal class WebsocketMessage : WebsocketMessage + { + public T Data { get; set; } + } + /// /// Tick data structure /// @@ -637,58 +647,23 @@ public OrderMarginPNL(Dictionary data) /// public class Position { - public Position(Dictionary data) - { - try - { - Product = data["product"]; - OvernightQuantity = Convert.ToInt32(data["overnight_quantity"]); - Exchange = data["exchange"]; - SellValue = data["sell_value"]; - BuyM2M = data["buy_m2m"]; - LastPrice = data["last_price"]; - TradingSymbol = data["tradingsymbol"]; - Realised = data["realised"]; - PNL = data["pnl"]; - Multiplier = data["multiplier"]; - SellQuantity = Convert.ToInt32(data["sell_quantity"]); - SellM2M = data["sell_m2m"]; - BuyValue = data["buy_value"]; - BuyQuantity = Convert.ToInt32(data["buy_quantity"]); - AveragePrice = data["average_price"]; - Unrealised = data["unrealised"]; - Value = data["value"]; - BuyPrice = data["buy_price"]; - SellPrice = data["sell_price"]; - M2M = data["m2m"]; - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - ClosePrice = data["close_price"]; - Quantity = Convert.ToInt32(data["quantity"]); - DayBuyQuantity = Convert.ToInt32(data["day_buy_quantity"]); - DayBuyValue = data["day_buy_value"]; - DayBuyPrice = data["day_buy_price"]; - DaySellQuantity = Convert.ToInt32(data["day_sell_quantity"]); - DaySellValue = data["day_sell_value"]; - DaySellPrice = data["day_sell_price"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - public string Product { get; set; } public decimal OvernightQuantity { get; set; } public string Exchange { get; set; } public decimal SellValue { get; set; } + + [JsonPropertyName("buy_m2m")] public decimal BuyM2M { get; set; } public decimal LastPrice { get; set; } + + [JsonPropertyName("tradingsymbol")] public string TradingSymbol { get; set; } public decimal Realised { get; set; } public decimal PNL { get; set; } public decimal Multiplier { get; set; } public decimal SellQuantity { get; set; } + + [JsonPropertyName("sell_m2m")] public decimal SellM2M { get; set; } public decimal BuyValue { get; set; } public decimal BuyQuantity { get; set; } @@ -697,6 +672,8 @@ public Position(Dictionary data) public decimal Value { get; set; } public decimal BuyPrice { get; set; } public decimal SellPrice { get; set; } + + [JsonPropertyName("m2m")] public decimal M2M { get; set; } public uint InstrumentToken { get; set; } public decimal ClosePrice { get; set; } @@ -714,17 +691,6 @@ public Position(Dictionary data) /// public class PositionResponse { - public PositionResponse(Dictionary data) - { - Day = new List(); - Net = new List(); - - foreach (Dictionary item in data["day"]) - Day.Add(new Position(item)); - foreach (Dictionary item in data["net"]) - Net.Add(new Position(item)); - } - public List Day { get; set; } public List Net { get; set; } } @@ -734,65 +700,6 @@ public PositionResponse(Dictionary data) /// public class Order { - public Order(Dictionary data) - { - try - { - AveragePrice = data["average_price"]; - CancelledQuantity = Convert.ToInt32(data["cancelled_quantity"]); - DisclosedQuantity = Convert.ToInt32(data["disclosed_quantity"]); - Exchange = data["exchange"]; - ExchangeOrderId = data["exchange_order_id"]; - ExchangeTimestamp = Utils.StringToDate(data["exchange_timestamp"]); - FilledQuantity = Convert.ToInt32(data["filled_quantity"]); - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - OrderId = data["order_id"]; - OrderTimestamp = Utils.StringToDate(data["order_timestamp"]); - OrderType = data["order_type"]; - ParentOrderId = data["parent_order_id"]; - PendingQuantity = Convert.ToInt32(data["pending_quantity"]); - PlacedBy = data["placed_by"]; - Price = data["price"]; - Product = data["product"]; - Quantity = Convert.ToInt32(data["quantity"]); - Status = data["status"]; - StatusMessage = data["status_message"]; - Tag = data["tag"]; - Tags = new List(); - if (data.ContainsKey("tags")) - { - Tags = ((data["tags"] ?? Tags) as ArrayList).Cast().ToList(); - } - Tradingsymbol = data["tradingsymbol"]; - TransactionType = data["transaction_type"]; - TriggerPrice = data["trigger_price"]; - Validity = data["validity"]; - ValidityTTL = 0; - if (data.ContainsKey("validity_ttl")) - { - ValidityTTL = Convert.ToInt32(data["validity_ttl"]); - } - Variety = data["variety"]; - - AuctionNumber = 0; - if (data.ContainsKey("auction_number")) - { - AuctionNumber = Convert.ToInt32(data["auction_number"]); - } - - Meta = new Dictionary(); - if (data.ContainsKey("meta")) - { - Meta = data["meta"]; - } - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - public decimal AveragePrice { get; set; } public decimal CancelledQuantity { get; set; } public decimal DisclosedQuantity { get; set; } @@ -821,7 +728,7 @@ public Order(Dictionary data) public int ValidityTTL { get; set; } public int AuctionNumber { get; set; } public string Variety { get; set; } - public Dictionary Meta { get; set; } + public JsonNode Meta { get; set; } } /// @@ -829,32 +736,10 @@ public Order(Dictionary data) /// public class GTT { - public GTT(Dictionary data) - { - try - { - Id = Convert.ToInt32(data["id"]); - Condition = new GTTCondition(data["condition"]); - TriggerType = data["type"]; - - Orders = new List(); - foreach (Dictionary item in data["orders"]) - Orders.Add(new GTTOrder(item)); - - Status = data["status"]; - CreatedAt = Utils.StringToDate(data["created_at"]); - UpdatedAt = Utils.StringToDate(data["updated_at"]); - ExpiresAt = Utils.StringToDate(data["expires_at"]); - Meta = new GTTMeta(data["meta"]); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public int Id { get; set; } public GTTCondition? Condition { get; set; } + + [JsonPropertyName("type")] public string TriggerType { get; set; } public List Orders { get; set; } public string Status { get; set; } @@ -869,18 +754,6 @@ public GTT(Dictionary data) /// public class GTTMeta { - public GTTMeta(Dictionary data) - { - try - { - RejectionReason = data != null && data.ContainsKey("rejection_reason") ? data["rejection_reason"] : ""; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public string RejectionReason { get; set; } } @@ -889,28 +762,10 @@ public GTTMeta(Dictionary data) /// public class GTTCondition { - public GTTCondition(Dictionary data) - { - try - { - InstrumentToken = 0; - if (data.ContainsKey("instrument_token")) - { - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - } - Exchange = data["exchange"]; - TradingSymbol = data["tradingsymbol"]; - TriggerValues = (data["trigger_values"] as ArrayList).Cast().ToList(); - LastPrice = data["last_price"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public uint InstrumentToken { get; set; } public string Exchange { get; set; } + + [JsonPropertyName("tradingsymbol")] public string TradingSymbol { get; set; } public List TriggerValues { get; set; } public decimal LastPrice { get; set; } @@ -921,23 +776,6 @@ public GTTCondition(Dictionary data) /// public class GTTOrder { - public GTTOrder(Dictionary data) - { - try - { - TransactionType = data["transaction_type"]; - Product = data["product"]; - OrderType = data["order_type"]; - Quantity = Convert.ToInt32(data["quantity"]); - Price = data["price"]; - Result = data["result"] == null ? null : new GTTResult(data["result"]); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public string TransactionType { get; set; } public string Product { get; set; } public string OrderType { get; set; } @@ -951,22 +789,11 @@ public GTTOrder(Dictionary data) /// public class GTTResult { - public GTTResult(Dictionary data) - { - try - { - OrderResult = data["order_result"] == null ? null : new GTTOrderResult(data["order_result"]); - Timestamp = data["timestamp"]; - TriggeredAtPrice = data["triggered_at"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - + //TODO missing some documented fields public GTTOrderResult? OrderResult { get; set; } public string Timestamp { get; set; } + + [JsonPropertyName("triggered_at")] public decimal TriggeredAtPrice { get; set; } } @@ -975,19 +802,6 @@ public GTTResult(Dictionary data) /// public class GTTOrderResult { - public GTTOrderResult(Dictionary data) - { - try - { - OrderId = data["order_id"]; - RejectionReason = data["rejection_reason"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public string OrderId { get; set; } public string RejectionReason { get; set; } } @@ -1070,30 +884,6 @@ public Instrument(Dictionary data) /// public class Trade { - public Trade(Dictionary data) - { - try - { - TradeId = data["trade_id"]; - OrderId = data["order_id"]; - ExchangeOrderId = data["exchange_order_id"]; - Tradingsymbol = data["tradingsymbol"]; - Exchange = data["exchange"]; - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - TransactionType = data["transaction_type"]; - Product = data["product"]; - AveragePrice = data["average_price"]; - Quantity = Convert.ToInt32(data["quantity"]); - FillTimestamp = Utils.StringToDate(data["fill_timestamp"]); - ExchangeTimestamp = Utils.StringToDate(data["exchange_timestamp"]); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - public string TradeId { get; set; } public string OrderId { get; set; } public string ExchangeOrderId { get; set; } @@ -1139,36 +929,11 @@ public TrigerRange(Dictionary data) /// public class User { - public User(Dictionary data) - { - try - { - APIKey = data["data"]["api_key"]; - Products = (string[])data["data"]["products"].ToArray(typeof(string)); - UserName = data["data"]["user_name"]; - UserShortName = data["data"]["user_shortname"]; - AvatarURL = data["data"]["avatar_url"]; - Broker = data["data"]["broker"]; - AccessToken = data["data"]["access_token"]; - PublicToken = data["data"]["public_token"]; - RefreshToken = data["data"]["refresh_token"]; - UserType = data["data"]["user_type"]; - UserId = data["data"]["user_id"]; - LoginTime = Utils.StringToDate(data["data"]["login_time"]); - Exchanges = (string[])data["data"]["exchanges"].ToArray(typeof(string)); - OrderTypes = (string[])data["data"]["order_types"].ToArray(typeof(string)); - Email = data["data"]["email"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - public string APIKey { get; set; } public string[] Products { get; set; } public string UserName { get; set; } + + [JsonPropertyName("user_shortname")] public string UserShortName { get; set; } public string AvatarURL { get; set; } public string Broker { get; set; } @@ -1185,19 +950,6 @@ public User(Dictionary data) public class TokenSet { - public TokenSet(Dictionary data) - { - try - { - UserId = data["data"]["user_id"]; - AccessToken = data["data"]["access_token"]; - RefreshToken = data["data"]["refresh_token"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } public string UserId { get; set; } public string AccessToken { get; set; } public string RefreshToken { get; set; } @@ -1579,4 +1331,13 @@ public MFSIP(Dictionary data) public string OrderId { get; set; } } + public class OrderResponse + { + public string OrderId { get; set; } + } + + public class GTTResponse + { + public int TriggerId { get; set; } + } } diff --git a/KiteConnect/Ticker.cs b/KiteConnect/Ticker.cs index 2111da2..06a1275 100644 --- a/KiteConnect/Ticker.cs +++ b/KiteConnect/Ticker.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net.WebSockets; using System.Text; -using System.Threading; +using System.Text.Json; namespace KiteConnect { @@ -395,14 +394,16 @@ private void _onData(byte[] Data, int Count, string MessageType) string message = Encoding.UTF8.GetString(Data.Take(Count).ToArray()); if (_debug) Console.WriteLine("WebSocket Message: " + message); - Dictionary messageDict = Utils.JsonDeserialize(message); - if (messageDict["type"] == "order") + WebsocketMessage messageDict = JsonSerializer.Deserialize(message, Kite.JsonSerializerOptions); + if (messageDict.Type == "order") { - OnOrderUpdate?.Invoke(new Order(messageDict["data"])); + var order = JsonSerializer.Deserialize>(message, Kite.JsonSerializerOptions); + OnOrderUpdate?.Invoke(order.Data); } - else if (messageDict["type"] == "error") + else if (messageDict.Type == "error") { - OnError?.Invoke(messageDict["data"]); + var error = JsonSerializer.Deserialize>(message, Kite.JsonSerializerOptions); + OnError?.Invoke(error.Data); } } else if (MessageType == "Close") diff --git a/KiteConnectSample/Program.cs b/KiteConnectSample/Program.cs index ed54c71..01e8d7b 100644 --- a/KiteConnectSample/Program.cs +++ b/KiteConnectSample/Program.cs @@ -1,5 +1,5 @@ -using System; -using KiteConnect; +using KiteConnect; +using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -32,7 +32,7 @@ static async Task Main(string[] args) try { - initSession(); + await initSession(); } catch (Exception e) { @@ -50,12 +50,12 @@ static async Task Main(string[] args) // Get all GTTs - List gtts = kite.GetGTTs(); + List gtts = await kite.GetGTTsAsync(); Console.WriteLine(Utils.JsonSerialize(gtts[0])); // Get GTT by Id - GTT gtt = kite.GetGTT(99691); + GTT gtt = await kite.GetGTTAsync(99691); Console.WriteLine(Utils.JsonSerialize(gtt)); // Cacncel GTT by Id @@ -102,15 +102,15 @@ static async Task Main(string[] args) ordersList.Add(order2Params); gttParams.Orders = ordersList; - var placeGTTResponse = kite.PlaceGTT(gttParams); + var placeGTTResponse = await kite.PlaceGTTAsync(gttParams); Console.WriteLine(Utils.JsonSerialize(placeGTTResponse)); - var modifyGTTResponse = kite.ModifyGTT(407301, gttParams); + var modifyGTTResponse = kite.ModifyGTTAsync(407301, gttParams); Console.WriteLine(Utils.JsonSerialize(modifyGTTResponse)); // Positions - PositionResponse positions = kite.GetPositions(); + PositionResponse positions = await kite.GetPositionsAsync(); Console.WriteLine(Utils.JsonSerialize(positions.Net[0])); kite.ConvertPosition( @@ -158,17 +158,17 @@ static async Task Main(string[] args) // Get all orders - List orders = kite.GetOrders(); + List orders = await kite.GetOrdersAsync(); Console.WriteLine(Utils.JsonSerialize(orders[0])); // Get order by id - List orderinfo = kite.GetOrderHistory("1234"); + List orderinfo = await kite.GetOrderHistoryAsync("1234"); Console.WriteLine(Utils.JsonSerialize(orderinfo[0])); // Place sell order - Dictionary response = kite.PlaceOrder( + OrderResponse response = await kite.PlaceOrderAsync( Exchange: Constants.Exchange.CDS, TradingSymbol: "USDINR17AUGFUT", TransactionType: Constants.Transaction.Sell, @@ -177,11 +177,11 @@ static async Task Main(string[] args) OrderType: Constants.OrderType.Market, Product: Constants.Product.MIS ); - Console.WriteLine("Order Id: " + response["data"]["order_id"]); + Console.WriteLine("Order Id: " + response.OrderId); // Place buy order - kite.PlaceOrder( + await kite.PlaceOrderAsync( Exchange: Constants.Exchange.CDS, TradingSymbol: "USDINR17AUGFUT", TransactionType: Constants.Transaction.Buy, @@ -193,11 +193,11 @@ static async Task Main(string[] args) // Cancel order by id - kite.CancelOrder("1234"); + await kite.CancelOrderAsync("1234"); //BO LIMIT order placing - kite.PlaceOrder( + await kite.PlaceOrderAsync( Exchange: Constants.Exchange.NSE, TradingSymbol: "ASHOKLEY", TransactionType: Constants.Transaction.Buy, @@ -213,7 +213,7 @@ static async Task Main(string[] args) // BO LIMIT exiting - kite.CancelOrder( + await kite.CancelOrderAsync( OrderId: "1234", Variety: Constants.Variety.BO, ParentOrderId: "5678" @@ -221,7 +221,7 @@ static async Task Main(string[] args) // BO SL order placing - kite.PlaceOrder( + await kite.PlaceOrderAsync( Exchange: Constants.Exchange.NSE, TradingSymbol: "ASHOKLEY", TransactionType: Constants.Transaction.Buy, @@ -238,7 +238,7 @@ static async Task Main(string[] args) // BO SL exiting - kite.CancelOrder( + await kite.CancelOrderAsync( OrderId: "1234", Variety: Constants.Variety.BO, ParentOrderId: "5678" @@ -246,7 +246,7 @@ static async Task Main(string[] args) // CO LIMIT order placing - kite.PlaceOrder( + await kite.PlaceOrderAsync( Exchange: Constants.Exchange.NSE, TradingSymbol: "ASHOKLEY", TransactionType: Constants.Transaction.Buy, @@ -261,7 +261,7 @@ static async Task Main(string[] args) // CO LIMIT exiting - kite.CancelOrder( + await kite.CancelOrderAsync( OrderId: "1234", Variety: Constants.Variety.BO, ParentOrderId: "5678" @@ -269,7 +269,7 @@ static async Task Main(string[] args) // CO MARKET order placing - kite.PlaceOrder( + await kite.PlaceOrderAsync( Exchange: Constants.Exchange.NSE, TradingSymbol: "ASHOKLEY", TransactionType: Constants.Transaction.Buy, @@ -283,14 +283,14 @@ static async Task Main(string[] args) // CO MARKET exiting - kite.CancelOrder( + await kite.CancelOrderAsync( OrderId: "1234", Variety: Constants.Variety.BO, ParentOrderId: "5678" ); // Place order with TTL validity - kite.PlaceOrder( + await kite.PlaceOrderAsync( Exchange: Constants.Exchange.NSE, TradingSymbol: "INFY", TransactionType: Constants.Transaction.Buy, @@ -303,7 +303,7 @@ static async Task Main(string[] args) ); // Place an Iceberg order - kite.PlaceOrder( + await kite.PlaceOrderAsync( Exchange: Constants.Exchange.NSE, TradingSymbol: "INFY", TransactionType: Constants.Transaction.Buy, @@ -318,7 +318,7 @@ static async Task Main(string[] args) // Trades - List trades = kite.GetOrderTrades("1234"); + List trades = await kite.GetOrderTradesAsync("1234"); Console.WriteLine(Utils.JsonSerialize(trades[0])); // Margins @@ -451,12 +451,12 @@ static async Task Main(string[] args) ticker.Close(); } - private static void initSession() + private static async Task initSession() { Console.WriteLine("Goto " + kite.GetLoginURL()); Console.WriteLine("Enter request token: "); string requestToken = Console.ReadLine(); - User user = kite.GenerateSession(requestToken, MySecret); + User user = await kite.GenerateSessionAsync(requestToken, MySecret); Console.WriteLine(Utils.JsonSerialize(user)); diff --git a/KiteConnectTest/KiteTest.cs b/KiteConnectTest/KiteTest.cs index a14cba7..40c0134 100644 --- a/KiteConnectTest/KiteTest.cs +++ b/KiteConnectTest/KiteTest.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using System.IO; using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading.Tasks; namespace KiteConnectTest @@ -13,8 +11,6 @@ namespace KiteConnectTest [TestClass] public class KiteTest { - private static readonly JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, Converters = { new JsonStringEnumConverter() } }; - MockServer ms; [TestInitialize] @@ -34,7 +30,7 @@ public void TestSetAccessToken() { Kite kite = new Kite("apikey"); kite.SetAccessToken("access_token"); - Assert.Throws(() => kite.GetPositions()); + Assert.ThrowsAsync(async () => await kite.GetPositionsAsync()); } @@ -60,12 +56,12 @@ public async Task TestProfile() } [TestMethod] - public void TestPositions() + public async Task TestPositions() { string json = File.ReadAllText(@"responses/positions.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - PositionResponse positionResponse = kite.GetPositions(); + PositionResponse positionResponse = await kite.GetPositionsAsync(); Assert.AreEqual(positionResponse.Net[0].TradingSymbol, "LEADMINI17DECFUT"); Assert.AreEqual(positionResponse.Day[0].TradingSymbol, "GOLDGUINEA17DECFUT"); } @@ -290,12 +286,12 @@ public void TestQuote() } [TestMethod] - public void TestOrders() + public async Task TestOrders() { string json = File.ReadAllText(@"responses/orders.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List orders = kite.GetOrders(); + List orders = await kite.GetOrdersAsync(); Assert.AreEqual(orders[0].Price, 72); @@ -304,7 +300,7 @@ public void TestOrders() Assert.AreEqual(orders[3].ValidityTTL, 2); - Assert.AreEqual(orders[3].Meta["iceberg"]["legs"], 5); + Assert.AreEqual(orders[3].Meta["iceberg"]["legs"].GetValue(), 5); Assert.AreEqual(orders[0].AuctionNumber, 10); @@ -312,12 +308,12 @@ public void TestOrders() } [TestMethod] - public void TestGTTs() + public async Task TestGTTs() { string json = File.ReadAllText(@"responses/gtt_get_orders.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List gtts = kite.GetGTTs(); + List gtts = await kite.GetGTTsAsync(); Assert.AreEqual(gtts[0].Id, 105099); Assert.AreEqual(gtts[0].Condition?.TriggerValues[0], 102m); @@ -326,23 +322,23 @@ public void TestGTTs() } [TestMethod] - public void TestGTT() + public async Task TestGTT() { string json = File.ReadAllText(@"responses/gtt_get_order.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - GTT gtt = kite.GetGTT(123); + GTT gtt = await kite.GetGTTAsync(123); Assert.AreEqual(gtt.Id, 123); } [TestMethod] - public void TestOrderInfo() + public async Task TestOrderInfo() { string json = File.ReadAllText(@"responses/orderinfo.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List orderhistory = kite.GetOrderHistory("171124000819854"); + List orderhistory = await kite.GetOrderHistoryAsync("171124000819854"); Assert.AreEqual(orderhistory[0].PendingQuantity, 100); } @@ -372,12 +368,12 @@ public void TestSegmentInstruments() } [TestMethod] - public void TestTrades() + public async Task TestTrades() { string json = File.ReadAllText(@"responses/trades.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List trades = kite.GetOrderTrades("151220000000000"); + List trades = await kite.GetOrderTradesAsync("151220000000000"); Assert.AreEqual(trades[0].TradeId, "159918"); } diff --git a/KiteConnectTest/responses/trades.json b/KiteConnectTest/responses/trades.json index 1ba0c1a..c87c75d 100644 --- a/KiteConnectTest/responses/trades.json +++ b/KiteConnectTest/responses/trades.json @@ -7,7 +7,7 @@ "exchange_order_id": "511220371736111", "tradingsymbol": "ACC", "exchange": "NSE", - "instrument_token": "22", + "instrument_token": 22, "transaction_type": "BUY", "product": "MIS", "average_price": 100.98, From 12c994095480a5ebaecd07afdae0572ed8f0b073 Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Fri, 6 Feb 2026 16:18:26 +0530 Subject: [PATCH 8/9] refactored remaining api --- KiteConnect/CandleJsonConverter.cs | 53 ++ ...rter.cs => CustomDateTimeJsonConverter.cs} | 4 +- KiteConnect/Kite.cs | 481 ++++++--------- KiteConnect/KiteConnect.csproj | 1 + KiteConnect/ParametersBuilder.cs | 21 +- KiteConnect/Structures.cs | 581 +++--------------- KiteConnectSample/Program.cs | 49 +- KiteConnectTest/KiteConnectTest.csproj | 7 + KiteConnectTest/KiteTest.cs | 136 ++-- KiteConnectTest/responses/historical-oi.json | 61 ++ KiteConnectTest/responses/instruments_all.csv | 2 +- KiteConnectTest/responses/mf_instruments.csv | 2 +- 12 files changed, 552 insertions(+), 846 deletions(-) create mode 100644 KiteConnect/CandleJsonConverter.cs rename KiteConnect/{CustomDateTimeConverter.cs => CustomDateTimeJsonConverter.cs} (77%) create mode 100644 KiteConnectTest/responses/historical-oi.json diff --git a/KiteConnect/CandleJsonConverter.cs b/KiteConnect/CandleJsonConverter.cs new file mode 100644 index 0000000..24d9aea --- /dev/null +++ b/KiteConnect/CandleJsonConverter.cs @@ -0,0 +1,53 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace KiteConnect +{ + internal class CandleJsonConverter : JsonConverter + { + public override Candle Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartArray) + throw new JsonException("Expected StartArray token."); + + var candle = new Candle(); + + reader.Read(); + candle.TimeStamp = DateTime.ParseExact(reader.GetString(), "yyyy-MM-ddTHH:mm:sszzz", CultureInfo.InvariantCulture); + + reader.Read(); + candle.Open = reader.GetDecimal(); + + reader.Read(); + candle.High = reader.GetDecimal(); + + reader.Read(); + candle.Low = reader.GetDecimal(); + + reader.Read(); + candle.Close = reader.GetDecimal(); + + reader.Read(); + candle.Volume = reader.GetUInt64(); + + reader.Read(); + if (reader.TokenType == JsonTokenType.EndArray) + return candle; + else + candle.OI = reader.GetUInt64(); + + reader.Read(); + if (reader.TokenType != JsonTokenType.EndArray) + throw new JsonException("Expected EndArray token."); + + return candle; + } + + public override void Write(Utf8JsonWriter writer, Candle value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } +} diff --git a/KiteConnect/CustomDateTimeConverter.cs b/KiteConnect/CustomDateTimeJsonConverter.cs similarity index 77% rename from KiteConnect/CustomDateTimeConverter.cs rename to KiteConnect/CustomDateTimeJsonConverter.cs index 8f17fc1..f5d716e 100644 --- a/KiteConnect/CustomDateTimeConverter.cs +++ b/KiteConnect/CustomDateTimeJsonConverter.cs @@ -5,13 +5,15 @@ namespace KiteConnect { - internal class CustomDateTimeConverter : JsonConverter + internal class CustomDateTimeJsonConverter : JsonConverter { public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var value = reader.GetString(); if (value.Length == 10) return DateTime.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture); + else if (value.Length == 16) + return DateTime.ParseExact(value, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture); else return DateTime.ParseExact(value, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); } diff --git a/KiteConnect/Kite.cs b/KiteConnect/Kite.cs index 4942ce5..6c4ca93 100644 --- a/KiteConnect/Kite.cs +++ b/KiteConnect/Kite.cs @@ -1,12 +1,15 @@ -using System; -using System.Collections; +using CsvHelper; +using System; using System.Collections.Generic; +using System.Globalization; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Net.Mime; using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; @@ -21,7 +24,7 @@ namespace KiteConnect /// public class Kite { - internal static readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, Converters = { new JsonStringEnumConverter(), new CustomDateTimeConverter() } }; + internal static readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, Converters = { new JsonStringEnumConverter(), new CustomDateTimeJsonConverter(), new CandleJsonConverter() } }; // Default root API endpoint. It's possible to // override this by passing the `Root` parameter during initialisation. private string _root = "https://api.kite.trade"; @@ -117,14 +120,15 @@ public string GetLoginURL() /// /// Do the token exchange with the `RequestToken` obtained after the login flow, - /// and retrieve the `AccessToken` required for all subsequent requests.The + /// and retrieve the `AccessToken` required for all subsequent requests.The /// response contains not just the `AccessToken`, but metadata for /// the user who has authenticated. /// /// Token obtained from the GET paramers after a successful login redirect. /// API secret issued with the API key. + /// /// User structure with tokens and profile data - public Task GenerateSessionAsync(string RequestToken, string AppSecret) + public Task GenerateSessionAsync(string RequestToken, string AppSecret, CancellationToken cancellationToken = default) { string checksum = Utils.SHA256Hash(_apiKey + RequestToken + AppSecret); @@ -133,35 +137,37 @@ public Task GenerateSessionAsync(string RequestToken, string AppSecret) .Add("request_token", RequestToken) .Add("checksum", checksum); - return PostAsync("/session/token", formData: formDataBuilder.Build()); + return PostAsync("/session/token", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// /// Kill the session by invalidating the access token /// /// Access token to invalidate. Default is the active access token. + /// /// Json response in the form of nested string dictionary. - public Task InvalidateAccessTokenAsync(string AccessToken = null) + public Task InvalidateAccessTokenAsync(string AccessToken = null, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder() .AddIfNotNull("api_key", _apiKey) .AddIfNotNull("access_token", AccessToken); - return DeleteAsync("/session/token", queryParameters: queryParametersBuilder.Build()); + return DeleteAsync("/session/token", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// /// Invalidates RefreshToken /// /// RefreshToken to invalidate + /// /// Json response in the form of nested string dictionary. - public Task InvalidateRefreshTokenAsync(string RefreshToken) + public Task InvalidateRefreshTokenAsync(string RefreshToken, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder() .AddIfNotNull("api_key", _apiKey) .AddIfNotNull("refresh_token", RefreshToken); - return DeleteAsync("/session/token", queryParameters: queryParametersBuilder.Build()); + return DeleteAsync("/session/token", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// @@ -169,8 +175,9 @@ public Task InvalidateRefreshTokenAsync(string RefreshToken) /// /// RefreshToken to renew the AccessToken. /// API secret issued with the API key. + /// /// TokenRenewResponse that contains new AccessToken and RefreshToken. - public Task RenewAccessTokenAsync(string RefreshToken, string AppSecret) + public Task RenewAccessTokenAsync(string RefreshToken, string AppSecret, CancellationToken cancellationToken = default) { string checksum = Utils.SHA256Hash(_apiKey + RefreshToken + AppSecret); var formDataBuilder = new ParametersBuilder() @@ -178,12 +185,13 @@ public Task RenewAccessTokenAsync(string RefreshToken, string AppSecre .AddIfNotNull("refresh_token", RefreshToken) .AddIfNotNull("checksum", checksum); - return PostAsync("/session/refresh_token", formData: formDataBuilder.Build()); + return PostAsync("/session/refresh_token", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// /// Gets currently logged in user details /// + /// /// User profile public Task GetProfileAsync(CancellationToken cancellationToken = default) { @@ -194,34 +202,11 @@ public Task GetProfileAsync(CancellationToken cancellationToken = defau /// A virtual contract provides detailed charges order-wise for brokerage, STT, stamp duty, exchange transaction charges, SEBI turnover charge, and GST. /// /// List of all order params to get contract notes for + /// /// List of contract notes for the params - public List GetVirtualContractNote(List ContractNoteParams) + public Task> GetVirtualContractNoteAsync(List ContractNoteParams, CancellationToken cancellationToken = default) { - var paramList = new List>(); - - foreach (var item in ContractNoteParams) - { - var param = new Dictionary(); - param["order_id"] = item.OrderID; - param["exchange"] = item.Exchange; - param["tradingsymbol"] = item.TradingSymbol; - param["transaction_type"] = item.TransactionType; - param["quantity"] = item.Quantity; - param["average_price"] = item.AveragePrice; - param["product"] = item.Product; - param["order_type"] = item.OrderType; - param["variety"] = item.Variety; - - paramList.Add(param); - } - - var contractNoteData = Post(Routes.Order.ContractNote, paramList, json: true); - - List contractNotes = new List(); - foreach (Dictionary item in contractNoteData["data"]) - contractNotes.Add(new ContractNote(item)); - - return contractNotes; + return PostJsonAsync, List>("/charges/orders", jsonData: ContractNoteParams, cancellationToken: cancellationToken); } /// @@ -229,40 +214,14 @@ public List GetVirtualContractNote(List Contra /// /// List of all order params to get margins for /// Mode of the returned response content. Eg: Constants.Margin.Mode.Compact + /// /// List of margins of order - public List GetOrderMargins(List OrderMarginParams, string Mode = null) + public Task> GetOrderMarginsAsync(List OrderMarginParams, string Mode = null, CancellationToken cancellationToken = default) { - var paramList = new List>(); - - foreach (var item in OrderMarginParams) - { - var param = new Dictionary(); - param["exchange"] = item.Exchange; - param["tradingsymbol"] = item.TradingSymbol; - param["transaction_type"] = item.TransactionType; - param["quantity"] = item.Quantity; - param["price"] = item.Price; - param["product"] = item.Product; - param["order_type"] = item.OrderType; - param["trigger_price"] = item.TriggerPrice; - param["variety"] = item.Variety; - - paramList.Add(param); - } - - var queryParams = new Dictionary(); - if (Mode != null) - { - queryParams["mode"] = Mode; - } + var queryParameterBuilder = new ParametersBuilder() + .AddIfNotNull("mode", Mode); - var orderMarginsData = Post(Routes.Order.Margins, paramList, QueryParams: queryParams, json: true); - - List orderMargins = new List(); - foreach (Dictionary item in orderMarginsData["data"]) - orderMargins.Add(new OrderMargin(item)); - - return orderMargins; + return PostJsonAsync, List>("/margins/orders", queryParameters: queryParameterBuilder.Build(), jsonData: OrderMarginParams, cancellationToken: cancellationToken); } /// @@ -271,37 +230,15 @@ public List GetOrderMargins(List OrderMarginPara /// List of all order params to get margins for /// Consider users positions while calculating margins /// Mode of the returned response content. Eg: Constants.Margin.Mode.Compact + /// /// List of margins of order - public BasketMargin GetBasketMargins(List OrderMarginParams, bool ConsiderPositions = true, string Mode = null) + public Task GetBasketMarginsAsync(List OrderMarginParams, bool ConsiderPositions = true, string Mode = null, CancellationToken cancellationToken = default) { - var paramList = new List>(); - - foreach (var item in OrderMarginParams) - { - var param = new Dictionary(); - param["exchange"] = item.Exchange; - param["tradingsymbol"] = item.TradingSymbol; - param["transaction_type"] = item.TransactionType; - param["quantity"] = item.Quantity; - param["price"] = item.Price; - param["product"] = item.Product; - param["order_type"] = item.OrderType; - param["trigger_price"] = item.TriggerPrice; - param["variety"] = item.Variety; - - paramList.Add(param); - } - - var queryParams = new Dictionary(); - queryParams["consider_positions"] = ConsiderPositions ? "true" : "false"; - if (Mode != null) - { - queryParams["mode"] = Mode; - } + var queryParameterBuilder = new ParametersBuilder() + .Add("consider_positions", ConsiderPositions) + .AddIfNotNull("mode", Mode); - var basketMarginsData = Post(Routes.Basket.Margins, paramList, QueryParams: queryParams, json: true); - - return new BasketMargin(basketMarginsData["data"]); + return PostJsonAsync, BasketMargin>("/margins/basket", queryParameters: queryParameterBuilder.Build(), jsonData: OrderMarginParams, cancellationToken: cancellationToken); } /// @@ -346,6 +283,8 @@ public Task GetMarginsAsync(string segment, CancellationToken cancel /// Order life span in minutes for TTL validity orders /// Total number of legs for iceberg order type (number of legs per Iceberg should be between 2 and 10) /// Split quantity for each iceberg leg order (Quantity/IcebergLegs) + /// A unique identifier for a particular auction + /// /// Json response in the form of nested string dictionary. public Task PlaceOrderAsync( string Exchange, @@ -366,7 +305,8 @@ public Task PlaceOrderAsync( int? ValidityTTL = null, int? IcebergLegs = null, decimal? IcebergQuantity = null, - string AuctionNumber = null + string AuctionNumber = null, + CancellationToken cancellationToken = default ) { var formDataBuilder = new ParametersBuilder() @@ -390,7 +330,7 @@ public Task PlaceOrderAsync( .AddIfNotNull("iceberg_quantity", IcebergQuantity) .AddIfNotNull("auction_number", AuctionNumber); - return PostAsync($"/orders/{Variety}", formData: formDataBuilder.Build()); + return PostAsync($"/orders/{Variety}", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// @@ -409,8 +349,9 @@ public Task PlaceOrderAsync( /// Quantity to disclose publicly (for equity trades) /// For SL, SL-M etc. /// You can place orders of varieties; regular orders, after market orders, cover orders etc. + /// /// Json response in the form of nested string dictionary. - public Task ModifyOrder( + public Task ModifyOrderAsync( string OrderId, string ParentOrderId = null, string Exchange = null, @@ -423,7 +364,8 @@ public Task ModifyOrder( string Validity = Constants.Validity.Day, decimal? DisclosedQuantity = null, decimal? TriggerPrice = null, - string Variety = Constants.Variety.Regular) + string Variety = Constants.Variety.Regular, + CancellationToken cancellationToken = default) { var formDataBuilder = new ParametersBuilder(); @@ -457,7 +399,7 @@ public Task ModifyOrder( .AddIfNotNull("disclosed_quantity", DisclosedQuantity); } - return PutAsync($"/orders/{Variety}/{OrderId}", formData: formDataBuilder.Build()); + return PutAsync($"/orders/{Variety}/{OrderId}", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// @@ -466,32 +408,35 @@ public Task ModifyOrder( /// Id of the order to be cancelled /// You can place orders of varieties; regular orders, after market orders, cover orders etc. /// Id of the parent order (obtained from the /orders call) as BO is a multi-legged order + /// /// Json response in the form of nested string dictionary. - public Task CancelOrderAsync(string OrderId, string Variety = Constants.Variety.Regular, string ParentOrderId = null) + public Task CancelOrderAsync(string OrderId, string Variety = Constants.Variety.Regular, string ParentOrderId = null, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder() .AddIfNotNull("parent_order_id", ParentOrderId);//TODO undocumented parameter - return DeleteAsync($"/orders/{Variety}/{OrderId}", queryParameters: queryParametersBuilder.Build()); + return DeleteAsync($"/orders/{Variety}/{OrderId}", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// /// Gets the collection of orders from the orderbook. /// + /// /// List of orders. - public Task> GetOrdersAsync() + public Task> GetOrdersAsync(CancellationToken cancellationToken = default) { - return GetAsync>("/orders"); + return GetAsync>("/orders", cancellationToken: cancellationToken); } /// /// Gets information about given OrderId. /// /// Unique order id + /// /// List of order objects. - public Task> GetOrderHistoryAsync(string OrderId) + public Task> GetOrderHistoryAsync(string OrderId, CancellationToken cancellationToken = default) { - return GetAsync>($"/orders/{OrderId}"); + return GetAsync>($"/orders/{OrderId}", cancellationToken: cancellationToken); } /// @@ -500,54 +445,44 @@ public Task> GetOrderHistoryAsync(string OrderId) /// These trades are individually recorded under an order. /// /// is the ID of the order (optional) whose trades are to be retrieved. If no `OrderId` is specified, all trades for the day are returned. + /// /// List of trades of given order. - public Task> GetOrderTradesAsync(string OrderId = null) + public Task> GetOrderTradesAsync(string OrderId = null, CancellationToken cancellationToken = default) { if (!string.IsNullOrEmpty(OrderId)) - return GetAsync>($"/orders/{OrderId}/trades"); + return GetAsync>($"/orders/{OrderId}/trades", cancellationToken: cancellationToken); else - return GetAsync>("/trades"); + return GetAsync>("/trades", cancellationToken: cancellationToken); } /// /// Retrieve the list of positions. /// + /// /// Day and net positions. - public Task GetPositionsAsync() + public Task GetPositionsAsync(CancellationToken cancellationToken = default) { - return GetAsync("/portfolio/positions"); + return GetAsync("/portfolio/positions", cancellationToken: cancellationToken); } /// /// Retrieve the list of equity holdings. /// + /// /// List of holdings. - public List GetHoldings() + public Task> GetHoldingsAsync(CancellationToken cancellationToken = default) { - var holdingsData = Get(Routes.Portfolio.Holdings); - - List holdings = new List(); - - foreach (Dictionary item in holdingsData["data"]) - holdings.Add(new Holding(item)); - - return holdings; + return GetAsync>("/portfolio/holdings", cancellationToken: cancellationToken); } /// /// Retrieve the list of auction instruments. /// + /// /// List of auction instruments. - public List GetAuctionInstruments() + public Task> GetAuctionInstrumentsAsync(CancellationToken cancellationToken = default) { - var instrumentsData = Get(Routes.Portfolio.AuctionInstruments); - - List instruments = new List(); - - foreach (Dictionary item in instrumentsData["data"]) - instruments.Add(new AuctionInstrument(item)); - - return instruments; + return GetAsync>("/portfolio/holdings/auctions", cancellationToken: cancellationToken); } /// @@ -560,110 +495,95 @@ public List GetAuctionInstruments() /// Quantity to convert /// Existing margin product of the position /// Margin product to convert to + /// /// Json response in the form of nested string dictionary. - public Dictionary ConvertPosition( + public Task ConvertPositionAsync( string Exchange, string TradingSymbol, string TransactionType, string PositionType, decimal? Quantity, string OldProduct, - string NewProduct) + string NewProduct, + CancellationToken cancellationToken = default) { - var param = new Dictionary(); - - Utils.AddIfNotNull(param, "exchange", Exchange); - Utils.AddIfNotNull(param, "tradingsymbol", TradingSymbol); - Utils.AddIfNotNull(param, "transaction_type", TransactionType); - Utils.AddIfNotNull(param, "position_type", PositionType); - Utils.AddIfNotNull(param, "quantity", Quantity.ToString()); - Utils.AddIfNotNull(param, "old_product", OldProduct); - Utils.AddIfNotNull(param, "new_product", NewProduct); + var formDataBuilder = new ParametersBuilder() + .AddIfNotNull("exchange", Exchange) + .AddIfNotNull("tradingsymbol", TradingSymbol) + .AddIfNotNull("transaction_type", TransactionType) + .AddIfNotNull("position_type", PositionType) + .AddIfNotNull("quantity", Quantity) + .AddIfNotNull("old_product", OldProduct) + .AddIfNotNull("new_product", NewProduct); - return Put(Routes.Portfolio.ModifyPositions, param); + return PutAsync("/portfolio/positions", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// /// Retrieve the list of market instruments available to trade. /// Note that the results could be large, several hundred KBs in size, - /// with tens of thousands of entries in the list. + /// with tens of thousands of entries in the list. /// /// Name of the exchange + /// /// List of instruments. - public List GetInstruments(string Exchange = null) + public IAsyncEnumerable GetInstrumentsAsync(string Exchange = null, CancellationToken cancellationToken = default) { - var param = new Dictionary(); - - List> instrumentsData; - if (string.IsNullOrEmpty(Exchange)) - instrumentsData = Get(Routes.Market.AllInstruments, param); + return GetCsvAsync("/instruments", cancellationToken: cancellationToken); else - { - param.Add("exchange", Exchange); - instrumentsData = Get(Routes.Market.Instruments, param); - } - - List instruments = new List(); - - foreach (Dictionary item in instrumentsData) - instruments.Add(new Instrument(item)); - - return instruments; + return GetCsvAsync($"/instruments/{Exchange}", cancellationToken: cancellationToken); } /// /// Retrieve quote and market depth of upto 200 instruments /// /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) + /// /// Dictionary of all Quote objects with keys as in InstrumentId - public Dictionary GetQuote(string[] InstrumentId) + public Task> GetQuoteAsync(string[] InstrumentId, CancellationToken cancellationToken = default) { - var param = new Dictionary(); - param.Add("i", InstrumentId); - Dictionary quoteData = Get(Routes.Market.Quote, param)["data"]; - - Dictionary quotes = new Dictionary(); - foreach (string item in quoteData.Keys) - quotes.Add(item, new Quote(quoteData[item])); + var queryParametersBuilder = new ParametersBuilder(); + foreach (var i in InstrumentId) + { + queryParametersBuilder.Add("i", i); + } - return quotes; + return GetAsync>("/quote", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// /// Retrieve LTP and OHLC of upto 200 instruments /// /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) + /// /// Dictionary of all OHLC objects with keys as in InstrumentId - public Dictionary GetOHLC(string[] InstrumentId) + public Task> GetOHLCAsync(string[] InstrumentId, CancellationToken cancellationToken = default) { - var param = new Dictionary(); - param.Add("i", InstrumentId); - Dictionary ohlcData = Get(Routes.Market.OHLC, param)["data"]; - - Dictionary ohlcs = new Dictionary(); - foreach (string item in ohlcData.Keys) - ohlcs.Add(item, new OHLC(ohlcData[item])); + var queryParametersBuilder = new ParametersBuilder(); + foreach (var i in InstrumentId) + { + queryParametersBuilder.Add("i", i); + } - return ohlcs; + return GetAsync>("/quote/ohlc", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// /// Retrieve LTP of upto 200 instruments /// /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) + /// /// Dictionary with InstrumentId as key and LTP as value. - public Dictionary GetLTP(string[] InstrumentId) + public Task> GetLTPAsync(string[] InstrumentId, CancellationToken cancellationToken = default) { - var param = new Dictionary(); - param.Add("i", InstrumentId); - Dictionary ltpData = Get(Routes.Market.LTP, param)["data"]; - - Dictionary ltps = new Dictionary(); - foreach (string item in ltpData.Keys) - ltps.Add(item, new LTP(ltpData[item])); + var queryParametersBuilder = new ParametersBuilder(); + foreach (var i in InstrumentId) + { + queryParametersBuilder.Add("i", i); + } - return ltps; + return GetAsync>("/quote/ltp", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// @@ -675,34 +595,29 @@ public Dictionary GetLTP(string[] InstrumentId) /// The candle record interval. Possible values are: minute, day, 3minute, 5minute, 10minute, 15minute, 30minute, 60minute /// Pass true to get continous data of expired instruments. /// Pass true to get open interest data. + /// /// List of Historical objects. - public List GetHistoricalData( + public Task GetHistoricalDataAsync( string InstrumentToken, DateTime FromDate, DateTime ToDate, string Interval, bool Continuous = false, - bool OI = false) + bool OI = false, + CancellationToken cancellationToken = default) { - var param = new Dictionary(); - - param.Add("instrument_token", InstrumentToken); - param.Add("from", FromDate.ToString("yyyy-MM-dd HH:mm:ss")); - param.Add("to", ToDate.ToString("yyyy-MM-dd HH:mm:ss")); - param.Add("interval", Interval); - param.Add("continuous", Continuous ? "1" : "0"); - param.Add("oi", OI ? "1" : "0"); - - var historicalData = Get(Routes.Market.Historical, param); - - List historicals = new List(); + var queryParametersBuilder = new ParametersBuilder(); - foreach (ArrayList item in historicalData["data"]["candles"]) - historicals.Add(new Historical(item)); + queryParametersBuilder.Add("from", FromDate); + queryParametersBuilder.Add("to", ToDate); + queryParametersBuilder.AddAsO1("continuous", Continuous); + queryParametersBuilder.AddAsO1("oi", OI); - return historicals; + return GetAsync($"/instruments/historical/{InstrumentToken}/{Interval}", queryParametersBuilder.Build(), cancellationToken: cancellationToken); } + //TODO undocumented API + /// /// Retrieve the buy/sell trigger range for Cover Orders. /// @@ -730,10 +645,11 @@ public Dictionary GetTriggerRange(string[] InstrumentId, st /// /// Retrieve the list of GTTs. /// + /// /// List of GTTs. - public Task> GetGTTsAsync() + public Task> GetGTTsAsync(CancellationToken cancellationToken = default) { - return GetAsync>("/gtt/triggers"); + return GetAsync>("/gtt/triggers", cancellationToken: cancellationToken); } @@ -741,23 +657,25 @@ public Task> GetGTTsAsync() /// Retrieve a single GTT /// /// Id of the GTT + /// /// GTT info - public Task GetGTTAsync(int GTTId) + public Task GetGTTAsync(int GTTId, CancellationToken cancellationToken = default) { - return GetAsync($"/gtt/triggers/{GTTId}"); + return GetAsync($"/gtt/triggers/{GTTId}", cancellationToken: cancellationToken); } /// /// Place a GTT order /// /// Contains the parameters for the GTT order + /// /// Json response in the form of nested string dictionary. - public Task PlaceGTTAsync(GTTParams gttParams) + public Task PlaceGTTAsync(GTTParams gttParams, CancellationToken cancellationToken = default) { var condition = new Dictionary { { "exchange", gttParams.Exchange }, - { "tradingsymbol", gttParams.TradingSymbol }, + { "tradingsymbol", gttParams.Tradingsymbol }, { "trigger_values", gttParams.TriggerPrices }, { "last_price", gttParams.LastPrice }, { "instrument_token", gttParams.InstrumentToken } //TODO undocumented @@ -769,7 +687,7 @@ public Task PlaceGTTAsync(GTTParams gttParams) var order = new Dictionary() { { "exchange", gttParams.Exchange }, - { "tradingsymbol", gttParams.TradingSymbol }, + { "tradingsymbol", gttParams.Tradingsymbol }, { "transaction_type", o.TransactionType }, { "quantity", o.Quantity }, { "price", o.Price }, @@ -784,7 +702,7 @@ public Task PlaceGTTAsync(GTTParams gttParams) .Add("orders", JsonSerializer.Serialize(ordersParam, JsonSerializerOptions)) .Add("type", gttParams.TriggerType); - return PostAsync("/gtt/triggers", formData: formDataBuilder.Build()); + return PostAsync("/gtt/triggers", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// @@ -792,13 +710,14 @@ public Task PlaceGTTAsync(GTTParams gttParams) /// /// Id of the GTT to be modified /// Contains the parameters for the GTT order + /// /// Json response in the form of nested string dictionary. - public Task ModifyGTTAsync(int GTTId, GTTParams gttParams) + public Task ModifyGTTAsync(int GTTId, GTTParams gttParams, CancellationToken cancellationToken = default) { var condition = new Dictionary { { "exchange", gttParams.Exchange }, - { "tradingsymbol", gttParams.TradingSymbol }, + { "tradingsymbol", gttParams.Tradingsymbol }, { "trigger_values", gttParams.TriggerPrices }, { "last_price", gttParams.LastPrice }, { "instrument_token", gttParams.InstrumentToken } //TODO undocumented @@ -810,7 +729,7 @@ public Task ModifyGTTAsync(int GTTId, GTTParams gttParams) var order = new Dictionary() { { "exchange", gttParams.Exchange }, - { "tradingsymbol", gttParams.TradingSymbol }, + { "tradingsymbol", gttParams.Tradingsymbol }, { "transaction_type", o.TransactionType }, { "quantity", o.Quantity }, { "price", o.Price }, @@ -825,17 +744,18 @@ public Task ModifyGTTAsync(int GTTId, GTTParams gttParams) .Add("orders", JsonSerializer.Serialize(ordersParam, JsonSerializerOptions)) .Add("type", gttParams.TriggerType); - return PutAsync($"/gtt/triggers/{GTTId}", formDataBuilder.Build()); + return PutAsync($"/gtt/triggers/{GTTId}", formDataBuilder.Build(), cancellationToken: cancellationToken); } /// /// Cancel a GTT order /// /// Id of the GTT to be modified + /// /// Json response in the form of nested string dictionary. - public Task CancelGTT(int GTTId) + public Task CancelGTTAsync(int GTTId, CancellationToken cancellationToken = default) { - return DeleteAsync($"/gtt/triggers/{GTTId}"); + return DeleteAsync($"/gtt/triggers/{GTTId}", cancellationToken: cancellationToken); } #endregion GTT @@ -846,40 +766,21 @@ public Task CancelGTT(int GTTId) /// /// Gets the Mutual funds Instruments. /// + /// /// The Mutual funds Instruments. - public List GetMFInstruments() + public IAsyncEnumerable GetMFInstrumentsAsync(CancellationToken cancellationToken = default) { - var param = new Dictionary(); - - List> instrumentsData; - - instrumentsData = Get(Routes.MutualFunds.Instruments, param); - - List instruments = new List(); - - foreach (Dictionary item in instrumentsData) - instruments.Add(new MFInstrument(item)); - - return instruments; + return GetCsvAsync("/mf/instruments", cancellationToken: cancellationToken); } /// /// Gets all Mutual funds orders. /// + /// /// The Mutual funds orders. - public List GetMFOrders() + public Task> GetMFOrdersAsync(CancellationToken cancellationToken = default) { - var param = new Dictionary(); - - Dictionary ordersData; - ordersData = Get(Routes.MutualFunds.Orders, param); - - List orderlist = new List(); - - foreach (Dictionary item in ordersData["data"]) - orderlist.Add(new MFOrder(item)); - - return orderlist; + return GetAsync>("/mf/orders", cancellationToken: cancellationToken); } /// @@ -887,17 +788,14 @@ public List GetMFOrders() /// /// The Mutual funds order. /// Order id. - public MFOrder GetMFOrders(string OrderId) + /// + public Task GetMFOrdersAsync(string OrderId, CancellationToken cancellationToken = default) { - var param = new Dictionary(); - param.Add("order_id", OrderId); - - Dictionary orderData; - orderData = Get(Routes.MutualFunds.Order, param); - - return new MFOrder(orderData["data"]); + return GetAsync($"/mf/orders/{OrderId}", cancellationToken: cancellationToken); } + //TODO undocumented API + /// /// Places a Mutual funds order. /// @@ -925,6 +823,8 @@ public Dictionary PlaceMFOrder( return Post(Routes.MutualFunds.PlaceOrder, param); } + //TODO undocumented API + /// /// Cancels the Mutual funds order. /// @@ -942,20 +842,11 @@ public Dictionary CancelMFOrder(string OrderId) /// /// Gets all Mutual funds SIPs. /// + /// /// The list of all Mutual funds SIPs. - public List GetMFSIPs() + public Task> GetMFSIPsAsync(CancellationToken cancellationToken = default) { - var param = new Dictionary(); - - Dictionary sipData; - sipData = Get(Routes.MutualFunds.SIPs, param); - - List siplist = new List(); - - foreach (Dictionary item in sipData["data"]) - siplist.Add(new MFSIP(item)); - - return siplist; + return GetAsync>("/mf/sips", cancellationToken: cancellationToken); } /// @@ -963,17 +854,14 @@ public List GetMFSIPs() /// /// The Mutual funds SIP. /// SIP id. - public MFSIP GetMFSIPs(string SIPID) + /// + public Task GetMFSIPsAsync(string SIPID, CancellationToken cancellationToken = default) { - var param = new Dictionary(); - param.Add("sip_id", SIPID); - - Dictionary sipData; - sipData = Get(Routes.MutualFunds.SIP, param); - - return new MFSIP(sipData["data"]); + return GetAsync($"/mf/sips/{SIPID}", cancellationToken: cancellationToken); } + //TODO undocumented API + /// /// Places a Mutual funds SIP order. /// @@ -1006,6 +894,8 @@ public Dictionary PlaceMFSIP( return Post(Routes.MutualFunds.PlaceSIP, param); } + //TODO undocumented API + /// /// Modifies the Mutual funds SIP. /// @@ -1036,12 +926,14 @@ public Dictionary ModifyMFSIP( return Put(Routes.MutualFunds.ModifySIP, param); } + //TODO undocumented API + /// /// Cancels the Mutual funds SIP. /// /// JSON response as nested string dictionary. /// SIP id. - public Dictionary CancelMFSIP(string SIPId) + public Dictionary CancelMFSIP(string SIPId) { var param = new Dictionary(); @@ -1053,20 +945,11 @@ public Dictionary CancelMFSIP(string SIPId) /// /// Gets the Mutual funds holdings. /// + /// /// The list of all Mutual funds holdings. - public List GetMFHoldings() + public async Task> GetMFHoldingsAsync(CancellationToken cancellationToken = default) { - var param = new Dictionary(); - - Dictionary holdingsData; - holdingsData = Get(Routes.MutualFunds.Holdings, param); - - List holdingslist = new List(); - - foreach (Dictionary item in holdingsData["data"]) - holdingslist.Add(new MFHolding(item)); - - return holdingslist; + return await GetAsync>("/mf/holdings", cancellationToken: cancellationToken); } #endregion @@ -1272,6 +1155,24 @@ private Task GetAsync(string path, IReadOnlyCollection(HttpMethod.Get, url, cancellationToken: cancellationToken); } + private async IAsyncEnumerable GetCsvAsync(string path, IReadOnlyCollection> queryParameters = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + string url = BuildUrl(_root, path, queryParameters); + using var httpResponse = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken); + httpResponse.EnsureSuccessStatusCode(); + if (httpResponse.Content.Headers.ContentType.MediaType != "text/csv") + throw new DataException($"Unexpected content type {httpResponse.Content.Headers.ContentType.MediaType}"); + using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken); + using (var reader = new StreamReader(stream)) + using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) + { + await foreach (var record in csv.GetRecordsAsync(cancellationToken)) + { + yield return record; + } + } + } + private Task PostAsync(string path, IReadOnlyCollection> queryParameters = null, IReadOnlyCollection> formData = default, CancellationToken cancellationToken = default) { string url = BuildUrl(_root, path, queryParameters); @@ -1281,6 +1182,15 @@ private Task PostAsync(string path, IReadOnlyCollection(HttpMethod.Post, url, content, cancellationToken); } + private Task PostJsonAsync(string path, IReadOnlyCollection> queryParameters = null, T jsonData = default, CancellationToken cancellationToken = default) + { + string url = BuildUrl(_root, path, queryParameters); + HttpContent content = null; + if (jsonData != null) + content = JsonContent.Create(jsonData); + return SendRequestAsync(HttpMethod.Post, url, content, cancellationToken); + } + private Task PutAsync(string path, IReadOnlyCollection> queryParameters = null, IReadOnlyCollection> formData = default, CancellationToken cancellationToken = default) { string url = BuildUrl(_root, path, queryParameters); @@ -1327,6 +1237,7 @@ private async Task ParseResponseAsync(HttpResponseMessage httpResponse, Ca { if (httpResponse.IsSuccessStatusCode) { + var strResponse = await httpResponse.Content.ReadAsStringAsync();//TODO remove var response = await httpResponse.Content.ReadFromJsonAsync>(JsonSerializerOptions, cancellationToken); if (response.Status == ResponseStatus.Success) return response.Data; diff --git a/KiteConnect/KiteConnect.csproj b/KiteConnect/KiteConnect.csproj index 9507747..0220769 100644 --- a/KiteConnect/KiteConnect.csproj +++ b/KiteConnect/KiteConnect.csproj @@ -35,6 +35,7 @@ + diff --git a/KiteConnect/ParametersBuilder.cs b/KiteConnect/ParametersBuilder.cs index 24f08fe..9d19b5b 100644 --- a/KiteConnect/ParametersBuilder.cs +++ b/KiteConnect/ParametersBuilder.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace KiteConnect { @@ -16,6 +17,24 @@ public ParametersBuilder Add(string key, string value) return this; } + public ParametersBuilder Add(string key, bool value) + { + _parameters.Add(new KeyValuePair(key, value.ToString())); + return this; + } + + public ParametersBuilder AddAsO1(string key, bool value) + { + _parameters.Add(new KeyValuePair(key, value ? "1" : "0")); + return this; + } + + public ParametersBuilder Add(string key, DateTime value) + { + _parameters.Add(new KeyValuePair(key, value.ToString("yyyy-MM-dd HH:mm:ss"))); + return this; + } + public ParametersBuilder AddIfNotNull(string key, string value) { if (value != null) diff --git a/KiteConnect/Structures.cs b/KiteConnect/Structures.cs index cc4d042..ca6b9d7 100644 --- a/KiteConnect/Structures.cs +++ b/KiteConnect/Structures.cs @@ -1,5 +1,5 @@ -using System; -using System.Collections; +using CsvHelper.Configuration.Attributes; +using System; using System.Collections.Generic; using System.Net; using System.Text.Json.Nodes; @@ -72,34 +72,24 @@ public class Tick /// public class DepthItem { - public DepthItem(Dictionary data) - { - Quantity = Convert.ToUInt32(data["quantity"]); - Price = data["price"]; - Orders = Convert.ToUInt32(data["orders"]); - } - public uint Quantity { get; set; } public decimal Price { get; set; } public uint Orders { get; set; } } /// - /// Historical structure + /// Historical Response structure /// - public class Historical + public class HistoricalResponse { - public Historical(ArrayList data) - { - TimeStamp = Convert.ToDateTime(data[0]); - Open = Convert.ToDecimal(data[1]); - High = Convert.ToDecimal(data[2]); - Low = Convert.ToDecimal(data[3]); - Close = Convert.ToDecimal(data[4]); - Volume = Convert.ToUInt64(data[5]); - OI = data.Count > 6 ? Convert.ToUInt64(data[6]) : 0; - } + public List Candles { get; set; } + } + /// + /// Candle structure + /// + public class Candle + { public DateTime TimeStamp { get; set; } public decimal Open { get; set; } public decimal High { get; set; } @@ -114,37 +104,6 @@ public Historical(ArrayList data) /// public class Holding { - public Holding(Dictionary data) - { - try - { - Product = data["product"]; - Exchange = data["exchange"]; - Price = data["price"]; - LastPrice = data["last_price"]; - CollateralQuantity = Convert.ToInt32(data["collateral_quantity"]); - PNL = data["pnl"]; - ClosePrice = data["close_price"]; - AveragePrice = data["average_price"]; - TradingSymbol = data["tradingsymbol"]; - CollateralType = data["collateral_type"]; - T1Quantity = Convert.ToInt32(data["t1_quantity"]); - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - ISIN = data["isin"]; - RealisedQuantity = Convert.ToInt32(data["realised_quantity"]); - Quantity = Convert.ToInt32(data["quantity"]); - UsedQuantity = Convert.ToInt32(data["used_quantity"]); - AuthorisedQuantity = Convert.ToInt32(data["authorised_quantity"]); - AuthorisedDate = Utils.StringToDate(data["authorised_date"]); - Discrepancy = data["discrepancy"]; - MTF = new MTFHolding(data["mtf"]); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public string Product { get; set; } public string Exchange { get; set; } public decimal Price { get; set; } @@ -153,7 +112,7 @@ public Holding(Dictionary data) public decimal PNL { get; set; } public decimal ClosePrice { get; set; } public decimal AveragePrice { get; set; } - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } public string CollateralType { get; set; } public decimal T1Quantity { get; set; } public uint InstrumentToken { get; set; } @@ -172,22 +131,6 @@ public Holding(Dictionary data) /// public class MTFHolding { - public MTFHolding(Dictionary data) - { - try - { - Quantity = data["quantity"]; - UsedQuantity = data["used_quantity"]; - AveragePrice = data["average_price"]; - Value = data["value"]; - InitialMargin = data["initial_margin"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public decimal Quantity { get; set; } public decimal UsedQuantity { get; set; } public decimal AveragePrice { get; set; } @@ -200,40 +143,7 @@ public MTFHolding(Dictionary data) /// public class AuctionInstrument { - public AuctionInstrument(Dictionary data) - { - try - { - TradingSymbol = data["tradingsymbol"]; - Exchange = data["exchange"]; - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - ISIN = data["isin"]; - Product = data["product"]; - Price = data["price"]; - Quantity = Convert.ToInt32(data["quantity"]); - T1Quantity = Convert.ToInt32(data["t1_quantity"]); - RealisedQuantity = Convert.ToInt32(data["realised_quantity"]); - AuthorisedQuantity = Convert.ToInt32(data["authorised_quantity"]); - AuthorisedDate = Utils.StringToDate(data["authorised_date"]); - OpeningQuantity = Convert.ToInt32(data["opening_quantity"]); - CollateralQuantity = Convert.ToInt32(data["collateral_quantity"]); - CollateralType = data["collateral_type"]; - Discrepancy = data["discrepancy"]; - AveragePrice = data["average_price"]; - LastPrice = data["last_price"]; - ClosePrice = data["close_price"]; - PNL = data["pnl"]; - DayChange = data["day_change"]; - DayChangePercentage = data["day_change_percentage"]; - AuctionNumber = data["auction_number"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } public string Exchange { get; set; } public uint InstrumentToken { get; set; } public string ISIN { get; set; } @@ -323,7 +233,7 @@ public class OrderMarginParams /// /// Tradingsymbol of the instrument (ex. RELIANCE, INFY) /// - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } /// /// Transaction type (Constants.Transaction.Buy or Constants.Transaction.Sell) @@ -366,33 +276,6 @@ public class OrderMarginParams /// public class OrderMargin { - public OrderMargin(Dictionary data) - { - try - { - Type = data["type"]; - Exchange = data["exchange"]; - Tradingsymbol = data["tradingsymbol"]; - Total = data["total"]; - - // available only in non compact mode - OptionPremium = Utils.GetValueOrDefault(data, "option_premium", 0m); - SPAN = Utils.GetValueOrDefault(data, "span", 0m); - Exposure = Utils.GetValueOrDefault(data, "exposure", 0m); - Additional = Utils.GetValueOrDefault(data, "additional", 0m); - BO = Utils.GetValueOrDefault(data, "bo", 0m); - Cash = Utils.GetValueOrDefault(data, "cash", 0m); - VAR = Utils.GetValueOrDefault(data, "var", 0m); - Leverage = Utils.GetValueOrDefault(data, "leverage", 0m); - Charges = new OrderCharges(Utils.GetValueOrDefault(data, "charges", new Dictionary())); - PNL = new OrderMarginPNL(Utils.GetValueOrDefault(data, "pnl", new Dictionary())); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public string Type { get; set; } public string Exchange { get; set; } public string Tradingsymbol { get; set; } @@ -427,7 +310,7 @@ public class ContractNoteParams /// /// Tradingsymbol of the instrument (ex. RELIANCE, INFY) /// - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } /// /// Transaction type (Constants.Transaction.Buy or Constants.Transaction.Sell) @@ -465,26 +348,6 @@ public class ContractNoteParams /// public class ContractNote { - public ContractNote(Dictionary data) - { - try - { - Exchange = data["exchange"]; - TradingSymbol = data["tradingsymbol"]; - TransactionType = data["transaction_type"]; - Quantity = Convert.ToInt32(data["quantity"]); - Price = Utils.GetValueOrDefault(data, "price", 0m); - Product = data["product"]; - OrderType = data["order_type"]; - Variety = data["variety"]; - Charges = new OrderCharges(Utils.GetValueOrDefault(data, "charges", new Dictionary())); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - /// /// Exchange in which instrument is listed (Constants.Exchange.NSE, Constants.Exchange.BSE, etc.) /// @@ -493,7 +356,7 @@ public ContractNote(Dictionary data) /// /// Tradingsymbol of the instrument (ex. RELIANCE, INFY) /// - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } /// /// Transaction type (Constants.Transaction.Buy or Constants.Transaction.Sell) @@ -508,7 +371,7 @@ public ContractNote(Dictionary data) /// /// Order price /// - public decimal? Price { get; set; } + public decimal Price { get; set; } /// /// Product code (Constants.Product.CNC, Constants.Product.MIS, Constants.Product.NRML) @@ -536,25 +399,6 @@ public ContractNote(Dictionary data) /// public class OrderCharges { - public OrderCharges(Dictionary data) - { - try - { - TransactionTax = Utils.GetValueOrDefault(data, "transaction_tax", 0m); - TransactionTaxType = Utils.GetValueOrDefault(data, "transaction_tax_type", ""); - ExchangeTurnoverCharge = Utils.GetValueOrDefault(data, "exchange_turnover_charge", 0m); - SEBITurnoverCharge = Utils.GetValueOrDefault(data, "sebi_turnover_charge", 0m); - Brokerage = Utils.GetValueOrDefault(data, "brokerage", 0m); - StampDuty = Utils.GetValueOrDefault(data, "stamp_duty", 0m); - Total = Utils.GetValueOrDefault(data, "total", 0m); - GST = new OrderChargesGST(Utils.GetValueOrDefault(data, "gst", new Dictionary())); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public decimal TransactionTax { get; set; } public string TransactionTaxType { get; set; } public decimal ExchangeTurnoverCharge { get; set; } @@ -570,21 +414,6 @@ public OrderCharges(Dictionary data) /// public class OrderChargesGST { - public OrderChargesGST(Dictionary data) - { - try - { - IGST = Utils.GetValueOrDefault(data, "igst", 0m); - CGST = Utils.GetValueOrDefault(data, "cgst", 0m); - SGST = Utils.GetValueOrDefault(data, "sgst", 0m); - Total = Utils.GetValueOrDefault(data, "total", 0m); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public decimal IGST { get; set; } public decimal CGST { get; set; } public decimal SGST { get; set; } @@ -596,23 +425,6 @@ public OrderChargesGST(Dictionary data) /// public class BasketMargin { - public BasketMargin(Dictionary data) - { - try - { - Initial = new OrderMargin(data["initial"]); - Final = new OrderMargin(data["final"]); - Orders = new List(); - - foreach (Dictionary item in data["orders"]) - Orders.Add(new OrderMargin(item)); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public OrderMargin Initial { get; set; } public OrderMargin Final { get; set; } public List Orders { get; set; } @@ -625,19 +437,6 @@ public BasketMargin(Dictionary data) /// public class OrderMarginPNL { - public OrderMarginPNL(Dictionary data) - { - try - { - Realised = Utils.GetValueOrDefault(data, "realised", 0m); - Unrealised = Utils.GetValueOrDefault(data, "unrealised", 0m); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public decimal Realised { get; set; } public decimal Unrealised { get; set; } } @@ -655,9 +454,7 @@ public class Position [JsonPropertyName("buy_m2m")] public decimal BuyM2M { get; set; } public decimal LastPrice { get; set; } - - [JsonPropertyName("tradingsymbol")] - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } public decimal Realised { get; set; } public decimal PNL { get; set; } public decimal Multiplier { get; set; } @@ -764,9 +561,7 @@ public class GTTCondition { public uint InstrumentToken { get; set; } public string Exchange { get; set; } - - [JsonPropertyName("tradingsymbol")] - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } public List TriggerValues { get; set; } public decimal LastPrice { get; set; } } @@ -811,7 +606,7 @@ public class GTTOrderResult /// public class GTTParams { - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } public string Exchange { get; set; } public uint InstrumentToken { get; set; } public string TriggerType { get; set; } @@ -840,42 +635,40 @@ public class GTTOrderParams /// public class Instrument { - public Instrument(Dictionary data) - { - try - { - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - ExchangeToken = Convert.ToUInt32(data["exchange_token"]); - TradingSymbol = data["tradingsymbol"]; - Name = data["name"]; - LastPrice = Utils.StringToDecimal(data["last_price"]); - TickSize = Utils.StringToDecimal(data["tick_size"]); - Expiry = Utils.StringToDate(data["expiry"]); - InstrumentType = data["instrument_type"]; - Segment = data["segment"]; - Exchange = data["exchange"]; - Strike = Utils.StringToDecimal(data["strike"]); - - LotSize = Convert.ToUInt32(data["lot_size"]); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - + [Name("instrument_token")] public uint InstrumentToken { get; set; } + + [Name("exchange_token")] public uint ExchangeToken { get; set; } - public string TradingSymbol { get; set; } + + [Name("tradingsymbol")] + public string Tradingsymbol { get; set; } + + [Name("name")] public string Name { get; set; } + + [Name("last_price")] public decimal LastPrice { get; set; } + + [Name("tick_size")] public decimal TickSize { get; set; } + + [Name("expiry")] public DateTime? Expiry { get; set; } + + [Name("instrument_type")] public string InstrumentType { get; set; } + + [Name("segment")] public string Segment { get; set; } + + [Name("exchange")] public string Exchange { get; set; } + + [Name("strike")] public decimal Strike { get; set; } + + [Name("lot_size")] public uint LotSize { get; set; } } @@ -978,85 +771,6 @@ public class Profile /// public class Quote { - public Quote(Dictionary data) - { - try - { - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - Timestamp = Utils.StringToDate(data["timestamp"]); - LastPrice = data["last_price"]; - - Change = data["net_change"]; - - Open = data["ohlc"]["open"]; - Close = data["ohlc"]["close"]; - Low = data["ohlc"]["low"]; - High = data["ohlc"]["high"]; - - if (data.ContainsKey("last_quantity")) - { - // Non index quote - LastQuantity = Convert.ToUInt32(data["last_quantity"]); - LastTradeTime = Utils.StringToDate(data["last_trade_time"]); - AveragePrice = data["average_price"]; - Volume = Convert.ToUInt32(data["volume"]); - - BuyQuantity = Convert.ToUInt32(data["buy_quantity"]); - SellQuantity = Convert.ToUInt32(data["sell_quantity"]); - - OI = Convert.ToUInt32(data["oi"]); - - OIDayHigh = Convert.ToUInt32(data["oi_day_high"]); - OIDayLow = Convert.ToUInt32(data["oi_day_low"]); - - LowerCircuitLimit = data["lower_circuit_limit"]; - UpperCircuitLimit = data["upper_circuit_limit"]; - - Bids = new List(); - Offers = new List(); - - if (data["depth"]["buy"] != null) - { - foreach (Dictionary bid in data["depth"]["buy"]) - Bids.Add(new DepthItem(bid)); - } - - if (data["depth"]["sell"] != null) - { - foreach (Dictionary offer in data["depth"]["sell"]) - Offers.Add(new DepthItem(offer)); - } - } - else - { - // Index quote - LastQuantity = 0; - LastTradeTime = null; - AveragePrice = 0; - Volume = 0; - - BuyQuantity = 0; - SellQuantity = 0; - - OI = 0; - - OIDayHigh = 0; - OIDayLow = 0; - - LowerCircuitLimit = 0; - UpperCircuitLimit = 0; - - Bids = new List(); - Offers = new List(); - } - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - public uint InstrumentToken { get; set; } public decimal LastPrice { get; set; } public uint LastQuantity { get; set; } @@ -1064,15 +778,13 @@ public Quote(Dictionary data) public uint Volume { get; set; } public uint BuyQuantity { get; set; } public uint SellQuantity { get; set; } - public decimal Open { get; set; } - public decimal High { get; set; } - public decimal Low { get; set; } - public decimal Close { get; set; } + public OHLC Ohlc { get; set; } + + [JsonPropertyName("net_change")] public decimal Change { get; set; } public decimal LowerCircuitLimit { get; set; } public decimal UpperCircuitLimit { get; set; } - public List Bids { get; set; } - public List Offers { get; set; } + public QuoteDepth Depth { get; set; } // KiteConnect 3 Fields @@ -1083,35 +795,30 @@ public Quote(Dictionary data) public DateTime? Timestamp { get; set; } } + public class QuoteDepth + { + [JsonPropertyName("buy")] + public List Bids { get; set; } + [JsonPropertyName("sell")] + public List Offers { get; set; } + } + + public class OHLC + { + public decimal Open { get; set; } + public decimal High { get; set; } + public decimal Low { get; set; } + public decimal Close { get; set; } + } + /// /// OHLC Quote structure /// - public class OHLC + public class OHLCResponse { - public OHLC(Dictionary data) - { - try - { - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - LastPrice = data["last_price"]; - - Open = data["ohlc"]["open"]; - Close = data["ohlc"]["close"]; - Low = data["ohlc"]["low"]; - High = data["ohlc"]["high"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } public uint InstrumentToken { get; set; } public decimal LastPrice { get; set; } - public decimal Open { get; set; } - public decimal Close { get; set; } - public decimal High { get; set; } - public decimal Low { get; set; } + public OHLC Ohlc { get; set; } } /// @@ -1119,19 +826,6 @@ public OHLC(Dictionary data) /// public class LTP { - public LTP(Dictionary data) - { - try - { - InstrumentToken = Convert.ToUInt32(data["instrument_token"]); - LastPrice = data["last_price"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } public uint InstrumentToken { get; set; } public decimal LastPrice { get; set; } } @@ -1141,30 +835,11 @@ public LTP(Dictionary data) /// public class MFHolding { - public MFHolding(Dictionary data) - { - try - { - Quantity = data["quantity"]; - Fund = data["fund"]; - Folio = data["folio"]; - AveragePrice = data["average_price"]; - TradingSymbol = data["tradingsymbol"]; - LastPrice = data["last_price"]; - PNL = data["pnl"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - public decimal Quantity { get; set; } public string Fund { get; set; } public string Folio { get; set; } public decimal AveragePrice { get; set; } - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } public decimal LastPrice { get; set; } public decimal PNL { get; set; } } @@ -1174,55 +849,54 @@ public MFHolding(Dictionary data) /// public class MFInstrument { - public MFInstrument(Dictionary data) - { - try - { - TradingSymbol = data["tradingsymbol"]; - AMC = data["amc"]; - Name = data["name"]; - - PurchaseAllowed = data["purchase_allowed"] == "1"; - RedemtpionAllowed = data["redemption_allowed"] == "1"; - - MinimumPurchaseAmount = Utils.StringToDecimal(data["minimum_purchase_amount"]); - PurchaseAmountMultiplier = Utils.StringToDecimal(data["purchase_amount_multiplier"]); - MinimumAdditionalPurchaseAmount = Utils.StringToDecimal(data["minimum_additional_purchase_amount"]); - MinimumRedemptionQuantity = Utils.StringToDecimal(data["minimum_redemption_quantity"]); - RedemptionQuantityMultiplier = Utils.StringToDecimal(data["redemption_quantity_multiplier"]); - LastPrice = Utils.StringToDecimal(data["last_price"]); - - DividendType = data["dividend_type"]; - SchemeType = data["scheme_type"]; - Plan = data["plan"]; - SettlementType = data["settlement_type"]; - LastPriceDate = Utils.StringToDate(data["last_price_date"]); - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } + [Name("tradingsymbol")] + public string Tradingsymbol { get; set; } - public string TradingSymbol { get; set; } + [Name("amc")] public string AMC { get; set; } + + [Name("name")] public string Name { get; set; } - public bool PurchaseAllowed { get; set; } - public bool RedemtpionAllowed { get; set; } + [Name("purchase_allowed")] + public string PurchaseAllowedString { get; set; } + public bool PurchaseAllowed => PurchaseAllowedString == "1"; + [Name("redemption_allowed")] + public string RedemtpionAllowedString { get; set; } + public bool RedemtpionAllowed => RedemtpionAllowedString == "1"; + + [Name("minimum_purchase_amount")] public decimal MinimumPurchaseAmount { get; set; } + + [Name("purchase_amount_multiplier")] public decimal PurchaseAmountMultiplier { get; set; } + + [Name("minimum_additional_purchase_amount")] public decimal MinimumAdditionalPurchaseAmount { get; set; } + + [Name("minimum_redemption_quantity")] public decimal MinimumRedemptionQuantity { get; set; } + + [Name("redemption_quantity_multiplier")] public decimal RedemptionQuantityMultiplier { get; set; } + + [Name("last_price")] public decimal LastPrice { get; set; } + [Name("dividend_type")] public string DividendType { get; set; } + + [Name("scheme_type")] public string SchemeType { get; set; } + + [Name("plan")] public string Plan { get; set; } + + [Name("settlement_type")] public string SettlementType { get; set; } + + [Name("last_price_date")] public DateTime? LastPriceDate { get; set; } } @@ -1231,37 +905,6 @@ public MFInstrument(Dictionary data) /// public class MFOrder { - public MFOrder(Dictionary data) - { - try - { - StatusMessage = data["status_message"]; - PurchaseType = data["purchase_type"]; - PlacedBy = data["placed_by"]; - Amount = data["amount"]; - Quantity = data["quantity"]; - SettlementId = data["settlement_id"]; - OrderTimestamp = Utils.StringToDate(data["order_timestamp"]); - AveragePrice = data["average_price"]; - TransactionType = data["transaction_type"]; - ExchangeOrderId = data["exchange_order_id"]; - ExchangeTimestamp = Utils.StringToDate(data["exchange_timestamp"]); - Fund = data["fund"]; - Variety = data["variety"]; - Folio = data["folio"]; - Tradingsymbol = data["tradingsymbol"]; - Tag = data["tag"]; - OrderId = data["order_id"]; - Status = data["status"]; - LastPrice = data["last_price"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - - } - public string StatusMessage { get; set; } public string PurchaseType { get; set; } public string PlacedBy { get; set; } @@ -1288,32 +931,6 @@ public MFOrder(Dictionary data) /// public class MFSIP { - public MFSIP(Dictionary data) - { - try - { - DividendType = data["dividend_type"]; - PendingInstalments = Convert.ToInt32(data["pending_instalments"]); - Created = Utils.StringToDate(data["created"]); - LastInstalment = Utils.StringToDate(data["last_instalment"]); - TransactionType = data["transaction_type"]; - Frequency = data["frequency"]; - InstalmentDate = Convert.ToInt32(data["instalment_date"]); - Fund = data["fund"]; - SIPId = data["sip_id"]; - Tradingsymbol = data["tradingsymbol"]; - Tag = data["tag"]; - InstalmentAmount = Convert.ToInt32(data["instalment_amount"]); - Instalments = Convert.ToInt32(data["instalments"]); - Status = data["status"]; - OrderId = data.ContainsKey(("order_id")) ? data["order_id"] : ""; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - public string DividendType { get; set; } public int PendingInstalments { get; set; } public DateTime? Created { get; set; } diff --git a/KiteConnectSample/Program.cs b/KiteConnectSample/Program.cs index 01e8d7b..c7aa61f 100644 --- a/KiteConnectSample/Program.cs +++ b/KiteConnectSample/Program.cs @@ -1,6 +1,7 @@ using KiteConnect; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace KiteConnectSample @@ -68,7 +69,7 @@ static async Task Main(string[] args) GTTParams gttParams = new GTTParams(); gttParams.TriggerType = Constants.GTT.Trigger.OCO; gttParams.Exchange = "NSE"; - gttParams.TradingSymbol = "SBIN"; + gttParams.Tradingsymbol = "SBIN"; gttParams.LastPrice = 288.9m; List triggerPrices = new List(); @@ -105,7 +106,7 @@ static async Task Main(string[] args) var placeGTTResponse = await kite.PlaceGTTAsync(gttParams); Console.WriteLine(Utils.JsonSerialize(placeGTTResponse)); - var modifyGTTResponse = kite.ModifyGTTAsync(407301, gttParams); + var modifyGTTResponse = await kite.ModifyGTTAsync(407301, gttParams); Console.WriteLine(Utils.JsonSerialize(modifyGTTResponse)); // Positions @@ -113,7 +114,7 @@ static async Task Main(string[] args) PositionResponse positions = await kite.GetPositionsAsync(); Console.WriteLine(Utils.JsonSerialize(positions.Net[0])); - kite.ConvertPosition( + await kite.ConvertPositionAsync( Exchange: Constants.Exchange.NSE, TradingSymbol: "ASHOKLEY", TransactionType: Constants.Transaction.Buy, @@ -125,27 +126,27 @@ static async Task Main(string[] args) // Holdings - List holdings = kite.GetHoldings(); + List holdings = await kite.GetHoldingsAsync(); Console.WriteLine(Utils.JsonSerialize(holdings[0])); // Instruments - List instruments = kite.GetInstruments(); - Console.WriteLine(Utils.JsonSerialize(instruments[0])); + Instrument instrument = kite.GetInstrumentsAsync().ToBlockingEnumerable().FirstOrDefault(); + Console.WriteLine(Utils.JsonSerialize(instrument)); // Get quotes of upto 200 scrips - Dictionary quotes = kite.GetQuote(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); + Dictionary quotes = await kite.GetQuoteAsync(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); Console.WriteLine(Utils.JsonSerialize(quotes)); // Get OHLC and LTP of upto 200 scrips - Dictionary ohlcs = kite.GetOHLC(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); + Dictionary ohlcs = await kite.GetOHLCAsync(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); Console.WriteLine(Utils.JsonSerialize(ohlcs)); // Get LTP of upto 200 scrips - Dictionary ltps = kite.GetLTP(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); + Dictionary ltps = await kite.GetLTPAsync(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); Console.WriteLine(Utils.JsonSerialize(ltps)); // Trigger Range @@ -330,27 +331,27 @@ await kite.PlaceOrderAsync( OrderMarginParams orderParam = new OrderMarginParams(); orderParam.Exchange = Constants.Exchange.NFO; - orderParam.TradingSymbol = "ASHOKLEY21JULFUT"; + orderParam.Tradingsymbol = "ASHOKLEY21JULFUT"; orderParam.TransactionType = Constants.Transaction.Sell; orderParam.Quantity = 1; orderParam.Price = 64.0000m; orderParam.OrderType = Constants.OrderType.Market; orderParam.Product = Constants.Product.MIS; - List margins = kite.GetOrderMargins(new List() { orderParam }); + List margins = await kite.GetOrderMarginsAsync(new List() { orderParam }); // Basket margins OrderMarginParams basketParam = new OrderMarginParams(); basketParam.Exchange = Constants.Exchange.NFO; - basketParam.TradingSymbol = "NIFTY21JUL15000PE"; + basketParam.Tradingsymbol = "NIFTY21JUL15000PE"; basketParam.TransactionType = Constants.Transaction.Buy; basketParam.Quantity = 75; basketParam.Price = 300; basketParam.Product = Constants.Product.MIS; basketParam.OrderType = Constants.OrderType.Limit; - BasketMargin basketMargins = kite.GetBasketMargins(new List() { basketParam }, ConsiderPositions: true); + BasketMargin basketMargins = await kite.GetBasketMarginsAsync(new List() { basketParam }, ConsiderPositions: true); // Virtual contract notes @@ -359,38 +360,38 @@ await kite.PlaceOrderAsync( contractNoteParam.Quantity = 1; contractNoteParam.AveragePrice = 99.7m; contractNoteParam.Exchange = "NSE"; - contractNoteParam.TradingSymbol = "BHEL"; + contractNoteParam.Tradingsymbol = "BHEL"; contractNoteParam.TransactionType = Constants.Transaction.Buy; contractNoteParam.Variety = Constants.Variety.Regular; contractNoteParam.OrderType = Constants.OrderType.Limit; contractNoteParam.Product = Constants.Product.MIS; - List contractNotes = kite.GetVirtualContractNote(new List() { contractNoteParam }); + List contractNotes = await kite.GetVirtualContractNoteAsync(new List() { contractNoteParam }); Console.WriteLine(Utils.JsonSerialize(contractNotes)); // Historical Data With Dates - List historical = kite.GetHistoricalData( + HistoricalResponse historical = await kite.GetHistoricalDataAsync( InstrumentToken: "5633", FromDate: new DateTime(2016, 1, 1, 12, 50, 0), // 2016-01-01 12:50:00 AM ToDate: new DateTime(2016, 1, 1, 13, 10, 0), // 2016-01-01 01:10:00 PM Interval: Constants.Interval.Minute, Continuous: false ); - Console.WriteLine(Utils.JsonSerialize(historical[0])); + Console.WriteLine(Utils.JsonSerialize(historical.Candles[0])); // Mutual Funds Instruments - List mfinstruments = kite.GetMFInstruments(); - Console.WriteLine(Utils.JsonSerialize(mfinstruments[0])); + MFInstrument mfinstrument = kite.GetMFInstrumentsAsync().ToBlockingEnumerable().FirstOrDefault(); + Console.WriteLine(Utils.JsonSerialize(mfinstrument)); // Mutual funds get all orders - List mforders = kite.GetMFOrders(); + List mforders = await kite.GetMFOrdersAsync(); Console.WriteLine(Utils.JsonSerialize(mforders[0])); // Mutual funds get order by id - MFOrder mforder = kite.GetMFOrders(OrderId: "1234"); + MFOrder mforder = await kite.GetMFOrdersAsync(OrderId: "1234"); Console.WriteLine(Utils.JsonSerialize(mforder)); // Mutual funds place order @@ -407,12 +408,12 @@ await kite.PlaceOrderAsync( // Mutual Funds get all SIPs - List mfsips = kite.GetMFSIPs(); + List mfsips = await kite.GetMFSIPsAsync(); Console.WriteLine(Utils.JsonSerialize(mfsips[0])); // Mutual Funds get SIP by id - MFSIP sip = kite.GetMFSIPs("63429"); + MFSIP sip = await kite.GetMFSIPsAsync("63429"); Console.WriteLine(Utils.JsonSerialize(sip)); // Mutual Funds place SIP order @@ -441,7 +442,7 @@ await kite.PlaceOrderAsync( // Mutual Funds Holdings - List mfholdings = kite.GetMFHoldings(); + List mfholdings = await kite.GetMFHoldingsAsync(); Console.WriteLine(Utils.JsonSerialize(mfholdings[0])); Console.ReadKey(); diff --git a/KiteConnectTest/KiteConnectTest.csproj b/KiteConnectTest/KiteConnectTest.csproj index 8831e9f..c9904ce 100644 --- a/KiteConnectTest/KiteConnectTest.csproj +++ b/KiteConnectTest/KiteConnectTest.csproj @@ -120,4 +120,11 @@ Always + + + + + Always + + diff --git a/KiteConnectTest/KiteTest.cs b/KiteConnectTest/KiteTest.cs index 40c0134..49f1cfa 100644 --- a/KiteConnectTest/KiteTest.cs +++ b/KiteConnectTest/KiteTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -62,28 +63,28 @@ public async Task TestPositions() ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); PositionResponse positionResponse = await kite.GetPositionsAsync(); - Assert.AreEqual(positionResponse.Net[0].TradingSymbol, "LEADMINI17DECFUT"); - Assert.AreEqual(positionResponse.Day[0].TradingSymbol, "GOLDGUINEA17DECFUT"); + Assert.AreEqual(positionResponse.Net[0].Tradingsymbol, "LEADMINI17DECFUT"); + Assert.AreEqual(positionResponse.Day[0].Tradingsymbol, "GOLDGUINEA17DECFUT"); } [TestMethod] - public void TestHoldings() + public async Task TestHoldings() { string json = File.ReadAllText(@"responses/holdings.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List holdings = kite.GetHoldings(); + List holdings = await kite.GetHoldingsAsync(); Assert.AreEqual(holdings[0].AveragePrice, 40.67m); Assert.AreEqual(holdings[0].MTF.Quantity, 1000m); } [TestMethod] - public void TestAuctionInstruments() + public async Task TestAuctionInstruments() { string json = File.ReadAllText(@"responses/auction_instruments.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List instruments = kite.GetAuctionInstruments(); + List instruments = await kite.GetAuctionInstrumentsAsync(); Assert.AreEqual(instruments[0].PNL, 564.8000000000002m); } @@ -112,7 +113,7 @@ public async Task TestMarginsNoTurnover() } [TestMethod] - public void TestOrderMargins() + public async Task TestOrderMargins() { string json = File.ReadAllText(@"responses/order_margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); @@ -120,14 +121,14 @@ public void TestOrderMargins() OrderMarginParams param = new OrderMarginParams(); param.Exchange = Constants.Exchange.NFO; - param.TradingSymbol = "ASHOKLEY20NOVFUT"; + param.Tradingsymbol = "ASHOKLEY20NOVFUT"; param.TransactionType = Constants.Transaction.Sell; param.Quantity = 1; param.Price = 64.0000m; param.OrderType = Constants.OrderType.Market; param.Product = Constants.Product.MIS; - List margins = kite.GetOrderMargins(new List() { param }); + List margins = await kite.GetOrderMarginsAsync(new List() { param }); Assert.AreEqual(margins[0].Total, (decimal)8.36025); Assert.AreEqual(margins[0].SPAN, (decimal)5.408); @@ -137,7 +138,7 @@ public void TestOrderMargins() } [TestMethod] - public void TestOrderMarginsCompact() + public async Task TestOrderMarginsCompact() { string json = File.ReadAllText(@"responses/order_margins_compact.json", Encoding.UTF8); ms.SetResponse("application/json", json); @@ -145,7 +146,7 @@ public void TestOrderMarginsCompact() OrderMarginParams param = new OrderMarginParams(); param.Exchange = Constants.Exchange.NFO; - param.TradingSymbol = "ASHOKLEY21JULFUT"; + param.Tradingsymbol = "ASHOKLEY21JULFUT"; param.TransactionType = Constants.Transaction.Sell; param.Quantity = 1; param.Price = 64.0000m; @@ -154,21 +155,21 @@ public void TestOrderMarginsCompact() OrderMarginParams param2 = new OrderMarginParams(); param2.Exchange = Constants.Exchange.NFO; - param2.TradingSymbol = "NIFTY21JUL15000PE"; + param2.Tradingsymbol = "NIFTY21JUL15000PE"; param.TransactionType = Constants.Transaction.Buy; param2.Quantity = 75; param2.Price = 300; param2.Product = Constants.Product.MIS; param2.OrderType = Constants.OrderType.Limit; - List margins = kite.GetOrderMargins(new List() { param, param2 }, Mode: Constants.Margin.Mode.Compact); + List margins = await kite.GetOrderMarginsAsync(new List() { param, param2 }, Mode: Constants.Margin.Mode.Compact); Assert.AreEqual(margins[0].Total, (decimal)30.2280825); Assert.AreEqual(margins[0].SPAN, (decimal)0); } [TestMethod] - public void TestBasketMargins() + public async Task TestBasketMargins() { string json = File.ReadAllText(@"responses/basket_margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); @@ -176,7 +177,7 @@ public void TestBasketMargins() OrderMarginParams param = new OrderMarginParams(); param.Exchange = Constants.Exchange.NFO; - param.TradingSymbol = "ASHOKLEY21JULFUT"; + param.Tradingsymbol = "ASHOKLEY21JULFUT"; param.TransactionType = Constants.Transaction.Sell; param.Quantity = 1; param.Price = 64.0000m; @@ -185,21 +186,21 @@ public void TestBasketMargins() OrderMarginParams param2 = new OrderMarginParams(); param2.Exchange = Constants.Exchange.NFO; - param2.TradingSymbol = "NIFTY21JUL15000PE"; + param2.Tradingsymbol = "NIFTY21JUL15000PE"; param.TransactionType = Constants.Transaction.Buy; param2.Quantity = 75; param2.Price = 300; param2.Product = Constants.Product.MIS; param2.OrderType = Constants.OrderType.Limit; - BasketMargin margins = kite.GetBasketMargins(new List() { param, param2 }); + BasketMargin margins = await kite.GetBasketMarginsAsync(new List() { param, param2 }); Assert.AreEqual(margins.Final.Total, (decimal)22530.221345); Assert.AreEqual(margins.Final.SPAN, (decimal)26.9577); } [TestMethod] - public void TestBasketMarginsCompact() + public async Task TestBasketMarginsCompact() { string json = File.ReadAllText(@"responses/basket_margins_compact.json", Encoding.UTF8); ms.SetResponse("application/json", json); @@ -207,7 +208,7 @@ public void TestBasketMarginsCompact() OrderMarginParams param = new OrderMarginParams(); param.Exchange = Constants.Exchange.NFO; - param.TradingSymbol = "ASHOKLEY21JULFUT"; + param.Tradingsymbol = "ASHOKLEY21JULFUT"; param.TransactionType = Constants.Transaction.Sell; param.Quantity = 1; param.Price = 64.0000m; @@ -216,14 +217,14 @@ public void TestBasketMarginsCompact() OrderMarginParams param2 = new OrderMarginParams(); param2.Exchange = Constants.Exchange.NFO; - param2.TradingSymbol = "NIFTY21JUL15000PE"; + param2.Tradingsymbol = "NIFTY21JUL15000PE"; param.TransactionType = Constants.Transaction.Buy; param2.Quantity = 75; param2.Price = 300; param2.Product = Constants.Product.MIS; param2.OrderType = Constants.OrderType.Limit; - BasketMargin margins = kite.GetBasketMargins(new List() { param, param2 }, Mode: Constants.Margin.Mode.Compact); + BasketMargin margins = await kite.GetBasketMarginsAsync(new List() { param, param2 }, Mode: Constants.Margin.Mode.Compact); Assert.AreEqual(margins.Final.Total, (decimal)22530.2280825); Assert.AreEqual(margins.Final.SPAN, (decimal)0); @@ -252,37 +253,42 @@ public async Task TestCommodityMargins() } [TestMethod] - public void TestOHLC() + public async Task TestOHLC() { string json = File.ReadAllText(@"responses/ohlc.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - Dictionary ohlcs = kite.GetOHLC(new string[] { "408065", "NSE:INFY" }); + Dictionary ohlcs = await kite.GetOHLCAsync(new string[] { "408065", "NSE:INFY" }); - Assert.AreEqual(ohlcs["408065"].LastPrice, (decimal)966.8); + Assert.AreEqual(ohlcs["408065"].LastPrice, 966.8m); + Assert.AreEqual(ohlcs["408065"].Ohlc.Open, 966.6m); } [TestMethod] - public void TestLTP() + public async Task TestLTP() { string json = File.ReadAllText(@"responses/ltp.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - Dictionary ltps = kite.GetLTP(new string[] { "NSE:INFY" }); + Dictionary ltps = await kite.GetLTPAsync(new string[] { "NSE:INFY" }); Assert.AreEqual(ltps["NSE:INFY"].LastPrice, (decimal)989.2); } [TestMethod] - public void TestQuote() + public async Task TestQuote() { string json = File.ReadAllText(@"responses/quote.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - Dictionary quotes = kite.GetQuote(new string[] { "NSE:ASHOKLEY", "NSE:NIFTY 50" }); + Dictionary quotes = await kite.GetQuoteAsync(new string[] { "NSE:ASHOKLEY", "NSE:NIFTY 50" }); - Assert.AreEqual(quotes["NSE:ASHOKLEY"].LastPrice, (decimal)76.6); + Assert.AreEqual(quotes["NSE:ASHOKLEY"].LastPrice, 76.6m); Assert.AreEqual(quotes["NSE:NIFTY 50"].LowerCircuitLimit, 0); + Assert.AreEqual(quotes["NSE:ASHOKLEY"].Ohlc.Close, 76.45m); + Assert.AreEqual(quotes["NSE:NIFTY 50"].Ohlc.Low, 11888.85m); + Assert.AreEqual(quotes["NSE:ASHOKLEY"].Depth.Bids[0].Price, 76.5m); + Assert.AreEqual(quotes["NSE:ASHOKLEY"].Depth.Offers[0].Price, 76.6m); } [TestMethod] @@ -344,27 +350,55 @@ public async Task TestOrderInfo() } [TestMethod] - public void TestInstruments() + public async Task TestInstruments() { string csv = File.ReadAllText(@"responses/instruments_all.csv", Encoding.UTF8); ms.SetResponse("text/csv", csv); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List instruments = kite.GetInstruments(); + var instrument = kite.GetInstrumentsAsync().ToBlockingEnumerable().First(); - Assert.AreEqual(instruments[0].InstrumentToken, (uint)3813889); - Assert.AreEqual(instruments[0].LastPrice, 10.01m); - Assert.AreEqual(instruments[0].Strike, 13.14m); + Assert.AreEqual(instrument.InstrumentToken, (uint)3813889); + Assert.AreEqual(instrument.LastPrice, 10.01m); + Assert.AreEqual(instrument.Strike, 13.14m); } [TestMethod] - public void TestSegmentInstruments() + public async Task TestHistoricalData() + { + string csv = File.ReadAllText(@"responses/historical.json", Encoding.UTF8); + ms.SetResponse("application/json", csv); + Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + var historicalData = await kite.GetHistoricalDataAsync("3813889", DateTime.Now, DateTime.Now, "Minutes"); + + Assert.HasCount(6, historicalData.Candles); + Assert.AreEqual(886.7m, historicalData.Candles[0].Open); + Assert.AreEqual(886.95m, historicalData.Candles[1].High); + Assert.AreEqual(886.3m, historicalData.Candles[2].Low); + Assert.AreEqual(886.75m, historicalData.Candles[3].Close); + Assert.AreEqual((ulong)9414, historicalData.Candles[4].Volume); + } + + [TestMethod] + public async Task TestHistoricalDataWithOI() + { + string csv = File.ReadAllText(@"responses/historical-oi.json", Encoding.UTF8); + ms.SetResponse("application/json", csv); + Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + var historicalData = await kite.GetHistoricalDataAsync("3813889", DateTime.Now, DateTime.Now, "Minutes"); + + Assert.HasCount(6, historicalData.Candles); + Assert.AreEqual((ulong)13667775, historicalData.Candles[0].OI); + } + + [TestMethod] + public async Task TestSegmentInstruments() { string csv = File.ReadAllText(@"responses/instruments_nse.csv", Encoding.UTF8); ms.SetResponse("text/csv", csv); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List instruments = kite.GetInstruments(Constants.Exchange.NSE); + var instrument = kite.GetInstrumentsAsync(Constants.Exchange.NSE).ToBlockingEnumerable().First(); - Assert.AreEqual(instruments[0].InstrumentToken, (uint)3813889); + Assert.AreEqual(instrument.InstrumentToken, (uint)3813889); } [TestMethod] @@ -379,56 +413,56 @@ public async Task TestTrades() } [TestMethod] - public void TestMFSIPs() + public async Task TestMFSIPs() { string json = File.ReadAllText(@"responses/mf_sips.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List sips = kite.GetMFSIPs(); + List sips = await kite.GetMFSIPsAsync(); Assert.AreEqual(sips[0].SIPId, "1234"); } [TestMethod] - public void TestMFSIP() + public async Task TestMFSIP() { string json = File.ReadAllText(@"responses/mf_sip.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - MFSIP sip = kite.GetMFSIPs("1234"); + MFSIP sip = await kite.GetMFSIPsAsync("1234"); Assert.AreEqual(sip.SIPId, "1234"); } [TestMethod] - public void TestMFOrders() + public async Task TestMFOrders() { string json = File.ReadAllText(@"responses/mf_orders.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List orders = kite.GetMFOrders(); + List orders = await kite.GetMFOrdersAsync(); Assert.AreEqual(orders[0].OrderId, "123123"); } [TestMethod] - public void TestMFOrder() + public async Task TestMFOrder() { string json = File.ReadAllText(@"responses/mf_order.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - MFOrder order = kite.GetMFOrders("123123"); + MFOrder order = await kite.GetMFOrdersAsync("123123"); Assert.AreEqual(order.OrderId, "123123"); } [TestMethod] - public void TestMFHoldings() + public async Task TestMFHoldings() { string json = File.ReadAllText(@"responses/mf_holdings.json", Encoding.UTF8); ms.SetResponse("application/json", json); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List holdings = kite.GetMFHoldings(); + List holdings = await kite.GetMFHoldingsAsync(); Assert.AreEqual(holdings[0].Folio, "123123/123"); } @@ -439,11 +473,11 @@ public void TestMFInstruments() string csv = File.ReadAllText(@"responses/mf_instruments.csv", Encoding.UTF8); ms.SetResponse("text/csv", csv); Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List instruments = kite.GetMFInstruments(); + var instrument = kite.GetMFInstrumentsAsync().ToBlockingEnumerable().First(); - Assert.AreEqual(instruments[0].TradingSymbol, "INF209K01157"); - Assert.AreEqual(instruments[0].MinimumPurchaseAmount, 1234.0m); - Assert.AreEqual(instruments[0].PurchaseAmountMultiplier, 13.14m); + Assert.AreEqual(instrument.Tradingsymbol, "INF209K01157"); + Assert.AreEqual(instrument.MinimumPurchaseAmount, 1234.0m); + Assert.AreEqual(instrument.PurchaseAmountMultiplier, 13.14m); } } } diff --git a/KiteConnectTest/responses/historical-oi.json b/KiteConnectTest/responses/historical-oi.json new file mode 100644 index 0000000..470bd85 --- /dev/null +++ b/KiteConnectTest/responses/historical-oi.json @@ -0,0 +1,61 @@ +{ + "status": "success", + "data": { + "candles": [ + [ + "2019-12-04T09:15:00+0530", + 12009.9, + 12019.35, + 12001.25, + 12001.5, + 163275, + 13667775 + ], + [ + "2019-12-04T09:16:00+0530", + 12001, + 12003, + 11998.25, + 12001, + 105750, + 13667775 + ], + [ + "2019-12-04T09:17:00+0530", + 12001, + 12001, + 11995.1, + 11998.55, + 48450, + 13758000 + ], + [ + "2019-12-04T09:18:00+0530", + 11997.8, + 12002, + 11996.25, + 12001.55, + 52875, + 13758000 + ], + [ + "2019-12-04T09:19:00+0530", + 12002.35, + 12007, + 12001.45, + 12007, + 52200, + 13758000 + ], + [ + "2019-12-04T09:20:00+0530", + 12006.95, + 12009.25, + 11999.6, + 11999.6, + 65325, + 13777050 + ] + ] + } +} \ No newline at end of file diff --git a/KiteConnectTest/responses/instruments_all.csv b/KiteConnectTest/responses/instruments_all.csv index cd4d09b..8fd5ee3 100644 --- a/KiteConnectTest/responses/instruments_all.csv +++ b/KiteConnectTest/responses/instruments_all.csv @@ -1,5 +1,5 @@ instrument_token,exchange_token,tradingsymbol,name,last_price,expiry,strike,tick_size,lot_size,instrument_type,segment,exchange -3813889,14898,WEIRDSTRIKE,WEIRD STRIKE,10.01,,1.314E+1,0.05,1,EQ,NSE,NSE +3813889,14898,WEIRDSTRIKE,WEIRD STRIKE,10.01,,13.14,0.05,1,EQ,NSE,NSE 3813889,14898,CENTRALBK-BE,CENTRAL BANK OF INDIA,0.0,,0.0,0.05,1,EQ,NSE,NSE 4645121,18145,EMMBI-BL,EMMBI INDUSTRIES,0.0,,0.0,0.05,1,EQ,NSE,NSE 4531969,17703,MIDCAPIWIN-BL,ICICI PRU MIDCAP IWIN ETF,0.0,,0.0,0.01,1,EQ,NSE,NSE diff --git a/KiteConnectTest/responses/mf_instruments.csv b/KiteConnectTest/responses/mf_instruments.csv index 320cf91..f704c35 100644 --- a/KiteConnectTest/responses/mf_instruments.csv +++ b/KiteConnectTest/responses/mf_instruments.csv @@ -1,5 +1,5 @@ tradingsymbol,amc,name,purchase_allowed,redemption_allowed,minimum_purchase_amount,purchase_amount_multiplier,minimum_additional_purchase_amount,minimum_redemption_quantity,redemption_quantity_multiplier,dividend_type,scheme_type,plan,settlement_type,last_price,last_price_date -INF209K01157,FAKE_MF,FAKE_FUND,1,1,1234.0,1.314E+1,1000.0,0.001,0.001,payout,equity,regular,T3,106.8,2017-11-23 +INF209K01157,FAKE_MF,FAKE_FUND,1,1,1234.0,13.14,1000.0,0.001,0.001,payout,equity,regular,T3,106.8,2017-11-23 INF209K01157,BirlaSunLifeMutualFund_MF,Aditya Birla Sun Life Advantage Fund,1,1,1000.0,1.0,1000.0,0.001,0.001,payout,equity,regular,T3,106.8,2017-11-23 INF209K01165,BirlaSunLifeMutualFund_MF,Aditya Birla Sun Life Advantage Fund,1,1,1000.0,1.0,1000.0,0.001,0.001,growth,equity,regular,T3,436.72,2017-11-23 INF209K01VG0,BirlaSunLifeMutualFund_MF,Aditya Birla Sun Life Advantage Fund - Direct Plan,1,1,1000.0,1.0,1000.0,0.001,0.001,payout,equity,direct,T3,134.2,2017-11-23 From bb0c7c70c149dcd1c12eab82bbcf24109d7e80a5 Mon Sep 17 00:00:00 2001 From: Arjun Vachhani Date: Fri, 6 Feb 2026 16:56:15 +0530 Subject: [PATCH 9/9] fixed naming convention - using camelCase for method parameter - acronym above 2 should be pascal case --- KiteConnect/Kite.cs | 567 +++++++++++++++++------------------ KiteConnect/Structures.cs | 84 +++--- KiteConnectSample/Program.cs | 252 ++++++++-------- KiteConnectTest/KiteTest.cs | 94 +++--- 4 files changed, 498 insertions(+), 499 deletions(-) diff --git a/KiteConnect/Kite.cs b/KiteConnect/Kite.cs index 6c4ca93..96cb5a7 100644 --- a/KiteConnect/Kite.cs +++ b/KiteConnect/Kite.cs @@ -27,51 +27,50 @@ public class Kite internal static readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, Converters = { new JsonStringEnumConverter(), new CustomDateTimeJsonConverter(), new CandleJsonConverter() } }; // Default root API endpoint. It's possible to // override this by passing the `Root` parameter during initialisation. - private string _root = "https://api.kite.trade"; - private string _login = "https://kite.zerodha.com/connect/login"; + private readonly string _root = "https://api.kite.trade"; + private readonly string _login = "https://kite.zerodha.com/connect/login"; + private readonly int _timeout; + private readonly string _apiKey; + private readonly HttpClient _httpClient; - private string _apiKey; private string _accessToken; private bool _enableLogging; - - private int _timeout; - private Action _sessionHook; - private HttpClient httpClient; /// /// Initialize a new Kite Connect client instance. /// - /// API Key issued to you - /// The token obtained after the login flow in exchange for the `RequestToken` . + /// API Key issued to you + /// The token obtained after the login flow in exchange for the `RequestToken` . /// Pre-login, this will default to None,but once you have obtained it, you should persist it in a database or session to pass /// to the Kite Connect class initialisation for subsequent requests. - /// API end point root. Unless you explicitly want to send API requests to a non-default endpoint, this can be ignored. - /// If set to True, will serialise and print requests and responses to stdout. - /// Time in milliseconds for which the API client will wait for a request to complete before it fails - /// To set proxy for http request. Should be an object of WebProxy. - /// Number of connections to server. Client will reuse the connections if they are alive. - public Kite(string APIKey, string AccessToken = null, string Root = null, bool Debug = false, int Timeout = 7000, IWebProxy Proxy = null, int Pool = 2) + /// API end point root. Unless you explicitly want to send API requests to a non-default endpoint, this can be ignored. + /// If set to True, will serialise and print requests and responses to stdout. + /// Time in milliseconds for which the API client will wait for a request to complete before it fails + /// To set proxy for http request. Should be an object of WebProxy. + /// Number of connections to server. Client will reuse the connections if they are alive. + public Kite(string apiKey, string accessToken = null, string root = null, bool debug = false, int timeout = 7000, IWebProxy proxy = null, int pool = 2) { - _accessToken = AccessToken; - _apiKey = APIKey; - if (!string.IsNullOrEmpty(Root)) this._root = Root; - _enableLogging = Debug; + _accessToken = accessToken; + _apiKey = apiKey; + if (!string.IsNullOrEmpty(root)) + _root = root; + _enableLogging = debug; - _timeout = Timeout; + _timeout = timeout; HttpClientHandler httpClientHandler = new HttpClientHandler() { - Proxy = Proxy, + Proxy = proxy, }; - httpClient = new(httpClientHandler) + _httpClient = new(httpClientHandler) { BaseAddress = new Uri(_root), - Timeout = TimeSpan.FromMilliseconds(Timeout), + Timeout = TimeSpan.FromMilliseconds(timeout), }; - ServicePointManager.DefaultConnectionLimit = Pool; + ServicePointManager.DefaultConnectionLimit = pool; } /// @@ -94,26 +93,26 @@ public void EnableLogging(bool enableLogging) /// This callback, for instance, can log the user out of the UI, /// clear session cookies, or initiate a fresh login. /// - /// Action to be invoked when session becomes invalid. - public void SetSessionExpiryHook(Action Method) + /// Action to be invoked when session becomes invalid. + public void SetSessionExpiryHook(Action method) { - _sessionHook = Method; + _sessionHook = method; } /// /// Set the `AccessToken` received after a successful authentication. /// - /// Access token for the session. - public void SetAccessToken(string AccessToken) + /// Access token for the session. + public void SetAccessToken(string accessToken) { - this._accessToken = AccessToken; + _accessToken = accessToken; } /// /// Get the remote login url to which a user should be redirected to initiate the login flow. /// /// Login url to authenticate the user. - public string GetLoginURL() + public string GetLoginUrl() { return string.Format("{0}?api_key={1}&v=3", _login, _apiKey); } @@ -124,17 +123,17 @@ public string GetLoginURL() /// response contains not just the `AccessToken`, but metadata for /// the user who has authenticated. /// - /// Token obtained from the GET paramers after a successful login redirect. - /// API secret issued with the API key. + /// Token obtained from the GET paramers after a successful login redirect. + /// API secret issued with the API key. /// /// User structure with tokens and profile data - public Task GenerateSessionAsync(string RequestToken, string AppSecret, CancellationToken cancellationToken = default) + public Task GenerateSessionAsync(string requestToken, string appSecret, CancellationToken cancellationToken = default) { - string checksum = Utils.SHA256Hash(_apiKey + RequestToken + AppSecret); + string checksum = Utils.SHA256Hash(_apiKey + requestToken + appSecret); var formDataBuilder = new ParametersBuilder() .Add("api_key", _apiKey) - .Add("request_token", RequestToken) + .Add("request_token", requestToken) .Add("checksum", checksum); return PostAsync("/session/token", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); @@ -143,14 +142,14 @@ public Task GenerateSessionAsync(string RequestToken, string AppSecret, Ca /// /// Kill the session by invalidating the access token /// - /// Access token to invalidate. Default is the active access token. + /// Access token to invalidate. Default is the active access token. /// /// Json response in the form of nested string dictionary. - public Task InvalidateAccessTokenAsync(string AccessToken = null, CancellationToken cancellationToken = default) + public Task InvalidateAccessTokenAsync(string accessToken = null, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder() .AddIfNotNull("api_key", _apiKey) - .AddIfNotNull("access_token", AccessToken); + .AddIfNotNull("access_token", accessToken); return DeleteAsync("/session/token", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } @@ -158,14 +157,14 @@ public Task InvalidateAccessTokenAsync(string AccessToken = null, Cancella /// /// Invalidates RefreshToken /// - /// RefreshToken to invalidate + /// RefreshToken to invalidate /// /// Json response in the form of nested string dictionary. - public Task InvalidateRefreshTokenAsync(string RefreshToken, CancellationToken cancellationToken = default) + public Task InvalidateRefreshTokenAsync(string refreshToken, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder() .AddIfNotNull("api_key", _apiKey) - .AddIfNotNull("refresh_token", RefreshToken); + .AddIfNotNull("refresh_token", refreshToken); return DeleteAsync("/session/token", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } @@ -173,16 +172,16 @@ public Task InvalidateRefreshTokenAsync(string RefreshToken, CancellationT /// /// Renew AccessToken using RefreshToken /// - /// RefreshToken to renew the AccessToken. - /// API secret issued with the API key. + /// RefreshToken to renew the AccessToken. + /// API secret issued with the API key. /// /// TokenRenewResponse that contains new AccessToken and RefreshToken. - public Task RenewAccessTokenAsync(string RefreshToken, string AppSecret, CancellationToken cancellationToken = default) + public Task RenewAccessTokenAsync(string refreshToken, string appSecret, CancellationToken cancellationToken = default) { - string checksum = Utils.SHA256Hash(_apiKey + RefreshToken + AppSecret); + string checksum = Utils.SHA256Hash(_apiKey + refreshToken + appSecret); var formDataBuilder = new ParametersBuilder() .AddIfNotNull("api_key", _apiKey) - .AddIfNotNull("refresh_token", RefreshToken) + .AddIfNotNull("refresh_token", refreshToken) .AddIfNotNull("checksum", checksum); return PostAsync("/session/refresh_token", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); @@ -201,44 +200,44 @@ public Task GetProfileAsync(CancellationToken cancellationToken = defau /// /// A virtual contract provides detailed charges order-wise for brokerage, STT, stamp duty, exchange transaction charges, SEBI turnover charge, and GST. /// - /// List of all order params to get contract notes for + /// List of all order params to get contract notes for /// /// List of contract notes for the params - public Task> GetVirtualContractNoteAsync(List ContractNoteParams, CancellationToken cancellationToken = default) + public Task> GetVirtualContractNoteAsync(List contractNoteParams, CancellationToken cancellationToken = default) { - return PostJsonAsync, List>("/charges/orders", jsonData: ContractNoteParams, cancellationToken: cancellationToken); + return PostJsonAsync, List>("/charges/orders", jsonData: contractNoteParams, cancellationToken: cancellationToken); } /// /// Margin data for a specific order /// - /// List of all order params to get margins for - /// Mode of the returned response content. Eg: Constants.Margin.Mode.Compact + /// List of all order params to get margins for + /// Mode of the returned response content. Eg: Constants.Margin.Mode.Compact /// /// List of margins of order - public Task> GetOrderMarginsAsync(List OrderMarginParams, string Mode = null, CancellationToken cancellationToken = default) + public Task> GetOrderMarginsAsync(List orderMarginParams, string mode = null, CancellationToken cancellationToken = default) { var queryParameterBuilder = new ParametersBuilder() - .AddIfNotNull("mode", Mode); + .AddIfNotNull("mode", mode); - return PostJsonAsync, List>("/margins/orders", queryParameters: queryParameterBuilder.Build(), jsonData: OrderMarginParams, cancellationToken: cancellationToken); + return PostJsonAsync, List>("/margins/orders", queryParameters: queryParameterBuilder.Build(), jsonData: orderMarginParams, cancellationToken: cancellationToken); } /// /// Margin data for a basket orders /// - /// List of all order params to get margins for - /// Consider users positions while calculating margins - /// Mode of the returned response content. Eg: Constants.Margin.Mode.Compact + /// List of all order params to get margins for + /// Consider users positions while calculating margins + /// Mode of the returned response content. Eg: Constants.Margin.Mode.Compact /// /// List of margins of order - public Task GetBasketMarginsAsync(List OrderMarginParams, bool ConsiderPositions = true, string Mode = null, CancellationToken cancellationToken = default) + public Task GetBasketMarginsAsync(List orderMarginParams, bool considerPositions = true, string mode = null, CancellationToken cancellationToken = default) { var queryParameterBuilder = new ParametersBuilder() - .Add("consider_positions", ConsiderPositions) - .AddIfNotNull("mode", Mode); + .Add("consider_positions", considerPositions) + .AddIfNotNull("mode", mode); - return PostJsonAsync, BasketMargin>("/margins/basket", queryParameters: queryParameterBuilder.Build(), jsonData: OrderMarginParams, cancellationToken: cancellationToken); + return PostJsonAsync, BasketMargin>("/margins/basket", queryParameters: queryParameterBuilder.Build(), jsonData: orderMarginParams, cancellationToken: cancellationToken); } /// @@ -265,157 +264,157 @@ public Task GetMarginsAsync(string segment, CancellationToken cancel /// /// Place an order /// - /// Name of the exchange - /// Tradingsymbol of the instrument - /// BUY or SELL - /// Quantity to transact - /// For LIMIT orders - /// Margin product applied to the order (margin is blocked based on this) - /// Order type (MARKET, LIMIT etc.) - /// Order validity (DAY, IOC and TTL) - /// Quantity to disclose publicly (for equity trades) - /// For SL, SL-M etc. - /// Price difference at which the order should be squared off and profit booked (eg: Order price is 100. Profit target is 102. So squareoff = 2) - /// Stoploss difference at which the order should be squared off (eg: Order price is 100. Stoploss target is 98. So stoploss = 2) - /// Incremental value by which stoploss price changes when market moves in your favor by the same incremental value from the entry price (optional) - /// You can place orders of varieties; regular orders, after market orders, cover orders, iceberg orders etc. - /// An optional tag to apply to an order to identify it (alphanumeric, max 20 chars) - /// Order life span in minutes for TTL validity orders - /// Total number of legs for iceberg order type (number of legs per Iceberg should be between 2 and 10) - /// Split quantity for each iceberg leg order (Quantity/IcebergLegs) - /// A unique identifier for a particular auction + /// Name of the exchange + /// Tradingsymbol of the instrument + /// BUY or SELL + /// Quantity to transact + /// For LIMIT orders + /// Margin product applied to the order (margin is blocked based on this) + /// Order type (MARKET, LIMIT etc.) + /// Order validity (DAY, IOC and TTL) + /// Quantity to disclose publicly (for equity trades) + /// For SL, SL-M etc. + /// Price difference at which the order should be squared off and profit booked (eg: Order price is 100. Profit target is 102. So squareoff = 2) + /// Stoploss difference at which the order should be squared off (eg: Order price is 100. Stoploss target is 98. So stoploss = 2) + /// Incremental value by which stoploss price changes when market moves in your favor by the same incremental value from the entry price (optional) + /// You can place orders of varieties; regular orders, after market orders, cover orders, iceberg orders etc. + /// An optional tag to apply to an order to identify it (alphanumeric, max 20 chars) + /// Order life span in minutes for TTL validity orders + /// Total number of legs for iceberg order type (number of legs per Iceberg should be between 2 and 10) + /// Split quantity for each iceberg leg order (Quantity/IcebergLegs) + /// A unique identifier for a particular auction /// /// Json response in the form of nested string dictionary. public Task PlaceOrderAsync( - string Exchange, - string TradingSymbol, - string TransactionType, - decimal Quantity, - decimal? Price = null, - string Product = null, - string OrderType = null, - string Validity = null, - decimal? DisclosedQuantity = null, - decimal? TriggerPrice = null, - decimal? SquareOffValue = null, - decimal? StoplossValue = null, - decimal? TrailingStoploss = null, - string Variety = Constants.Variety.Regular, - string Tag = "", - int? ValidityTTL = null, - int? IcebergLegs = null, - decimal? IcebergQuantity = null, - string AuctionNumber = null, + string exchange, + string tradingSymbol, + string transactionType, + decimal quantity, + decimal? price = null, + string product = null, + string orderType = null, + string validity = null, + decimal? disclosedQuantity = null, + decimal? triggerPrice = null, + decimal? squareOffValue = null, + decimal? stoplossValue = null, + decimal? trailingStoploss = null, + string variety = Constants.Variety.Regular, + string tag = "", + int? validityTtl = null, + int? icebergLegs = null, + decimal? icebergQuantity = null, + string auctionNumber = null, CancellationToken cancellationToken = default ) { var formDataBuilder = new ParametersBuilder() - .AddIfNotNull("exchange", Exchange) - .AddIfNotNull("tradingsymbol", TradingSymbol) - .AddIfNotNull("transaction_type", TransactionType) - .Add("quantity", Quantity) - .AddIfNotNull("price", Price) - .AddIfNotNull("product", Product) - .AddIfNotNull("order_type", OrderType) - .AddIfNotNull("validity", Validity) - .AddIfNotNull("disclosed_quantity", DisclosedQuantity) - .AddIfNotNull("trigger_price", TriggerPrice) - .AddIfNotNull("squareoff", SquareOffValue) - .AddIfNotNull("stoploss", StoplossValue) - .AddIfNotNull("trailing_stoploss", TrailingStoploss) - .AddIfNotNull("variety", Variety) - .AddIfNotNull("tag", Tag) - .AddIfNotNull("validity_ttl", ValidityTTL) - .AddIfNotNull("iceberg_legs", IcebergLegs) - .AddIfNotNull("iceberg_quantity", IcebergQuantity) - .AddIfNotNull("auction_number", AuctionNumber); - - return PostAsync($"/orders/{Variety}", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); + .AddIfNotNull("exchange", exchange) + .AddIfNotNull("tradingsymbol", tradingSymbol) + .AddIfNotNull("transaction_type", transactionType) + .Add("quantity", quantity) + .AddIfNotNull("price", price) + .AddIfNotNull("product", product) + .AddIfNotNull("order_type", orderType) + .AddIfNotNull("validity", validity) + .AddIfNotNull("disclosed_quantity", disclosedQuantity) + .AddIfNotNull("trigger_price", triggerPrice) + .AddIfNotNull("squareoff", squareOffValue) + .AddIfNotNull("stoploss", stoplossValue) + .AddIfNotNull("trailing_stoploss", trailingStoploss) + .AddIfNotNull("variety", variety) + .AddIfNotNull("tag", tag) + .AddIfNotNull("validity_ttl", validityTtl) + .AddIfNotNull("iceberg_legs", icebergLegs) + .AddIfNotNull("iceberg_quantity", icebergQuantity) + .AddIfNotNull("auction_number", auctionNumber); + + return PostAsync($"/orders/{variety}", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// /// Modify an open order. /// - /// Id of the order to be modified - /// Id of the parent order (obtained from the /orders call) as BO is a multi-legged order - /// Name of the exchange - /// Tradingsymbol of the instrument - /// BUY or SELL - /// Quantity to transact - /// For LIMIT orders - /// Margin product applied to the order (margin is blocked based on this) - /// Order type (MARKET, LIMIT etc.) - /// Order validity - /// Quantity to disclose publicly (for equity trades) - /// For SL, SL-M etc. - /// You can place orders of varieties; regular orders, after market orders, cover orders etc. + /// Id of the order to be modified + /// Id of the parent order (obtained from the /orders call) as BO is a multi-legged order + /// Name of the exchange + /// Tradingsymbol of the instrument + /// BUY or SELL + /// Quantity to transact + /// For LIMIT orders + /// Margin product applied to the order (margin is blocked based on this) + /// Order type (MARKET, LIMIT etc.) + /// Order validity + /// Quantity to disclose publicly (for equity trades) + /// For SL, SL-M etc. + /// You can place orders of varieties; regular orders, after market orders, cover orders etc. /// /// Json response in the form of nested string dictionary. public Task ModifyOrderAsync( - string OrderId, - string ParentOrderId = null, - string Exchange = null, - string TradingSymbol = null, - string TransactionType = null, - decimal? Quantity = null, - decimal? Price = null, - string Product = null, - string OrderType = null, - string Validity = Constants.Validity.Day, - decimal? DisclosedQuantity = null, - decimal? TriggerPrice = null, - string Variety = Constants.Variety.Regular, + string orderId, + string parentOrderId = null, + string exchange = null, + string tradingSymbol = null, + string transactionType = null, + decimal? quantity = null, + decimal? price = null, + string product = null, + string orderType = null, + string validity = Constants.Validity.Day, + decimal? disclosedQuantity = null, + decimal? triggerPrice = null, + string variety = Constants.Variety.Regular, CancellationToken cancellationToken = default) { var formDataBuilder = new ParametersBuilder(); - string VarietyString = Variety; - string ProductString = Product; + string VarietyString = variety; + string ProductString = product; if ((ProductString == "bo" || ProductString == "co") && VarietyString != ProductString) throw new Exception(string.Format("Invalid variety. It should be: {0}", ProductString)); - formDataBuilder.AddIfNotNull("order_id", OrderId) - .AddIfNotNull("parent_order_id", ParentOrderId) - .AddIfNotNull("trigger_price", TriggerPrice) - .AddIfNotNull("variety", Variety); + formDataBuilder.AddIfNotNull("order_id", orderId) + .AddIfNotNull("parent_order_id", parentOrderId) + .AddIfNotNull("trigger_price", triggerPrice) + .AddIfNotNull("variety", variety); if (VarietyString == "bo" && ProductString == "bo") { - formDataBuilder.AddIfNotNull("quantity", Quantity) - .AddIfNotNull("price", Price) - .AddIfNotNull("disclosed_quantity", DisclosedQuantity); + formDataBuilder.AddIfNotNull("quantity", quantity) + .AddIfNotNull("price", price) + .AddIfNotNull("disclosed_quantity", disclosedQuantity); } else if (VarietyString != "co" && ProductString != "co") { - formDataBuilder.AddIfNotNull("exchange", Exchange) - .AddIfNotNull("tradingsymbol", TradingSymbol) - .AddIfNotNull("transaction_type", TransactionType) - .AddIfNotNull("quantity", Quantity) - .AddIfNotNull("price", Price) - .AddIfNotNull("product", Product) - .AddIfNotNull("order_type", OrderType) - .AddIfNotNull("validity", Validity) - .AddIfNotNull("disclosed_quantity", DisclosedQuantity); + formDataBuilder.AddIfNotNull("exchange", exchange) + .AddIfNotNull("tradingsymbol", tradingSymbol) + .AddIfNotNull("transaction_type", transactionType) + .AddIfNotNull("quantity", quantity) + .AddIfNotNull("price", price) + .AddIfNotNull("product", product) + .AddIfNotNull("order_type", orderType) + .AddIfNotNull("validity", validity) + .AddIfNotNull("disclosed_quantity", disclosedQuantity); } - return PutAsync($"/orders/{Variety}/{OrderId}", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); + return PutAsync($"/orders/{variety}/{orderId}", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// /// Cancel an order /// - /// Id of the order to be cancelled - /// You can place orders of varieties; regular orders, after market orders, cover orders etc. - /// Id of the parent order (obtained from the /orders call) as BO is a multi-legged order + /// Id of the order to be cancelled + /// You can place orders of varieties; regular orders, after market orders, cover orders etc. + /// Id of the parent order (obtained from the /orders call) as BO is a multi-legged order /// /// Json response in the form of nested string dictionary. - public Task CancelOrderAsync(string OrderId, string Variety = Constants.Variety.Regular, string ParentOrderId = null, CancellationToken cancellationToken = default) + public Task CancelOrderAsync(string orderId, string variety = Constants.Variety.Regular, string parentOrderId = null, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder() - .AddIfNotNull("parent_order_id", ParentOrderId);//TODO undocumented parameter + .AddIfNotNull("parent_order_id", parentOrderId);//TODO undocumented parameter - return DeleteAsync($"/orders/{Variety}/{OrderId}", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); + return DeleteAsync($"/orders/{variety}/{orderId}", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// @@ -431,12 +430,12 @@ public Task> GetOrdersAsync(CancellationToken cancellationToken = de /// /// Gets information about given OrderId. /// - /// Unique order id + /// Unique order id /// /// List of order objects. - public Task> GetOrderHistoryAsync(string OrderId, CancellationToken cancellationToken = default) + public Task> GetOrderHistoryAsync(string orderId, CancellationToken cancellationToken = default) { - return GetAsync>($"/orders/{OrderId}", cancellationToken: cancellationToken); + return GetAsync>($"/orders/{orderId}", cancellationToken: cancellationToken); } /// @@ -444,13 +443,13 @@ public Task> GetOrderHistoryAsync(string OrderId, CancellationToken /// An order can be executed in tranches based on market conditions. /// These trades are individually recorded under an order. /// - /// is the ID of the order (optional) whose trades are to be retrieved. If no `OrderId` is specified, all trades for the day are returned. + /// is the ID of the order (optional) whose trades are to be retrieved. If no `OrderId` is specified, all trades for the day are returned. /// /// List of trades of given order. - public Task> GetOrderTradesAsync(string OrderId = null, CancellationToken cancellationToken = default) + public Task> GetOrderTradesAsync(string orderId = null, CancellationToken cancellationToken = default) { - if (!string.IsNullOrEmpty(OrderId)) - return GetAsync>($"/orders/{OrderId}/trades", cancellationToken: cancellationToken); + if (!string.IsNullOrEmpty(orderId)) + return GetAsync>($"/orders/{orderId}/trades", cancellationToken: cancellationToken); else return GetAsync>("/trades", cancellationToken: cancellationToken); } @@ -488,33 +487,33 @@ public Task> GetAuctionInstrumentsAsync(CancellationToke /// /// Modify an open position's product type. /// - /// Name of the exchange - /// Tradingsymbol of the instrument - /// BUY or SELL - /// overnight or day - /// Quantity to convert - /// Existing margin product of the position - /// Margin product to convert to + /// Name of the exchange + /// Tradingsymbol of the instrument + /// BUY or SELL + /// overnight or day + /// Quantity to convert + /// Existing margin product of the position + /// Margin product to convert to /// /// Json response in the form of nested string dictionary. public Task ConvertPositionAsync( - string Exchange, - string TradingSymbol, - string TransactionType, - string PositionType, - decimal? Quantity, - string OldProduct, - string NewProduct, + string exchange, + string tradingSymbol, + string transactionType, + string positionType, + decimal? quantity, + string oldProduct, + string newProduct, CancellationToken cancellationToken = default) { var formDataBuilder = new ParametersBuilder() - .AddIfNotNull("exchange", Exchange) - .AddIfNotNull("tradingsymbol", TradingSymbol) - .AddIfNotNull("transaction_type", TransactionType) - .AddIfNotNull("position_type", PositionType) - .AddIfNotNull("quantity", Quantity) - .AddIfNotNull("old_product", OldProduct) - .AddIfNotNull("new_product", NewProduct); + .AddIfNotNull("exchange", exchange) + .AddIfNotNull("tradingsymbol", tradingSymbol) + .AddIfNotNull("transaction_type", transactionType) + .AddIfNotNull("position_type", positionType) + .AddIfNotNull("quantity", quantity) + .AddIfNotNull("old_product", oldProduct) + .AddIfNotNull("new_product", newProduct); return PutAsync("/portfolio/positions", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } @@ -524,27 +523,27 @@ public Task ConvertPositionAsync( /// Note that the results could be large, several hundred KBs in size, /// with tens of thousands of entries in the list. /// - /// Name of the exchange + /// Name of the exchange /// /// List of instruments. - public IAsyncEnumerable GetInstrumentsAsync(string Exchange = null, CancellationToken cancellationToken = default) + public IAsyncEnumerable GetInstrumentsAsync(string exchange = null, CancellationToken cancellationToken = default) { - if (string.IsNullOrEmpty(Exchange)) + if (string.IsNullOrEmpty(exchange)) return GetCsvAsync("/instruments", cancellationToken: cancellationToken); else - return GetCsvAsync($"/instruments/{Exchange}", cancellationToken: cancellationToken); + return GetCsvAsync($"/instruments/{exchange}", cancellationToken: cancellationToken); } /// /// Retrieve quote and market depth of upto 200 instruments /// - /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) + /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) /// /// Dictionary of all Quote objects with keys as in InstrumentId - public Task> GetQuoteAsync(string[] InstrumentId, CancellationToken cancellationToken = default) + public Task> GetQuoteAsync(string[] instrumentId, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder(); - foreach (var i in InstrumentId) + foreach (var i in instrumentId) { queryParametersBuilder.Add("i", i); } @@ -555,35 +554,35 @@ public Task> GetQuoteAsync(string[] InstrumentId, Canc /// /// Retrieve LTP and OHLC of upto 200 instruments /// - /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) + /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) /// /// Dictionary of all OHLC objects with keys as in InstrumentId - public Task> GetOHLCAsync(string[] InstrumentId, CancellationToken cancellationToken = default) + public Task> GetOhlcAsync(string[] instrumentId, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder(); - foreach (var i in InstrumentId) + foreach (var i in instrumentId) { queryParametersBuilder.Add("i", i); } - return GetAsync>("/quote/ohlc", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); + return GetAsync>("/quote/ohlc", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// /// Retrieve LTP of upto 200 instruments /// - /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) + /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) /// /// Dictionary with InstrumentId as key and LTP as value. - public Task> GetLTPAsync(string[] InstrumentId, CancellationToken cancellationToken = default) + public Task> GetLtpAsync(string[] instrumentId, CancellationToken cancellationToken = default) { var queryParametersBuilder = new ParametersBuilder(); - foreach (var i in InstrumentId) + foreach (var i in instrumentId) { queryParametersBuilder.Add("i", i); } - return GetAsync>("/quote/ltp", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); + return GetAsync>("/quote/ltp", queryParameters: queryParametersBuilder.Build(), cancellationToken: cancellationToken); } /// @@ -621,15 +620,15 @@ public Task GetHistoricalDataAsync( /// /// Retrieve the buy/sell trigger range for Cover Orders. /// - /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) - /// BUY or SELL + /// Indentification of instrument in the form of EXCHANGE:TRADINGSYMBOL (eg: NSE:INFY) or InstrumentToken (eg: 408065) + /// BUY or SELL /// List of trigger ranges for given instrument ids for given transaction type. - public Dictionary GetTriggerRange(string[] InstrumentId, string TrasactionType) + public Dictionary GetTriggerRange(string[] instrumentId, string trasactionType) { var param = new Dictionary(); - param.Add("i", InstrumentId); - param.Add("transaction_type", TrasactionType.ToLower()); + param.Add("i", instrumentId); + param.Add("transaction_type", trasactionType.ToLower()); var triggerdata = Get(Routes.Market.TriggerRange, param)["data"]; @@ -647,21 +646,21 @@ public Dictionary GetTriggerRange(string[] InstrumentId, st /// /// /// List of GTTs. - public Task> GetGTTsAsync(CancellationToken cancellationToken = default) + public Task> GetGttsAsync(CancellationToken cancellationToken = default) { - return GetAsync>("/gtt/triggers", cancellationToken: cancellationToken); + return GetAsync>("/gtt/triggers", cancellationToken: cancellationToken); } /// /// Retrieve a single GTT /// - /// Id of the GTT + /// Id of the GTT /// /// GTT info - public Task GetGTTAsync(int GTTId, CancellationToken cancellationToken = default) + public Task GetGttAsync(int GttId, CancellationToken cancellationToken = default) { - return GetAsync($"/gtt/triggers/{GTTId}", cancellationToken: cancellationToken); + return GetAsync($"/gtt/triggers/{GttId}", cancellationToken: cancellationToken); } /// @@ -670,7 +669,7 @@ public Task GetGTTAsync(int GTTId, CancellationToken cancellationToken = de /// Contains the parameters for the GTT order /// /// Json response in the form of nested string dictionary. - public Task PlaceGTTAsync(GTTParams gttParams, CancellationToken cancellationToken = default) + public Task PlaceGttAsync(GttParams gttParams, CancellationToken cancellationToken = default) { var condition = new Dictionary { @@ -702,17 +701,17 @@ public Task PlaceGTTAsync(GTTParams gttParams, CancellationToken ca .Add("orders", JsonSerializer.Serialize(ordersParam, JsonSerializerOptions)) .Add("type", gttParams.TriggerType); - return PostAsync("/gtt/triggers", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); + return PostAsync("/gtt/triggers", formData: formDataBuilder.Build(), cancellationToken: cancellationToken); } /// /// Modify a GTT order /// - /// Id of the GTT to be modified + /// Id of the GTT to be modified /// Contains the parameters for the GTT order /// /// Json response in the form of nested string dictionary. - public Task ModifyGTTAsync(int GTTId, GTTParams gttParams, CancellationToken cancellationToken = default) + public Task ModifyGttAsync(int gttId, GttParams gttParams, CancellationToken cancellationToken = default) { var condition = new Dictionary { @@ -744,18 +743,18 @@ public Task ModifyGTTAsync(int GTTId, GTTParams gttParams, Cancella .Add("orders", JsonSerializer.Serialize(ordersParam, JsonSerializerOptions)) .Add("type", gttParams.TriggerType); - return PutAsync($"/gtt/triggers/{GTTId}", formDataBuilder.Build(), cancellationToken: cancellationToken); + return PutAsync($"/gtt/triggers/{gttId}", formDataBuilder.Build(), cancellationToken: cancellationToken); } /// /// Cancel a GTT order /// - /// Id of the GTT to be modified + /// Id of the GTT to be modified /// /// Json response in the form of nested string dictionary. - public Task CancelGTTAsync(int GTTId, CancellationToken cancellationToken = default) + public Task CancelGttAsync(int gttId, CancellationToken cancellationToken = default) { - return DeleteAsync($"/gtt/triggers/{GTTId}", cancellationToken: cancellationToken); + return DeleteAsync($"/gtt/triggers/{gttId}", cancellationToken: cancellationToken); } #endregion GTT @@ -787,11 +786,11 @@ public Task> GetMFOrdersAsync(CancellationToken cancellationToken /// Gets the Mutual funds order by OrderId. /// /// The Mutual funds order. - /// Order id. + /// Order id. /// - public Task GetMFOrdersAsync(string OrderId, CancellationToken cancellationToken = default) + public Task GetMFOrdersAsync(string orderId, CancellationToken cancellationToken = default) { - return GetAsync($"/mf/orders/{OrderId}", cancellationToken: cancellationToken); + return GetAsync($"/mf/orders/{orderId}", cancellationToken: cancellationToken); } //TODO undocumented API @@ -800,25 +799,25 @@ public Task GetMFOrdersAsync(string OrderId, CancellationToken cancella /// Places a Mutual funds order. /// /// JSON response as nested string dictionary. - /// Tradingsymbol (ISIN) of the fund. - /// BUY or SELL. - /// Amount worth of units to purchase. Not applicable on SELLs. - /// Quantity to SELL. Not applicable on BUYs. If the holding is less than minimum_redemption_quantity, all the units have to be sold. - /// An optional tag to apply to an order to identify it (alphanumeric, max 8 chars). + /// Tradingsymbol (ISIN) of the fund. + /// BUY or SELL. + /// Amount worth of units to purchase. Not applicable on SELLs. + /// Quantity to SELL. Not applicable on BUYs. If the holding is less than minimum_redemption_quantity, all the units have to be sold. + /// An optional tag to apply to an order to identify it (alphanumeric, max 8 chars). public Dictionary PlaceMFOrder( - string TradingSymbol, - string TransactionType, - decimal? Amount, - decimal? Quantity = null, - string Tag = "") + string tradingSymbol, + string transactionType, + decimal? amount, + decimal? quantity = null, + string tag = "") { var param = new Dictionary(); - Utils.AddIfNotNull(param, "tradingsymbol", TradingSymbol); - Utils.AddIfNotNull(param, "transaction_type", TransactionType); - Utils.AddIfNotNull(param, "amount", Amount.ToString()); - Utils.AddIfNotNull(param, "quantity", Quantity.ToString()); - Utils.AddIfNotNull(param, "tag", Tag); + Utils.AddIfNotNull(param, "tradingsymbol", tradingSymbol); + Utils.AddIfNotNull(param, "transaction_type", transactionType); + Utils.AddIfNotNull(param, "amount", amount.ToString()); + Utils.AddIfNotNull(param, "quantity", quantity.ToString()); + Utils.AddIfNotNull(param, "tag", tag); return Post(Routes.MutualFunds.PlaceOrder, param); } @@ -829,12 +828,12 @@ public Dictionary PlaceMFOrder( /// Cancels the Mutual funds order. /// /// JSON response as nested string dictionary. - /// Unique order id. - public Dictionary CancelMFOrder(string OrderId) + /// Unique order id. + public Dictionary CancelMFOrder(string orderId) { var param = new Dictionary(); - Utils.AddIfNotNull(param, "order_id", OrderId); + Utils.AddIfNotNull(param, "order_id", orderId); return Delete(Routes.MutualFunds.CancelOrder, param); } @@ -844,20 +843,20 @@ public Dictionary CancelMFOrder(string OrderId) /// /// /// The list of all Mutual funds SIPs. - public Task> GetMFSIPsAsync(CancellationToken cancellationToken = default) + public Task> GetMFSipsAsync(CancellationToken cancellationToken = default) { - return GetAsync>("/mf/sips", cancellationToken: cancellationToken); + return GetAsync>("/mf/sips", cancellationToken: cancellationToken); } /// /// Gets a single Mutual funds SIP by SIP id. /// /// The Mutual funds SIP. - /// SIP id. + /// SIP id. /// - public Task GetMFSIPsAsync(string SIPID, CancellationToken cancellationToken = default) + public Task GetMFSipsAsync(string SipId, CancellationToken cancellationToken = default) { - return GetAsync($"/mf/sips/{SIPID}", cancellationToken: cancellationToken); + return GetAsync($"/mf/sips/{SipId}", cancellationToken: cancellationToken); } //TODO undocumented API @@ -866,30 +865,30 @@ public Task GetMFSIPsAsync(string SIPID, CancellationToken cancellationTo /// Places a Mutual funds SIP order. /// /// JSON response as nested string dictionary. - /// ISIN of the fund. - /// Amount worth of units to purchase. It should be equal to or greated than minimum_additional_purchase_amount and in multiple of purchase_amount_multiplier in the instrument master. - /// Amount worth of units to purchase before the SIP starts. Should be equal to or greater than minimum_purchase_amount and in multiple of purchase_amount_multiplier. This is only considered if there have been no prior investments in the target fund. - /// weekly, monthly, or quarterly. - /// If Frequency is monthly, the day of the month (1, 5, 10, 15, 20, 25) to trigger the order on. - /// Number of instalments to trigger. If set to -1, instalments are triggered at fixed intervals until the SIP is cancelled. - /// An optional tag to apply to an order to identify it (alphanumeric, max 8 chars). - public Dictionary PlaceMFSIP( - string TradingSymbol, - decimal? Amount, - decimal? InitialAmount, - string Frequency, - int? InstalmentDay, - int? Instalments, - string Tag = "") + /// ISIN of the fund. + /// Amount worth of units to purchase. It should be equal to or greated than minimum_additional_purchase_amount and in multiple of purchase_amount_multiplier in the instrument master. + /// Amount worth of units to purchase before the SIP starts. Should be equal to or greater than minimum_purchase_amount and in multiple of purchase_amount_multiplier. This is only considered if there have been no prior investments in the target fund. + /// weekly, monthly, or quarterly. + /// If Frequency is monthly, the day of the month (1, 5, 10, 15, 20, 25) to trigger the order on. + /// Number of instalments to trigger. If set to -1, instalments are triggered at fixed intervals until the SIP is cancelled. + /// An optional tag to apply to an order to identify it (alphanumeric, max 8 chars). + public Dictionary PlaceMFSip( + string tradingSymbol, + decimal? amount, + decimal? initialAmount, + string frequency, + int? instalmentDay, + int? instalments, + string tag = "") { var param = new Dictionary(); - Utils.AddIfNotNull(param, "tradingsymbol", TradingSymbol); - Utils.AddIfNotNull(param, "initial_amount", InitialAmount.ToString()); - Utils.AddIfNotNull(param, "amount", Amount.ToString()); - Utils.AddIfNotNull(param, "frequency", Frequency); - Utils.AddIfNotNull(param, "instalment_day", InstalmentDay.ToString()); - Utils.AddIfNotNull(param, "instalments", Instalments.ToString()); + Utils.AddIfNotNull(param, "tradingsymbol", tradingSymbol); + Utils.AddIfNotNull(param, "initial_amount", initialAmount.ToString()); + Utils.AddIfNotNull(param, "amount", amount.ToString()); + Utils.AddIfNotNull(param, "frequency", frequency); + Utils.AddIfNotNull(param, "instalment_day", instalmentDay.ToString()); + Utils.AddIfNotNull(param, "instalments", instalments.ToString()); return Post(Routes.MutualFunds.PlaceSIP, param); } @@ -906,7 +905,7 @@ public Dictionary PlaceMFSIP( /// If Frequency is monthly, the day of the month (1, 5, 10, 15, 20, 25) to trigger the order on. /// Number of instalments to trigger. If set to -1, instalments are triggered idefinitely until the SIP is cancelled. /// Pause or unpause an SIP (active or paused). - public Dictionary ModifyMFSIP( + public Dictionary ModifyMFSip( string SIPId, decimal? Amount, string Frequency, @@ -1102,7 +1101,7 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict AddExtraHeaders(request); } - HttpResponseMessage response = httpClient.Send(request); + HttpResponseMessage response = _httpClient.Send(request); HttpStatusCode status = response.StatusCode; string responseBody = response.Content.ReadAsStringAsync().Result; @@ -1158,7 +1157,7 @@ private Task GetAsync(string path, IReadOnlyCollection GetCsvAsync(string path, IReadOnlyCollection> queryParameters = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { string url = BuildUrl(_root, path, queryParameters); - using var httpResponse = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken); + using var httpResponse = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken); httpResponse.EnsureSuccessStatusCode(); if (httpResponse.Content.Headers.ContentType.MediaType != "text/csv") throw new DataException($"Unexpected content type {httpResponse.Content.Headers.ContentType.MediaType}"); @@ -1212,7 +1211,7 @@ private async Task SendRequestAsync(HttpMethod httpMethod, str AddExtraHeaders(httpRequestMessage); if (content != null) httpRequestMessage.Content = content; - using var httpResponse = await httpClient.SendAsync(httpRequestMessage); + using var httpResponse = await _httpClient.SendAsync(httpRequestMessage); return await ParseResponseAsync(httpResponse, cancellationToken); } diff --git a/KiteConnect/Structures.cs b/KiteConnect/Structures.cs index ca6b9d7..bba8cf5 100644 --- a/KiteConnect/Structures.cs +++ b/KiteConnect/Structures.cs @@ -109,27 +109,27 @@ public class Holding public decimal Price { get; set; } public decimal LastPrice { get; set; } public decimal CollateralQuantity { get; set; } - public decimal PNL { get; set; } + public decimal Pnl { get; set; } public decimal ClosePrice { get; set; } public decimal AveragePrice { get; set; } public string Tradingsymbol { get; set; } public string CollateralType { get; set; } public decimal T1Quantity { get; set; } public uint InstrumentToken { get; set; } - public string ISIN { get; set; } + public string Isin { get; set; } public decimal RealisedQuantity { get; set; } public decimal Quantity { get; set; } public decimal UsedQuantity { get; set; } public decimal AuthorisedQuantity { get; set; } public DateTime? AuthorisedDate { get; set; } public bool Discrepancy { get; set; } - public MTFHolding MTF { get; set; } + public MtfHolding Mtf { get; set; } } /// /// MTF Holding structure /// - public class MTFHolding + public class MtfHolding { public decimal Quantity { get; set; } public decimal UsedQuantity { get; set; } @@ -146,7 +146,7 @@ public class AuctionInstrument public string Tradingsymbol { get; set; } public string Exchange { get; set; } public uint InstrumentToken { get; set; } - public string ISIN { get; set; } + public string Isin { get; set; } public string Product { get; set; } public decimal Price { get; set; } public decimal Quantity { get; set; } @@ -161,7 +161,7 @@ public class AuctionInstrument public decimal AveragePrice { get; set; } public decimal LastPrice { get; set; } public decimal ClosePrice { get; set; } - public decimal PNL { get; set; } + public decimal Pnl { get; set; } public decimal DayChange { get; set; } public decimal DayChangePercentage { get; set; } public string AuctionNumber { get; set; } @@ -280,13 +280,13 @@ public class OrderMargin public string Exchange { get; set; } public string Tradingsymbol { get; set; } public decimal OptionPremium { get; set; } - public decimal SPAN { get; set; } + public decimal Span { get; set; } public decimal Exposure { get; set; } public decimal Additional { get; set; } public decimal BO { get; set; } public decimal Cash { get; set; } - public decimal VAR { get; set; } - public OrderMarginPNL PNL { get; set; } + public decimal Var { get; set; } + public OrderMarginPnl Pnl { get; set; } public OrderCharges Charges { get; set; } public decimal Leverage { get; set; } public decimal Total { get; set; } @@ -406,17 +406,17 @@ public class OrderCharges public decimal Brokerage { get; set; } public decimal StampDuty { get; set; } public decimal Total { get; set; } - public OrderChargesGST GST { get; set; } + public OrderChargesGst Gst { get; set; } } /// /// OrderChargesGST structure /// - public class OrderChargesGST + public class OrderChargesGst { - public decimal IGST { get; set; } - public decimal CGST { get; set; } - public decimal SGST { get; set; } + public decimal Igst { get; set; } + public decimal Cgst { get; set; } + public decimal Sgst { get; set; } public decimal Total { get; set; } } @@ -435,7 +435,7 @@ public class BasketMargin /// /// OrderMarginPNL structure /// - public class OrderMarginPNL + public class OrderMarginPnl { public decimal Realised { get; set; } public decimal Unrealised { get; set; } @@ -456,7 +456,7 @@ public class Position public decimal LastPrice { get; set; } public string Tradingsymbol { get; set; } public decimal Realised { get; set; } - public decimal PNL { get; set; } + public decimal Pnl { get; set; } public decimal Multiplier { get; set; } public decimal SellQuantity { get; set; } @@ -522,7 +522,7 @@ public class Order public string TransactionType { get; set; } public decimal TriggerPrice { get; set; } public string Validity { get; set; } - public int ValidityTTL { get; set; } + public int ValidityTtl { get; set; } public int AuctionNumber { get; set; } public string Variety { get; set; } public JsonNode Meta { get; set; } @@ -531,25 +531,25 @@ public class Order /// /// GTTOrder structure /// - public class GTT + public class Gtt { public int Id { get; set; } - public GTTCondition? Condition { get; set; } + public GttCondition? Condition { get; set; } [JsonPropertyName("type")] public string TriggerType { get; set; } - public List Orders { get; set; } + public List Orders { get; set; } public string Status { get; set; } public DateTime? CreatedAt { get; set; } public DateTime? UpdatedAt { get; set; } public DateTime? ExpiresAt { get; set; } - public GTTMeta? Meta { get; set; } + public GttMeta? Meta { get; set; } } /// /// GTTMeta structure /// - public class GTTMeta + public class GttMeta { public string RejectionReason { get; set; } } @@ -557,7 +557,7 @@ public class GTTMeta /// /// GTTCondition structure /// - public class GTTCondition + public class GttCondition { public uint InstrumentToken { get; set; } public string Exchange { get; set; } @@ -569,23 +569,23 @@ public class GTTCondition /// /// GTTOrder structure /// - public class GTTOrder + public class GttOrder { public string TransactionType { get; set; } public string Product { get; set; } public string OrderType { get; set; } public decimal Quantity { get; set; } public decimal Price { get; set; } - public GTTResult? Result { get; set; } + public GttResult? Result { get; set; } } /// /// GTTResult structure /// - public class GTTResult + public class GttResult { //TODO missing some documented fields - public GTTOrderResult? OrderResult { get; set; } + public GttOrderResult? OrderResult { get; set; } public string Timestamp { get; set; } [JsonPropertyName("triggered_at")] @@ -595,7 +595,7 @@ public class GTTResult /// /// GTTOrderResult structure /// - public class GTTOrderResult + public class GttOrderResult { public string OrderId { get; set; } public string RejectionReason { get; set; } @@ -604,21 +604,21 @@ public class GTTOrderResult /// /// GTTParams structure /// - public class GTTParams + public class GttParams { public string Tradingsymbol { get; set; } public string Exchange { get; set; } public uint InstrumentToken { get; set; } public string TriggerType { get; set; } public decimal LastPrice { get; set; } - public List Orders { get; set; } + public List Orders { get; set; } public List TriggerPrices { get; set; } } /// /// GTTOrderParams structure /// - public class GTTOrderParams + public class GttOrderParams { public decimal Quantity { get; set; } public decimal Price { get; set; } @@ -728,7 +728,7 @@ public class User [JsonPropertyName("user_shortname")] public string UserShortName { get; set; } - public string AvatarURL { get; set; } + public string AvatarUrl { get; set; } public string Broker { get; set; } public string AccessToken { get; set; } public string PublicToken { get; set; } @@ -758,7 +758,7 @@ public class Profile [JsonPropertyName("user_shortname")] public string UserShortName { get; set; } - public string AvatarURL { get; set; } + public string AvatarUrl { get; set; } public string Broker { get; set; } public string UserType { get; set; } public string[] Exchanges { get; set; } @@ -778,7 +778,7 @@ public class Quote public uint Volume { get; set; } public uint BuyQuantity { get; set; } public uint SellQuantity { get; set; } - public OHLC Ohlc { get; set; } + public Ohlc Ohlc { get; set; } [JsonPropertyName("net_change")] public decimal Change { get; set; } @@ -803,7 +803,7 @@ public class QuoteDepth public List Offers { get; set; } } - public class OHLC + public class Ohlc { public decimal Open { get; set; } public decimal High { get; set; } @@ -814,17 +814,17 @@ public class OHLC /// /// OHLC Quote structure /// - public class OHLCResponse + public class OhlcResponse { public uint InstrumentToken { get; set; } public decimal LastPrice { get; set; } - public OHLC Ohlc { get; set; } + public Ohlc Ohlc { get; set; } } /// /// LTP Quote structure /// - public class LTP + public class Ltp { public uint InstrumentToken { get; set; } public decimal LastPrice { get; set; } @@ -841,7 +841,7 @@ public class MFHolding public decimal AveragePrice { get; set; } public string Tradingsymbol { get; set; } public decimal LastPrice { get; set; } - public decimal PNL { get; set; } + public decimal Pnl { get; set; } } /// @@ -853,7 +853,7 @@ public class MFInstrument public string Tradingsymbol { get; set; } [Name("amc")] - public string AMC { get; set; } + public string Amc { get; set; } [Name("name")] public string Name { get; set; } @@ -929,7 +929,7 @@ public class MFOrder /// /// Mutual funds SIP structure /// - public class MFSIP + public class MFSip { public string DividendType { get; set; } public int PendingInstalments { get; set; } @@ -953,7 +953,7 @@ public class OrderResponse public string OrderId { get; set; } } - public class GTTResponse + public class GttResponse { public int TriggerId { get; set; } } diff --git a/KiteConnectSample/Program.cs b/KiteConnectSample/Program.cs index c7aa61f..f42303d 100644 --- a/KiteConnectSample/Program.cs +++ b/KiteConnectSample/Program.cs @@ -23,7 +23,7 @@ class Program static async Task Main(string[] args) { - kite = new Kite(MyAPIKey, Debug: true); + kite = new Kite(MyAPIKey, debug: true); // For handling 403 errors @@ -51,22 +51,22 @@ static async Task Main(string[] args) // Get all GTTs - List gtts = await kite.GetGTTsAsync(); + List gtts = await kite.GetGttsAsync(); Console.WriteLine(Utils.JsonSerialize(gtts[0])); // Get GTT by Id - GTT gtt = await kite.GetGTTAsync(99691); + Gtt gtt = await kite.GetGttAsync(305642230); Console.WriteLine(Utils.JsonSerialize(gtt)); // Cacncel GTT by Id - var gttCancelResponse = kite.CancelGTT(1582); + var gttCancelResponse = await kite.CancelGttAsync(305642230); Console.WriteLine(Utils.JsonSerialize(gttCancelResponse)); // Place GTT - GTTParams gttParams = new GTTParams(); + GttParams gttParams = new GttParams(); gttParams.TriggerType = Constants.GTT.Trigger.OCO; gttParams.Exchange = "NSE"; gttParams.Tradingsymbol = "SBIN"; @@ -83,14 +83,14 @@ static async Task Main(string[] args) // A stop-loss order must have trigger and price below last price and target order must have trigger and price above last price. // Only limit order type and CNC product type is allowed for now. - GTTOrderParams order1Params = new GTTOrderParams(); + GttOrderParams order1Params = new GttOrderParams(); order1Params.OrderType = Constants.OrderType.Limit; order1Params.Price = 250m; order1Params.Product = Constants.Product.CNC; order1Params.TransactionType = Constants.Transaction.Sell; order1Params.Quantity = 0; - GTTOrderParams order2Params = new GTTOrderParams(); + GttOrderParams order2Params = new GttOrderParams(); order2Params.OrderType = Constants.OrderType.Limit; order2Params.Price = 320m; order2Params.Product = Constants.Product.CNC; @@ -98,15 +98,15 @@ static async Task Main(string[] args) order2Params.Quantity = 1; // Target or upper trigger - List ordersList = new List(); + List ordersList = new List(); ordersList.Add(order1Params); ordersList.Add(order2Params); gttParams.Orders = ordersList; - var placeGTTResponse = await kite.PlaceGTTAsync(gttParams); + var placeGTTResponse = await kite.PlaceGttAsync(gttParams); Console.WriteLine(Utils.JsonSerialize(placeGTTResponse)); - var modifyGTTResponse = await kite.ModifyGTTAsync(407301, gttParams); + var modifyGTTResponse = await kite.ModifyGttAsync(407301, gttParams); Console.WriteLine(Utils.JsonSerialize(modifyGTTResponse)); // Positions @@ -115,13 +115,13 @@ static async Task Main(string[] args) Console.WriteLine(Utils.JsonSerialize(positions.Net[0])); await kite.ConvertPositionAsync( - Exchange: Constants.Exchange.NSE, - TradingSymbol: "ASHOKLEY", - TransactionType: Constants.Transaction.Buy, - PositionType: Constants.Position.Day, - Quantity: 1, - OldProduct: Constants.Product.MIS, - NewProduct: Constants.Product.CNC + exchange: Constants.Exchange.NSE, + tradingSymbol: "ASHOKLEY", + transactionType: Constants.Transaction.Buy, + positionType: Constants.Position.Day, + quantity: 1, + oldProduct: Constants.Product.MIS, + newProduct: Constants.Product.CNC ); // Holdings @@ -136,24 +136,24 @@ await kite.ConvertPositionAsync( // Get quotes of upto 200 scrips - Dictionary quotes = await kite.GetQuoteAsync(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); + Dictionary quotes = await kite.GetQuoteAsync(instrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); Console.WriteLine(Utils.JsonSerialize(quotes)); // Get OHLC and LTP of upto 200 scrips - Dictionary ohlcs = await kite.GetOHLCAsync(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); + Dictionary ohlcs = await kite.GetOhlcAsync(instrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); Console.WriteLine(Utils.JsonSerialize(ohlcs)); // Get LTP of upto 200 scrips - Dictionary ltps = await kite.GetLTPAsync(InstrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); + Dictionary ltps = await kite.GetLtpAsync(instrumentId: new string[] { "NSE:INFY", "NSE:ASHOKLEY" }); Console.WriteLine(Utils.JsonSerialize(ltps)); // Trigger Range Dictionary triggerRange = kite.GetTriggerRange( - InstrumentId: new string[] { "NSE:ASHOKLEY" }, - TrasactionType: Constants.Transaction.Buy + instrumentId: new string[] { "NSE:ASHOKLEY" }, + trasactionType: Constants.Transaction.Buy ); Console.WriteLine(Utils.JsonSerialize(triggerRange)); @@ -170,26 +170,26 @@ await kite.ConvertPositionAsync( // Place sell order OrderResponse response = await kite.PlaceOrderAsync( - Exchange: Constants.Exchange.CDS, - TradingSymbol: "USDINR17AUGFUT", - TransactionType: Constants.Transaction.Sell, - Quantity: 1, - Price: 64.0000m, - OrderType: Constants.OrderType.Market, - Product: Constants.Product.MIS + exchange: Constants.Exchange.CDS, + tradingSymbol: "USDINR17AUGFUT", + transactionType: Constants.Transaction.Sell, + quantity: 1, + price: 64.0000m, + orderType: Constants.OrderType.Market, + product: Constants.Product.MIS ); Console.WriteLine("Order Id: " + response.OrderId); // Place buy order await kite.PlaceOrderAsync( - Exchange: Constants.Exchange.CDS, - TradingSymbol: "USDINR17AUGFUT", - TransactionType: Constants.Transaction.Buy, - Quantity: 1, - Price: 63.9000m, - OrderType: Constants.OrderType.Limit, - Product: Constants.Product.MIS + exchange: Constants.Exchange.CDS, + tradingSymbol: "USDINR17AUGFUT", + transactionType: Constants.Transaction.Buy, + quantity: 1, + price: 63.9000m, + orderType: Constants.OrderType.Limit, + product: Constants.Product.MIS ); // Cancel order by id @@ -199,122 +199,122 @@ await kite.PlaceOrderAsync( //BO LIMIT order placing await kite.PlaceOrderAsync( - Exchange: Constants.Exchange.NSE, - TradingSymbol: "ASHOKLEY", - TransactionType: Constants.Transaction.Buy, - Quantity: 1, - Price: 115, - Product: Constants.Product.MIS, - OrderType: Constants.OrderType.Limit, - Validity: Constants.Validity.Day, - SquareOffValue: 2, - StoplossValue: 2, - Variety: Constants.Variety.BO + exchange: Constants.Exchange.NSE, + tradingSymbol: "ASHOKLEY", + transactionType: Constants.Transaction.Buy, + quantity: 1, + price: 115, + product: Constants.Product.MIS, + orderType: Constants.OrderType.Limit, + validity: Constants.Validity.Day, + squareOffValue: 2, + stoplossValue: 2, + variety: Constants.Variety.BO ); // BO LIMIT exiting await kite.CancelOrderAsync( - OrderId: "1234", - Variety: Constants.Variety.BO, - ParentOrderId: "5678" + orderId: "1234", + variety: Constants.Variety.BO, + parentOrderId: "5678" ); // BO SL order placing await kite.PlaceOrderAsync( - Exchange: Constants.Exchange.NSE, - TradingSymbol: "ASHOKLEY", - TransactionType: Constants.Transaction.Buy, - Quantity: 1, - Price: 117, - Product: Constants.Product.MIS, - OrderType: Constants.OrderType.SL, - Validity: Constants.Validity.Day, - SquareOffValue: 2, - StoplossValue: 2, - TriggerPrice: 117.5m, - Variety: Constants.Variety.BO + exchange: Constants.Exchange.NSE, + tradingSymbol: "ASHOKLEY", + transactionType: Constants.Transaction.Buy, + quantity: 1, + price: 117, + product: Constants.Product.MIS, + orderType: Constants.OrderType.SL, + validity: Constants.Validity.Day, + squareOffValue: 2, + stoplossValue: 2, + triggerPrice: 117.5m, + variety: Constants.Variety.BO ); // BO SL exiting await kite.CancelOrderAsync( - OrderId: "1234", - Variety: Constants.Variety.BO, - ParentOrderId: "5678" + orderId: "1234", + variety: Constants.Variety.BO, + parentOrderId: "5678" ); // CO LIMIT order placing await kite.PlaceOrderAsync( - Exchange: Constants.Exchange.NSE, - TradingSymbol: "ASHOKLEY", - TransactionType: Constants.Transaction.Buy, - Quantity: 1, - Price: 115.5m, - Product: Constants.Product.MIS, - OrderType: Constants.OrderType.Limit, - Validity: Constants.Validity.Day, - TriggerPrice: 116.5m, - Variety: Constants.Variety.CO + exchange: Constants.Exchange.NSE, + tradingSymbol: "ASHOKLEY", + transactionType: Constants.Transaction.Buy, + quantity: 1, + price: 115.5m, + product: Constants.Product.MIS, + orderType: Constants.OrderType.Limit, + validity: Constants.Validity.Day, + triggerPrice: 116.5m, + variety: Constants.Variety.CO ); // CO LIMIT exiting await kite.CancelOrderAsync( - OrderId: "1234", - Variety: Constants.Variety.BO, - ParentOrderId: "5678" + orderId: "1234", + variety: Constants.Variety.BO, + parentOrderId: "5678" ); // CO MARKET order placing await kite.PlaceOrderAsync( - Exchange: Constants.Exchange.NSE, - TradingSymbol: "ASHOKLEY", - TransactionType: Constants.Transaction.Buy, - Quantity: 1, - Product: Constants.Product.MIS, - OrderType: Constants.OrderType.Market, - Validity: Constants.Validity.Day, - TriggerPrice: 116.5m, - Variety: Constants.Variety.CO + exchange: Constants.Exchange.NSE, + tradingSymbol: "ASHOKLEY", + transactionType: Constants.Transaction.Buy, + quantity: 1, + product: Constants.Product.MIS, + orderType: Constants.OrderType.Market, + validity: Constants.Validity.Day, + triggerPrice: 116.5m, + variety: Constants.Variety.CO ); // CO MARKET exiting await kite.CancelOrderAsync( - OrderId: "1234", - Variety: Constants.Variety.BO, - ParentOrderId: "5678" + orderId: "1234", + variety: Constants.Variety.BO, + parentOrderId: "5678" ); // Place order with TTL validity await kite.PlaceOrderAsync( - Exchange: Constants.Exchange.NSE, - TradingSymbol: "INFY", - TransactionType: Constants.Transaction.Buy, - Quantity: 1, - Price: 1500.0m, - OrderType: Constants.OrderType.Limit, - Product: Constants.Product.MIS, - Validity: Constants.Validity.TTL, - ValidityTTL: 5 + exchange: Constants.Exchange.NSE, + tradingSymbol: "INFY", + transactionType: Constants.Transaction.Buy, + quantity: 1, + price: 1500.0m, + orderType: Constants.OrderType.Limit, + product: Constants.Product.MIS, + validity: Constants.Validity.TTL, + validityTtl: 5 ); // Place an Iceberg order await kite.PlaceOrderAsync( - Exchange: Constants.Exchange.NSE, - TradingSymbol: "INFY", - TransactionType: Constants.Transaction.Buy, - Quantity: 10, - Price: 1500.0m, - OrderType: Constants.OrderType.Limit, - Product: Constants.Product.MIS, - Variety: Constants.Variety.Iceberg, - IcebergLegs: 2, - IcebergQuantity: 5 + exchange: Constants.Exchange.NSE, + tradingSymbol: "INFY", + transactionType: Constants.Transaction.Buy, + quantity: 10, + price: 1500.0m, + orderType: Constants.OrderType.Limit, + product: Constants.Product.MIS, + variety: Constants.Variety.Iceberg, + icebergLegs: 2, + icebergQuantity: 5 ); // Trades @@ -351,7 +351,7 @@ await kite.PlaceOrderAsync( basketParam.Product = Constants.Product.MIS; basketParam.OrderType = Constants.OrderType.Limit; - BasketMargin basketMargins = await kite.GetBasketMarginsAsync(new List() { basketParam }, ConsiderPositions: true); + BasketMargin basketMargins = await kite.GetBasketMarginsAsync(new List() { basketParam }, considerPositions: true); // Virtual contract notes @@ -391,45 +391,45 @@ await kite.PlaceOrderAsync( // Mutual funds get order by id - MFOrder mforder = await kite.GetMFOrdersAsync(OrderId: "1234"); + MFOrder mforder = await kite.GetMFOrdersAsync(orderId: "1234"); Console.WriteLine(Utils.JsonSerialize(mforder)); // Mutual funds place order kite.PlaceMFOrder( - TradingSymbol: "INF174K01LS2", - TransactionType: Constants.Transaction.Buy, - Amount: 20000 + tradingSymbol: "INF174K01LS2", + transactionType: Constants.Transaction.Buy, + amount: 20000 ); // Mutual funds cancel order by id - kite.CancelMFOrder(OrderId: "1234"); + kite.CancelMFOrder(orderId: "1234"); // Mutual Funds get all SIPs - List mfsips = await kite.GetMFSIPsAsync(); + List mfsips = await kite.GetMFSipsAsync(); Console.WriteLine(Utils.JsonSerialize(mfsips[0])); // Mutual Funds get SIP by id - MFSIP sip = await kite.GetMFSIPsAsync("63429"); + MFSip sip = await kite.GetMFSipsAsync("63429"); Console.WriteLine(Utils.JsonSerialize(sip)); // Mutual Funds place SIP order - kite.PlaceMFSIP( - TradingSymbol: "INF174K01LS2", - Amount: 1000, - InitialAmount: 5000, - Frequency: "monthly", - InstalmentDay: 1, - Instalments: -1 // -1 means infinite + kite.PlaceMFSip( + tradingSymbol: "INF174K01LS2", + amount: 1000, + initialAmount: 5000, + frequency: "monthly", + instalmentDay: 1, + instalments: -1 // -1 means infinite ); // Mutual Funds modify SIP order - kite.ModifyMFSIP( + kite.ModifyMFSip( SIPId: "1234", Amount: 1000, Frequency: "monthly", @@ -454,7 +454,7 @@ await kite.PlaceOrderAsync( private static async Task initSession() { - Console.WriteLine("Goto " + kite.GetLoginURL()); + Console.WriteLine("Goto " + kite.GetLoginUrl()); Console.WriteLine("Enter request token: "); string requestToken = Console.ReadLine(); User user = await kite.GenerateSessionAsync(requestToken, MySecret); diff --git a/KiteConnectTest/KiteTest.cs b/KiteConnectTest/KiteTest.cs index 49f1cfa..af24eae 100644 --- a/KiteConnectTest/KiteTest.cs +++ b/KiteConnectTest/KiteTest.cs @@ -41,7 +41,7 @@ public void TestError() string json = File.ReadAllText(@"responses/error.json", Encoding.UTF8); ms.SetStatusCode(403); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080", Debug: true); + Kite kite = new Kite("apikey", root: "http://localhost:8080", debug: true); Assert.ThrowsAsync(async () => await kite.GetProfileAsync()); } @@ -50,7 +50,7 @@ public async Task TestProfile() { string json = File.ReadAllText(@"responses/profile.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); Profile profile = await kite.GetProfileAsync(); Console.WriteLine(profile.Email); Assert.AreEqual(profile.Email, "xxxyyy@gmail.com"); @@ -61,7 +61,7 @@ public async Task TestPositions() { string json = File.ReadAllText(@"responses/positions.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); PositionResponse positionResponse = await kite.GetPositionsAsync(); Assert.AreEqual(positionResponse.Net[0].Tradingsymbol, "LEADMINI17DECFUT"); Assert.AreEqual(positionResponse.Day[0].Tradingsymbol, "GOLDGUINEA17DECFUT"); @@ -72,10 +72,10 @@ public async Task TestHoldings() { string json = File.ReadAllText(@"responses/holdings.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); List holdings = await kite.GetHoldingsAsync(); Assert.AreEqual(holdings[0].AveragePrice, 40.67m); - Assert.AreEqual(holdings[0].MTF.Quantity, 1000m); + Assert.AreEqual(holdings[0].Mtf.Quantity, 1000m); } [TestMethod] @@ -83,9 +83,9 @@ public async Task TestAuctionInstruments() { string json = File.ReadAllText(@"responses/auction_instruments.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); List instruments = await kite.GetAuctionInstrumentsAsync(); - Assert.AreEqual(instruments[0].PNL, 564.8000000000002m); + Assert.AreEqual(instruments[0].Pnl, 564.8000000000002m); } [TestMethod] @@ -93,7 +93,7 @@ public async Task TestMargins() { string json = File.ReadAllText(@"responses/margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); UserMarginsResponse margins = await kite.GetMarginsAsync(); Assert.AreEqual(margins.Equity.Net, (decimal)1697.7); @@ -105,7 +105,7 @@ public async Task TestMarginsNoTurnover() { string json = File.ReadAllText(@"responses/margins_noturnover.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); UserMarginsResponse margins = await kite.GetMarginsAsync(); Assert.AreEqual(margins.Equity.Utilised.Turnover, (decimal)0); @@ -117,7 +117,7 @@ public async Task TestOrderMargins() { string json = File.ReadAllText(@"responses/order_margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); OrderMarginParams param = new OrderMarginParams(); param.Exchange = Constants.Exchange.NFO; @@ -131,10 +131,10 @@ public async Task TestOrderMargins() List margins = await kite.GetOrderMarginsAsync(new List() { param }); Assert.AreEqual(margins[0].Total, (decimal)8.36025); - Assert.AreEqual(margins[0].SPAN, (decimal)5.408); + Assert.AreEqual(margins[0].Span, (decimal)5.408); Assert.AreEqual(margins[0].Leverage, (decimal)5); Assert.AreEqual(margins[0].Charges.TransactionTax, (decimal)0.5); - Assert.AreEqual(margins[0].Charges.GST.IGST, (decimal)0.386496); + Assert.AreEqual(margins[0].Charges.Gst.Igst, (decimal)0.386496); } [TestMethod] @@ -142,7 +142,7 @@ public async Task TestOrderMarginsCompact() { string json = File.ReadAllText(@"responses/order_margins_compact.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); OrderMarginParams param = new OrderMarginParams(); param.Exchange = Constants.Exchange.NFO; @@ -162,10 +162,10 @@ public async Task TestOrderMarginsCompact() param2.Product = Constants.Product.MIS; param2.OrderType = Constants.OrderType.Limit; - List margins = await kite.GetOrderMarginsAsync(new List() { param, param2 }, Mode: Constants.Margin.Mode.Compact); + List margins = await kite.GetOrderMarginsAsync(new List() { param, param2 }, mode: Constants.Margin.Mode.Compact); Assert.AreEqual(margins[0].Total, (decimal)30.2280825); - Assert.AreEqual(margins[0].SPAN, (decimal)0); + Assert.AreEqual(margins[0].Span, (decimal)0); } [TestMethod] @@ -173,7 +173,7 @@ public async Task TestBasketMargins() { string json = File.ReadAllText(@"responses/basket_margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); OrderMarginParams param = new OrderMarginParams(); param.Exchange = Constants.Exchange.NFO; @@ -196,7 +196,7 @@ public async Task TestBasketMargins() BasketMargin margins = await kite.GetBasketMarginsAsync(new List() { param, param2 }); Assert.AreEqual(margins.Final.Total, (decimal)22530.221345); - Assert.AreEqual(margins.Final.SPAN, (decimal)26.9577); + Assert.AreEqual(margins.Final.Span, (decimal)26.9577); } [TestMethod] @@ -204,7 +204,7 @@ public async Task TestBasketMarginsCompact() { string json = File.ReadAllText(@"responses/basket_margins_compact.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); OrderMarginParams param = new OrderMarginParams(); param.Exchange = Constants.Exchange.NFO; @@ -224,10 +224,10 @@ public async Task TestBasketMarginsCompact() param2.Product = Constants.Product.MIS; param2.OrderType = Constants.OrderType.Limit; - BasketMargin margins = await kite.GetBasketMarginsAsync(new List() { param, param2 }, Mode: Constants.Margin.Mode.Compact); + BasketMargin margins = await kite.GetBasketMarginsAsync(new List() { param, param2 }, mode: Constants.Margin.Mode.Compact); Assert.AreEqual(margins.Final.Total, (decimal)22530.2280825); - Assert.AreEqual(margins.Final.SPAN, (decimal)0); + Assert.AreEqual(margins.Final.Span, (decimal)0); } [TestMethod] @@ -235,7 +235,7 @@ public async Task TestEquityMargins() { string json = File.ReadAllText(@"responses/equity_margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); UserMargin margin = await kite.GetMarginsAsync("equity"); Assert.AreEqual(margin.Net, (decimal)1812.3535); @@ -246,7 +246,7 @@ public async Task TestCommodityMargins() { string json = File.ReadAllText(@"responses/equity_margins.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); UserMargin margin = await kite.GetMarginsAsync("commodity"); Assert.AreEqual(margin.Net, (decimal)1812.3535); @@ -257,8 +257,8 @@ public async Task TestOHLC() { string json = File.ReadAllText(@"responses/ohlc.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - Dictionary ohlcs = await kite.GetOHLCAsync(new string[] { "408065", "NSE:INFY" }); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + Dictionary ohlcs = await kite.GetOhlcAsync(new string[] { "408065", "NSE:INFY" }); Assert.AreEqual(ohlcs["408065"].LastPrice, 966.8m); Assert.AreEqual(ohlcs["408065"].Ohlc.Open, 966.6m); @@ -269,8 +269,8 @@ public async Task TestLTP() { string json = File.ReadAllText(@"responses/ltp.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - Dictionary ltps = await kite.GetLTPAsync(new string[] { "NSE:INFY" }); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + Dictionary ltps = await kite.GetLtpAsync(new string[] { "NSE:INFY" }); Assert.AreEqual(ltps["NSE:INFY"].LastPrice, (decimal)989.2); } @@ -280,7 +280,7 @@ public async Task TestQuote() { string json = File.ReadAllText(@"responses/quote.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); Dictionary quotes = await kite.GetQuoteAsync(new string[] { "NSE:ASHOKLEY", "NSE:NIFTY 50" }); Assert.AreEqual(quotes["NSE:ASHOKLEY"].LastPrice, 76.6m); @@ -296,7 +296,7 @@ public async Task TestOrders() { string json = File.ReadAllText(@"responses/orders.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); List orders = await kite.GetOrdersAsync(); Assert.AreEqual(orders[0].Price, 72); @@ -304,7 +304,7 @@ public async Task TestOrders() Assert.AreEqual(orders[2].Tag, "connect test order2"); Assert.AreEqual(orders[2].Tags[1], "XXXXX"); - Assert.AreEqual(orders[3].ValidityTTL, 2); + Assert.AreEqual(orders[3].ValidityTtl, 2); Assert.AreEqual(orders[3].Meta["iceberg"]["legs"].GetValue(), 5); @@ -318,8 +318,8 @@ public async Task TestGTTs() { string json = File.ReadAllText(@"responses/gtt_get_orders.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List gtts = await kite.GetGTTsAsync(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + List gtts = await kite.GetGttsAsync(); Assert.AreEqual(gtts[0].Id, 105099); Assert.AreEqual(gtts[0].Condition?.TriggerValues[0], 102m); @@ -332,8 +332,8 @@ public async Task TestGTT() { string json = File.ReadAllText(@"responses/gtt_get_order.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - GTT gtt = await kite.GetGTTAsync(123); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + Gtt gtt = await kite.GetGttAsync(123); Assert.AreEqual(gtt.Id, 123); } @@ -343,7 +343,7 @@ public async Task TestOrderInfo() { string json = File.ReadAllText(@"responses/orderinfo.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); List orderhistory = await kite.GetOrderHistoryAsync("171124000819854"); Assert.AreEqual(orderhistory[0].PendingQuantity, 100); @@ -354,7 +354,7 @@ public async Task TestInstruments() { string csv = File.ReadAllText(@"responses/instruments_all.csv", Encoding.UTF8); ms.SetResponse("text/csv", csv); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); var instrument = kite.GetInstrumentsAsync().ToBlockingEnumerable().First(); Assert.AreEqual(instrument.InstrumentToken, (uint)3813889); @@ -367,7 +367,7 @@ public async Task TestHistoricalData() { string csv = File.ReadAllText(@"responses/historical.json", Encoding.UTF8); ms.SetResponse("application/json", csv); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); var historicalData = await kite.GetHistoricalDataAsync("3813889", DateTime.Now, DateTime.Now, "Minutes"); Assert.HasCount(6, historicalData.Candles); @@ -383,7 +383,7 @@ public async Task TestHistoricalDataWithOI() { string csv = File.ReadAllText(@"responses/historical-oi.json", Encoding.UTF8); ms.SetResponse("application/json", csv); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); var historicalData = await kite.GetHistoricalDataAsync("3813889", DateTime.Now, DateTime.Now, "Minutes"); Assert.HasCount(6, historicalData.Candles); @@ -395,7 +395,7 @@ public async Task TestSegmentInstruments() { string csv = File.ReadAllText(@"responses/instruments_nse.csv", Encoding.UTF8); ms.SetResponse("text/csv", csv); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); var instrument = kite.GetInstrumentsAsync(Constants.Exchange.NSE).ToBlockingEnumerable().First(); Assert.AreEqual(instrument.InstrumentToken, (uint)3813889); @@ -406,7 +406,7 @@ public async Task TestTrades() { string json = File.ReadAllText(@"responses/trades.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); List trades = await kite.GetOrderTradesAsync("151220000000000"); Assert.AreEqual(trades[0].TradeId, "159918"); @@ -417,8 +417,8 @@ public async Task TestMFSIPs() { string json = File.ReadAllText(@"responses/mf_sips.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - List sips = await kite.GetMFSIPsAsync(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + List sips = await kite.GetMFSipsAsync(); Assert.AreEqual(sips[0].SIPId, "1234"); } @@ -428,8 +428,8 @@ public async Task TestMFSIP() { string json = File.ReadAllText(@"responses/mf_sip.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); - MFSIP sip = await kite.GetMFSIPsAsync("1234"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + MFSip sip = await kite.GetMFSipsAsync("1234"); Assert.AreEqual(sip.SIPId, "1234"); } @@ -439,7 +439,7 @@ public async Task TestMFOrders() { string json = File.ReadAllText(@"responses/mf_orders.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); List orders = await kite.GetMFOrdersAsync(); Assert.AreEqual(orders[0].OrderId, "123123"); @@ -450,7 +450,7 @@ public async Task TestMFOrder() { string json = File.ReadAllText(@"responses/mf_order.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); MFOrder order = await kite.GetMFOrdersAsync("123123"); Assert.AreEqual(order.OrderId, "123123"); @@ -461,7 +461,7 @@ public async Task TestMFHoldings() { string json = File.ReadAllText(@"responses/mf_holdings.json", Encoding.UTF8); ms.SetResponse("application/json", json); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); List holdings = await kite.GetMFHoldingsAsync(); Assert.AreEqual(holdings[0].Folio, "123123/123"); @@ -472,7 +472,7 @@ public void TestMFInstruments() { string csv = File.ReadAllText(@"responses/mf_instruments.csv", Encoding.UTF8); ms.SetResponse("text/csv", csv); - Kite kite = new Kite("apikey", Root: "http://localhost:8080"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); var instrument = kite.GetMFInstrumentsAsync().ToBlockingEnumerable().First(); Assert.AreEqual(instrument.Tradingsymbol, "INF209K01157");