AuthenticateUser ( string clientId ) { // Method members string authCode = string.Empty; string postData = string.Empty; string apiResult = string.Empty; try { // Create the initial authentication form for the user from TD // Ameritrade AuthForm authForm = new AuthForm(ApiMethod.GetAuthCode .GetAttribute("Name") .Replace("{account_id}", clientId), "https://127.0.0.1"); // Show the authentication form authForm.ShowDialog(); // Destroy the Windows Form Icon bool bDestroy = Helper.DestroyIcon(authForm.icon.Handle); if (!bDestroy) { LogHelper.Log(LogLevel.Error, $"{Resx.GetString("WINDOWS_FORM_ICON_NOT_DESTROYED")}"); } // Once here, the dialog control will be closed and the code // needed to request the first access token will be in the // querystring if (authForm.Query != null && !string.IsNullOrEmpty(authForm.Query["code"])) { // Get the authorization code, which will be automatically // url decoded authCode = authForm.Query["code"]; // Authorization code is present in the query string. Form // the url-encoded post data to retrieve an access token postData = $"grant_type=authorization_code&refresh_token=&access_type=offline&code={HttpUtility.UrlEncode(authCode)}"; postData += $"&client_id={HttpUtility.UrlEncode(clientId)}&redirect_uri={HttpUtility.UrlEncode("http://127.0.0.1")}"; // Get a TD Ameritrade REST API interface object, if needed if (rest == null) { rest = new TDAmeritradeREST(); } // Execute a query to the TD Ameritrade API for an access // token apiResult = rest.QueryApi( // The method on the TD Ameritrade REST API being // called ApiMethod.PostAccessToken, // The data helper method ApiHelper.UrlEncodedData( // The encoded form data postData, // Not using authentication in order to receive // the first access token, which will then be // used whenever subsequent authentication is // needed false ) ); // Was an error encountered? if (!apiResult.StartsWith("ERROR:")) { // NO: Get a json serializer based on the Token // Model class AuthToken token = Broker.DeserializeJson <AuthToken>(apiResult); // Write the refresh token to encrypted file storage token.Save(clientId); // Return the refresh token return(token); } } } catch (Exception e) { // Log the error LogHelper.Log(LogLevel.Error, $" {Resx.GetString("ERROR")}: {Resx.GetString("GETTING_ACCESS_TOKEN")}. " + e.Message); // Return an empty access token return(null); } // Log any errors LogHelper.Log(LogLevel.Error, apiResult); // Return an empty access token return(null); }
GetQuotes ( string symbols ) { // Method members List <EquityETF> equityList = new List <EquityETF>(); List <MutualFund> mutualFundList = new List <MutualFund>(); List <Forex> forexList = new List <Forex>(); List <TDAsset> assetList = new List <TDAsset>(); Dictionary <string, object> assetDict = new Dictionary <string, object>(); // Were symbols obtained? if (!string.IsNullOrEmpty(symbols)) { // YES: Get the TD Ameritrade REST API object TDAmeritradeREST rest = new TDAmeritradeREST(); // Call TD Ameritratde API to get current quotes for these symbols string result = rest.QueryApi( // The TD Ameritrade API method ApiMethod.GetQuotes, // The data object passed to the API method ApiHelper.AccountDataWithQueryString( // No data in URL before query string null, // The query string used to get the quotes symbols, // Use authentication true ) ); // Is the result not in error? if (!string.IsNullOrEmpty(result) && !result.StartsWith("ERROR:")) { // NO: Create a non-data contract JSON serializer JavaScriptSerializer serializer = new JavaScriptSerializer(); // Deserialize the result returned from TD Ameritrade into // the 1st level dictionary, i.e. <string, object> assetDict = (Dictionary <string, object>)serializer.Deserialize <object>(result); // Iterate through each asset in the asset dictionary foreach (string key in assetDict.Keys) { // The 2nd level object for each asset is also a // <string, object> dictionary. What type of asset? switch (((Dictionary <string, object>)assetDict[key])["assetType"].ToString()) { case "EQUITY": case "ETF": // Convert object to an Equity/ETF class object equityList.Add(Broker.JsonDictConvert <EquityETF>((Dictionary <string, object>)assetDict[key])); break; case "MUTUAL_FUND": // Convert object to a mutual fund class object mutualFundList.Add(Broker.JsonDictConvert <MutualFund>((Dictionary <string, object>)assetDict[key])); break; case "FOREX": //********************************************* // NOTE: The TD Ameritrade REST API currently // does not support FOREX trading. //********************************************* // Convert object to a Forex class object //forexList.Add(Broker.JsonDictConvert<Forex>((Dictionary<string, object>)assetDict[key])); break; default: break; } } // Iterate through the equities and ETFs foreach (EquityETF asset in equityList) { // Get the ask price double askPrice = Broker.GetAskPrice(asset); // If no ask price can be determined, do not trade this security if (askPrice < -9000.0) { continue; } // Get the bid price double bidPrice = Broker.GetBidPrice(asset); assetList.Add(new TDAsset { Symbol = asset.Symbol, Price = asset.AskPrice, Spread = askPrice - bidPrice, Volume = 0, LotAmount = 1, MarginCost = 0.00, Pip = 0.01, PipCost = 0.01 }); } // Iterate through the mutual funds foreach (MutualFund asset in mutualFundList) { // Get the ask price double askPrice = Broker.GetAskPrice(asset); // If no ask price can be determined, do not trade this security if (askPrice < -9000.0) { continue; } // Get the bid price double bidPrice = Broker.GetBidPrice(asset); assetList.Add(new TDAsset { Symbol = asset.Symbol, Price = asset.AskPrice, Spread = askPrice - bidPrice, Volume = 0, LotAmount = 1, MarginCost = 0.00, Pip = 0.01, PipCost = 0.01 }); } //********************************************************* // NOTE: FOREX trading is not currently supported by the // TD Ameritrade REST API. // // Iterate through the Forex assets. Main issue is to // compute the pipCost and the Rollover interest fees: // // PipCost = LotAmount * Pip / ( {Counter Currency} / {Account Currency} ) //********************************************************* /* * foreach (Forex asset in forexList) * { * // Get the ask price * double askPrice = Broker.GetAskPrice(asset); * * // If no ask price can be determined, do not trade this security * if (askPrice < -9000.0) continue; * * // Get the bid price * double bidPrice = Broker.GetBidPrice(asset); * * // Get the rollover rates * double ROR = CurrencyInterestRates.ComputeRollover(asset.Symbol, askPrice); * * // Round the rollover to five places * ROR = Math.Round(ROR, 5); * * assetList.Add(new TDAsset * { * Symbol = asset.Symbol, * Price = asset.AskPrice, * Spread = askPrice - bidPrice, * Volume = 0, * LotAmount = 10000, * MarginCost = 0.00, * Pip = (asset.Symbol.Contains("/JPY") || asset.Symbol.Contains("JPY/")) ? 0.01 : 0.0001, * PipCost = Broker.ComputePipCost(asset.Symbol), * RolloverLong = ROR, * RolloverShort = ROR * }); * } */ } } // Return the asset list return(assetList); }