diff --git a/.gitignore b/.gitignore index 0e99b0b..ad3a379 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,82 @@ eNavigator/eNavigatorUI/bin/** eNavigator/eNavigatorUI/obj/** eNavigator/MarketDataLib/bin/** eNavigator/MarketDataLib/obj/** +MarketDataServer/bin/Debug/net8.0/appsettings.json +MarketDataServer/bin/Debug/net8.0/Axiom.Core.dll +MarketDataServer/bin/Debug/net8.0/Axiom.Core.pdb +MarketDataServer/bin/Debug/net8.0/BouncyCastle.Cryptography.dll +MarketDataServer/bin/Debug/net8.0/Google.Protobuf.dll +MarketDataServer/bin/Debug/net8.0/HtmlAgilityPack.dll +MarketDataServer/bin/Debug/net8.0/K4os.Compression.LZ4.dll +MarketDataServer/bin/Debug/net8.0/K4os.Compression.LZ4.Streams.dll +MarketDataServer/bin/Debug/net8.0/K4os.Hash.xxHash.dll +MarketDataServer/bin/Debug/net8.0/log4net.dll +MarketDataServer/bin/Debug/net8.0/log4net.xml +MarketDataServer/bin/Debug/net8.0/MarketDataLib.dll +MarketDataServer/bin/Debug/net8.0/MarketDataLib.pdb +MarketDataServer/bin/Debug/net8.0/Microsoft.Extensions.Configuration.Abstractions.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.Extensions.Configuration.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.Extensions.Configuration.FileExtensions.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.Extensions.Configuration.Json.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.Extensions.FileProviders.Abstractions.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.Extensions.FileProviders.Physical.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.Extensions.FileSystemGlobbing.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.Extensions.Primitives.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.OpenApi.dll +MarketDataServer/bin/Debug/net8.0/Microsoft.Win32.SystemEvents.dll +MarketDataServer/bin/Debug/net8.0/mks +MarketDataServer/bin/Debug/net8.0/mks.deps.json +MarketDataServer/bin/Debug/net8.0/mks.dll +MarketDataServer/bin/Debug/net8.0/mks.pdb +MarketDataServer/bin/Debug/net8.0/mks.runtimeconfig.json +MarketDataServer/bin/Debug/net8.0/MySql.Data.dll +MarketDataServer/bin/Debug/net8.0/Newtonsoft.Json.dll +MarketDataServer/bin/Debug/net8.0/Swashbuckle.AspNetCore.Swagger.dll +MarketDataServer/bin/Debug/net8.0/Swashbuckle.AspNetCore.SwaggerGen.dll +MarketDataServer/bin/Debug/net8.0/Swashbuckle.AspNetCore.SwaggerUI.dll +MarketDataServer/bin/Debug/net8.0/System.Configuration.ConfigurationManager.dll +MarketDataServer/bin/Debug/net8.0/System.Drawing.Common.dll +MarketDataServer/bin/Debug/net8.0/System.IO.Pipelines.dll +MarketDataServer/bin/Debug/net8.0/System.Private.Windows.Core.dll +MarketDataServer/bin/Debug/net8.0/System.Security.Cryptography.ProtectedData.dll +MarketDataServer/bin/Debug/net8.0/System.Security.Permissions.dll +MarketDataServer/bin/Debug/net8.0/System.Text.Encodings.Web.dll +MarketDataServer/bin/Debug/net8.0/System.Text.Json.dll +MarketDataServer/bin/Debug/net8.0/System.Windows.Extensions.dll +MarketDataServer/bin/Debug/net8.0/ZstdSharp.dll +MarketDataServer/bin/Debug/net8.0/logs/marketdata_marketdataserver.log +MarketDataServer/bin/Debug/net8.0/runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll +MarketDataServer/bin/Debug/net8.0/runtimes/win/lib/net8.0/Microsoft.Win32.SystemEvents.dll +MarketDataServer/bin/Debug/net8.0/runtimes/win/lib/net8.0/System.Windows.Extensions.dll +MarketDataServer/bin/Debug/net8.0/runtimes/win-x64/native/comerr64.dll +MarketDataServer/bin/Debug/net8.0/runtimes/win-x64/native/gssapi64.dll +MarketDataServer/bin/Debug/net8.0/runtimes/win-x64/native/k5sprt64.dll +MarketDataServer/bin/Debug/net8.0/runtimes/win-x64/native/krb5_64.dll +MarketDataServer/bin/Debug/net8.0/runtimes/win-x64/native/krbcc64.dll +MarketDataServer/obj/MarketDataServer.csproj.nuget.dgspec.json +MarketDataServer/obj/MarketDataServer.csproj.nuget.g.props +MarketDataServer/obj/MarketDataServer.csproj.nuget.g.targets +MarketDataServer/obj/project.assets.json +MarketDataServer/obj/project.nuget.cache +MarketDataServer/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +MarketDataServer/obj/Debug/net8.0/apphost +MarketDataServer/obj/Debug/net8.0/MarketDa.2D592492.Up2Date +MarketDataServer/obj/Debug/net8.0/MarketDataServer.AssemblyInfo.cs +MarketDataServer/obj/Debug/net8.0/MarketDataServer.AssemblyInfoInputs.cache +MarketDataServer/obj/Debug/net8.0/MarketDataServer.assets.cache +MarketDataServer/obj/Debug/net8.0/MarketDataServer.csproj.AssemblyReference.cache +MarketDataServer/obj/Debug/net8.0/MarketDataServer.csproj.CoreCompileInputs.cache +MarketDataServer/obj/Debug/net8.0/MarketDataServer.csproj.FileListAbsolute.txt +MarketDataServer/obj/Debug/net8.0/MarketDataServer.GeneratedMSBuildEditorConfig.editorconfig +MarketDataServer/obj/Debug/net8.0/MarketDataServer.genruntimeconfig.cache +MarketDataServer/obj/Debug/net8.0/MarketDataServer.GlobalUsings.g.cs +MarketDataServer/obj/Debug/net8.0/mks.dll +MarketDataServer/obj/Debug/net8.0/mks.MvcApplicationPartsAssemblyInfo.cache +MarketDataServer/obj/Debug/net8.0/mks.MvcApplicationPartsAssemblyInfo.cs +MarketDataServer/obj/Debug/net8.0/mks.pdb +MarketDataServer/obj/Debug/net8.0/staticwebassets.build.json +MarketDataServer/obj/Debug/net8.0/ref/mks.dll +MarketDataServer/obj/Debug/net8.0/refint/mks.dll +MarketDataServer/obj/Debug/net8.0/staticwebassets/msbuild.build.mks.props +MarketDataServer/obj/Debug/net8.0/staticwebassets/msbuild.buildMultiTargeting.mks.props +MarketDataServer/obj/Debug/net8.0/staticwebassets/msbuild.buildTransitive.mks.props diff --git a/MarketDataServer/.vscode/launch.json b/MarketDataServer/.vscode/launch.json new file mode 100644 index 0000000..cde9cd7 --- /dev/null +++ b/MarketDataServer/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/bin/Debug/net8.0/mks.dll", + "args": [], + "cwd": "${workspaceFolder}", + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/MarketDataServer/.vscode/tasks.json b/MarketDataServer/.vscode/tasks.json new file mode 100644 index 0000000..62a5c5a --- /dev/null +++ b/MarketDataServer/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/MarketDataServer.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/MarketDataServer.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/MarketDataServer.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/MarketDataServer/Authorization/Authorizations.cs b/MarketDataServer/Authorization/Authorizations.cs new file mode 100755 index 0000000..af64069 --- /dev/null +++ b/MarketDataServer/Authorization/Authorizations.cs @@ -0,0 +1,78 @@ +using MarketData; +using MarketData.DataAccess; +using MarketData.Extensions; +using MarketData.MarketDataModel.User; +using System.Text; + +namespace MarketDataServer.Authorization +{ + public class Authorizations + { + private Dictionary authorizationDictionary = null; + private static Authorizations authorizations = null; + private bool isEnabled=true; + + private Authorizations() + { + authorizationDictionary=new Dictionary(); + } + + public static Authorizations GetInstance() + { + lock (typeof(Authorizations)) + { + if (null == authorizations) authorizations = new Authorizations(); + } + return authorizations; + } + + public bool IsEnabled + { + get{return isEnabled;} + set{isEnabled=value;} + } + + public bool IsAuthorized(String token) + { + lock (this) + { + if(!IsEnabled)return true; + return authorizationDictionary.ContainsKey(token); + } + } + + public String GetAuthenticationToken() + { + lock (this) + { + String token = Guid.NewGuid().ToString(); + authorizationDictionary.Add(token, token); + return token; + } + } + + public bool IsValidUser(String username,String password) + { + lock (this) + { + if(!UserDA.UserExists(username))return false; + MDTrace.WriteLine(MarketData.LogLevel.DEBUG,String.Format("[{0:G}][User {1} exists.]",DateTime.Now ,username)); + User user = UserDA.GetUser(username); + if(null == user) + { + MDTrace.WriteLine(MarketData.LogLevel.DEBUG,String.Format("[{0:G}][User {1} validation failed.]",DateTime.Now ,username)); + return false; + } + MDTrace.WriteLine(MarketData.LogLevel.DEBUG,String.Format("[{0:G}][User {1} is validated.]",DateTime.Now ,username)); + return user.Verify(password); + } + } + + public static String Xor(String input, int magic) + { + StringBuilder sb = new StringBuilder(); + foreach (char ch in input) sb.Append((char)(ch ^ (char)magic)); + return sb.ToString(); + } + } +} diff --git a/MarketDataServer/Controllers/GainLossController.cs b/MarketDataServer/Controllers/GainLossController.cs new file mode 100755 index 0000000..8335151 --- /dev/null +++ b/MarketDataServer/Controllers/GainLossController.cs @@ -0,0 +1,288 @@ +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; +using MarketData.Generator.GainLoss; +using MarketData.MarketDataModel.GainLoss; +using MarketDataServer.Authorization; +using MarketData.Cache; +using MarketData.Generator; +using MarketData; +using LogLevel = MarketData.LogLevel; +using Microsoft.AspNetCore.Mvc; + +namespace MarketDataServer.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + public class GainLossController : ControllerBase + { + private ActiveGainLossGenerator gainLossGenerator=new ActiveGainLossGenerator(); + + [HttpGet(Name = "GetGainLoss")] + public IEnumerable GetGainLoss(String token, DateTime selectedDate) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][GainLossController::GetGainLoss](String token, DateTime selectedDate)", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + LocalPriceCache.GetInstance().Refresh(); + PortfolioTrades portfolioTrades = PortfolioDA.GetTrades(); + PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(selectedDate); + GainLossSummaryItemCollection gainLossSummaryItems = new GainLossSummaryItemCollection(tradesOnOrBefore, selectedDate); + +// **** Add an aggregate entry + GainLossSummaryItem gainLossSummaryTotals=new GainLossSummaryItem(); + gainLossSummaryTotals.Symbol=""; + gainLossSummaryTotals.CompanyName="Account Summary"; + if(null!=gainLossSummaryItems&&gainLossSummaryItems.Count>0) + { + gainLossSummaryTotals.Date=gainLossSummaryItems.Min(x => x.Date); + gainLossSummaryTotals.Change=gainLossSummaryItems.Sum(x=>x.Change); + gainLossSummaryTotals.CurrentGainLoss=gainLossSummaryItems.Sum(x => x.CurrentGainLoss); + gainLossSummaryTotals.PreviousGainLoss = gainLossSummaryItems.Sum(x => x.PreviousGainLoss); + gainLossSummaryTotals.ChangePercent=((gainLossSummaryTotals.CurrentGainLoss-gainLossSummaryTotals.PreviousGainLoss)/Math.Abs(gainLossSummaryTotals.PreviousGainLoss))*100.00; + } + else + { + gainLossSummaryTotals.Date = selectedDate; + gainLossSummaryTotals.Change = 0.00; + gainLossSummaryTotals.CurrentGainLoss = 0.00; + gainLossSummaryTotals.PreviousGainLoss = 0.00; + gainLossSummaryTotals.ChangePercent = 0.00; + } + gainLossSummaryItems.Insert(0,gainLossSummaryTotals); +// **** + return gainLossSummaryItems; + } + + [HttpGet(Name = "GetGainLoss")] + public IEnumerable GetGainLoss(String token, DateTime selectedDate,String account) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][GainLossController::GetGainLoss](String token, DateTime selectedDate,String account)", DateTime.Now)); + LocalPriceCache.GetInstance().Refresh(); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + PortfolioTrades portfolioTrades = PortfolioDA.GetTrades(); + portfolioTrades=new PortfolioTrades(portfolioTrades.Where(x=>x.Account.Equals(account)).ToList()); + PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(selectedDate); + GainLossSummaryItemCollection gainLossSummaryItems = new GainLossSummaryItemCollection(tradesOnOrBefore, selectedDate); + + // **** Add an aggregate entry + GainLossSummaryItem gainLossSummaryTotals = new GainLossSummaryItem(); + gainLossSummaryTotals.Symbol = ""; + gainLossSummaryTotals.CompanyName="Account Summary"; + if (null != gainLossSummaryItems && gainLossSummaryItems.Count > 0) + { + gainLossSummaryTotals.Date = gainLossSummaryItems.Min(x => x.Date); + gainLossSummaryTotals.Change = gainLossSummaryItems.Sum(x => x.Change); + gainLossSummaryTotals.CurrentGainLoss = gainLossSummaryItems.Sum(x => x.CurrentGainLoss); + gainLossSummaryTotals.PreviousGainLoss = gainLossSummaryItems.Sum(x => x.PreviousGainLoss); + gainLossSummaryTotals.ChangePercent = ((gainLossSummaryTotals.CurrentGainLoss - gainLossSummaryTotals.PreviousGainLoss) / Math.Abs(gainLossSummaryTotals.PreviousGainLoss)) * 100.00; + } + else + { + gainLossSummaryTotals.Date = selectedDate; + gainLossSummaryTotals.Change = 0.00; + gainLossSummaryTotals.CurrentGainLoss = 0.00; + gainLossSummaryTotals.PreviousGainLoss = 0.00; + gainLossSummaryTotals.ChangePercent = 0.00; + } + gainLossSummaryItems.Insert(0, gainLossSummaryTotals); + // **** + return gainLossSummaryItems; + } + + [HttpGet(Name = "GetGainLossWithDetail")] + public IEnumerable GetGainLossWithDetail(String token, DateTime selectedDate) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][GainLossController::GetGainLossWithDetail](String token, DateTime selectedDate)", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + LocalPriceCache.GetInstance().Refresh(); + PortfolioTrades portfolioTrades = PortfolioDA.GetTrades(); + PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(selectedDate); + GainLossSummaryItemCollection gainLossSummaryItems = new GainLossSummaryItemCollection(tradesOnOrBefore, selectedDate); + + List gainLossSummaryItemDetailCollection = new List(); + foreach (GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItems) + { + GainLossSummaryItemDetail gainLossSummaryItemDetail = new GainLossSummaryItemDetail(gainLossSummaryItem); + portfolioTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol); + double weightAdjustedDividendYield = portfolioTrades.GetWeightAdjustedDividendYield(); + DateTime currentDate = PricingDA.GetLatestDate(gainLossSummaryItem.Symbol); + if (null == portfolioTrades || 0 == portfolioTrades.Count) continue; + double shares = (from PortfolioTrade portfolioTrade in portfolioTrades select portfolioTrade.Shares).Sum(); + double exposure = portfolioTrades.Sum(x => x.Exposure()); + if(null==gainLossGenerator) gainLossGenerator=new ActiveGainLossGenerator(); + GainLossCollection gainLoss=gainLossGenerator.GenerateGainLoss(portfolioTrades); // gainLoss contains the gain/loss from active positions. Never includes dividends .. just positions + GainLossItem gainLossItem = gainLoss.OrderByDescending(x => x.GainLossPercent).FirstOrDefault(); + gainLossSummaryItemDetail.Lots = portfolioTrades.Count; + gainLossSummaryItemDetail.Shares = shares; + gainLossSummaryItemDetail.Exposure = exposure; + if (!double.IsNaN(weightAdjustedDividendYield)) + { + gainLossSummaryItemDetail.DividendYield = weightAdjustedDividendYield; + gainLossSummaryItemDetail.AnnualDividend = exposure * weightAdjustedDividendYield; + } + ParityElement parityElement = ParityGenerator.GenerateBreakEven(gainLossSummaryItem.Symbol); + gainLossSummaryItemDetail.ParityElement = parityElement; + if (null != parityElement) + { + gainLossSummaryItemDetail.AllTimeGainLossPercent = gainLossItem.GainLossPercent; + gainLossSummaryItemDetail.PercentDistanceFromAllTimeGainLossPercent = parityElement.ParityOffsetPercent - (gainLossItem.GainLossPercent / 100); + } + DateGenerator dateGenerator = new DateGenerator(); + DateTime priorDate = dateGenerator.FindPrevBusinessDay(currentDate); + Price p1 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, currentDate); + Price p2 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, priorDate); + if (null == p2 && null != p1) + { + priorDate = dateGenerator.FindPrevBusinessDay(priorDate); + p2 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, priorDate); + } + if (null != p1 && null != p2) + { + double change = (p1.Close - p2.Close) / p2.Close; + gainLossSummaryItemDetail.LatestPrice = p1; + gainLossSummaryItemDetail.PriceChange = change; + } + gainLossSummaryItemDetailCollection.Add(gainLossSummaryItemDetail); + } + + // **** Add an aggregate entry + GainLossSummaryItemDetail gainLossSummaryTotals = new GainLossSummaryItemDetail(); + gainLossSummaryTotals.Symbol = ""; + gainLossSummaryTotals.CompanyName = "Account Summary"; + if (null != gainLossSummaryItemDetailCollection && gainLossSummaryItemDetailCollection.Count > 0) + { + gainLossSummaryTotals.Date = gainLossSummaryItemDetailCollection.Min(x => x.Date); + gainLossSummaryTotals.Exposure = gainLossSummaryItemDetailCollection.Sum(x => x.Exposure); + gainLossSummaryTotals.Change = gainLossSummaryItemDetailCollection.Sum(x => x.Change); + gainLossSummaryTotals.CurrentGainLoss = gainLossSummaryItemDetailCollection.Sum(x => x.CurrentGainLoss); + gainLossSummaryTotals.PreviousGainLoss = gainLossSummaryItemDetailCollection.Sum(x => x.PreviousGainLoss); + gainLossSummaryTotals.ChangePercent = ((gainLossSummaryTotals.CurrentGainLoss - gainLossSummaryTotals.PreviousGainLoss) / Math.Abs(gainLossSummaryTotals.PreviousGainLoss)) * 100.00; + gainLossSummaryTotals.LatestPrice = new Price(); + gainLossSummaryTotals.PriceChange = 0; + } + else + { + gainLossSummaryTotals.Date = selectedDate; + gainLossSummaryTotals.Change = 0.00; + gainLossSummaryTotals.CurrentGainLoss = 0.00; + gainLossSummaryTotals.PreviousGainLoss = 0.00; + gainLossSummaryTotals.ChangePercent = 0.00; + gainLossSummaryTotals.LatestPrice = new Price(); + gainLossSummaryTotals.PriceChange = 0; + } + gainLossSummaryItemDetailCollection.Insert(0, gainLossSummaryTotals); + // **** + return gainLossSummaryItemDetailCollection; + } + + [HttpGet(Name = "GetGainLossWithDetail")] + public IEnumerable GetGainLossWithDetail(String token, DateTime selectedDate, String account) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][GainLossController::GetGainLossWithDetail](String token, DateTime selectedDate,String account)", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + LocalPriceCache.GetInstance().Refresh(); + PortfolioTrades portfolioTrades = PortfolioDA.GetTrades(); + portfolioTrades = new PortfolioTrades(portfolioTrades.Where(x => x.Account.Equals(account)).ToList()); + PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(selectedDate); + GainLossSummaryItemCollection gainLossSummaryItems = new GainLossSummaryItemCollection(tradesOnOrBefore, selectedDate); + + List gainLossSummaryItemDetailCollection=new List(); + foreach(GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItems) + { + GainLossSummaryItemDetail gainLossSummaryItemDetail = new GainLossSummaryItemDetail(gainLossSummaryItem); + portfolioTrades = PortfolioDA.GetOpenTradesSymbol(gainLossSummaryItem.Symbol); + double weightAdjustedDividendYield = portfolioTrades.GetWeightAdjustedDividendYield(); + DateTime currentDate = PricingDA.GetLatestDate(gainLossSummaryItem.Symbol); + if(null==portfolioTrades||0==portfolioTrades.Count)continue; + double shares = (from PortfolioTrade portfolioTrade in portfolioTrades select portfolioTrade.Shares).Sum(); + double exposure = portfolioTrades.Sum(x => x.Exposure()); + if(null==gainLossGenerator) gainLossGenerator=new ActiveGainLossGenerator(); + GainLossCollection gainLoss = gainLossGenerator.GenerateGainLoss(portfolioTrades); // gainLoss contains the gain/loss from active positions. Never includes dividends .. just positions + GainLossItem gainLossItem = gainLoss.OrderByDescending(x => x.GainLossPercent).FirstOrDefault(); + gainLossSummaryItemDetail.Lots=portfolioTrades.Count; + gainLossSummaryItemDetail.Shares=shares; + gainLossSummaryItemDetail.Exposure=exposure; + if (!double.IsNaN(weightAdjustedDividendYield)) + { + gainLossSummaryItemDetail.DividendYield=weightAdjustedDividendYield; + gainLossSummaryItemDetail.AnnualDividend=exposure * weightAdjustedDividendYield; + } + ParityElement parityElement = ParityGenerator.GenerateBreakEven(gainLossSummaryItem.Symbol); + gainLossSummaryItemDetail.ParityElement=parityElement; + if (null != parityElement) + { + gainLossSummaryItemDetail.AllTimeGainLossPercent=gainLossItem.GainLossPercent; + gainLossSummaryItemDetail.PercentDistanceFromAllTimeGainLossPercent=parityElement.ParityOffsetPercent - (gainLossItem.GainLossPercent / 100); + } + DateGenerator dateGenerator = new DateGenerator(); + DateTime priorDate = dateGenerator.FindPrevBusinessDay(currentDate); + Price p1 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, currentDate); + Price p2 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, priorDate); + if (null == p2 && null != p1) + { + priorDate = dateGenerator.FindPrevBusinessDay(priorDate); + p2 = PricingDA.GetPrice(gainLossSummaryItem.Symbol, priorDate); + } + if(null!=p1&&null!=p2) + { + double change = (p1.Close - p2.Close) / p2.Close; + gainLossSummaryItemDetail.LatestPrice=p1; + gainLossSummaryItemDetail.PriceChange=change; + } + gainLossSummaryItemDetailCollection.Add(gainLossSummaryItemDetail); + } + + // **** Add an aggregate entry + GainLossSummaryItemDetail gainLossSummaryTotals = new GainLossSummaryItemDetail(); + gainLossSummaryTotals.Symbol = ""; + gainLossSummaryTotals.CompanyName = "Account Summary"; + if (null != gainLossSummaryItemDetailCollection && gainLossSummaryItemDetailCollection.Count > 0) + { + gainLossSummaryTotals.Date = gainLossSummaryItemDetailCollection.Min(x => x.Date); + gainLossSummaryTotals.Exposure=gainLossSummaryItemDetailCollection.Sum(x=>x.Exposure); + gainLossSummaryTotals.Change = gainLossSummaryItemDetailCollection.Sum(x => x.Change); + gainLossSummaryTotals.CurrentGainLoss = gainLossSummaryItemDetailCollection.Sum(x => x.CurrentGainLoss); + gainLossSummaryTotals.PreviousGainLoss = gainLossSummaryItemDetailCollection.Sum(x => x.PreviousGainLoss); + gainLossSummaryTotals.ChangePercent = ((gainLossSummaryTotals.CurrentGainLoss - gainLossSummaryTotals.PreviousGainLoss) / Math.Abs(gainLossSummaryTotals.PreviousGainLoss)) * 100.00; + gainLossSummaryTotals.LatestPrice=new Price(); + gainLossSummaryTotals.PriceChange=0; + } + else + { + gainLossSummaryTotals.Date = selectedDate; + gainLossSummaryTotals.Change = 0.00; + gainLossSummaryTotals.CurrentGainLoss = 0.00; + gainLossSummaryTotals.PreviousGainLoss = 0.00; + gainLossSummaryTotals.ChangePercent = 0.00; + gainLossSummaryTotals.LatestPrice = new Price(); + gainLossSummaryTotals.PriceChange = 0; + } + gainLossSummaryItemDetailCollection.Insert(0, gainLossSummaryTotals); + // **** + return gainLossSummaryItemDetailCollection; + } + + [HttpGet(Name = "GetCompoundGainLoss")] + public GainLossCompoundModelCollection GetCompoundGainLoss(String token, int selectedDays, bool includeDividends) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][GainLossController::GetCompundGainLoss](String token, int days)", DateTime.Now)); + if(!Authorizations.GetInstance().IsAuthorized(token)) return null; + LocalPriceCache.GetInstance().Refresh(); + DividendPayments dividendPayments = null; + PortfolioTrades portfolioTrades = PortfolioDA.GetTrades(); + GainLossGenerator gainLossGenerator=new GainLossGenerator(); + if(includeDividends)dividendPayments=DividendPaymentDA.GetDividendPayments(); + ActiveGainLossGenerator activeGainLossGenerator=new ActiveGainLossGenerator(); + GainLossCollection gainLoss=activeGainLossGenerator.GenerateGainLoss(portfolioTrades); // gainLoss contains the gain/loss from active positions. Never includes dividends .. just positions + TotalGainLossCollection totalGainLoss=null; + if(null!=dividendPayments)totalGainLoss=gainLossGenerator.GenerateTotalGainLossWithDividends(portfolioTrades,dividendPayments); + else totalGainLoss=gainLossGenerator.GenerateTotalGainLoss(portfolioTrades); + GainLossCompoundModelCollection gainLossModelCollection=null; + gainLossModelCollection=new GainLossCompoundModelCollection(gainLoss,totalGainLoss); + if(-1==selectedDays)return gainLossModelCollection; + int skip=gainLossModelCollection.Count-selectedDays; + if(skip<0)return gainLossModelCollection; + return new GainLossCompoundModelCollection(gainLossModelCollection.Skip(skip).ToList()); + } + } +} diff --git a/MarketDataServer/Controllers/HeadlinesController.cs b/MarketDataServer/Controllers/HeadlinesController.cs new file mode 100755 index 0000000..30d9a3c --- /dev/null +++ b/MarketDataServer/Controllers/HeadlinesController.cs @@ -0,0 +1,40 @@ +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketDataServer.Authorization; +using MarketData; +using LogLevel = MarketData.LogLevel; +using Microsoft.AspNetCore.Mvc; + +namespace MarketDataServer.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + public class HeadlinesController : ControllerBase + { + [HttpGet(Name = "GetLatestHeadlines")] + public IEnumerable GetLatestHeadlines(String token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][HeadlinesController::GetLatestHeadlines]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + return HeadlinesDA.GetLatestHeadlines(); + } + + [HttpGet(Name = "GetHeadlineDates")] + public IEnumerable GetHeadlineDates(String token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][HeadlinesController::GetHeadlineDates]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + List headlineDates = HeadlinesDA.GetHeadlineDates(); + if(headlineDates.Count>0)headlineDates=headlineDates.Take(252).ToList(); + return headlineDates; + } + + [HttpGet(Name = "GetHeadlines")] + public IEnumerable GetHeadlines(String token,DateTime headlineDate) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][HeadlinesController::GetHeadliness(DateTime headlineDate)]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + return HeadlinesDA.GetHeadlines(headlineDate); + } + } +} diff --git a/MarketDataServer/Controllers/LoginController.cs b/MarketDataServer/Controllers/LoginController.cs new file mode 100755 index 0000000..2761f29 --- /dev/null +++ b/MarketDataServer/Controllers/LoginController.cs @@ -0,0 +1,30 @@ +using MarketData; +using MarketDataServer.Authorization; +using Microsoft.AspNetCore.Mvc; +using LogLevel = MarketData.LogLevel; + +namespace MarketDataServer.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + public class AuthorizationController : ControllerBase + { + [HttpGet(Name = "GetToken")] + public String GetToken(String user, String password) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][AuthorizationController::Authorize]",DateTime.Now)); + if(null==user)return null; + user=Authorizations.Xor(user,5); + password=Authorizations.Xor(password,5); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][Login requested for user '{1}']",DateTime.Now, user)); + if(!Authorizations.GetInstance().IsValidUser(user, password)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][User '{1}' is not authorized]", DateTime.Now,user)); + return null; + } + String accessToken= Authorizations.GetInstance().GetAuthenticationToken(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][Access token granted for user {1} : {2}]",DateTime.Now ,user, accessToken)); + return accessToken; + } + } +} diff --git a/MarketDataServer/Controllers/PingController.cs b/MarketDataServer/Controllers/PingController.cs new file mode 100755 index 0000000..2b7a474 --- /dev/null +++ b/MarketDataServer/Controllers/PingController.cs @@ -0,0 +1,19 @@ +using MarketData; +using Microsoft.AspNetCore.Mvc; +using LogLevel = MarketData.LogLevel; + + +namespace MarketDataServer.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + public class PingController : ControllerBase + { + [HttpGet(Name = "GetPing")] + public bool GetPing() + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PingController::GetPing]", DateTime.Now)); + return true; + } + } +} diff --git a/MarketDataServer/Controllers/PortfolioController.cs b/MarketDataServer/Controllers/PortfolioController.cs new file mode 100755 index 0000000..60b0433 --- /dev/null +++ b/MarketDataServer/Controllers/PortfolioController.cs @@ -0,0 +1,80 @@ +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketDataServer.Authorization; +using MarketData.Generator; +using MarketData; +using LogLevel = MarketData.LogLevel; +using Microsoft.AspNetCore.Mvc; + +namespace MarketDataServer.Controllers +{ + +//http://localhost:8000/api/Portfolio/GetTradesSymbol?&symbol=SPY +//http://73.245.214.234:8000/api/Portfolio/GetTradesSymbol?&symbol=SPY + namespace MarketDataServer.Controllers + { + [ApiController] + [Route("api/[controller]/[action]")] + public class PortfolioController : ControllerBase + { + [HttpGet(Name = "GetOpenPositionsWithDescription")] + public IEnumerable GetOpenPositionsWithDescription(String token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PortfolioController::GetOpenPositionsWithDescriptionAsOf]",DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + List positionsWithDescription=new List(); + PortfolioTrades openTrades=PortfolioDA.GetOpenTrades(); + List positions=openTrades.GetPositions(DateTime.Now); + foreach(Position position in positions) + { + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(position.Symbol); + if(null==companyProfile.Description)companyProfile.Description="Description unvailable"; + positionsWithDescription.Add(new PositionWithDescription(position,companyProfile.CompanyName, companyProfile.Description)); + } + return positionsWithDescription; + } + + [HttpGet(Name = "GetAccounts")] + public IEnumerable GetAccounts(String token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PortfolioController::GetAccounts]",DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + return PortfolioDA.GetAccounts(); + } + + [HttpGet(Name = "GetAccountsWithOpenTrades")] + public IEnumerable GetAccountsWithOpenTrades(String token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PortfolioController::GetAccountsWithOpenTrades]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + return PortfolioDA.GetAccountsWithOpenTrades(); + } + + [HttpGet(Name = "GetStopLimit")] + public StopLimit GetStopLimit(String token,String symbol) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PortfolioController::GetStopLimit]",DateTime.Now)); + if(!Authorizations.GetInstance().IsAuthorized(token)) return null; + StopLimit stopLimit=PortfolioDA.GetStopLimit(symbol); + return stopLimit; + } + + [HttpGet(Name = "GetPortfolioTradesWithParityPrice")] + public PortfolioTradesWithParityPrice GetPortfolioTradesWithParityPrice(String token, String symbol) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PortfolioController::GetPortfolioTradesWithParityPrice]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + Price zeroPrice=null; + DateTime latestPricingDate=PricingDA.GetLatestDate(symbol); + Price latestPrice = PricingDA.GetPrice(symbol, latestPricingDate); + PortfolioTrades portfolioTrades = PortfolioDA.GetTradesSymbol(symbol); + if (null == portfolioTrades) return null; + portfolioTrades = portfolioTrades.GetOpenTrades(); + if (null == portfolioTrades) return null; + PortfolioTrades portfolioTradesLots = LotAggregator.CombineLots(portfolioTrades); + zeroPrice=ParityGenerator.GenerateGainLossValue(portfolioTrades,latestPrice); + return new PortfolioTradesWithParityPrice(portfolioTradesLots,zeroPrice); + } + } + } +} diff --git a/MarketDataServer/Controllers/PreMarketController.cs b/MarketDataServer/Controllers/PreMarketController.cs new file mode 100755 index 0000000..7eca1bd --- /dev/null +++ b/MarketDataServer/Controllers/PreMarketController.cs @@ -0,0 +1,40 @@ +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketDataServer.Authorization; +using MarketData; +using LogLevel = MarketData.LogLevel; +using Microsoft.AspNetCore.Mvc; + +namespace MarketDataServer.Controllers +{ + //http://localhost:8000/api/PreMarket/GetAvailableMarketDates?&market=S&P + [ApiController] + [Route("api/[controller]/[action]")] + public class PreMarketController: ControllerBase + { + [HttpGet(Name = "GetAvailableMarketDates")] + public IEnumerable GetAvailableMarketDates(String token,String market) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PreMarketController::GetAvailableMarketDates]{1}",DateTime.Now,market)); + if(!Authorizations.GetInstance().IsAuthorized(token)) return null; + return PremarketDA.GetAvailableMarketDates(market); + } + + [HttpGet(Name = "GetAvailableMarkets")] + public IEnumerable GetAvailableMarkets(String token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PreMarketController::GetAvailableMarkets]",DateTime.Now)); + if(!Authorizations.GetInstance().IsAuthorized(token)) return null; + return PremarketDA.GetDistinctMarkets(); + } + + [HttpGet(Name = "GetLatestPremarketData")] + public IEnumerable GetLatestPremarketData(String token,String market,DateTime marketDate) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PreMarketController::GetLatestPremarketData]{1},{2}",DateTime.Now,market,marketDate.ToShortDateString())); + if(!Authorizations.GetInstance().IsAuthorized(token)) return null; + return PremarketDA.GetLatestPremarketData(market,marketDate); + } + } +} + diff --git a/MarketDataServer/Controllers/PriceController.cs b/MarketDataServer/Controllers/PriceController.cs new file mode 100755 index 0000000..cde2179 --- /dev/null +++ b/MarketDataServer/Controllers/PriceController.cs @@ -0,0 +1,55 @@ +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketDataServer.Authorization; +using MarketData.Generator; +using MarketData; +using LogLevel = MarketData.LogLevel; +using Microsoft.AspNetCore.Mvc; + +namespace MarketDataServer.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] +//http://localhost:8000/api/Price +//http://localhost:8000/api/Price/GetPrices?&symbol=MIDD&days=5 +//http://73.245.214.234:8000/api/Price/GetPrices?&symbol=MIDD&days=5 + + public class PriceController : ControllerBase + { + [HttpGet(Name = "GetPrices")] + public IEnumerable GetPrices(String token, String symbol, int days) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PriceController::GetPrices]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + return PricingDA.GetPrices(symbol, days); + } + + [HttpGet(Name = "GetBollingerBands")] + public BollingerBands GetBollingerBands(String token,String symbol,int dayCount) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PriceController::GetBollingerBands]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + Prices prices=PricingDA.GetPrices(symbol,dayCount); + BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices); + return bollingerBands; + } + + [HttpGet(Name = "GetLatestPricingDate")] + public DateTime GetLatestPricingDate(String token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PriceController::GetLatestPricingDate]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return DateTime.MinValue; + DateTime latestPricingDate=PricingDA.GetLatestDate(); + return latestPricingDate; + } + + [HttpGet(Name = "GetCompanyNameForSymbol")] + public String GetCompanyNameForSymbol(String token, String symbol) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PortfolioController::GetCompanyNameForSymbol]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + String companyName=PricingDA.GetNameForSymbol(symbol); + return companyName; + } + } +} diff --git a/MarketDataServer/Controllers/PriceIndexController.cs b/MarketDataServer/Controllers/PriceIndexController.cs new file mode 100755 index 0000000..1c01fed --- /dev/null +++ b/MarketDataServer/Controllers/PriceIndexController.cs @@ -0,0 +1,32 @@ +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketDataServer.Authorization; +using MarketData; +using Microsoft.AspNetCore.Mvc; +using LogLevel = MarketData.LogLevel; + +namespace MarketDataServer.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + public class PriceIndexController : ControllerBase + { +//http://localhost:8000/api/PriceIndex/GetDistnctPriceIndices + [HttpGet(Name = "GetDistinctPriceIndices")] + public IEnumerable GetDistinctPriceIndices(String token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PriceIndexController::GetDistinctPriceIndices]",DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + return ConsumerPriceIndexDA.GetDistinctIndices(); + } + + [HttpGet(Name = "GetConsumerPriceIndex")] + public IEnumerable GetConsumerPriceIndex(String token,String indexCode) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][PriceIndexController::GetOpenPositionsWithDescriptionAsOf]",DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + PriceIndices priceIndices=ConsumerPriceIndexDA.GetConsumerPriceIndex(indexCode); + return priceIndices; + } + } +} diff --git a/MarketDataServer/Controllers/WatchListController.cs b/MarketDataServer/Controllers/WatchListController.cs new file mode 100755 index 0000000..fef06be --- /dev/null +++ b/MarketDataServer/Controllers/WatchListController.cs @@ -0,0 +1,21 @@ +using MarketData; +using MarketData.DataAccess; +using MarketDataServer.Authorization; +using Microsoft.AspNetCore.Mvc; +using LogLevel = MarketData.LogLevel; + +namespace MarketDataServer.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + public class WatchListController : ControllerBase + { + [HttpGet(Name = "GetWatchList")] + public IEnumerable GetWatchList(String token,String watchList) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[{0:G}][WatchListController::GetWatchList]", DateTime.Now)); + if (!Authorizations.GetInstance().IsAuthorized(token)) return null; + return WatchListDA.GetWatchList(watchList); + } + } +} diff --git a/MarketDataServer/Handlers/CustomHeaderHandler.cs b/MarketDataServer/Handlers/CustomHeaderHandler.cs new file mode 100755 index 0000000..8c501b1 --- /dev/null +++ b/MarketDataServer/Handlers/CustomHeaderHandler.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Net.Http; + +namespace MarketDataServer.Handlers +{ + public class CustomHeaderHandler : DelegatingHandler + { + protected override Task SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) + { + return base.SendAsync(request, cancellationToken) + .ContinueWith((task) => + { + HttpResponseMessage response = task.Result; + response.Headers.Add("Access-Control-Allow-Origin", "*"); + //response.Headers.Add("Access-Control-Allow-Credentials", "true"); + //response.Headers.Add("Access-Control-Allow-Methods", "OPTIONS, GET, POST"); + //response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control"); + return response; + }); + } + } +} diff --git a/MarketDataServer/MarketDataServer.csproj b/MarketDataServer/MarketDataServer.csproj new file mode 100755 index 0000000..59934c5 --- /dev/null +++ b/MarketDataServer/MarketDataServer.csproj @@ -0,0 +1,23 @@ + + + Exe + net8.0 + mks + enable + disable + SYSLIB0014;CA1416;CS8769;CS0108;CS8602;CS8601;CS8620;CS8618;CS8603;CS8767;CS8625;CS8604;CS8600;CS8604 + + + + + + + + + + + + PreserveNewest + + + diff --git a/MarketDataServer/Program.cs b/MarketDataServer/Program.cs new file mode 100755 index 0000000..2cec283 --- /dev/null +++ b/MarketDataServer/Program.cs @@ -0,0 +1,68 @@ +using System.Diagnostics; +using MarketData; +using MarketData.Configuration; +using MarketData.Utils; +using MarketDataServer.Authorization; + +namespace MarketDataServer +{ + class Program + { + static void Main(string[] args) + { + String logFileName="marketdataserver"; + Authorizations.GetInstance().IsEnabled=false; + WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + + // Add services to the container. + GlobalConfig.Instance.Configuration = builder.Configuration; + String baseAddress = GlobalConfig.Instance.Configuration["server_address"]; + CreateLogging(logFileName); + + MDTrace.WriteLine(MarketData.LogLevel.DEBUG,$"Server Address:{baseAddress}"); + + builder.Services.AddControllers(); + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddSwaggerGen( config => + { + config.ResolveConflictingActions (apiDescriptions => apiDescriptions.First ()); + }); + + WebApplication webApplication = builder.Build(); + + // Configure the HTTP request pipeline. + if (webApplication.Environment.IsDevelopment()||webApplication.Environment.IsProduction() ) + { + webApplication.UseSwagger(); + webApplication.UseSwaggerUI(); + } + + webApplication.UseHttpsRedirection(); + webApplication.UseAuthorization(); + webApplication.MapControllers(); + webApplication.MapControllerRoute(name: "default",pattern: "api/{controller}/{action}/{id?}"); + webApplication.Run(baseAddress); + } + + private static bool CreateLogging(String task) + { + if(String.IsNullOrEmpty(task))return false; + task=task.ToLower(); + MDTrace.LogLevel = MarketData.LogLevel.DEBUG; + String logFolder = "/logs"; + DateTime currentDate=DateTime.Now; + String strLogFile = "marketdata_" + task + ".log"; + String currentWorkingDirectory = Directory.GetCurrentDirectory(); + Console.WriteLine($"Current directory is {currentWorkingDirectory}"); + Utility.EnsureLogFolder(currentWorkingDirectory+logFolder); + Utility.ExpireLogs(currentWorkingDirectory+logFolder,1); + Trace.Listeners.Remove("Default"); + Console.WriteLine($"Adding Trace Listener :{currentWorkingDirectory+logFolder+"/"+strLogFile}"); + Trace.Listeners.Add(new TextWriterTraceListener(currentWorkingDirectory+logFolder+"/"+strLogFile)); + MDTrace.WriteLine($"Trace Listener added."); + Utility.ShowLogs(currentWorkingDirectory + logFolder); + return true; + } + } +} + diff --git a/MarketDataServer/appsettings.json b/MarketDataServer/appsettings.json new file mode 100755 index 0000000..0b47758 --- /dev/null +++ b/MarketDataServer/appsettings.json @@ -0,0 +1,17 @@ +{ +"market_data" : "Database=market_data;Datasource=euporie;Username=guest;Password=guest", +"portfolio_data" : "Database=portfolio_data;Datasource=euporie;Username=guest;Password=guest", +"user_data" : "Database=user_data;Datasource=euporie;Username=guest;Password=guest", +"server_address" : "http://localhost:8000/", +"sms_smtpaddress" : "smtp.gmail.com", +"sms_smsusername" : "skessler1964@gmail.com", +"sms_smspassword" : "xjfo isnf gmyi zovr", +"sms_smsrecipients" : "skessler1964@gmail.com", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}