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/CustomDateTimeJsonConverter.cs b/KiteConnect/CustomDateTimeJsonConverter.cs new file mode 100644 index 0000000..f5d716e --- /dev/null +++ b/KiteConnect/CustomDateTimeJsonConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace KiteConnect +{ + 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); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + } +} diff --git a/KiteConnect/Kite.cs b/KiteConnect/Kite.cs index aa9b648..96cb5a7 100644 --- a/KiteConnect/Kite.cs +++ b/KiteConnect/Kite.cs @@ -1,12 +1,21 @@ -using System; +using CsvHelper; +using System; using System.Collections.Generic; +using System.Globalization; +using System.IO; 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.Runtime.CompilerServices; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; +using System.Web; namespace KiteConnect { @@ -15,53 +24,53 @@ namespace KiteConnect /// 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; } /// @@ -84,438 +93,349 @@ 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); + return string.Format("{0}?api_key={1}&v=3", _login, _apiKey); } /// /// 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. + /// 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, CancellationToken cancellationToken = default) { - string checksum = Utils.SHA256Hash(_apiKey + RequestToken + AppSecret); - - var param = new Dictionary - { - {"api_key", _apiKey}, - {"request_token", RequestToken}, - {"checksum", checksum} - }; + string checksum = Utils.SHA256Hash(_apiKey + requestToken + appSecret); - 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(), cancellationToken: cancellationToken); } /// /// 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 Dictionary InvalidateAccessToken(string AccessToken = null) + public Task InvalidateAccessTokenAsync(string accessToken = null, CancellationToken cancellationToken = default) { - 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(), cancellationToken: cancellationToken); } /// /// Invalidates RefreshToken /// - /// RefreshToken to invalidate + /// RefreshToken to invalidate + /// /// Json response in the form of nested string dictionary. - public Dictionary InvalidateRefreshToken(string RefreshToken) + public Task InvalidateRefreshTokenAsync(string refreshToken, CancellationToken cancellationToken = default) { - 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(), cancellationToken: cancellationToken); } /// /// 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 TokenSet RenewAccessToken(string RefreshToken, string AppSecret) + public Task RenewAccessTokenAsync(string refreshToken, string appSecret, CancellationToken cancellationToken = default) { - 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); - string checksum = Utils.SHA256Hash(_apiKey + RefreshToken + AppSecret); - - 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(), cancellationToken: cancellationToken); } /// /// 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: cancellationToken); } /// /// 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 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); } /// /// 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 List GetOrderMargins(List OrderMarginParams, string Mode = null) + public Task> GetOrderMarginsAsync(List orderMarginParams, string mode = null, CancellationToken cancellationToken = default) { - var paramList = new List>(); + var queryParameterBuilder = new ParametersBuilder() + .AddIfNotNull("mode", mode); - 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 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); } /// /// 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 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 queryParameterBuilder = new ParametersBuilder() + .Add("consider_positions", considerPositions) + .AddIfNotNull("mode", mode); - var queryParams = new Dictionary(); - queryParams["consider_positions"] = ConsiderPositions ? "true" : "false"; - if (Mode != null) - { - queryParams["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); } /// /// 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: 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 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: cancellationToken); } /// /// 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) + /// 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 Dictionary PlaceOrder( - 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 + 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, + 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, "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(), 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 Dictionary ModifyOrder( - 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) + 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, + CancellationToken cancellationToken = default) { - var param = new Dictionary(); + 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)); + 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(), 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 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, CancellationToken cancellationToken = default) { - 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(), cancellationToken: cancellationToken); } /// /// Gets the collection of orders from the orderbook. /// + /// /// List of orders. - public List GetOrders() + public Task> GetOrdersAsync(CancellationToken cancellationToken = default) { - 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", cancellationToken: cancellationToken); } /// /// Gets information about given OrderId. /// - /// Unique order id + /// Unique order id + /// /// List of order objects. - public List GetOrderHistory(string OrderId) + public Task> GetOrderHistoryAsync(string orderId, CancellationToken cancellationToken = default) { - 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}", cancellationToken: cancellationToken); } /// @@ -523,184 +443,146 @@ public List GetOrderHistory(string OrderId) /// 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 List GetOrderTrades(string OrderId = null) + public Task> GetOrderTradesAsync(string orderId = null, CancellationToken cancellationToken = default) { - Dictionary tradesdata; - if (!String.IsNullOrEmpty(OrderId)) - { - var param = new Dictionary(); - param.Add("order_id", OrderId); - tradesdata = Get(Routes.Order.Trades, param); - } + if (!string.IsNullOrEmpty(orderId)) + return GetAsync>($"/orders/{orderId}/trades", cancellationToken: cancellationToken); 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", cancellationToken: cancellationToken); } /// /// Retrieve the list of positions. /// + /// /// Day and net positions. - public PositionResponse GetPositions() + public Task GetPositionsAsync(CancellationToken cancellationToken = default) { - var positionsdata = Get(Routes.Portfolio.Positions); - return new PositionResponse(positionsdata["data"]); + 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); } /// /// 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 Dictionary ConvertPosition( - string Exchange, - string TradingSymbol, - string TransactionType, - string PositionType, - decimal? Quantity, - string OldProduct, - string NewProduct) + public Task ConvertPositionAsync( + string exchange, + string tradingSymbol, + string transactionType, + string positionType, + decimal? quantity, + string oldProduct, + 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); - - return Put(Routes.Portfolio.ModifyPositions, param); + 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 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 + /// 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); + if (string.IsNullOrEmpty(exchange)) + 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) + /// 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) + /// 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) + /// 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); } /// @@ -712,46 +594,41 @@ 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(); + var queryParametersBuilder = new ParametersBuilder(); - 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"); + queryParametersBuilder.Add("from", FromDate); + queryParametersBuilder.Add("to", ToDate); + queryParametersBuilder.AddAsO1("continuous", Continuous); + queryParametersBuilder.AddAsO1("oi", OI); - var historicalData = Get(Routes.Market.Historical, param); - - List historicals = new List(); - - foreach (ArrayList item in historicalData["data"]["candles"]) - historicals.Add(new Historical(item)); - - return historicals; + return GetAsync($"/instruments/historical/{InstrumentToken}/{Interval}", queryParametersBuilder.Build(), cancellationToken: cancellationToken); } + //TODO undocumented API + /// /// 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"]; @@ -767,120 +644,117 @@ public Dictionary GetTriggerRange(string[] InstrumentId, st /// /// Retrieve the list of GTTs. /// + /// /// List of GTTs. - public List GetGTTs() + public Task> GetGttsAsync(CancellationToken cancellationToken = default) { - 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", cancellationToken: cancellationToken); } /// /// Retrieve a single GTT /// - /// Id of the GTT + /// Id of the GTT + /// /// GTT info - public GTT GetGTT(int GTTId) + public Task GetGttAsync(int GttId, CancellationToken cancellationToken = default) { - 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}", cancellationToken: cancellationToken); } /// /// Place a GTT order /// /// 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, CancellationToken cancellationToken = default) { - 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(), 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 Dictionary ModifyGTT(int GTTId, GTTParams gttParams) + public Task ModifyGttAsync(int gttId, GttParams gttParams, CancellationToken cancellationToken = default) { - 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(), 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 Dictionary CancelGTT(int GTTId) + public Task CancelGttAsync(int gttId, CancellationToken cancellationToken = default) { - var parms = new Dictionary(); - parms.Add("id", GTTId.ToString()); - - return Delete(Routes.GTT.Delete, parms); + return DeleteAsync($"/gtt/triggers/{gttId}", cancellationToken: cancellationToken); } #endregion GTT @@ -891,95 +765,75 @@ public Dictionary 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); } /// /// Gets the Mutual funds order by OrderId. /// /// The Mutual funds order. - /// Order id. - public MFOrder GetMFOrders(String OrderId) + /// Order id. + /// + 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. /// /// 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); } + //TODO undocumented API + /// /// 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); } @@ -987,70 +841,60 @@ 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); } /// /// Gets a single Mutual funds SIP by SIP id. /// /// The Mutual funds SIP. - /// SIP id. - public MFSIP GetMFSIPs(String SIPID) + /// SIP id. + /// + 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. /// /// 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); } + //TODO undocumented API + /// /// Modifies the Mutual funds SIP. /// @@ -1061,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, @@ -1081,12 +925,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(); @@ -1098,20 +944,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 @@ -1165,23 +1002,23 @@ 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())); + Console.WriteLine("DEBUG: " + header.Key + ": " + string.Join(",", header.Value.ToArray())); } } } @@ -1222,18 +1059,18 @@ 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); - AddExtraHeaders(ref request); + AddExtraHeaders(request); if (_enableLogging) Console.WriteLine("DEBUG: " + Method + " " + url + "\n" + requestBody); @@ -1255,16 +1092,16 @@ 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); request.Method = new HttpMethod(Method); if (_enableLogging) Console.WriteLine("DEBUG: " + Method + " " + url); - AddExtraHeaders(ref request); + AddExtraHeaders(request); } - HttpResponseMessage response = httpClient.Send(request); + HttpResponseMessage response = _httpClient.Send(request); HttpStatusCode status = response.StatusCode; string responseBody = response.Content.ReadAsStringAsync().Result; @@ -1311,6 +1148,128 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict } + 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 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); + HttpContent content = null; + if (formData != null && formData.Count > 0) + content = new FormUrlEncodedContent(formData); + return SendRequestAsync(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); + 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) + { + 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; + 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/KiteConnect.csproj b/KiteConnect/KiteConnect.csproj index 6be6aa7..0220769 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 @@ -22,14 +22,23 @@ true + + $(WarningsAsErrors);NU1605;CS4014 + + + + $(WarningsAsErrors);NU1605;CS4014 + + - + - + + - + diff --git a/KiteConnect/ParametersBuilder.cs b/KiteConnect/ParametersBuilder.cs new file mode 100644 index 0000000..9d19b5b --- /dev/null +++ b/KiteConnect/ParametersBuilder.cs @@ -0,0 +1,76 @@ +using System; +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 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) + _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 33a84e1..bba8cf5 100644 --- a/KiteConnect/Structures.cs +++ b/KiteConnect/Structures.cs @@ -1,25 +1,55 @@ -using System; -using System.Collections; +using CsvHelper.Configuration.Attributes; +using System; using System.Collections.Generic; -using System.Linq; using System.Net; +using System.Text.Json.Nodes; +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; } + } + + internal class WebsocketMessage + { + public string Type { get; set; } + } + + internal class WebsocketMessage : WebsocketMessage + { + public T Data { get; set; } + } + /// /// Tick data structure /// - public struct Tick + 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,133 +61,76 @@ public struct 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; } } /// /// Market depth item structure /// - public struct DepthItem + public class DepthItem { - public DepthItem(Dictionary data) - { - Quantity = Convert.ToUInt32(data["quantity"]); - Price = data["price"]; - 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; } } /// - /// Historical structure + /// Historical Response structure /// - public struct 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; } + } - public DateTime TimeStamp { get; } - public decimal Open { get; } - public decimal High { get; } - public decimal Low { get; } - public decimal Close { get; } - public UInt64 Volume { get; } - public UInt64 OI { get; } + /// + /// Candle structure + /// + public class Candle + { + 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; } } /// /// Holding structure /// - public struct Holding + 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; } 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 Tradingsymbol { get; set; } public string CollateralType { get; set; } public decimal T1Quantity { get; set; } - public UInt32 InstrumentToken { get; set; } - public string ISIN { get; set; } + public uint InstrumentToken { 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 struct MTFHolding + 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; } @@ -168,45 +141,12 @@ public MTFHolding(Dictionary data) /// /// AuctionInstrument structure /// - public struct AuctionInstrument + 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 UInt32 InstrumentToken { get; set; } - public string ISIN { get; set; } + public uint InstrumentToken { get; set; } + public string Isin { get; set; } public string Product { get; set; } public decimal Price { get; set; } public decimal Quantity { get; set; } @@ -221,7 +161,7 @@ public AuctionInstrument(Dictionary data) 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; } @@ -230,23 +170,9 @@ public AuctionInstrument(Dictionary data) /// /// Available margin structure /// - public struct AvailableMargin + 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; } @@ -256,31 +182,15 @@ public AvailableMargin(Dictionary data) /// /// Utilised margin structure /// - public struct UtilisedMargin + 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; } @@ -293,23 +203,8 @@ public UtilisedMargin(Dictionary data) /// /// UserMargin structure /// - public struct UserMargin + 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; } @@ -319,20 +214,8 @@ public UserMargin(Dictionary data) /// /// User margins response structure /// - public struct UserMarginsResponse + 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; } } @@ -340,7 +223,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.) @@ -350,7 +233,7 @@ public struct 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) @@ -391,46 +274,19 @@ public struct OrderMarginParams /// /// OrderMargin structure /// - public struct OrderMargin + 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; } 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; } @@ -439,7 +295,7 @@ public OrderMargin(Dictionary data) /// /// ContractNoteParams structure /// - public struct ContractNoteParams + public class ContractNoteParams { /// /// Order ID that is received in the orderbook @@ -454,7 +310,7 @@ public struct 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) @@ -490,28 +346,8 @@ public struct ContractNoteParams /// /// ContractNote structure /// - public struct ContractNote + 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.) /// @@ -520,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) @@ -535,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) @@ -561,27 +397,8 @@ public ContractNote(Dictionary data) /// /// OrderCharges structure /// - public struct OrderCharges + 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; } @@ -589,57 +406,25 @@ public OrderCharges(Dictionary data) 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 struct OrderChargesGST + 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; } + public decimal Igst { get; set; } + public decimal Cgst { get; set; } + public decimal Sgst { get; set; } public decimal Total { get; set; } } /// /// BasketMargin structure /// - public struct BasketMargin + 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; } @@ -650,21 +435,8 @@ public BasketMargin(Dictionary data) /// /// OrderMarginPNL structure /// - public struct OrderMarginPNL + 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; } } @@ -672,164 +444,59 @@ public OrderMarginPNL(Dictionary data) /// /// Position structure /// - public struct Position + 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; } + 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; } + 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 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 UInt32 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; } + [JsonPropertyName("m2m")] + 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; } } /// /// Position response structure /// - public struct PositionResponse + 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; } - public List Net { get; } + public List Day { get; set; } + public List Net { get; set; } } /// /// Order structure /// - public struct Order + 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; } @@ -837,7 +504,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; } @@ -855,100 +522,46 @@ public Order(Dictionary data) 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 Dictionary Meta { get; set; } + public JsonNode Meta { get; set; } } /// /// GTTOrder structure /// - public struct GTT + 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; } + 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 struct GTTMeta + 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; } } /// /// GTTCondition structure /// - public struct GTTCondition + 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 UInt32 InstrumentToken { get; set; } + public uint InstrumentToken { get; set; } public string Exchange { get; set; } - public string TradingSymbol { get; set; } + public string Tradingsymbol { get; set; } public List TriggerValues { get; set; } public decimal LastPrice { get; set; } } @@ -956,75 +569,34 @@ public GTTCondition(Dictionary data) /// /// GTTOrder structure /// - public struct GTTOrder + 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 Nullable(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; } public decimal Quantity { get; set; } public decimal Price { get; set; } - public GTTResult? Result { get; set; } + public GttResult? Result { get; set; } } /// /// 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"])); - Timestamp = data["timestamp"]; - TriggeredAtPrice = data["triggered_at"]; - } - catch (Exception e) - { - throw new DataException(e.Message + " " + Utils.JsonSerialize(data), HttpStatusCode.OK, e); - } - } - - public GTTOrderResult? OrderResult { get; set; } + //TODO missing some documented fields + public GttOrderResult? OrderResult { get; set; } public string Timestamp { get; set; } + + [JsonPropertyName("triggered_at")] public decimal TriggeredAtPrice { get; set; } } /// /// GTTOrderResult structure /// - public struct GTTOrderResult + 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; } } @@ -1032,21 +604,21 @@ public GTTOrderResult(Dictionary data) /// /// GTTParams structure /// - public struct GTTParams + public class GttParams { - public string TradingSymbol { get; set; } + 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; } + public List Orders { get; set; } public List TriggerPrices { get; set; } } /// /// GTTOrderParams structure /// - public struct GTTOrderParams + public class GttOrderParams { public decimal Quantity { get; set; } public decimal Price { get; set; } @@ -1061,94 +633,68 @@ public struct GTTOrderParams /// /// Instrument structure /// - public struct Instrument + 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; } + + [Name("tradingsymbol")] + public string Tradingsymbol { get; set; } - public UInt32 InstrumentToken { get; set; } - public UInt32 ExchangeToken { get; set; } - 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; } - public UInt32 LotSize { get; set; } + + [Name("lot_size")] + public uint LotSize { get; set; } } /// /// Trade structure /// - public struct Trade + 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; } - public string OrderId { get; } - public string ExchangeOrderId { get; } - public string Tradingsymbol { get; } - public string Exchange { get; } - public UInt32 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; } } /// /// Trigger range structure /// - public struct TrigerRange + public class TrigerRange { public TrigerRange(Dictionary data) { @@ -1165,475 +711,250 @@ public TrigerRange(Dictionary data) } } - public UInt32 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; } } /// /// User structure /// - public struct User + 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; } - 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; } + [JsonPropertyName("user_shortname")] + 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 struct TokenSet + 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; } - public string AccessToken { get; } - public string RefreshToken { get; } + public string UserId { get; set; } + public string AccessToken { get; set; } + public string RefreshToken { get; set; } } /// /// User structure /// - public struct Profile + 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; } - } - - - 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; } + [JsonPropertyName("user_shortname")] + 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; } } /// /// Quote structure /// - public struct Quote + 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 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 decimal Open { get; set; } - public decimal High { get; set; } - public decimal Low { get; set; } - public decimal Close { get; set; } + public uint Volume { get; set; } + public uint BuyQuantity { get; set; } + public uint SellQuantity { 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 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; } } + 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 struct 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 UInt32 InstrumentToken { get; set; } - public decimal LastPrice { get; } - public decimal Open { get; } - public decimal Close { get; } - public decimal High { get; } - public decimal Low { get; } + public uint InstrumentToken { get; set; } + public decimal LastPrice { get; set; } + public Ohlc Ohlc { get; set; } } /// /// LTP Quote structure /// - public struct LTP + 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 UInt32 InstrumentToken { get; set; } - public decimal LastPrice { get; } + public uint InstrumentToken { get; set; } + public decimal LastPrice { get; set; } } /// /// Mutual funds holdings structure /// - public struct MFHolding + 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; } - 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; } } /// /// Mutual funds instrument structure /// - public struct MFInstrument + 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; } - } + [Name("amc")] + public string Amc { get; set; } + + [Name("name")] + public string Name { 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; } - 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; } + [Name("settlement_type")] + public string SettlementType { get; set; } + + [Name("last_price_date")] + public DateTime? LastPriceDate { get; set; } } /// /// Mutual funds order structure /// - public struct MFOrder + 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; } - 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; } } /// /// Mutual funds SIP structure /// - public struct MFSIP + 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; } + 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; } + } - 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 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 6f0d0ad..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 { @@ -35,7 +34,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 +132,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 +188,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; } @@ -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") @@ -496,16 +497,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 +515,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 +534,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 +554,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/KiteConnectSample.csproj b/KiteConnectSample/KiteConnectSample.csproj index 027bae7..40c6608 100644 --- a/KiteConnectSample/KiteConnectSample.csproj +++ b/KiteConnectSample/KiteConnectSample.csproj @@ -2,7 +2,15 @@ Exe - net6.0 + net8.0 + + + + $(WarningsAsErrors);NU1605;CS4014 + + + + $(WarningsAsErrors);NU1605;CS4014 diff --git a/KiteConnectSample/Program.cs b/KiteConnectSample/Program.cs index b41a43c..f42303d 100644 --- a/KiteConnectSample/Program.cs +++ b/KiteConnectSample/Program.cs @@ -1,6 +1,8 @@ -using System; -using KiteConnect; +using KiteConnect; +using System; using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; namespace KiteConnectSample { @@ -19,9 +21,9 @@ 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); + kite = new Kite(MyAPIKey, debug: true); // For handling 403 errors @@ -31,7 +33,7 @@ static void Main(string[] args) try { - initSession(); + await initSession(); } catch (Exception e) { @@ -49,25 +51,25 @@ static void 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(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"; + gttParams.Tradingsymbol = "SBIN"; gttParams.LastPrice = 288.9m; List triggerPrices = new List(); @@ -81,14 +83,14 @@ static void 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; @@ -96,260 +98,260 @@ static void 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 = kite.PlaceGTT(gttParams); + var placeGTTResponse = await kite.PlaceGttAsync(gttParams); Console.WriteLine(Utils.JsonSerialize(placeGTTResponse)); - var modifyGTTResponse = kite.ModifyGTT(407301, gttParams); + var modifyGTTResponse = await 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( - Exchange: Constants.Exchange.NSE, - TradingSymbol: "ASHOKLEY", - TransactionType: Constants.Transaction.Buy, - PositionType: Constants.Position.Day, - Quantity: 1, - OldProduct: Constants.Product.MIS, - NewProduct: Constants.Product.CNC + 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 ); // 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 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)); // 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( - Exchange: Constants.Exchange.CDS, - TradingSymbol: "USDINR17AUGFUT", - TransactionType: Constants.Transaction.Sell, - Quantity: 1, - Price: 64.0000m, - OrderType: Constants.OrderType.Market, - Product: Constants.Product.MIS + 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 ); - Console.WriteLine("Order Id: " + response["data"]["order_id"]); + Console.WriteLine("Order Id: " + response.OrderId); // Place buy order - kite.PlaceOrder( - Exchange: Constants.Exchange.CDS, - TradingSymbol: "USDINR17AUGFUT", - TransactionType: Constants.Transaction.Buy, - Quantity: 1, - Price: 63.9000m, - OrderType: Constants.OrderType.Limit, - Product: Constants.Product.MIS + 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 ); // Cancel order by id - kite.CancelOrder("1234"); + await kite.CancelOrderAsync("1234"); //BO LIMIT order placing - kite.PlaceOrder( - 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 + 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 ); // BO LIMIT exiting - kite.CancelOrder( - OrderId: "1234", - Variety: Constants.Variety.BO, - ParentOrderId: "5678" + await kite.CancelOrderAsync( + orderId: "1234", + variety: Constants.Variety.BO, + parentOrderId: "5678" ); // BO SL order placing - kite.PlaceOrder( - 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 + 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 ); // BO SL exiting - kite.CancelOrder( - OrderId: "1234", - Variety: Constants.Variety.BO, - ParentOrderId: "5678" + await kite.CancelOrderAsync( + orderId: "1234", + variety: Constants.Variety.BO, + parentOrderId: "5678" ); // CO LIMIT order placing - kite.PlaceOrder( - 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 + 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 ); // CO LIMIT exiting - kite.CancelOrder( - OrderId: "1234", - Variety: Constants.Variety.BO, - ParentOrderId: "5678" + await kite.CancelOrderAsync( + orderId: "1234", + variety: Constants.Variety.BO, + parentOrderId: "5678" ); // CO MARKET order placing - kite.PlaceOrder( - 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 + 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 ); // CO MARKET exiting - kite.CancelOrder( - OrderId: "1234", - Variety: Constants.Variety.BO, - ParentOrderId: "5678" + await kite.CancelOrderAsync( + orderId: "1234", + variety: Constants.Variety.BO, + parentOrderId: "5678" ); // Place order with TTL validity - kite.PlaceOrder( - 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 + 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 ); // Place an Iceberg order - kite.PlaceOrder( - 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 + 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 ); // Trades - List trades = kite.GetOrderTrades("1234"); + List trades = await kite.GetOrderTradesAsync("1234"); Console.WriteLine(Utils.JsonSerialize(trades[0])); // 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 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 @@ -358,76 +360,76 @@ static void Main(string[] args) 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 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 = 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 - 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", @@ -440,7 +442,7 @@ static void Main(string[] args) // Mutual Funds Holdings - List mfholdings = kite.GetMFHoldings(); + List mfholdings = await kite.GetMFHoldingsAsync(); Console.WriteLine(Utils.JsonSerialize(mfholdings[0])); Console.ReadKey(); @@ -450,12 +452,12 @@ static void Main(string[] args) ticker.Close(); } - private static void initSession() + 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 = kite.GenerateSession(requestToken, MySecret); + User user = await kite.GenerateSessionAsync(requestToken, MySecret); Console.WriteLine(Utils.JsonSerialize(user)); @@ -479,8 +481,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() diff --git a/KiteConnectTest/KiteConnectTest.csproj b/KiteConnectTest/KiteConnectTest.csproj index 2cca2c2..c9904ce 100644 --- a/KiteConnectTest/KiteConnectTest.csproj +++ b/KiteConnectTest/KiteConnectTest.csproj @@ -1,16 +1,29 @@ - net6.0 + net8.0 false + + $(WarningsAsErrors);NU1605;CS4014 + + + + $(WarningsAsErrors);NU1605;CS4014 + + - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + @@ -107,4 +120,11 @@ Always + + + + + Always + + diff --git a/KiteConnectTest/KiteTest.cs b/KiteConnectTest/KiteTest.cs index 9f75487..af24eae 100644 --- a/KiteConnectTest/KiteTest.cs +++ b/KiteConnectTest/KiteTest.cs @@ -1,10 +1,11 @@ -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.Linq; using System.Text; +using System.Threading.Tasks; namespace KiteConnectTest { @@ -30,7 +31,7 @@ public void TestSetAccessToken() { Kite kite = new Kite("apikey"); kite.SetAccessToken("access_token"); - Assert.ThrowsException(() => kite.GetPositions()); + Assert.ThrowsAsync(async () => await kite.GetPositionsAsync()); } @@ -40,112 +41,112 @@ 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); - Assert.ThrowsException(() => kite.GetProfile()); + Kite kite = new Kite("apikey", root: "http://localhost:8080", debug: true); + 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(); + 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"); } [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(); - Assert.AreEqual(positionResponse.Net[0].TradingSymbol, "LEADMINI17DECFUT"); - Assert.AreEqual(positionResponse.Day[0].TradingSymbol, "GOLDGUINEA17DECFUT"); + 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"); } [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(); + 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] - 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(); - Assert.AreEqual(instruments[0].PNL, 564.8000000000002m); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + List instruments = await kite.GetAuctionInstrumentsAsync(); + Assert.AreEqual(instruments[0].Pnl, 564.8000000000002m); } [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(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + UserMarginsResponse margins = await kite.GetMarginsAsync(); Assert.AreEqual(margins.Equity.Utilised.Turnover, (decimal)0); Assert.AreEqual(margins.Commodity.Utilised.Turnover, (decimal)0); } [TestMethod] - public void TestOrderMargins() + 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; - 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); + 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] - public void TestOrderMarginsCompact() + 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; - param.TradingSymbol = "ASHOKLEY21JULFUT"; + param.Tradingsymbol = "ASHOKLEY21JULFUT"; param.TransactionType = Constants.Transaction.Sell; param.Quantity = 1; param.Price = 64.0000m; @@ -154,29 +155,29 @@ 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); + 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); - 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; - param.TradingSymbol = "ASHOKLEY21JULFUT"; + param.Tradingsymbol = "ASHOKLEY21JULFUT"; param.TransactionType = Constants.Transaction.Sell; param.Quantity = 1; param.Price = 64.0000m; @@ -185,29 +186,29 @@ 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); + 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); - 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; - param.TradingSymbol = "ASHOKLEY21JULFUT"; + param.Tradingsymbol = "ASHOKLEY21JULFUT"; param.TransactionType = Constants.Transaction.Sell; param.Quantity = 1; param.Price = 64.0000m; @@ -216,91 +217,96 @@ 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); + Assert.AreEqual(margins.Final.Span, (decimal)0); } [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"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + UserMargin margin = await kite.GetMarginsAsync("commodity"); Assert.AreEqual(margin.Net, (decimal)1812.3535); } [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" }); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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" }); + 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); } [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" }); + 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, (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] - 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(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + List orders = await kite.GetOrdersAsync(); Assert.AreEqual(orders[0].Price, 72); 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"], 5); + Assert.AreEqual(orders[3].Meta["iceberg"]["legs"].GetValue(), 5); Assert.AreEqual(orders[0].AuctionNumber, 10); @@ -308,12 +314,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(); + 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); @@ -322,113 +328,141 @@ 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); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + List orderhistory = await kite.GetOrderHistoryAsync("171124000819854"); Assert.AreEqual(orderhistory[0].PendingQuantity, 100); } [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(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + var instrument = kite.GetInstrumentsAsync(Constants.Exchange.NSE).ToBlockingEnumerable().First(); - Assert.AreEqual(instruments[0].InstrumentToken, (uint)3813889); + Assert.AreEqual(instrument.InstrumentToken, (uint)3813889); } [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"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + List trades = await kite.GetOrderTradesAsync("151220000000000"); Assert.AreEqual(trades[0].TradeId, "159918"); } [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(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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"); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + List holdings = await kite.GetMFHoldingsAsync(); Assert.AreEqual(holdings[0].Folio, "123123/123"); } @@ -438,12 +472,12 @@ 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(); + Kite kite = new Kite("apikey", root: "http://localhost:8080"); + 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 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,