From 30c33d3cfd0758ab7f1d4ac178b0461db61d720a Mon Sep 17 00:00:00 2001 From: Sean Date: Tue, 25 Mar 2025 21:42:32 -0400 Subject: [PATCH] Initial Commit --- .gitignore | 153 + MarketData/.vscode/launch.json | 25 + MarketData/.vscode/tasks.json | 41 + MarketData/MarketData.sln | 28 + MarketData/MarketData/.vscode/launch.json | 24 + MarketData/MarketData/.vscode/tasks.json | 41 + MarketData/MarketData/CommandArgs.cs | 77 + MarketData/MarketData/Executor.cs | 26 + MarketData/MarketData/Interface/IArguments.cs | 7 + .../MarketData/Interface/IMainService.cs | 9 + MarketData/MarketData/MarketData.csproj | 24 + MarketData/MarketData/Program.cs | 25 + MarketData/MarketData/Services/Arguments.cs | 19 + MarketData/MarketData/Services/MainService.cs | 593 + MarketData/MarketData/Services/scraps.txt | 456 + MarketData/MarketData/appsettings.json | 21 + MarketData/MarketData/marketdata.log | 1138 ++ .../MarketDataLib/CSVHelper/CSVFileExt.cs | 543 + .../MarketDataLib/CSVHelper/CSVFileExt2.cs | 84 + .../CSVHelper/ExtractFileHelper.cs | 86 + .../MarketDataLib/CSVHelper/StringParser.cs | 29 + .../Cache/DividendHistoryCache.cs | 148 + .../MarketDataLib/Cache/GBPriceCache.cs | 259 + .../MarketDataLib/Cache/LocalPriceCache.cs | 306 + .../Configuration/GlobalConfig.cs | 34 + .../DataAccess/AnalystPriceTargetDA.cs | 168 + .../DataAccess/AnalystRatingsDA.cs | 653 + .../DataAccess/BalanceSheetDA.cs | 618 + MarketData/MarketDataLib/DataAccess/CashDA.cs | 124 + .../DataAccess/CashflowStatementDA.cs | 377 + .../DataAccess/CompanyProfileDA.cs | 247 + .../MarketDataLib/DataAccess/CompositeDA.cs | 357 + .../DataAccess/ConsumerPriceIndexDA.cs | 276 + .../DataAccess/CurrencyConversionDA.cs | 174 + .../MarketDataLib/DataAccess/DataSource.cs | 45 + .../MarketDataLib/DataAccess/DataSourceEx.cs | 91 + .../MarketDataLib/DataAccess/DictionaryDA.cs | 342 + .../DataAccess/DividendHistoryDA.cs | 286 + .../DataAccess/DividendPaymentDA.cs | 368 + .../MarketDataLib/DataAccess/ETFHoldingsDA.cs | 292 + .../DataAccess/EarningsAnnouncementsDA.cs | 249 + .../DataAccess/EconomicIndicatorDA.cs | 176 + .../MarketDataLib/DataAccess/FundamentalDA.cs | 766 ++ .../MarketDataLib/DataAccess/HeadlinesDA.cs | 434 + .../MarketDataLib/DataAccess/HistoricalDA.cs | 191 + .../MarketDataLib/DataAccess/HolidayDA.cs | 159 + .../DataAccess/IncomeStatementDA.cs | 522 + .../DataAccess/InsiderTransactionDA.cs | 318 + .../MarketDataLib/DataAccess/LexicalDA.cs | 305 + .../DataAccess/MStarSecurityDA.cs | 181 + .../MarketDataLib/DataAccess/OptionsDA.cs | 433 + .../MarketDataLib/DataAccess/PortfolioDA.cs | 933 ++ .../MarketDataLib/DataAccess/PremarketDA.cs | 281 + .../MarketDataLib/DataAccess/PricingDA.cs | 1518 +++ .../MarketDataLib/DataAccess/SECFilingDA.cs | 485 + .../MarketDataLib/DataAccess/SplitsDA.cs | 335 + MarketData/MarketDataLib/DataAccess/UserDA.cs | 135 + .../MarketDataLib/DataAccess/ValuationDA.cs | 437 + .../MarketDataLib/DataAccess/WatchListDA.cs | 239 + .../MarketDataLib/DataAccess/YieldCurveDA.cs | 454 + .../MarketDataLib/DataAccess/ZacksRankDA.cs | 225 + .../Generator/AcquirersMultipleGenerator.cs | 173 + .../Generator/BollingerBandGenerator.cs | 73 + .../MarketDataLib/Generator/DCFGenerator.cs | 310 + .../Generator/DividendHistoryGenerator.cs | 114 + .../GainLoss/ActiveGainLossGenerator.cs | 91 + .../Generator/GainLoss/GainLossGenerator.cs | 127 + .../GainLoss/GainLossGeneratorCum.cs | 193 + .../Generator/GainLoss/GainLossHelper.cs | 111 + .../GainLoss/IActiveGainLossGenerator.cs | 12 + .../GainLoss/ITotalGainLossGenerator.cs | 12 + .../Generator/GrahamGenerator.cs | 32 + .../Indicators/BandBreakIndicator.cs | 65 + .../Indicators/ChannelBreakoutIndicator.cs | 32 + .../Generator/Indicators/MVPIndicator.cs | 62 + .../Indicators/NarrowRangeIndicator.cs | 47 + .../Indicators/OverExtendedIndicator.cs | 78 + .../Indicators/PriceTrendIndicator.cs | 44 + .../Indicators/VolumeTrendIndicator.cs | 26 + .../Generator/Interface/IPosition.cs | 13 + .../Generator/Interface/IPurePosition.cs | 19 + .../MarketDataLib/Generator/MACDGenerator.cs | 131 + .../Generator/Model/Expectancy.cs | 24 + .../Generator/Model/StopLimits.cs | 128 + .../ModelGenerators/EdgeRatioGenerator.cs | 89 + .../ModelGenerators/TrueRangeGenerator.cs | 52 + .../ModelGenerators/VolatilityGenerator.cs | 50 + .../ExponentialMovingAverageCrossover.cs | 212 + .../MovingAverage/MovingAverageCrossover.cs | 47 + .../MovingAverage/MovingAverageGenerator.cs | 255 + .../Generator/ParityGenerator.cs | 111 + .../MarketDataLib/Generator/RSIGenerator.cs | 125 + .../Generator/RiskFreeRateGenerator.cs | 90 + .../Generator/SentimentGenerator.cs | 417 + .../Generator/SignalGenerator.cs | 409 + .../MarketDataLib/Generator/SignalTrader.cs | 177 + .../Generator/StochasticsGenerator.cs | 96 + .../Generator/TLBRankGenerator.cs | 204 + .../Generator/TermStructure/CurveMapping.cs | 141 + .../TermStructure/TermStructureGenerator.cs | 138 + .../Generator/TradeSignalWatchGenerator.cs | 102 + .../Generator/ValuationGenerator.cs | 549 + .../AnalystPriceTargetMarketDataHelper.cs | 126 + .../Helper/BollingerBandHelperSheet.cs | 144 + .../Helper/CIKMarketDataHelper.cs | 91 + .../Helper/CompanyProfileMarketDataHelper.cs | 131 + .../Helper/DividendHistoryMarketDataHelper.cs | 170 + .../Helper/ETFHoldingsMarketDataHelper.cs | 133 + .../EarningsAnnouncementsMarketDataHelper.cs | 103 + .../FinancialStatementsMarketDataHelper.cs | 249 + .../Helper/FundamentalMarketDataHelper.cs | 260 + .../Helper/HeadlinesMarketDataHelper.cs | 191 + .../Helper/HistoricalMarketDataHelper.cs | 131 + .../InsiderTransactionMarketDataHelper.cs | 197 + .../Helper/InsiderTransactionsParser.cs | 243 + .../MarketDataLib/Helper/MarketDataHelper.cs | 5527 ++++++++ .../Helper/MarketDataHelperBase.cs | 103 + .../Helper/MovingAverageHelperSheet.cs | 133 + .../Helper/OptionsChainsMarketDataHelper.cs | 106 + .../Helper/PricingMarketDataHelper.cs | 831 ++ .../Helper/SECFilingMarketDataHelper.cs | 162 + .../MarketDataLib/Helper/SplitHelper.cs | 55 + .../Helper/StochasticsHelperSheet.cs | 112 + .../MarketDataLib/Helper/SwingTradeHelper.cs | 87 + .../MarketDataLib/Helper/ThreadHelper.cs | 36 + .../MarketDataLib/Helper/TimeZoneHelper.cs | 89 + .../Helper/ZacksRankMarketDataHelper.cs | 114 + .../Integration/HttpNetRequest.cs | 1774 +++ .../MarketDataLib/Integration/Network.cs | 92 + .../MarketDataLib/Integration/SMSClient.cs | 93 + .../MarketDataLib/Integration/Socket.cs | 548 + .../MarketDataLib/Integration/UserAgent.cs | 54 + MarketData/MarketDataLib/MDTrace.cs | 159 + MarketData/MarketDataLib/MarketDataLib.csproj | 22 + .../MarketDataModel/AnalystPriceTarget.cs | 76 + .../MarketDataModel/AnalystRatings.cs | 108 + .../MarketDataModel/BalanceSheet.cs | 209 + .../MarketDataModel/BetaModel.cs | 88 + .../MarketDataModel/BollingerBand.cs | 162 + .../MarketDataModel/CashTransactions.cs | 23 + .../MarketDataModel/CashflowStatement.cs | 160 + .../MarketDataModel/Cashflows.cs | 19 + .../MarketDataModel/CompanyProfile.cs | 95 + .../MarketDataModel/Constants.cs | 17 + .../CurrencyConversionElement.cs | 27 + .../MarketDataModel/DCFValuation.cs | 317 + .../MarketDataModel/DMADeviation.cs | 42 + .../MarketDataLib/MarketDataModel/DMAPrice.cs | 150 + .../MarketDataLib/MarketDataModel/Decay.cs | 122 + .../MarketDataModel/DividendHistory.cs | 93 + .../MarketDataModel/DividendLoad.cs | 37 + .../MarketDataModel/DividendPayment.cs | 45 + .../MarketDataModel/ETFHoldings.cs | 64 + .../MarketDataModel/EarningsAnnouncement.cs | 33 + .../EarningsAnnouncementModel.cs | 51 + .../MarketDataModel/EconomicIndicators.cs | 156 + .../MarketDataModel/ExponentialDecay.cs | 35 + .../MarketDataModel/FeedStatistics.cs | 113 + .../MarketDataModel/Fundamentals.cs | 398 + .../GainLoss/GainLossCompoundModel.cs | 27 + .../GainLossCompoundModelCollection.cs | 97 + .../MarketDataModel/GainLoss/GainLossItem.cs | 142 + .../GainLoss/GainLossSummaryItem.cs | 27 + .../GainLoss/GainLossSummaryItemCollection.cs | 145 + ...ainLossCompoundModelYearDescendingOrder.cs | 22 + .../SortTotalGainLossYearDescendingOrder.cs | 22 + .../GainLoss/SortYearDescendingOrder.cs | 23 + .../GainLoss/TotalGainLossCollection.cs | 24 + .../GainLoss/TotalGainLossItem.cs | 52 + .../MarketDataModel/Headlines.cs | 60 + .../MarketDataModel/IncomeStatement.cs | 165 + .../MarketDataModel/InsiderTransaction.cs | 80 + .../MarketDataLib/MarketDataModel/KeyValue.cs | 22 + .../MarketDataLib/MarketDataModel/Lexical.cs | 60 + .../MarketDataLib/MarketDataModel/MACD.cs | 193 + .../MarketDataModel/MACDSetup.cs | 61 + .../MarketDataModel/MobileDataModels.cs | 50 + .../MarketDataModel/ModelPerformance.cs | 83 + .../MarketDataModel/ModelTrade.cs | 95 + .../MarketDataModel/MovingAverage.cs | 98 + .../MarketDataModel/MovingDeviation.cs | 40 + .../MarketDataModel/OptionsModel.cs | 335 + .../MarketDataModel/ParityElement.cs | 23 + .../MarketDataModel/Portfolio.cs | 107 + .../MarketDataModel/PortfolioTrade.cs | 172 + .../MarketDataModel/PortfolioTrades.cs | 297 + .../PositionWithDescription.cs | 25 + .../MarketDataModel/PremarketElement.cs | 22 + .../MarketDataModel/PriceIndex.cs | 24 + .../MarketDataLib/MarketDataModel/Prices.cs | 462 + .../MarketDataModel/Prices.cs.bak | 454 + .../MarketDataModel/PricesByDate.cs | 39 + .../MarketDataModel/RSICollection.cs | 95 + .../MarketDataModel/ResistanceSupport.cs | 103 + .../MarketDataModel/ReturnItem.cs | 72 + .../MarketDataModel/SECFiling.cs | 104 + .../MarketDataModel/Securities.cs | 84 + .../MarketDataModel/Sentiment.cs | 43 + .../MarketDataModel/SharpeRatioModel.cs | 97 + .../MarketDataLib/MarketDataModel/Signal.cs | 171 + .../MarketDataModel/SignalHolder.cs | 52 + .../MarketDataLib/MarketDataModel/Splits.cs | 44 + .../MarketDataModel/Statistic.cs | 75 + .../MarketDataModel/StickerPrice.cs | 115 + .../MarketDataModel/Stochastic.cs | 138 + .../MarketDataModel/StopLimit.cs | 109 + .../MarketDataModel/SwingTrade.cs | 108 + .../MarketDataModel/TimeSeriesElement.cs | 166 + .../MarketDataModel/TradeResult.cs | 80 + .../MarketDataModel/User/User.cs | 11 + .../MarketDataModel/Valuations.cs | 164 + .../MarketDataModel/WatchListItem.cs | 13 + .../MarketDataModel/WordDictionary.cs | 72 + .../MarketDataModel/YieldCurve.cs | 354 + .../MarketDataModel/ZacksRank.cs | 14 + .../MarketDataLib/Numerics/BetaGenerator.cs | 289 + MarketData/MarketDataLib/Numerics/Bin.cs | 66 + .../MarketDataLib/Numerics/BlackScholes.cs | 73 + MarketData/MarketDataLib/Numerics/KStest.cs | 52 + .../MarketDataLib/Numerics/LeastSquares.cs | 133 + MarketData/MarketDataLib/Numerics/Numerics.cs | 1443 ++ .../Numerics/SharpeRatioGenerator.cs | 76 + MarketData/MarketDataLib/Numerics/Spline.cs | 114 + .../MarketDataLib/Utility/CSVLineHelper.cs | 57 + .../MarketDataLib/Utility/DateGenerator.cs | 456 + MarketData/MarketDataLib/Utility/DateRange.cs | 28 + .../MarketDataLib/Utility/ExtensionMethods.cs | 25 + .../MarketDataLib/Utility/FeedParser.cs | 343 + .../MarketDataLib/Utility/HolidayCache.cs | 35 + MarketData/MarketDataLib/Utility/NVP.cs | 110 + MarketData/MarketDataLib/Utility/Profiler.cs | 36 + MarketData/MarketDataLib/Utility/SQLUtils.cs | 263 + MarketData/MarketDataLib/Utility/Sections.cs | 497 + .../MarketDataLib/Utility/UpdateManager.cs | 97 + MarketData/MarketDataLib/Utility/Utility.cs | 726 + .../MarketDataLib/ValueAtRisk/BinItem.cs | 42 + .../MarketDataLib/ValueAtRisk/BinManager.cs | 147 + MarketData/MarketDataLib/ValueAtRisk/HVaR.cs | 91 + .../ValueAtRisk/PortfolioHoldings.cs | 163 + .../MarketDataLib/ValueAtRisk/VaRResult.cs | 46 + .../WeightedReturnsWithContributions.cs | 116 + MarketData/assemblies/HtmlAgilityPack.dll | Bin 0 -> 135168 bytes .../Microsoft.Office.Interop.Excel.dll | Bin 0 -> 1628856 bytes .../Newtonsoft.Json/Newtonsoft.Json.dll | Bin 0 -> 700336 bytes .../Newtonsoft.Json/Newtonsoft.Json.pdb | Bin 0 -> 253696 bytes .../Newtonsoft.Json/Newtonsoft.Json.xml | 11262 ++++++++++++++++ MarketData/assemblies/Readme.txt | 12 + 247 files changed, 60107 insertions(+) create mode 100644 .gitignore create mode 100755 MarketData/.vscode/launch.json create mode 100755 MarketData/.vscode/tasks.json create mode 100755 MarketData/MarketData.sln create mode 100644 MarketData/MarketData/.vscode/launch.json create mode 100644 MarketData/MarketData/.vscode/tasks.json create mode 100644 MarketData/MarketData/CommandArgs.cs create mode 100755 MarketData/MarketData/Executor.cs create mode 100755 MarketData/MarketData/Interface/IArguments.cs create mode 100755 MarketData/MarketData/Interface/IMainService.cs create mode 100755 MarketData/MarketData/MarketData.csproj create mode 100755 MarketData/MarketData/Program.cs create mode 100755 MarketData/MarketData/Services/Arguments.cs create mode 100755 MarketData/MarketData/Services/MainService.cs create mode 100644 MarketData/MarketData/Services/scraps.txt create mode 100755 MarketData/MarketData/appsettings.json create mode 100644 MarketData/MarketData/marketdata.log create mode 100755 MarketData/MarketDataLib/CSVHelper/CSVFileExt.cs create mode 100755 MarketData/MarketDataLib/CSVHelper/CSVFileExt2.cs create mode 100755 MarketData/MarketDataLib/CSVHelper/ExtractFileHelper.cs create mode 100755 MarketData/MarketDataLib/CSVHelper/StringParser.cs create mode 100755 MarketData/MarketDataLib/Cache/DividendHistoryCache.cs create mode 100755 MarketData/MarketDataLib/Cache/GBPriceCache.cs create mode 100755 MarketData/MarketDataLib/Cache/LocalPriceCache.cs create mode 100755 MarketData/MarketDataLib/Configuration/GlobalConfig.cs create mode 100755 MarketData/MarketDataLib/DataAccess/AnalystPriceTargetDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/AnalystRatingsDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/BalanceSheetDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/CashDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/CashflowStatementDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/CompanyProfileDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/CompositeDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/ConsumerPriceIndexDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/CurrencyConversionDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/DataSource.cs create mode 100755 MarketData/MarketDataLib/DataAccess/DataSourceEx.cs create mode 100755 MarketData/MarketDataLib/DataAccess/DictionaryDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/DividendHistoryDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/DividendPaymentDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/ETFHoldingsDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/EarningsAnnouncementsDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/EconomicIndicatorDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/FundamentalDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/HeadlinesDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/HistoricalDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/HolidayDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/IncomeStatementDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/InsiderTransactionDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/LexicalDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/MStarSecurityDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/OptionsDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/PortfolioDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/PremarketDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/PricingDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/SECFilingDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/SplitsDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/UserDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/ValuationDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/WatchListDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/YieldCurveDA.cs create mode 100755 MarketData/MarketDataLib/DataAccess/ZacksRankDA.cs create mode 100755 MarketData/MarketDataLib/Generator/AcquirersMultipleGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/BollingerBandGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/DCFGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/DividendHistoryGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/GainLoss/ActiveGainLossGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/GainLoss/GainLossGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/GainLoss/GainLossGeneratorCum.cs create mode 100755 MarketData/MarketDataLib/Generator/GainLoss/GainLossHelper.cs create mode 100755 MarketData/MarketDataLib/Generator/GainLoss/IActiveGainLossGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/GainLoss/ITotalGainLossGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/GrahamGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/Indicators/BandBreakIndicator.cs create mode 100755 MarketData/MarketDataLib/Generator/Indicators/ChannelBreakoutIndicator.cs create mode 100755 MarketData/MarketDataLib/Generator/Indicators/MVPIndicator.cs create mode 100755 MarketData/MarketDataLib/Generator/Indicators/NarrowRangeIndicator.cs create mode 100755 MarketData/MarketDataLib/Generator/Indicators/OverExtendedIndicator.cs create mode 100755 MarketData/MarketDataLib/Generator/Indicators/PriceTrendIndicator.cs create mode 100755 MarketData/MarketDataLib/Generator/Indicators/VolumeTrendIndicator.cs create mode 100755 MarketData/MarketDataLib/Generator/Interface/IPosition.cs create mode 100755 MarketData/MarketDataLib/Generator/Interface/IPurePosition.cs create mode 100755 MarketData/MarketDataLib/Generator/MACDGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/Model/Expectancy.cs create mode 100755 MarketData/MarketDataLib/Generator/Model/StopLimits.cs create mode 100755 MarketData/MarketDataLib/Generator/ModelGenerators/EdgeRatioGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/ModelGenerators/TrueRangeGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/ModelGenerators/VolatilityGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/MovingAverage/ExponentialMovingAverageCrossover.cs create mode 100755 MarketData/MarketDataLib/Generator/MovingAverage/MovingAverageCrossover.cs create mode 100755 MarketData/MarketDataLib/Generator/MovingAverage/MovingAverageGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/ParityGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/RSIGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/RiskFreeRateGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/SentimentGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/SignalGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/SignalTrader.cs create mode 100755 MarketData/MarketDataLib/Generator/StochasticsGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/TLBRankGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/TermStructure/CurveMapping.cs create mode 100755 MarketData/MarketDataLib/Generator/TermStructure/TermStructureGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/TradeSignalWatchGenerator.cs create mode 100755 MarketData/MarketDataLib/Generator/ValuationGenerator.cs create mode 100755 MarketData/MarketDataLib/Helper/AnalystPriceTargetMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/BollingerBandHelperSheet.cs create mode 100755 MarketData/MarketDataLib/Helper/CIKMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/CompanyProfileMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/DividendHistoryMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/ETFHoldingsMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/EarningsAnnouncementsMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/FinancialStatementsMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/FundamentalMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/HeadlinesMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/HistoricalMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/InsiderTransactionMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/InsiderTransactionsParser.cs create mode 100755 MarketData/MarketDataLib/Helper/MarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/MarketDataHelperBase.cs create mode 100755 MarketData/MarketDataLib/Helper/MovingAverageHelperSheet.cs create mode 100755 MarketData/MarketDataLib/Helper/OptionsChainsMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/PricingMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/SECFilingMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/SplitHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/StochasticsHelperSheet.cs create mode 100755 MarketData/MarketDataLib/Helper/SwingTradeHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/ThreadHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/TimeZoneHelper.cs create mode 100755 MarketData/MarketDataLib/Helper/ZacksRankMarketDataHelper.cs create mode 100755 MarketData/MarketDataLib/Integration/HttpNetRequest.cs create mode 100755 MarketData/MarketDataLib/Integration/Network.cs create mode 100755 MarketData/MarketDataLib/Integration/SMSClient.cs create mode 100755 MarketData/MarketDataLib/Integration/Socket.cs create mode 100755 MarketData/MarketDataLib/Integration/UserAgent.cs create mode 100755 MarketData/MarketDataLib/MDTrace.cs create mode 100755 MarketData/MarketDataLib/MarketDataLib.csproj create mode 100755 MarketData/MarketDataLib/MarketDataModel/AnalystPriceTarget.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/AnalystRatings.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/BalanceSheet.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/BetaModel.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/BollingerBand.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/CashTransactions.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/CashflowStatement.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Cashflows.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/CompanyProfile.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Constants.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/CurrencyConversionElement.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/DCFValuation.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/DMADeviation.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/DMAPrice.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Decay.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/DividendHistory.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/DividendLoad.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/DividendPayment.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/ETFHoldings.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/EarningsAnnouncement.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/EarningsAnnouncementModel.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/EconomicIndicators.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/ExponentialDecay.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/FeedStatistics.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Fundamentals.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossCompoundModel.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossCompoundModelCollection.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossItem.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossSummaryItem.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossSummaryItemCollection.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/SortGainLossCompoundModelYearDescendingOrder.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/SortTotalGainLossYearDescendingOrder.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/SortYearDescendingOrder.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/TotalGainLossCollection.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/GainLoss/TotalGainLossItem.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Headlines.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/IncomeStatement.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/InsiderTransaction.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/KeyValue.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Lexical.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/MACD.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/MACDSetup.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/MobileDataModels.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/ModelPerformance.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/ModelTrade.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/MovingAverage.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/MovingDeviation.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/OptionsModel.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/ParityElement.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Portfolio.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/PortfolioTrade.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/PortfolioTrades.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/PositionWithDescription.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/PremarketElement.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/PriceIndex.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Prices.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Prices.cs.bak create mode 100755 MarketData/MarketDataLib/MarketDataModel/PricesByDate.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/RSICollection.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/ResistanceSupport.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/ReturnItem.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/SECFiling.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Securities.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Sentiment.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/SharpeRatioModel.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Signal.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/SignalHolder.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Splits.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Statistic.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/StickerPrice.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Stochastic.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/StopLimit.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/SwingTrade.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/TimeSeriesElement.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/TradeResult.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/User/User.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/Valuations.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/WatchListItem.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/WordDictionary.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/YieldCurve.cs create mode 100755 MarketData/MarketDataLib/MarketDataModel/ZacksRank.cs create mode 100755 MarketData/MarketDataLib/Numerics/BetaGenerator.cs create mode 100755 MarketData/MarketDataLib/Numerics/Bin.cs create mode 100755 MarketData/MarketDataLib/Numerics/BlackScholes.cs create mode 100755 MarketData/MarketDataLib/Numerics/KStest.cs create mode 100755 MarketData/MarketDataLib/Numerics/LeastSquares.cs create mode 100755 MarketData/MarketDataLib/Numerics/Numerics.cs create mode 100755 MarketData/MarketDataLib/Numerics/SharpeRatioGenerator.cs create mode 100755 MarketData/MarketDataLib/Numerics/Spline.cs create mode 100755 MarketData/MarketDataLib/Utility/CSVLineHelper.cs create mode 100755 MarketData/MarketDataLib/Utility/DateGenerator.cs create mode 100755 MarketData/MarketDataLib/Utility/DateRange.cs create mode 100755 MarketData/MarketDataLib/Utility/ExtensionMethods.cs create mode 100755 MarketData/MarketDataLib/Utility/FeedParser.cs create mode 100755 MarketData/MarketDataLib/Utility/HolidayCache.cs create mode 100755 MarketData/MarketDataLib/Utility/NVP.cs create mode 100755 MarketData/MarketDataLib/Utility/Profiler.cs create mode 100755 MarketData/MarketDataLib/Utility/SQLUtils.cs create mode 100755 MarketData/MarketDataLib/Utility/Sections.cs create mode 100755 MarketData/MarketDataLib/Utility/UpdateManager.cs create mode 100755 MarketData/MarketDataLib/Utility/Utility.cs create mode 100755 MarketData/MarketDataLib/ValueAtRisk/BinItem.cs create mode 100755 MarketData/MarketDataLib/ValueAtRisk/BinManager.cs create mode 100755 MarketData/MarketDataLib/ValueAtRisk/HVaR.cs create mode 100755 MarketData/MarketDataLib/ValueAtRisk/PortfolioHoldings.cs create mode 100755 MarketData/MarketDataLib/ValueAtRisk/VaRResult.cs create mode 100755 MarketData/MarketDataLib/ValueAtRisk/WeightedReturnsWithContributions.cs create mode 100755 MarketData/assemblies/HtmlAgilityPack.dll create mode 100755 MarketData/assemblies/Microsoft.Office.Interop.Excel.dll create mode 100755 MarketData/assemblies/Newtonsoft.Json/Newtonsoft.Json.dll create mode 100755 MarketData/assemblies/Newtonsoft.Json/Newtonsoft.Json.pdb create mode 100755 MarketData/assemblies/Newtonsoft.Json/Newtonsoft.Json.xml create mode 100755 MarketData/assemblies/Readme.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4d034c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,153 @@ +Axiom/Axiom.Core/bin/Debug/net8.0/Axiom.Core.deps.json +Axiom/Axiom.Core/bin/Debug/net8.0/Axiom.Core.dll +Axiom/Axiom.Core/bin/Debug/net8.0/Axiom.Core.pdb +Axiom/Axiom.Core/bin/Debug/net8.0/log4net.dll +Axiom/Axiom.Core/bin/Debug/net8.0/log4net.xml +Axiom/Axiom.Core/obj/Axiom.Core.csproj.nuget.dgspec.json +Axiom/Axiom.Core/obj/Axiom.Core.csproj.nuget.g.props +Axiom/Axiom.Core/obj/Axiom.Core.csproj.nuget.g.targets +Axiom/Axiom.Core/obj/project.assets.json +Axiom/Axiom.Core/obj/project.nuget.cache +Axiom/Axiom.Core/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.AssemblyInfo.cs +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.AssemblyInfoInputs.cache +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.assets.cache +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.csproj.AssemblyReference.cache +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.csproj.CoreCompileInputs.cache +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.csproj.FileListAbsolute.txt +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.csproj.Up2Date +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.dll +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.GeneratedMSBuildEditorConfig.editorconfig +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.GlobalUsings.g.cs +Axiom/Axiom.Core/obj/Debug/net8.0/Axiom.Core.pdb +Axiom/Axiom.Core/obj/Debug/net8.0/ref/Axiom.Core.dll +Axiom/Axiom.Core/obj/Debug/net8.0/refint/Axiom.Core.dll +Axiom/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +Axiom/obj/Debug/net8.0/Axiom.AssemblyInfo.cs +Axiom/obj/Debug/net8.0/Axiom.AssemblyInfoInputs.cache +Axiom/obj/Debug/net8.0/Axiom.assets.cache +Axiom/obj/Debug/net8.0/Axiom.GeneratedMSBuildEditorConfig.editorconfig +Axiom/obj/Debug/net8.0/Axiom.GlobalUsings.g.cs +Axiom/obj/Axiom.csproj.nuget.dgspec.json +Axiom/obj/Axiom.csproj.nuget.g.props +Axiom/obj/Axiom.csproj.nuget.g.targets +Axiom/obj/project.assets.json +Axiom/obj/project.nuget.cache +MarketData/MarketData/bin/Debug/net8.0/appsettings.json +MarketData/MarketData/bin/Debug/net8.0/Axiom.Core.dll +MarketData/MarketData/bin/Debug/net8.0/Axiom.Core.pdb +MarketData/MarketData/bin/Debug/net8.0/BouncyCastle.Cryptography.dll +MarketData/MarketData/bin/Debug/net8.0/Google.Protobuf.dll +MarketData/MarketData/bin/Debug/net8.0/HtmlAgilityPack.dll +MarketData/MarketData/bin/Debug/net8.0/K4os.Compression.LZ4.dll +MarketData/MarketData/bin/Debug/net8.0/K4os.Compression.LZ4.Streams.dll +MarketData/MarketData/bin/Debug/net8.0/K4os.Hash.xxHash.dll +MarketData/MarketData/bin/Debug/net8.0/log4net.dll +MarketData/MarketData/bin/Debug/net8.0/log4net.xml +MarketData/MarketData/bin/Debug/net8.0/marketdata.log +MarketData/MarketData/bin/Debug/net8.0/MarketDataLib.dll +MarketData/MarketData/bin/Debug/net8.0/MarketDataLib.pdb +MarketData/MarketData/bin/Debug/net8.0/Microsoft.AspNetCore.Hosting.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.AspNetCore.Hosting.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.AspNetCore.Hosting.Server.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.AspNetCore.Http.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.AspNetCore.Http.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.AspNetCore.Http.Extensions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.AspNetCore.Http.Features.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.AspNetCore.WebUtilities.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Configuration.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Configuration.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Configuration.EnvironmentVariables.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Configuration.FileExtensions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Configuration.Json.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.DependencyInjection.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Diagnostics.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.FileProviders.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.FileProviders.Physical.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.FileSystemGlobbing.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Hosting.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Logging.Abstractions.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Logging.Debug.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Logging.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.ObjectPool.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Options.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Extensions.Primitives.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Net.Http.Headers.dll +MarketData/MarketData/bin/Debug/net8.0/Microsoft.Win32.SystemEvents.dll +MarketData/MarketData/bin/Debug/net8.0/mk +MarketData/MarketData/bin/Debug/net8.0/mk.deps.json +MarketData/MarketData/bin/Debug/net8.0/mk.dll +MarketData/MarketData/bin/Debug/net8.0/mk.pdb +MarketData/MarketData/bin/Debug/net8.0/mk.runtimeconfig.json +MarketData/MarketData/bin/Debug/net8.0/MySql.Data.dll +MarketData/MarketData/bin/Debug/net8.0/Newtonsoft.Json.dll +MarketData/MarketData/bin/Debug/net8.0/System.Configuration.ConfigurationManager.dll +MarketData/MarketData/bin/Debug/net8.0/System.Diagnostics.EventLog.dll +MarketData/MarketData/bin/Debug/net8.0/System.Drawing.Common.dll +MarketData/MarketData/bin/Debug/net8.0/System.IO.Pipelines.dll +MarketData/MarketData/bin/Debug/net8.0/System.Private.Windows.Core.dll +MarketData/MarketData/bin/Debug/net8.0/System.Security.Cryptography.ProtectedData.dll +MarketData/MarketData/bin/Debug/net8.0/System.Security.Permissions.dll +MarketData/MarketData/bin/Debug/net8.0/System.Text.Encodings.Web.dll +MarketData/MarketData/bin/Debug/net8.0/System.Text.Json.dll +MarketData/MarketData/bin/Debug/net8.0/System.Windows.Extensions.dll +MarketData/MarketData/bin/Debug/net8.0/ZstdSharp.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win/lib/net8.0/Microsoft.Win32.SystemEvents.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.Messages.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win/lib/net8.0/System.Windows.Extensions.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win-x64/native/comerr64.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win-x64/native/gssapi64.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win-x64/native/k5sprt64.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win-x64/native/krb5_64.dll +MarketData/MarketData/bin/Debug/net8.0/runtimes/win-x64/native/krbcc64.dll +MarketData/MarketDataLib/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDa.1BB7F803.Up2Date +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.AssemblyInfo.cs +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.AssemblyInfoInputs.cache +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.assets.cache +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.csproj.AssemblyReference.cache +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.csproj.CoreCompileInputs.cache +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.csproj.FileListAbsolute.txt +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.dll +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.GeneratedMSBuildEditorConfig.editorconfig +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.GlobalUsings.g.cs +MarketData/MarketDataLib/obj/Debug/net8.0/MarketDataLib.pdb +MarketData/MarketDataLib/obj/Debug/net8.0/ref/MarketDataLib.dll +MarketData/MarketDataLib/obj/Debug/net8.0/refint/MarketDataLib.dll +MarketData/MarketData/obj/MarketData.csproj.nuget.dgspec.json +MarketData/MarketData/obj/MarketData.csproj.nuget.g.props +MarketData/MarketData/obj/MarketData.csproj.nuget.g.targets +MarketData/MarketData/obj/project.assets.json +MarketData/MarketData/obj/project.nuget.cache +MarketData/MarketData/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +MarketData/MarketData/obj/Debug/net8.0/apphost +MarketData/MarketData/obj/Debug/net8.0/MarketData.AssemblyInfo.cs +MarketData/MarketData/obj/Debug/net8.0/MarketData.AssemblyInfoInputs.cache +MarketData/MarketData/obj/Debug/net8.0/MarketData.assets.cache +MarketData/MarketData/obj/Debug/net8.0/MarketData.csproj.AssemblyReference.cache +MarketData/MarketData/obj/Debug/net8.0/MarketData.csproj.CoreCompileInputs.cache +MarketData/MarketData/obj/Debug/net8.0/MarketData.csproj.FileListAbsolute.txt +MarketData/MarketData/obj/Debug/net8.0/MarketData.csproj.Up2Date +MarketData/MarketData/obj/Debug/net8.0/MarketData.GeneratedMSBuildEditorConfig.editorconfig +MarketData/MarketData/obj/Debug/net8.0/MarketData.genruntimeconfig.cache +MarketData/MarketData/obj/Debug/net8.0/MarketData.GlobalUsings.g.cs +MarketData/MarketData/obj/Debug/net8.0/mk.dll +MarketData/MarketData/obj/Debug/net8.0/mk.pdb +MarketData/MarketData/obj/Debug/net8.0/ref/mk.dll +MarketData/MarketData/obj/Debug/net8.0/refint/mk.dll +MarketData/MarketDataLib/bin/Debug/net8.0/Axiom.Core.dll +MarketData/MarketDataLib/bin/Debug/net8.0/Axiom.Core.pdb +MarketData/MarketDataLib/bin/Debug/net8.0/HtmlAgilityPack.dll +MarketData/MarketDataLib/bin/Debug/net8.0/log4net.dll +MarketData/MarketDataLib/bin/Debug/net8.0/log4net.xml +MarketData/MarketDataLib/bin/Debug/net8.0/MarketDataLib.deps.json +MarketData/MarketDataLib/bin/Debug/net8.0/MarketDataLib.dll +MarketData/MarketDataLib/bin/Debug/net8.0/MarketDataLib.pdb +MarketData/MarketDataLib/obj/MarketDataLib.csproj.nuget.dgspec.json +MarketData/MarketDataLib/obj/MarketDataLib.csproj.nuget.g.props +MarketData/MarketDataLib/obj/MarketDataLib.csproj.nuget.g.targets +MarketData/MarketDataLib/obj/project.assets.json +MarketData/MarketDataLib/obj/project.nuget.cache diff --git a/MarketData/.vscode/launch.json b/MarketData/.vscode/launch.json new file mode 100755 index 0000000..db3f1ef --- /dev/null +++ b/MarketData/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // 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}/MarketData/bin/Debug/net8.0/mk.dll", + "args": [], + "cwd": "${workspaceFolder}/MarketData", + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/MarketData/.vscode/tasks.json b/MarketData/.vscode/tasks.json new file mode 100755 index 0000000..dff9de6 --- /dev/null +++ b/MarketData/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/MarketData.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/MarketData.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/MarketData.sln" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/MarketData/MarketData.sln b/MarketData/MarketData.sln new file mode 100755 index 0000000..41a7b53 --- /dev/null +++ b/MarketData/MarketData.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarketDataLib", "MarketDataLib\MarketDataLib.csproj", "{19942998-5623-4D8E-B66A-B09215DB1F9A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarketData", "MarketData\MarketData.csproj", "{B7528822-FC40-40EE-8694-48E217FAF1A5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {19942998-5623-4D8E-B66A-B09215DB1F9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19942998-5623-4D8E-B66A-B09215DB1F9A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19942998-5623-4D8E-B66A-B09215DB1F9A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19942998-5623-4D8E-B66A-B09215DB1F9A}.Release|Any CPU.Build.0 = Release|Any CPU + {B7528822-FC40-40EE-8694-48E217FAF1A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7528822-FC40-40EE-8694-48E217FAF1A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7528822-FC40-40EE-8694-48E217FAF1A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7528822-FC40-40EE-8694-48E217FAF1A5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/MarketData/MarketData/.vscode/launch.json b/MarketData/MarketData/.vscode/launch.json new file mode 100644 index 0000000..a916fde --- /dev/null +++ b/MarketData/MarketData/.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/MarketData.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/MarketData/MarketData/.vscode/tasks.json b/MarketData/MarketData/.vscode/tasks.json new file mode 100644 index 0000000..12b42e9 --- /dev/null +++ b/MarketData/MarketData/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/MarketData.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/MarketData.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/MarketData.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/MarketData/MarketData/CommandArgs.cs b/MarketData/MarketData/CommandArgs.cs new file mode 100644 index 0000000..1e0113e --- /dev/null +++ b/MarketData/MarketData/CommandArgs.cs @@ -0,0 +1,77 @@ +using System.Text; +using MarketData.Utils; + +namespace MarketData +{ + public class CommandArgs : Dictionary + { +// While the commands are converted to uppercase care must be taken to preserve the case of the arguments. + public CommandArgs(String[] args) + { + for(int index=1;index2) + { + StringBuilder sb=new StringBuilder(); + for(int subIndex=1;subIndex(String name) + { + T result=default(T); + try {result = (T)Convert.ChangeType(this[name].Value, typeof(T));} + catch {result = default(T);} + return result; + } + public T Coalesce(String name,T coalesce) + { + T result=default(T); + try + { + if(!Contains(name))result=coalesce; + else result = (T)Convert.ChangeType(this[name].Value, typeof(T)); + } + catch {result = default(T);} + return result; + } + public T Coalesce(String name) + { + T result=default(T); + try {result = (T)Convert.ChangeType(this[name].Value, typeof(T));} + catch {result = default(T);} + return result; + } + } +} \ No newline at end of file diff --git a/MarketData/MarketData/Executor.cs b/MarketData/MarketData/Executor.cs new file mode 100755 index 0000000..502a1d8 --- /dev/null +++ b/MarketData/MarketData/Executor.cs @@ -0,0 +1,26 @@ +using MarketData.Interface; +using Microsoft.Extensions.Configuration; + +namespace MarketData +{ + public class Executor + { + private readonly IConfiguration _configuration; + private readonly IMainService _mainService; + private readonly IArguments _arguments; + + public Executor(IMainService mainService,IConfigurationRoot configuration,IArguments arguments) + { + _configuration = configuration ?? throw new ArgumentException(nameof(configuration)); + _mainService = mainService ?? throw new ArgumentException(nameof(mainService)); + _arguments = arguments ?? throw new ArgumentException(nameof(arguments)); + } + + /// + /// This is essentially the starting point where we bootstrap the legacy entry point + /// + public void Execute() + { _mainService.RunService(_arguments.GetArguments(), _configuration); + } + } +} diff --git a/MarketData/MarketData/Interface/IArguments.cs b/MarketData/MarketData/Interface/IArguments.cs new file mode 100755 index 0000000..4c29275 --- /dev/null +++ b/MarketData/MarketData/Interface/IArguments.cs @@ -0,0 +1,7 @@ +namespace MarketData.Interface +{ + public interface IArguments + { + public String[] GetArguments(); + } +} \ No newline at end of file diff --git a/MarketData/MarketData/Interface/IMainService.cs b/MarketData/MarketData/Interface/IMainService.cs new file mode 100755 index 0000000..fb39ba1 --- /dev/null +++ b/MarketData/MarketData/Interface/IMainService.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.Configuration; + +namespace MarketData.Interface +{ + public interface IMainService + { + public void RunService(String[] args,IConfiguration configuration); + } +} \ No newline at end of file diff --git a/MarketData/MarketData/MarketData.csproj b/MarketData/MarketData/MarketData.csproj new file mode 100755 index 0000000..cb971b7 --- /dev/null +++ b/MarketData/MarketData/MarketData.csproj @@ -0,0 +1,24 @@ + + + + Exe + net8.0 + mk + enable + disable + CA1416;CS8769;CS0108;CS8602;CS8601;CS8620;CS8618;CS8603;CS8767;CS8625;CS8604;CS8600;CS8604 + + + + + + + + + + + + PreserveNewest + + + diff --git a/MarketData/MarketData/Program.cs b/MarketData/MarketData/Program.cs new file mode 100755 index 0000000..253cbfc --- /dev/null +++ b/MarketData/MarketData/Program.cs @@ -0,0 +1,25 @@ +using MarketData.Interface; +using MarketData.Services; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace MarketData +{ + class Program + { + static void Main(string[] args) + { + IConfigurationBuilder builder = new ConfigurationBuilder() + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); + IConfigurationRoot configurationRoot = builder.Build(); + Arguments arguments = new Arguments(args); + IServiceCollection services = new ServiceCollection(); + services.AddSingleton(arguments); + services.AddSingleton(configurationRoot); + services.AddSingleton(); + services.AddSingleton(); + services.BuildServiceProvider().GetService().Execute(); + } + + } +} diff --git a/MarketData/MarketData/Services/Arguments.cs b/MarketData/MarketData/Services/Arguments.cs new file mode 100755 index 0000000..ebba462 --- /dev/null +++ b/MarketData/MarketData/Services/Arguments.cs @@ -0,0 +1,19 @@ +using MarketData.Interface; + +namespace MarketData.Services +{ + public class Arguments : IArguments + { + private readonly String[] _args; + + public Arguments(String[] args) + { + _args = args ?? throw new ArgumentNullException(nameof(args)); + } + + public String[] GetArguments() + { + return _args; + } + } +} \ No newline at end of file diff --git a/MarketData/MarketData/Services/MainService.cs b/MarketData/MarketData/Services/MainService.cs new file mode 100755 index 0000000..b34cce2 --- /dev/null +++ b/MarketData/MarketData/Services/MainService.cs @@ -0,0 +1,593 @@ +using System.Diagnostics; +using MarketData.DataAccess; +using MarketData.Interface; +using MarketData.Utils; +using MarketData.Configuration; +using Microsoft.Extensions.Configuration; +using MarketData.MarketDataModel; +using MarketData.Helper; +using MarketData.Integration; +using MarketData.Cache; + +namespace MarketData.Services +{ + public class MainService : IMainService + { + public static void DisplayUsage() + { + MDTrace.WriteLine(LogLevel.DEBUG,$"USAGE"); + MDTrace.WriteLine(LogLevel.DEBUG,$"LOADHEADLINESWATCHLIST"); + MDTrace.WriteLine(LogLevel.DEBUG,$"LOADPREMARKETDATA"); + MDTrace.WriteLine(LogLevel.DEBUG,"UPDATEDAILY2 /DATE: - updates prices, yields, and ratings"); + } + +// ********************************************************************************************************************************************** +// ************************************************* U P D A T E D A I L Y 2 M E T H O D S *************************************************** +// ********************************************************************************************************************************************** + + public static void UpdateDaily2(DateTime startDate) + { + DateGenerator dateGenerator=new DateGenerator(); + IConfiguration configuration = GlobalConfig.Instance.Configuration; + String smsSMTPAddress = configuration["sms_smtpaddress"]; + String smsUserName = configuration["sms_smsusername"]; + String smsPassword = configuration["sms_smspassword"]; + String[] smsRecipients = configuration["sms_smsrecipients"].Split(','); + DateTime currentDate=DateTime.Now.Date; + +// Sanity check. If the given date is not today then ask the user to confirm + if (currentDate != startDate.Date) + { + Console.WriteLine(String.Format("Run date is not today, please confirm Y/N:{0}?",startDate.ToShortDateString())); + String result=Console.ReadLine(); + if(null==result||!(result.ToUpper().Equals("Y")||result.ToUpper().Equals("YES")))return; + } + if(!dateGenerator.IsMarketOpen(currentDate)) + { + String description=""; + if(HolidayDA.IsMarketHoliday(currentDate)) description=HolidayDA.GetHolidayDescription(currentDate); + else description=Utility.DayOfWeekToString(currentDate.DayOfWeek); + Console.WriteLine(String.Format("Market is closed today ({0}), please confirm Y/N:{1}?",description,startDate.ToShortDateString())); + String result=Console.ReadLine(); + if(null==result||!(result.ToUpper().Equals("Y")||result.ToUpper().Equals("YES"))) return; + } + if(!NetworkStatus.IsInternetConnected()) + { + Console.WriteLine(String.Format("The internet is not connected, continue anyway Y/N:?")); + String result=Console.ReadLine(); + if(null==result||!(result.ToUpper().Equals("Y")||result.ToUpper().Equals("YES")))return; + } + Utility.RemoveLogFiles(); + int STAGE_1=0,STAGE_2=1,STAGE_3=2,STAGE_4=3,STAGE_5=4,STAGE_6=5,STAGE_7=6,STAGE_8=7,STAGE_9=8,STAGE_10=9,STAGE_11=10,STAGE_12=11,STAGE_FINAL=12; + DeletePriceWatchList("valuations",startDate.ToShortDateString()); + DeletePriceWatchList("Momentum",startDate.ToShortDateString()); + + ManualResetEvent[] resetEvents = new ManualResetEvent[STAGE_FINAL+1]; + for(int index=0;index manualResetEventsList = resetEvents.ToList(); + + manualResetEventsList.Remove(resetEvents[STAGE_FINAL]); // Remove THIS thread from the events we will wait on..no sense waiting on ourselves + ManualResetEvent[] allResetEventsSans12 = manualResetEventsList.ToArray(); + bool running = true; + bool connectionIssue = false; + + SMSClient.SendSMSEmail("UPDATEDAILY2 Network monitor activated", smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword); + while (running) + { + if (!NetworkStatus.IsInternetConnected()) + { + connectionIssue = true; + SMSClient.SendSMSEmail("UPDATEDAILY2 Network is not connected", smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword); + } + else if (connectionIssue) + { + connectionIssue = false; + SMSClient.SendSMSEmail("UPDATEDAILY2 There was a network connection issue.", smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword); + } + if (WaitHandle.WaitAll(allResetEventsSans12, 30000)) running = false; // if all worker threads are done then wrap it up here. + } + SMSClient.SendSMSEmail("UPDATEDAILY2 Network monitor ended", smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword); + resetEvents[STAGE_FINAL].Set(); + }); +// Here is the start of the real workers + ThreadPool.QueueUserWorkItem(delegate + { + UpdatePricesBigCharts(startDate); // bigcharts.marketwatch.com + UpdatePricesYahooSweep(startDate); // The sweep variation of the method is intended to be used after the BigCharts update because the sweep will take pricing_source into consideration when fetching prices. + resetEvents[STAGE_1].Set(); + SMSClient.SendSMSEmail("UPDATEDAILY2 UPDATEPRICESBIGCHARTS/YAHOO done.", smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword); + }); + resetEvents[STAGE_1].WaitOne(); // wait for pricing to finish + ThreadPool.QueueUserWorkItem(delegate + { + LoadConsumerPriceIndex(); // Load consumer price index data from Bureau of Labor Statistics + UpdateCompanyProfiles(); // financials.morningstar.com and finance.yahoo.com + LoadGDPPerCapita(); // api.worldbank.org + resetEvents[STAGE_2].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + UpdateYieldCurve(); // www.treasury.gov + resetEvents[STAGE_3].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + UpdateLatestAnalystRatings(true); // WWW.BRIEFING.COM + UpdateMissingAnalystRatings(); // MARKET BEAT + resetEvents[STAGE_4].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + UpdateSplits(); // eoddata.com + ProcessAllSplits(); // non-network operation + resetEvents[STAGE_5].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + LoadInsiderTransactions(); + resetEvents[STAGE_6].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + UpdateEarningsAnnouncements(); // www.zacks.com + LoadZacksRank(); // www.zacks.com + resetEvents[STAGE_7].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + GetSECFilingsWatchList("Valuations");// www.sec.gov + resetEvents[STAGE_8].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + UpdateAnalystPriceTarget(); // MarketBeat + GetETFHoldings(); // finance.yahoo.com + resetEvents[STAGE_9].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + UpdateAllMissingCIK(); // /www.sec.gov + resetEvents[STAGE_10].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + UpdateDividendHistory(); // www.nasdaq.com DIVIDEND HISTORY IS BROKEN.... WORKING ON THIS ONE. + resetEvents[STAGE_11].Set(); + }); + + ThreadPool.QueueUserWorkItem(delegate + { + resetEvents[STAGE_12].Set(); + }); + WaitHandle.WaitAll(resetEvents); + } + + public static void UpdatePricesBigCharts(DateTime startDate) + { + PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper(); + pricingMarketDataHelper.UpdatePricesBigCharts(startDate); + } + + public static void UpdatePricesYahooSweep(DateTime startDate) + { + PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper(); + pricingMarketDataHelper.UpdatePricesYahooSweep(startDate); + } + + public static void DeletePriceWatchList(String watchListName,String strDate) + { + try + { + List symbols = WatchListDA.GetWatchList(watchListName); + if(null==symbols||0==symbols.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("There are no symbols for watchlist {0}",watchListName)); + return; + } + foreach (String symbol in symbols) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Delete price {0} on {1}, watchlist {2}",symbol,strDate,watchListName)); + DeletePriceSymbol(symbol, strDate); + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + } + } + + public static void DeletePriceSymbol(String symbol, String strDate) + { + try + { + DateTime pricingDate = DateTime.Parse(strDate); + MDTrace.WriteLine(LogLevel.DEBUG,"Delete price '" + symbol + "' for " + Utility.DateTimeToStringMMSDDSYYYY(pricingDate)); + if(PricingDA.DeletePrice(symbol, pricingDate)) MDTrace.WriteLine(LogLevel.DEBUG,"Ok"); + else MDTrace.WriteLine(LogLevel.DEBUG,"Failed."); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + } + } + + public static void LoadConsumerPriceIndex() + { + try + { + MDTrace.WriteLine("[LoadConsumerPriceIndex] started."); + PriceIndices priceIndices=MarketDataHelper.GetConsumerPriceIndices(); + if(null==priceIndices) + { + MDTrace.WriteLine(LogLevel.DEBUG,"[LoadConsumerPriceIndex] Failed, check log file for isssues."); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadConsumerPriceIndex] Got:{0} records from source feed.",priceIndices.Count())); + MDTrace.WriteLine(LogLevel.DEBUG,"[LoadConsumerPriceIndex] Saving..."); + ConsumerPriceIndexDA.InsertUpdatePriceIndices(priceIndices); + MDTrace.WriteLine(LogLevel.DEBUG,"[LoadConsumerPriceIndex] Save complete..."); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadConsumerPriceIndex] Exception:{0}",exception.ToString())); + } + } + + public static void UpdateCompanyProfiles() + { + try + { + CompanyProfileMarketDataHelper companyProfileMarketDataHelper=new CompanyProfileMarketDataHelper(); + companyProfileMarketDataHelper.UpdateCompanyProfiles(); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + } + } + + public static void LoadGDPPerCapita() + { + try + { + MDTrace.WriteLine("[LoadGSPPerCapita]"); + EconomicIndicators economicIndicators=MarketDataHelper.GetGDPPerCapita(); + if(null==economicIndicators||0==economicIndicators.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"[LoadGDPPerCapita] No data, see log file for potential issues."); + return; + } + List distinctCountry=(from EconomicIndicator economicIndicator in economicIndicators select economicIndicator.CountryCode).Distinct().ToList(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadGDPPerCapita] Downloaded {0} countries.",distinctCountry.Count)); + MDTrace.WriteLine(LogLevel.DEBUG,"[LoadGDPPerCapita] Saving..."); + if(EconomicIndicatorDA.InsertUpdateEconomicIndicators(economicIndicators)) + { + MDTrace.WriteLine(LogLevel.DEBUG,"[LoadGDPPerCapita] Success."); + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,"[LoadGDPPerCapita] Failed, check log file for isssues."); + } + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadGDPPerCapita] Exception:{0}",exception.ToString())); + } + } + + public static void UpdateYieldCurve() // maintains current year of yield curve data + { + int year = DateTime.Now.Year; + MDTrace.WriteLine(LogLevel.DEBUG,"Retrieving yield curve for year "+year); + YieldCurve yieldCurve=MarketDataHelper.GetYieldCurve(year); + if (null == yieldCurve) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Failed to get YieldCurve for {0}", year)); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,"got "+yieldCurve.Count+" points for "+year); + YieldCurveDA.InsertOrUpdate(yieldCurve); + } + + public static void UpdateLatestAnalystRatings(Boolean createSecurityMaster = true) + { + try + { + DateGenerator dateGenerator = new DateGenerator(); + MDTrace.WriteLine(LogLevel.DEBUG, "[UPDATELATESTANALYSTRATINGS]"); + AnalystRatings analystRatings = MarketDataHelper.GetLatestAnalystRatings(); + List symbols = PricingDA.GetSymbolsNotIn(analystRatings.Symbols); + foreach (String symbol in symbols) + { + if (false == createSecurityMaster) + { + MDTrace.WriteLine(LogLevel.DEBUG, "Removing " + symbol + ", missing from security master."); + AnalystRating analystRating = (from item in analystRatings where item.Symbol.Equals(symbol) select item).FirstOrDefault(); + if (null != analystRating) MDTrace.WriteLine(LogLevel.DEBUG, analystRating.ToString()); + } + } + MDTrace.WriteLine(LogLevel.DEBUG, "*************************"); + if (false == createSecurityMaster) analystRatings.Remove(symbols); + foreach (AnalystRating analystRating in analystRatings) + { + String symbolNotFound = (from symbol in symbols where symbol.Equals(analystRating.Symbol) select symbol).FirstOrDefault(); + if (null != symbolNotFound && createSecurityMaster) + { + MDTrace.WriteLine(LogLevel.DEBUG, "Adding security '" + analystRating.Symbol + "' '" + analystRating.CompanyName + "'"); + if (!PricingDA.AddSecurity(analystRating.Symbol, analystRating.CompanyName)) MDTrace.WriteLine(LogLevel.DEBUG, "Failed to add '" + symbols + "'"); + else + { + MDTrace.WriteLine(LogLevel.DEBUG, "Added '" + analystRating.Symbol + "'"); + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Loading prices for {0}", analystRating.Symbol)); + DateTime pricingDate = dateGenerator.FindPrevBusinessDay(analystRating.Date); + Prices prices = MarketDataHelper.GetDailyPrices(analystRating.Symbol, Constants.MIN_PRICING_DATE, pricingDate); // use the Yahoo JSON bulk feed + if (null != prices) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Inserting {0} prices for {1}", prices.Count, analystRating.Symbol)); + PricingDA.InsertPrices(prices); + MDTrace.WriteLine(LogLevel.DEBUG, "Done."); + } + } + } + MDTrace.WriteLine(LogLevel.DEBUG, analystRating.ToString()); + } + AnalystRatingsDA.InsertAnalystRatings(analystRatings); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + } + } + + public static void UpdateMissingAnalystRatings() + { + try + { + DateGenerator dateGenerator = new DateGenerator(); + List symbols = PricingDA.GetSymbols(); + DateTime maxDate=AnalystRatingsDA.GetMaxDateNoZacks(); + foreach (String symbol in symbols) + { + AnalystRatings analystRatings = MarketDataHelper.GetAnalystRatingsMarketBeat(symbol); + if (null == analystRatings || 0 == analystRatings.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("No analyst ratings for {0}", symbol)); + continue; + } + analystRatings = new AnalystRatings((from AnalystRating analystRating in analystRatings where analystRating.Date >= maxDate.Date select analystRating).ToList()); + AnalystRatings duplicateList = new AnalystRatings(); + foreach (AnalystRating analystRating in analystRatings) + { + if (AnalystRatingsDA.ContainsAnalystRating(analystRating)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Already have analyst rating for {0} on {1} from brokerage firm {2}", analystRating.Symbol, analystRating.Date.ToShortDateString(), analystRating.BrokerageFirm)); + duplicateList.Add(analystRating); + continue; + } + } + analystRatings = new AnalystRatings(analystRatings.Except(duplicateList).ToList()); + foreach (AnalystRating analystRating in analystRatings) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Inserting Analyst Rating for {0} on {1} from brokerage firm {2}", analystRating.Symbol, analystRating.Date.ToShortDateString(), analystRating.BrokerageFirm)); + } + AnalystRatingsDA.InsertAnalystRatings(analystRatings); + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + } + } + + public static void UpdateSplits() + { + MDTrace.WriteLine("Updating splits."); + Splits splits=MarketDataHelper.GetSplits(); + if(null==splits||0==splits.Count)return; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Got {0} split records.",splits.Count)); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Writing to database.",splits.Count)); + SplitsDA.InsertSplits(splits); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Done.")); + } + + public static void ProcessAllSplits() + { + MDTrace.WriteLine("Processing all splits"); + Splits splits=SplitsDA.GetUnappliedSplits(); + if(null==splits||0==splits.Count)return; + SplitHelper.ProcessSplits(splits); + } + + public static void LoadInsiderTransactions() + { + List symbols = PricingDA.GetSymbols(); + InsiderTransactionMarketDataHelper insiderTransactionMarketDataHelper = new InsiderTransactionMarketDataHelper(); + insiderTransactionMarketDataHelper.LoadInsiderTransactions(symbols); + } + + public static void UpdateEarningsAnnouncements(String symbol=null) + { + MDTrace.WriteLine(LogLevel.DEBUG,"[UPDATEEARNINGSANNOUNCEMENTS]"); + EarningsAnnouncementsMarketDataHelper earningsAnnouncementsMarketDataHelper=new EarningsAnnouncementsMarketDataHelper(); + earningsAnnouncementsMarketDataHelper.UpdateEarningsAnnouncements(symbol); + MDTrace.WriteLine(LogLevel.DEBUG,"[UPDATEEARNINGSANNOUNCEMENTS] Done"); + } + + public static void LoadZacksRank() + { + ZacksRankMarketDataHelper zacksRankMarketDataHelper=new ZacksRankMarketDataHelper(); + zacksRankMarketDataHelper.LoadZacksRank(); + } + + public static void GetSECFilingsWatchList(String watchListName) + { + List symbols = WatchListDA.GetWatchList(watchListName); + SECFilingMarketDataHelper secFilingMarketDataHelper=new SECFilingMarketDataHelper(); + secFilingMarketDataHelper.UpdateSECFilings(symbols); + } + + public static void UpdateAnalystPriceTarget() + { + MDTrace.WriteLine(LogLevel.DEBUG,"[UPDATEANALYSTPRICETARGET]"); + AnalystPriceTargetMarketDataHelper analystPriceTargetMarketDataHelper=new AnalystPriceTargetMarketDataHelper(); + analystPriceTargetMarketDataHelper.LoadAnalystPriceTarget(); + MDTrace.WriteLine(LogLevel.DEBUG,"[UPDATEANALYSTPRICETARGET] Done"); + } + + public static void GetETFHoldings() + { + ETFHoldingsMarketDataHelper etfHoldingsMarketDataHelper=new ETFHoldingsMarketDataHelper(); + etfHoldingsMarketDataHelper.LoadETFHoldings(); + } + + public static void UpdateAllMissingCIK() + { + CIKMarketDataHelper cikMarketDataHelper=new CIKMarketDataHelper(); + cikMarketDataHelper.UpdateAllMissingCIK(); + } + + public static void UpdateDividendHistory() + { + DividendHistoryMarketDataHelper dividendHistoryMarketDataHelper=new DividendHistoryMarketDataHelper(); + dividendHistoryMarketDataHelper.UpdateDividendHistory(); + } + +// ********************************************************************************************************************************************** +// ******************************************* E N D U P D A T E D A I L Y 2 M E T H O D S *************************************************** +// ********************************************************************************************************************************************** + +// ********************************************************************************************************************************************** + + public static void LoadHeadlinesWatchList(String watchList) + { + if(!CheckRunCriteria())return; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("LoadHeadlinesWatchList {0}",watchList)); + List symbols = WatchListDA.GetWatchList(watchList); + HeadlinesMarketDataHelper headlinesMarketDataHelper= new HeadlinesMarketDataHelper(); + headlinesMarketDataHelper.LoadHeadlines(symbols); + } + + private static void LoadPremarketData() + { + int retries=3; + int sleepTime=2000; + PremarketElements premarketElements=null; + + if(!CheckRunCriteria())return; + for(int retry=0;retrymaxHolidayDate) + { + Console.WriteLine(String.Format("There are no holidays defined in the system. Add holidays for year {0} into marketholidays table",currentDate.Year)); + return; + } + + if (args.Length < 1) + { + DisplayUsage(); + return; + } + + string arg = args[0].ToUpper(); + MDTrace.WriteLine(LogLevel.DEBUG,$"[RunService] Argument {arg}"); + + try + { + if(arg.Equals("LOADHEADLINESWATCHLIST")) + { + CommandArgs commandArgs=new CommandArgs(args); + if(!commandArgs.Has("WATCHLIST")){Console.WriteLine("LOADHEADLINESWATCHLIST REQUIRES WATCHLIST");return;} + else LoadHeadlinesWatchList(commandArgs.Coalesce("WATCHLIST")); + } + else if(arg.Equals("LOADPREMARKETDATA")) + { + LoadPremarketData(); + } + else if (arg.Equals("UPDATEDAILY2")) + { + CommandArgs commandArgs=new CommandArgs(args); + if(!commandArgs.Has("DATE")){Console.WriteLine("UPDATEDAILY2 MISSING DATE");return;} + UpdateDaily2(commandArgs.Coalesce("DATE")); + } + else + { + DisplayUsage(); + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return; + } + finally + { + LocalPriceCache.GetInstance().Dispose(); + GBPriceCache.GetInstance().Dispose(); + } + MDTrace.WriteLine(LogLevel.DEBUG,$"[RunService] Done, total took {profiler.End()}(ms)"); + } + } +} \ No newline at end of file diff --git a/MarketData/MarketData/Services/scraps.txt b/MarketData/MarketData/Services/scraps.txt new file mode 100644 index 0000000..5a8c41e --- /dev/null +++ b/MarketData/MarketData/Services/scraps.txt @@ -0,0 +1,456 @@ +// I have to now test all of the MarketDataHelper methods. Also, I WebRequest is obsolete so I will have to rewrite them somehow to use HttpClient +// uses proxy - not working MarketDataHelper.GetWorldTime(); + +// GetPremarketData : working + // PremarketElements elements = MarketDataHelper.GetPremarketData(); + // foreach(PremarketElement element in elements) + // { + // Console.WriteLine($"Market: {element.Market} {element.Timestamp} "); + // } + +// EarningsAnnouncements : working + // EarningsAnnouncements earningsAnnouncements = MarketDataHelper.GetEarningsAnnouncements("AAPL"); + // foreach(EarningsAnnouncement ea in earningsAnnouncements) + // { + // MDTrace.WriteLine(LogLevel.DEBUG,$"Symbol:{ea.Symbol} Date:{ea.Date.ToShortDateString()} Estimate:{Utility.FormatCurrency(ea.Estimate)}"); + // } + +//GetZacksRank : working + // ZacksRank zacksRank = MarketDataHelper.GetZacksRank("AAPL"); + // MDTrace.WriteLine(LogLevel.DEBUG,$"Zacks Rank: {zacksRank.Symbol} {zacksRank.Rank}"); + +// GetSplits + // Splits splits = MarketDataHelper.GetSplits(); + // foreach(Split split in splits) + // { + // MDTrace.WriteLine(LogLevel.DEBUG,$"Symbol:{split.Symbol} Exchange:{split.Exchange} EffectiveDate:{split.EffectiveDate} Ratio:{split.Ratio} "); + // } + +// GetGDPPerCapita - working + // EconomicIndicators economicIndicators = MarketDataHelper.GetGDPPerCapita(); + // foreach(EconomicIndicator economicIndicator in economicIndicators) + // { + // String message=$"Source:{economicIndicator.Source} CountryName:{economicIndicator.CountryName} CountryCode:{economicIndicator.CountryName} IndicatorName{economicIndicator.IndicatorName} IndicatorCode:{economicIndicator.IndicatorCode} IndicatorValue:{economicIndicator.IndicatorValue} Year:{economicIndicator.Year}"; + // MDTrace.WriteLine(LogLevel.DEBUG,message); + // } + +/// GetDividendHistory - working + // DividendHistory history = MarketDataHelper.GetDividendHistory("MRK"); + // String json = JsonSerializer.Serialize(history); + // MDTrace.WriteLine(json); + +// AnalystRatings - working + // AnalystRatings analystRatings = MarketDataHelper.GetLatestAnalystRatings(); + // if(null!=analystRatings) + // { + // String json = JsonSerializer.Serialize(analystRatings, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetAnalystRatingsMarketBeat - working + // AnalystRatings analystRatings = MarketDataHelper.GetAnalystRatingsMarketBeat("MRK"); + // if(null!=analystRatings) + // { + // String json = JsonSerializer.Serialize(analystRatings, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCIK - works + // String cik=MarketDataHelper.GetCIK("MRK"); + // MDTrace.WriteLine($"{cik}"); + +// GetInsiderTransactions - works + // InsiderTransactions insiderTransactions = MarketDataHelper.GetInsiderTransactions("AAPL",30); + // if(null!=insiderTransactions) + // { + // String json = JsonSerializer.Serialize(insiderTransactions, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetInsiderTransactions - works + // InsiderTransactions insiderTransactions = MarketDataHelper.GetInsiderTransactionsYear("AAPL",2023); + // if(null!=insiderTransactions) + // { + // String json = JsonSerializer.Serialize(insiderTransactions, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetSECFilings - works + // SECFilings secFilings = MarketDataHelper.GetSECFilings("MRK"); + // MDTrace.WriteLine(LogLevel.DEBUG,$"Got {secFilings.Count} filings."); + +// GetYieldCurve - works + // YieldCurve yieldCurve = MarketDataHelper.GetYieldCurve(2024); + // if(null!=yieldCurve) + // { + // String json = JsonSerializer.Serialize(yieldCurve, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetETFHoldings - works + // ETFHoldings etfHoldings = MarketDataHelper.GetETFHoldings("JFNNX"); + // if(null!=etfHoldings) + // { + // String json = JsonSerializer.Serialize(etfHoldings, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCompanyProfile - works + // CompanyProfile companyProfile = MarketDataHelper.GetCompanyProfile("MRK"); + // if(null!=companyProfile) + // { + // String json = JsonSerializer.Serialize(companyProfile, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCompanyProfileYahoo - works + // CompanyProfile companyProfile = MarketDataHelper.GetCompanyProfileYahoo("MRK"); + // if(null!=companyProfile) + // { + // String json = JsonSerializer.Serialize(companyProfile, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCompanyProfileMorningStar - works + // CompanyProfile companyProfile = MarketDataHelper.GetCompanyProfileMorningStar("MRK","xnys"); + // if(null!=companyProfile) + // { + // String json = JsonSerializer.Serialize(companyProfile, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCompanyProfileYahoo - works + // CompanyProfile companyProfile = MarketDataHelper.GetCompanyProfileYahoo("MRK"); + // if(null!=companyProfile) + // { + // String json = JsonSerializer.Serialize(companyProfile, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCompanyHeadlinesSeekingAlpha - works + // Headlines headlines = MarketDataHelper.GetCompanyHeadlinesSeekingAlpha("GLD"); + // if(null!=headlines) + // { + // String json = JsonSerializer.Serialize(headlines, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCompanyHeadlinesMarketWatch - gets unauthorized + // Headlines headlines = MarketDataHelper.GetCompanyHeadlinesMarketWatch("SPY"); + // if(null!=headlines) + // { + // String json = JsonSerializer.Serialize(headlines, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCompanyHeadlinesNASDAQ - works + // Headlines headlines = MarketDataHelper.GetCompanyHeadlinesNASDAQ("SPY"); + // if(null!=headlines) + // { + // String json = JsonSerializer.Serialize(headlines, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetConsumerPriceIndices - works + // PriceIndices priceIndices = MarketDataHelper.GetConsumerPriceIndices(); + // if(null!=priceIndices) + // { + // String json = JsonSerializer.Serialize(priceIndices, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetAnalystPriceTarget - works + // AnalystPriceTarget analystPriceTarget = MarketDataHelper.GetAnalystPriceTarget("MRK"); + // if(null!=analystPriceTarget) + // { + // String json = JsonSerializer.Serialize(analystPriceTarget, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + + // public static Dictionary GetHistoricalValues(String symbol) + +// GetHistoricalValues - works + // Dictionary series = MarketDataHelper.GetHistoricalValues("MRK"); + // if(null!=series) + // { + // String json = JsonSerializer.Serialize>(series, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCashflowStatement - works + // List cashflowStatements = MarketDataHelper.GetCashflowStatement("NVDA",CashflowStatement.PeriodType.Annual); + // if(null!=cashflowStatements) + // { + // String json = JsonSerializer.Serialize>(cashflowStatements, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetIncomeStatement - works + // List incomeStatements = MarketDataHelper.GetIncomeStatement("NVDA",IncomeStatement.PeriodType.Annual); + // if(null!=incomeStatements) + // { + // String json = JsonSerializer.Serialize>(incomeStatements, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetIncomeStatementFinViz - works + // List incomeStatements = MarketDataHelper.GetIncomeStatementFinViz("NVDA",IncomeStatement.PeriodType.Annual); + // if(null!=incomeStatements) + // { + // String json = JsonSerializer.Serialize>(incomeStatements, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } +// GetIncomeStatementNASDAQ - works + // List incomeStatements = MarketDataHelper.GetIncomeStatementNASDAQ("NVDA",IncomeStatement.PeriodType.Annual); + // if(null!=incomeStatements) + // { + // String json = JsonSerializer.Serialize>(incomeStatements, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetBalanceSheet - works + // List balanceSheets = MarketDataHelper.GetBalanceSheet("NVDA",BalanceSheet.PeriodType.Annual); + // if(null!=balanceSheets) + // { + // String json = JsonSerializer.Serialize>(balanceSheets, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetBalanceSheetFinViz - works + // List balanceSheets = MarketDataHelper.GetBalanceSheetFinViz("NVDA",BalanceSheet.PeriodType.Annual); + // if(null!=balanceSheets) + // { + // String json = JsonSerializer.Serialize>(balanceSheets, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetBalanceSheetNASDAQ - works + // List balanceSheets = MarketDataHelper.GetBalanceSheetNASDAQ("NVDA",BalanceSheet.PeriodType.Annual); + // if(null!=balanceSheets) + // { + // String json = JsonSerializer.Serialize>(balanceSheets, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetCurrencyConversion - works + // CurrencyConversionCollection collection = MarketDataHelper.GetCurrencyConversion("USD",DateTime.Parse("24-03-2025")); + // if(null!=collection) + // { + // String json = JsonSerializer.Serialize>((List)collection, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetFundamentalFinViz - works + // Fundamental fundamental = MarketDataHelper.GetFundamentalFinViz("NVDA"); + // if(null!=fundamental) + // { + // String json = JsonSerializer.Serialize(fundamental, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetFundamental - works + // Fundamental fundamental = MarketDataHelper.GetFundamental("NVDA"); + // if(null!=fundamental) + // { + // String json = JsonSerializer.Serialize(fundamental, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetLatestPrice - works + // Price price = MarketDataHelper.GetLatestPrice("NVDA"); + // if(null!=price) + // { + // String json = JsonSerializer.Serialize(price, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetLatestPriceYahoo - works + // Price price = MarketDataHelper.GetLatestPriceYahoo("NVDA"); + // if(null!=price) + // { + // String json = JsonSerializer.Serialize(price, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +//GetLatestPriceBigCharts - works + // Price price = MarketDataHelper.GetLatestPriceBigCharts("NVDA"); + // if(null!=price) + // { + // String json = JsonSerializer.Serialize(price, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetLatestPriceGoogle - works + // Price price = MarketDataHelper.GetLatestPriceGoogle("NVDA"); + // if(null!=price) + // { + // String json = JsonSerializer.Serialize(price, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetPricesAsOf - works + // Prices prices = MarketDataHelper.GetPricesAsOf("NVDA", DateTime.Parse("03/25/2025"),DateTime.Parse("03/02/2025")); + // if(null!=prices) + // { + // String json = JsonSerializer.Serialize(prices, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetPriceAsOf - works + // Price price = MarketDataHelper.GetPriceAsOf("NVDA",DateTime.Parse("03/24/2025")); + // if(null!=price) + // { + // String json = JsonSerializer.Serialize(price, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + +// GetDailyPrice - works + // Price price = MarketDataHelper.GetDailyPrice("NVDA",DateTime.Parse("03/24/2025")); + // if(null!=price) + // { + // String json = JsonSerializer.Serialize(price, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } + + // Prices prices = MarketDataHelper.GetDailyPrices("NVDA", DateTime.Parse("03/25/2025"),DateTime.Parse("03/02/2025")); + // if(null!=prices) + // { + // String json = JsonSerializer.Serialize(prices, + // new JsonSerializerOptions() + // { + // NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals + // }); + // MDTrace.WriteLine(json); + // } diff --git a/MarketData/MarketData/appsettings.json b/MarketData/MarketData/appsettings.json new file mode 100755 index 0000000..f613d1d --- /dev/null +++ b/MarketData/MarketData/appsettings.json @@ -0,0 +1,21 @@ +{ +"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", +"sms_smtpaddress" : "smtp.gmail.com", +"sms_smsusername" : "skessler1964@gmail.com", +"sms_smspassword" : "xjfo isnf gmyi zovr", +"sms_smsrecipients" : "skessler1964sms@gmail.com", +"proxy_address" : "http://localhost:8182", +"proxy_GetLatestPriceYahoo" : "false", +"proxy_GetLatestPriceFidelity" : "true", +"proxy_GetLatestPriceBigCharts" : "false", +"proxy_GetETFHoldings" : "false", +"proxy_GetAnalystPriceTargetYahoo" : "true", +"proxy_GetDailyPrices" : "false", +"proxy_GetFundamentalEx" : "false", +"proxy_GetDividendHistory" : "false", +"proxy_GetAnalystPriceTargetMarketBeat" : "false", +"proxy_GetCompanyHeadlinesSeekingAlphaV1" : "true", +"proxy_GetCompanyHeadlinesSeekingAlphaV2" : "true" +} diff --git a/MarketData/MarketData/marketdata.log b/MarketData/MarketData/marketdata.log new file mode 100644 index 0000000..a4ad38c --- /dev/null +++ b/MarketData/MarketData/marketdata.log @@ -0,0 +1,1138 @@ +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:04:15 PM] [MarketData.Services.MainService::RunService(args,configuration)][RunService] Started @ 2025-03-25 04:04:15 PM +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:04:16 PM] [MarketData.Services.MainService::RunService(args,configuration)][RunService] Argument LOADHEADLINESWATCHLIST +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:04:16 PM] [MarketData.Services.MainService::LoadHeadlinesWatchList(watchList)]LoadHeadlinesWatchList VALUATIONS +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for ^GSPC... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ ^GSPC +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:17 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=^GSPC|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for ^GSPC from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: ^GSPC, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch ^GSPC +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for ^VIX... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ ^VIX +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:19 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=^VIX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for ^VIX from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: ^VIX, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch ^VIX +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for ACWX... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:20 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/^VIX?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ ACWX +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:21 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=ACWX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 2 headlines for ACWX from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: ACWX, 3/17/2025 -> iShares MSCI ACWI ex U.S. ETF Experiences Big Inflow +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: ACWX, 12/17/2024 -> ACWX Makes Bullish Cross Above Critical Moving Average +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch ACWX +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for AMSC... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:22 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/ACWX?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/ACWX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ACWX from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha ACWX +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ AMSC +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=AMSC|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for AMSC from NASDAQ +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: AMSC, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch AMSC +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/^GSPC?mod=search_symbol +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/^GSPC?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ^GSPC from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha ^GSPC +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/ACWX/news?filter[since]=0&filter[until]=0&id=ACWX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ACWX from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for ACWX +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for APG... +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/AMSC?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/AMSC?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for AMSC from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha AMSC +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/^GSPC/news?filter[since]=0&filter[until]=0&id=^GSPC&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]Request:https://seekingalpha.com/api/v3/symbols/^GSPC/news?filter[since]=0&filter[until]=0&id=^GSPC&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 failed with status NotFound +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ^GSPC from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for ^GSPC +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ APG +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=APG|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for APG from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: APG, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch APG +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/AMSC/news?filter[since]=0&filter[until]=0&id=AMSC&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for AMSC from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:04:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for AMSC +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:04:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:26 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/APG?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:29 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/^VIX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ^VIX from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha ^VIX +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:30 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/^VIX/news?filter[since]=0&filter[until]=0&id=^VIX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:30 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]Request:https://seekingalpha.com/api/v3/symbols/^VIX/news?filter[since]=0&filter[until]=0&id=^VIX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 failed with status NotFound +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ^VIX from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for ^VIX +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:31 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/APG?mod=search_symbol failed with status 0 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:31 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for APG from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:31 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha APG +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:32 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/APG/news?filter[since]=0&filter[until]=0&id=APG&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for APG from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for APG +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for AS... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:33 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ AS +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:33 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=AS|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for AS from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: AS, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch AS +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 9 started for ASND... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/AS?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/AS?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for AS from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha AS +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ ASND +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=ASND|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for ASND from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:36 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/AS/news?filter[since]=0&filter[until]=0&id=AS&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: ASND, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch ASND +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for AS from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for AS +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for AWI... +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:37 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/ASND?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ AWI +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:37 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=AWI|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for AWI from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: AWI, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch AWI +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 17 started for AZZ... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/AWI?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/AWI?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for AWI from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha AWI +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ AZZ +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=AZZ|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for AZZ from NASDAQ +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: AZZ, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch AZZ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:40 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/AWI/news?filter[since]=0&filter[until]=0&id=AWI&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for AWI from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:04:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for AWI +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for BIL... +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:41 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/AZZ?mod=search_symbol +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:41 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/AZZ?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for AZZ from MARKETWATCH +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha AZZ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ BIL +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:41 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=BIL|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for BIL from NASDAQ +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/ASND?mod=search_symbol failed with status 0 +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ASND from MARKETWATCH +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha ASND +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: BIL, 3/18/2025 -> SPDR Bloomberg 1-3 Month T-Bill ETF Experiences Big Inflow +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch BIL +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/AZZ/news?filter[since]=0&filter[until]=0&id=AZZ&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for AZZ from Seeking Alpha +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 17 ended for AZZ +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:04:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:43 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/BIL?mod=search_symbol +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:43 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/ASND/news?filter[since]=0&filter[until]=0&id=ASND&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:43 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/BIL?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for BIL from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha BIL +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ASND from Seeking Alpha +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:04:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 9 ended for ASND +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:44 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/BIL/news?filter[since]=0&filter[until]=0&id=BIL&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 3 headlines for BIL from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha BIL, 3/25/2025 -> Société Générale observes shift in momentum in yields, highlights key levels +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha BIL, 3/25/2025 -> Deutsche Bank shakes off recession fears as it points to the yield curve +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha BIL, 3/25/2025 -> Vanguard downgrades U.S. growth forecast for 2025 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for BIL +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for BITO... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ BITO +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:46 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=BITO|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for BITO from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: BITO, 2/5/2025 -> ProShares Bitcoin (BITO) Enters Oversold Territory +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch BITO +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:47 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 17 started for BRK.B... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:47 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/BITO?mod=search_symbol +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:47 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ BRK.B +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:47 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=BRK.B|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:48 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/BITO?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for BITO from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha BITO +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for BRK.B from NASDAQ +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: BRK.B, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch BRK.B +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for BSV... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:49 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/BITO/news?filter[since]=0&filter[until]=0&id=BITO&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:49 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/BRK.B?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for BITO from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for BITO +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:49 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/BRK.B?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for BRK.B from MARKETWATCH +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha BRK.B +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ BSV +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:50 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=BSV|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for BSV from NASDAQ +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:50 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/BRK.B/news?filter[since]=0&filter[until]=0&id=BRK.B&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: BSV, 2/6/2025 -> Vanguard Short-Term Bond ETF Experiences Big Inflow +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch BSV +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for BRK.B from Seeking Alpha +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:04:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 17 ended for BRK.B +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for CEPU... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:51 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/BSV?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:51 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/BSV?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for BSV from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha BSV +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ CEPU +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:52 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=CEPU|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for CEPU from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: CEPU, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch CEPU +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:52 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/BSV/news?filter[since]=0&filter[until]=0&id=BSV&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for BSV from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for BSV +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for CLS... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/CEPU?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/CEPU?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CEPU from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha CEPU +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ CLS +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:53 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=CLS|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for CLS from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: CLS, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch CLS +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:54 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/CEPU/news?filter[since]=0&filter[until]=0&id=CEPU&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CEPU from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:04:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for CEPU +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:04:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:55 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/CLS?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:55 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/CLS?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CLS from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha CLS +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:57 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/CLS/news?filter[since]=0&filter[until]=0&id=CLS&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CLS from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for CLS +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for CNK... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ CNK +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:58 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=CNK|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for CNK from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: CNK, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch CNK +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:04:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for CRK... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:59 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/CNK?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:59 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/CNK?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CNK from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:04:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha CNK +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ CRK +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:00 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=CRK|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for CRK from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: CRK, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch CRK +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:01 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/CNK/news?filter[since]=0&filter[until]=0&id=CNK&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:01 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for CTLT... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:01 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CNK from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:01 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for CNK +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:01 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/CRK?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:01 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ CTLT +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:01 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=CTLT|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:02 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/CRK?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CRK from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha CRK +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for CTLT from NASDAQ +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: CTLT, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch CTLT +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for DAWN... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:03 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/CRK/news?filter[since]=0&filter[until]=0&id=CRK&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CRK from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for CRK +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:03 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/CTLT?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ DAWN +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:04 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=DAWN|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:04 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/CTLT?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CTLT from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha CTLT +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for DAWN from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: DAWN, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch DAWN +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for DIA... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/DAWN?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/CTLT/news?filter[since]=0&filter[until]=0&id=CTLT&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for CTLT from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for CTLT +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/DAWN?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for DAWN from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha DAWN +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ DIA +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:05 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=DIA|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for DIA from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: DIA, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch DIA +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:06 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/DAWN/news?filter[since]=0&filter[until]=0&id=DAWN&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for DAWN from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for DAWN +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:05:07 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:07 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/DIA?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:07 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/DIA?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:07 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for DIA from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:07 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha DIA +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:08 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/DIA/news?filter[since]=0&filter[until]=0&id=DIA&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:08 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for DIA from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha DIA, 3/25/2025 -> Vanguard downgrades U.S. growth forecast for 2025 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for DIA +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for DJT... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ DJT +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:10 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=DJT|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for DJT from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: DJT, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch DJT +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for DVA... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:11 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/DJT?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:11 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/DJT?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for DJT from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha DJT +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ DVA +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:12 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=DVA|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for DVA from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: DVA, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch DVA +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:12 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/DJT/news?filter[since]=0&filter[until]=0&id=DJT&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for DJT from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for DYN... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha DJT, 3/25/2025 -> Biggest stock movers Tuesday: DJT, NET, CVNA, and more +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for DJT +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/DVA?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/DVA?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for DVA from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha DVA +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ DYN +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:13 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=DYN|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for DYN from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: DYN, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch DYN +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:14 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/DVA/news?filter[since]=0&filter[until]=0&id=DVA&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for DVA from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for DVA +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for ESEA... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:15 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/DYN?mod=search_symbol +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:15 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/DYN?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for DYN from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha DYN +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ ESEA +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:15 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=ESEA|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for ESEA from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: ESEA, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch ESEA +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:16 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/DYN/news?filter[since]=0&filter[until]=0&id=DYN&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for DYN from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for DYN +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for EWS... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:17 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/ESEA?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:17 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/ESEA?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ESEA from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha ESEA +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ EWS +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:17 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=EWS|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for EWS from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: EWS, 6/20/2024 -> 4 ETFs Under $25 to Add to Your Portfolio in 2025 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch EWS +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:18 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/ESEA/news?filter[since]=0&filter[until]=0&id=ESEA&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ESEA from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:05:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for ESEA +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:05:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:19 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/EWS?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:19 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/EWS?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for EWS from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha EWS +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:20 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/EWS/news?filter[since]=0&filter[until]=0&id=EWS&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for EWS from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for EWS +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for EXEL... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ EXEL +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:21 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=EXEL|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for EXEL from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: EXEL, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch EXEL +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for FIX... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ FIX +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=FIX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/EXEL?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/EXEL?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for EXEL from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha EXEL +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for FIX from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: FIX, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch FIX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/EXEL/news?filter[since]=0&filter[until]=0&id=EXEL&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for EXEL from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for EXEL +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for FUNDX... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/FIX?mod=search_symbol +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/FIX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for FIX from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha FIX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ FUNDX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=FUNDX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for FUNDX from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:26 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/FIX/news?filter[since]=0&filter[until]=0&id=FIX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: FUNDX, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch FUNDX +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for FIX from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for FIX +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for FXAIX... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:27 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/FUNDX?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:27 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/FUNDX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:27 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for FUNDX from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:27 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha FUNDX +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:27 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ FXAIX +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:27 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=FXAIX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:28 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for FXAIX from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:28 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: FXAIX, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:28 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch FXAIX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:28 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/FUNDX/news?filter[since]=0&filter[until]=0&id=FUNDX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:28 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for FUNDX from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:28 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for FUNDX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:28 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for FXB... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:29 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/FXAIX?mod=search_symbol +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:29 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/FXAIX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for FXAIX from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha FXAIX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ FXB +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:29 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=FXB|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for FXB from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: FXB, 7/5/2024 -> Position Your Portfolio for Rate Cuts With These Currency ETFs +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch FXB +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:30 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/FXAIX/news?filter[since]=0&filter[until]=0&id=FXAIX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for FXAIX from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for FXAIX +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:05:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:32 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/FXB?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:32 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/FXB?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for FXB from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha FXB +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:33 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/FXB/news?filter[since]=0&filter[until]=0&id=FXB&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:33 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 2 headlines for FXB from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha FXB, 3/25/2025 -> European markets end green over positive U.S. tariff, geopolitical updates +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha FXB, 3/25/2025 -> EU car sales drop 3.4% in February, German market sees sharpest decline in volume +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for FXB +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for GDDY... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ GDDY +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=GDDY|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for GDDY from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: GDDY, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch GDDY +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for GEV... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:36 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/GDDY?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:36 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/GDDY?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GDDY from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha GDDY +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ GEV +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:36 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=GEV|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for GEV from NASDAQ +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: GEV, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch GEV +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:37 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/GDDY/news?filter[since]=0&filter[until]=0&id=GDDY&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GDDY from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for GDDY +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for GFF... +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/GEV?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/GEV?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GEV from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha GEV +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ GFF +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=GFF|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for GFF from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: GFF, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch GFF +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/GEV/news?filter[since]=0&filter[until]=0&id=GEV&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GEV from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for GEV +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for GLD... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:40 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/GFF?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:40 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/GFF?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GFF from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha GFF +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ GLD +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:40 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=GLD|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 2 headlines for GLD from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:41 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/GFF/news?filter[since]=0&filter[until]=0&id=GFF&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GFF from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for GFF +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: GLD, 3/21/2025 -> Is SPDR Gold Trust a Millionaire Maker? +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: GLD, 3/17/2025 -> Are Silver ETFs Better Plays Than Gold Now? +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch GLD +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for GOVT... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ GOVT +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:43 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=GOVT|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 2 headlines for GOVT from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: GOVT, 3/24/2025 -> GOVT +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: GOVT, 3/3/2025 -> GOVT +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch GOVT +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:05:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:44 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/GOVT?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:45 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/GOVT?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GOVT from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha GOVT +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:46 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/GOVT/news?filter[since]=0&filter[until]=0&id=GOVT&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GOVT from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for GOVT +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:51 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/GLD?mod=search_symbol +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:51 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/GLD?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GLD from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha GLD +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:52 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/GLD/news?filter[since]=0&filter[until]=0&id=GLD&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GLD from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for GLD +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for GSY... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ GSY +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:54 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=GSY|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for GSY from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: GSY, 3/3/2025 -> Notable Two Hundred Day Moving Average Cross - GSY +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch GSY +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:05:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 9 started for ICAGY... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:55 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/GSY?mod=search_symbol +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:55 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/GSY?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for GSY from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha GSY +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:05:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ ICAGY +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:05:55 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=ICAGY|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:05:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for ICAGY from NASDAQ +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:05:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: ICAGY, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:05:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch ICAGY +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for IDCC... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:56 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/GSY/news?filter[since]=0&filter[until]=0&id=GSY&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for GSY from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha GSY, 3/25/2025 -> Invesco Ultra Short Duration ETF declares monthly distribution of $0.1964 +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:05:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for GSY +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ IDCC +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:57 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=IDCC|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for IDCC from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: IDCC, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch IDCC +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for IEFA... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:59 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/IDCC?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:59 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/IDCC?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for IDCC from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:05:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha IDCC +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ IEFA +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:59 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=IEFA|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:05:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for IEFA from NASDAQ +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: IEFA, 3/21/2025 -> Is SPDR MSCI EAFE StrategicFactors ETF (QEFA) a Strong ETF Right Now? +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch IEFA +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:00 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/IDCC/news?filter[since]=0&filter[until]=0&id=IDCC&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for IDCC from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for IDCC +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for JFNNX... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:01 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ JFNNX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:01 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=JFNNX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:01 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for JFNNX from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: JFNNX, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch JFNNX +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:06:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:03 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/ICAGY?mod=search_symbol +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:03 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/ICAGY?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ICAGY from MARKETWATCH +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha ICAGY +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:05 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/ICAGY/news?filter[since]=0&filter[until]=0&id=ICAGY&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for ICAGY from Seeking Alpha +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 9 ended for ICAGY +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:08 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/IEFA?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:08 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/IEFA?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:08 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for IEFA from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:08 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha IEFA +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:09 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/IEFA/news?filter[since]=0&filter[until]=0&id=IEFA&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for IEFA from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:06:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for IEFA +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:10 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/JFNNX?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:10 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/JFNNX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for JFNNX from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha JFNNX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:11 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/JFNNX/news?filter[since]=0&filter[until]=0&id=JFNNX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for JFNNX from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for JFNNX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for JHG... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ JHG +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:12 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=JHG|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for JHG from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: JHG, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch JHG +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for KGFHY... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:14 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/JHG?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:14 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/JHG?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for JHG from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha JHG +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ KGFHY +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:14 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=KGFHY|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for KGFHY from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: KGFHY, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch KGFHY +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:15 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/JHG/news?filter[since]=0&filter[until]=0&id=JHG&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for JHG from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for JHG +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for LTH... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:16 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/KGFHY?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:16 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/KGFHY?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for KGFHY from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha KGFHY +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ LTH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:16 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=LTH|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for LTH from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: LTH, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch LTH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:17 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/KGFHY/news?filter[since]=0&filter[until]=0&id=KGFHY&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for KGFHY from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for KGFHY +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for MDY... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ MDY +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:19 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=MDY|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for MDY from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: MDY, 3/10/2025 -> MDY +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch MDY +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 9 started for MIRM... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:20 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/MDY?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:20 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/MDY?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for MDY from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha MDY +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ MIRM +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:20 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=MIRM|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for MIRM from NASDAQ +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: MIRM, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch MIRM +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:21 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/MDY/news?filter[since]=0&filter[until]=0&id=MDY&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for MDY from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for MDY +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:06:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:22 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/MIRM?mod=search_symbol +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:22 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/MIRM?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for MIRM from MARKETWATCH +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha MIRM +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/MIRM/news?filter[since]=0&filter[until]=0&id=MIRM&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for MIRM from Seeking Alpha +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 9 ended for MIRM +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:28 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/LTH?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:28 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/LTH?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:28 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for LTH from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:28 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha LTH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:29 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/LTH/news?filter[since]=0&filter[until]=0&id=LTH&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for LTH from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for LTH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for MOD... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ MOD +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:30 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=MOD|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for MOD from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: MOD, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch MOD +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:31 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for NEAR... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:31 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/MOD?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:31 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/MOD?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:31 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for MOD from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:31 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha MOD +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ NEAR +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:32 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=NEAR|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for NEAR from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: NEAR, 12/20/2024 -> NEAR Makes Bullish Cross Above Critical Moving Average +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch NEAR +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:33 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/MOD/news?filter[since]=0&filter[until]=0&id=MOD&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:33 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for MOD from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:33 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for MOD +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:33 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for NWPX... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ NWPX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:34 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=NWPX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for NWPX from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: NWPX, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch NWPX +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 9 started for PFF... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/NWPX?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/NWPX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for NWPX from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha NWPX +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ PFF +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:36 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=PFF|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for PFF from NASDAQ +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: PFF, 1/21/2025 -> PFF Crosses Critical Technical Indicator +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch PFF +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:37 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/NWPX/news?filter[since]=0&filter[until]=0&id=NWPX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for NWPX from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for NWPX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for PLSE... +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/PFF?mod=search_symbol +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/PFF?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for PFF from MARKETWATCH +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha PFF +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/NEAR?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ PLSE +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=PLSE|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/NEAR?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for NEAR from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha NEAR +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for PLSE from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: PLSE, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch PLSE +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/PFF/news?filter[since]=0&filter[until]=0&id=PFF&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for PFF from Seeking Alpha +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:06:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 9 ended for PFF +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:06:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/NEAR/news?filter[since]=0&filter[until]=0&id=NEAR&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/PLSE?mod=search_symbol +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for NEAR from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for NEAR +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:40 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/PLSE?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for PLSE from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha PLSE +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:41 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/PLSE/news?filter[since]=0&filter[until]=0&id=PLSE&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for PLSE from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for PLSE +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for POWL... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ POWL +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:42 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=POWL|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for POWL from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: POWL, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch POWL +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for PRF... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:43 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/POWL?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:43 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/POWL?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for POWL from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha POWL +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ PRF +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:44 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=PRF|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for PRF from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: PRF, 3/14/2025 -> Notable ETF Inflow Detected - PRF +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch PRF +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:45 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/POWL/news?filter[since]=0&filter[until]=0&id=POWL&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for POWL from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for POWL +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 started for PRIM... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:45 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/PRF?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:46 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/PRF?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for PRF from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha PRF +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ PRIM +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:46 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=PRIM|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for PRIM from NASDAQ +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:47 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: PRIM, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:47 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch PRIM +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:47 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/PRF/news?filter[since]=0&filter[until]=0&id=PRF&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:47 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for PRF from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:47 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for PRF +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:47 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for QFIN... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:48 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/PRIM?mod=search_symbol +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:48 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/PRIM?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for PRIM from MARKETWATCH +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha PRIM +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ QFIN +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:48 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=QFIN|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for QFIN from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: QFIN, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch QFIN +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:49 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/PRIM/news?filter[since]=0&filter[until]=0&id=PRIM&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for RKLB... +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for PRIM from Seeking Alpha +[LOCAL][Thread=10][TRACE.DEBUG][3/25/2025 4:06:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 10 ended for PRIM +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:49 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/QFIN?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:50 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/QFIN?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for QFIN from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha QFIN +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ RKLB +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:50 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=RKLB|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for RKLB from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: RKLB, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch RKLB +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:51 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/QFIN/news?filter[since]=0&filter[until]=0&id=QFIN&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for QFIN from Seeking Alpha +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:06:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha QFIN, 3/25/2025 -> Qifu proposes $600M convertible senior notes offering +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:06:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for QFIN +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:51 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/RKLB?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:52 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/RKLB?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for RKLB from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha RKLB +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:53 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/RKLB/news?filter[since]=0&filter[until]=0&id=RKLB&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for RKLB from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for RKLB +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for RNA... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ RNA +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:54 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=RNA|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for RNA from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: RNA, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch RNA +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 15 started for RYCEY... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:55 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/RNA?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:55 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/RNA?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for RNA from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:55 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha RNA +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ RYCEY +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:56 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=RYCEY|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for RYCEY from NASDAQ +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: RYCEY, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:56 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch RYCEY +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:56 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/RNA/news?filter[since]=0&filter[until]=0&id=RNA&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for RNA from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for RNA +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:57 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for SH... +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:57 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/RYCEY?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ SH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:58 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=SH|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:58 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/RYCEY?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for RYCEY from MARKETWATCH +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha RYCEY +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for SH from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: SH, 2/3/2025 -> Pre-Market Most Active for Mar 13 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:58 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch SH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:06:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for SHV... +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:59 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/RYCEY/news?filter[since]=0&filter[until]=0&id=RYCEY&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:06:59 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/SH?mod=search_symbol +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for RYCEY from Seeking Alpha +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:06:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 15 ended for RYCEY +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:00 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/SH?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SH from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha SH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ SHV +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:00 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=SHV|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for SHV from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: SHV, 3/18/2025 -> Pre-Market Most Active for Mar 19 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch SHV +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:01 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/SH/news?filter[since]=0&filter[until]=0&id=SH&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:01 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 5 headlines for SH from Seeking Alpha +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:01 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 15 started for SKYW... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:01 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/SHV?mod=search_symbol +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ SKYW +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=SKYW|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/SHV?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SHV from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha SHV +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SH, 3/25/2025 -> 6 Buy-rated consumer discretionary stocks as consumer confidence crumbles +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SH, 3/25/2025 -> SA Sentiment: Seeking Alpha readers scale back expectations for S&P 500 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SH, 3/25/2025 -> Fed Governor Kugler notes 'unhelpful' trend reversal in goods inflation +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SH, 3/25/2025 -> Vanguard downgrades U.S. growth forecast for 2025 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SH, 3/25/2025 -> Trump tariffs sow more confusion, may grant breaks to 'a lot of countries' +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for SH +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for SKYW from NASDAQ +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: SKYW, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:02 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch SKYW +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:07:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:03 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/SHV/news?filter[since]=0&filter[until]=0&id=SHV&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:03 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/SKYW?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SHV from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for SHV +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:03 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/SKYW?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SKYW from MARKETWATCH +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:03 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha SKYW +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:04 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/SKYW/news?filter[since]=0&filter[until]=0&id=SKYW&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SKYW from Seeking Alpha +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 15 ended for SKYW +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:04 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 15 started for SMWB... +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:05 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ SMWB +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:05 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=SMWB|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for SMWB from NASDAQ +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: SMWB, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch SMWB +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:06 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for SOFI... +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:07 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/SMWB?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:07 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ SOFI +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:07 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=SOFI|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:07 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/SMWB?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:07 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SMWB from MARKETWATCH +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:07 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha SMWB +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:08 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for SOFI from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:08 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: SOFI, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:08 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch SOFI +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:08 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 17 started for SOXX... +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/SMWB/news?filter[since]=0&filter[until]=0&id=SMWB&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/SOFI?mod=search_symbol +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SMWB from Seeking Alpha +[LOCAL][Thread=15][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 15 ended for SMWB +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/SOFI?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SOFI from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha SOFI +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ SOXX +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:09 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=SOXX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 2 headlines for SOXX from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:10 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/SOFI/news?filter[since]=0&filter[until]=0&id=SOFI&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SOFI from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for SOFI +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: SOXX, 3/20/2025 -> SOXX +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: SOXX, 3/12/2025 -> Is First Trust NASDAQ Semiconductor ETF (FTXL) a Strong ETF Right Now? +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch SOXX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for SPY... +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:11 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/SOXX?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ SPY +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:11 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=SPY|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:11 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/SOXX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SOXX from MARKETWATCH +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha SOXX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for SPY from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: SPY, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch SPY +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for T... +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/SOXX/news?filter[since]=0&filter[until]=0&id=SOXX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SOXX from Seeking Alpha +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 17 ended for SOXX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/SPY?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ T +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=T|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/SPY?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for SPY from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha SPY +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for T from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: T, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch T +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:07:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:14 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/SPY/news?filter[since]=0&filter[until]=0&id=SPY&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/T?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 5 headlines for SPY from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/T?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for T from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha T +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SPY, 3/25/2025 -> 6 Buy-rated consumer discretionary stocks as consumer confidence crumbles +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SPY, 3/25/2025 -> SA Sentiment: Seeking Alpha readers scale back expectations for S&P 500 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SPY, 3/25/2025 -> Fed Governor Kugler notes 'unhelpful' trend reversal in goods inflation +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SPY, 3/25/2025 -> Vanguard downgrades U.S. growth forecast for 2025 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha SPY, 3/25/2025 -> Trump tariffs sow more confusion, may grant breaks to 'a lot of countries' +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for SPY +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:16 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/T/news?filter[since]=0&filter[until]=0&id=T&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for T from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha T, 3/25/2025 -> AT&T reportedly in talks for Lumen's consumer fiber unit +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for T +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for TPB... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ TPB +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:17 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=TPB|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for TPB from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: TPB, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch TPB +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for TPR... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:19 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/TPB?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:19 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/TPB?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for TPB from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha TPB +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ TPR +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:19 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=TPR|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for TPR from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: TPR, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch TPR +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:20 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/TPB/news?filter[since]=0&filter[until]=0&id=TPB&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for TPB from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for TPB +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:20 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for TRMD... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:21 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ TRMD +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:21 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=TRMD|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:21 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/TPR?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for TRMD from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:22 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/TPR?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for TPR from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha TPR +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: TRMD, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch TRMD +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:22 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for UAL... +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/TPR/news?filter[since]=0&filter[until]=0&id=TPR&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for TPR from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for TPR +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ UAL +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=UAL|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:23 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/TRMD?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:23 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for UAL from NASDAQ +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: UAL, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch UAL +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:24 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/TRMD?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for TRMD from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha TRMD +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:24 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for UDN... +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:24 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/UAL?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ UDN +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=UDN|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/TRMD/news?filter[since]=0&filter[until]=0&id=TRMD&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/UAL?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for UAL from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha UAL +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for TRMD from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for TRMD +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:25 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for UDN from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: UDN, 8/22/2024 -> Position Your Portfolio for Rate Cuts With These Currency ETFs +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch UDN +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:07:26 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:26 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/UAL/news?filter[since]=0&filter[until]=0&id=UAL&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:27 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for UAL from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:27 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for UAL +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:27 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/UDN?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:27 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/UDN?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:27 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for UDN from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:27 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha UDN +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:29 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/UDN/news?filter[since]=0&filter[until]=0&id=UDN&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for UDN from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for UDN +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for UUP... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:29 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ UUP +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:29 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=UUP|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for UUP from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: UUP, 2/21/2025 -> Is Invesco DB US Dollar Index Bullish ETF (UUP) a Strong ETF Right Now? +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:30 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch UUP +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:31 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for VDE... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:31 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/UUP?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:31 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/UUP?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:31 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for UUP from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:31 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha UUP +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ VDE +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:32 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=VDE|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for VDE from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: VDE, 3/18/2025 -> Is Invesco S\u0026P 500 Equal Weight Energy ETF (RSPG) a Strong ETF Right Now? +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch VDE +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:32 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/UUP/news?filter[since]=0&filter[until]=0&id=UUP&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for UUP from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:32 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for UUP +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:33 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 started for VRNA... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ VRNA +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:34 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=VRNA|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for VRNA from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: VRNA, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:34 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch VRNA +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for VRRM... +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/VRNA?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/VDE?mod=search_symbol +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:35 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/VRNA?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VRNA from MARKETWATCH +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:35 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha VRNA +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ VRRM +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:36 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=VRRM|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for VRRM from NASDAQ +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:36 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/VRNA/news?filter[since]=0&filter[until]=0&id=VRNA&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: VRRM, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch VRRM +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VRNA from Seeking Alpha +[LOCAL][Thread=13][TRACE.DEBUG][3/25/2025 4:07:36 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 13 ended for VRNA +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for VST... +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:37 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/VRRM?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:37 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/VRRM?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VRRM from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:37 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha VRRM +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ VST +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=VST|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for VST from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: VST, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:38 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch VST +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:38 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/VRRM/news?filter[since]=0&filter[until]=0&id=VRRM&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VRRM from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for VRRM +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:07:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/VST?mod=search_symbol +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:39 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/VST?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VST from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:39 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha VST +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:40 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/VST/news?filter[since]=0&filter[until]=0&id=VST&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VST from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:40 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for VST +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:41 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/VDE?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VDE from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:41 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha VDE +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:42 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/VDE/news?filter[since]=0&filter[until]=0&id=VDE&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VDE from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for VDE +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:42 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for VSTCX... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:43 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ VSTCX +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:43 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=VSTCX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for VSTCX from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: VSTCX, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch VSTCX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:44 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 started for VXX... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:45 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/VSTCX?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:45 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/VSTCX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VSTCX from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha VSTCX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:45 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ VXX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:45 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=VXX|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for VXX from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:46 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/VSTCX/news?filter[since]=0&filter[until]=0&id=VSTCX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: VXX, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch VXX +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VSTCX from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for VSTCX +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:46 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 17 started for VYM... +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:47 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ VYM +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:47 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=VYM|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 2 headlines for VYM from NASDAQ +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:48 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/VXX?mod=search_symbol +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: VYM, 3/17/2025 -> 5 ETFs That Investors Loved the Most Last Week +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: VYM, 3/14/2025 -> Cool +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch VYM +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:48 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for XBI... +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:49 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/VYM?mod=search_symbol +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:49 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/VYM?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VYM from MARKETWATCH +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha VYM +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:49 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ XBI +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:49 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=XBI|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 2 headlines for XBI from NASDAQ +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:50 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/VYM/news?filter[since]=0&filter[until]=0&id=VYM&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: XBI, 3/21/2025 -> Should You Invest in the Invesco Biotechnology \u0026 Genome ETF (PBE)? +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: XBI, 3/5/2025 -> Interesting XBI Put And Call Options For May 2nd +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:07:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch XBI +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for VYM from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:50 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for XLP... +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha VYM, 3/25/2025 -> Top 10 U.S. stocks with strong growth and dividends according to SA quant metrics +[LOCAL][Thread=17][TRACE.DEBUG][3/25/2025 4:07:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 17 ended for VYM +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:51 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ XLP +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:51 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=XLP|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 2 headlines for XLP from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: XLP, 3/24/2025 -> Should You Invest in the Fidelity MSCI Consumer Staples Index ETF (FSTA)? +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: XLP, 3/17/2025 -> ETFs in Focus as PepsiCo Buys Prebiotic Soda Brand Poppi +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch XLP +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:07:52 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:53 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/XLP?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:53 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/XLP?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for XLP from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:53 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha XLP +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:54 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/XLP/news?filter[since]=0&filter[until]=0&id=XLP&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for XLP from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:07:54 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for XLP +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:59 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/VXX?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VXX from MARKETWATCH +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:07:59 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha VXX +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:08:00 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/VXX/news?filter[since]=0&filter[until]=0&id=VXX&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:08:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for VXX from Seeking Alpha +[LOCAL][Thread=14][TRACE.DEBUG][3/25/2025 4:08:00 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 14 ended for VXX +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:01 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/XBI?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:10 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/XBI?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for XBI from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:10 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha XBI +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:11 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/XBI/news?filter[since]=0&filter[until]=0&id=XBI&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for XBI from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for XBI +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:11 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for XLY... +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:12 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ XLY +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:12 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=XLY|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for XLY from NASDAQ +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: XLY, 3/18/2025 -> ETF Fundamental Report for XLY +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch XLY +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:13 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 started for YPF... +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:14 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/XLY?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:14 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/XLY?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for XLY from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha XLY +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:14 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ YPF +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:14 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=YPF|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for YPF from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: YPF, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch YPF +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:15 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/XLY/news?filter[since]=0&filter[until]=0&id=XLY&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for XLY from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Seeking Alpha XLY, 3/25/2025 -> 6 Buy-rated consumer discretionary stocks as consumer confidence crumbles +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for XLY +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:15 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 started for YRD... +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:16 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/YPF?mod=search_symbol +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:16 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/YPF?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for YPF from MARKETWATCH +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha YPF +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:16 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesNASDAQ YRD +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:16 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesNASDAQ(symbol)]https://api.nasdaq.com/api/news/topic/articlebysymbol?q=YRD|etf&offset=0&limit=8&fallback=false +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]Got 1 headlines for YRD from NASDAQ +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:17 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/YPF/news?filter[since]=0&filter[until]=0&id=YPF&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]NASDAQ: YRD, 3/25/2025 -> Stocks Extend Monday's Gains as Trade Concerns Subside +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesMarketWatch YRD +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for YPF from Seeking Alpha +[LOCAL][Thread=7][TRACE.DEBUG][3/25/2025 4:08:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 7 ended for YPF +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:08:17 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)]Load Headline, waiting for queued items to complete. +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:18 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]https://www.marketwatch.com/investing/stock/YRD?mod=search_symbol +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:18 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesMarketWatch(symbol)]Request:https://www.marketwatch.com/investing/stock/YRD?mod=search_symbol failed with status Unauthorized +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for YRD from MARKETWATCH +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:18 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]GetCompanyHeadlinesSeekingAlpha YRD +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:19 PM] [MarketData.Helper.MarketDataHelper::GetCompanyHeadlinesSeekingAlphaV3(symbol,ignoreMarketDate)]https://seekingalpha.com/api/v3/symbols/YRD/news?filter[since]=0&filter[until]=0&id=YRD&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1 +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlineEx(symbol)]No headlines for YRD from Seeking Alpha +[LOCAL][Thread=12][TRACE.DEBUG][3/25/2025 4:08:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::ThreadPoolCallbackLoadHeadline(threadHelperContext)]Load Headline, Thread 12 ended for YRD +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:08:19 PM] [MarketData.Helper.HeadlinesMarketDataHelper::LoadHeadlines(requestSymbols)][LoadHeadlines]End, total took 243301(ms) +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:08:19 PM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose]Thread state is 'Running'. Joining main thread... +[LOCAL][Thread=9][TRACE.DEBUG][3/25/2025 4:08:19 PM] [MarketData.Cache.LocalPriceCache::ThreadProc()][LocalPriceCache:ThreadProc]Thread ended. Items in cache:0 +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:08:19 PM] [MarketData.Cache.LocalPriceCache::Dispose()][LocalPriceCache:Dispose] End +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:08:19 PM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose]Thread state is 'WaitSleepJoin'. Joining main thread... +[LOCAL][Thread=18][TRACE.DEBUG][3/25/2025 4:08:20 PM] [MarketData.Cache.GBPriceCache::ThreadProc()][GBPriceCache:ThreadProc]Thread ended. +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:08:20 PM] [MarketData.Cache.GBPriceCache::Dispose()][GBPriceCache:Dispose] End. +[LOCAL][Thread=1][TRACE.DEBUG][3/25/2025 4:08:20 PM] [MarketData.Services.MainService::RunService(args,configuration)][RunService] Done, total took 245236(ms) diff --git a/MarketData/MarketDataLib/CSVHelper/CSVFileExt.cs b/MarketData/MarketDataLib/CSVHelper/CSVFileExt.cs new file mode 100755 index 0000000..5a4fece --- /dev/null +++ b/MarketData/MarketDataLib/CSVHelper/CSVFileExt.cs @@ -0,0 +1,543 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Data; +using System.Threading.Tasks; +using System.Text.RegularExpressions; + +namespace MarketData.CSVHelper +{ + public class CSVFileExt + { + protected Dictionary header = new Dictionary(); + protected List columns = null; + protected List> rows = new List>(); + + public CSVFileExt() + { + } + public int FindLineWith(String strPathFileName,String strColumnName) + { + StreamReader streamReader = null; + try + { + DateTime modified = DateTime.Now; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Scanning CSV File {0} for '{1}'", strPathFileName,strColumnName)); + streamReader = File.OpenText(strPathFileName); + String strLine = null; + strColumnName=strColumnName.ToUpper(); + int row=0; + while (null != (strLine = streamReader.ReadLine())) + { + row++; + if ("".Equals(strLine))continue; + String[] rowData = StringParser.ParseDelimitedString(strLine); + if (1 == rowData.Length && rowData[0].Trim().ToUpper().Equals("**NOTE :")) break; + if (0 == rowData.Length) continue; + if (rowData[0].ToUpper().Trim().Equals(strColumnName)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Found '{0}' at row {1}", strColumnName,row)); + return row; + } + } + return -1; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return -1; + } + finally + { + if (null != streamReader) streamReader.Close(); + } + } + public virtual bool LoadCSVFile(String strPathFileName, String startDataRow) + { + StreamReader streamReader = null; + try + { + DateTime modified = DateTime.Now; +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loading CSV File {0}", strPathFileName)); + streamReader = File.OpenText(strPathFileName); + String strLine = null; + strLine=FindDataRows(streamReader, startDataRow); + if (null == strLine) return false; + CreateColumns(strLine); + int rowCount = 0; + + while (null != (strLine = streamReader.ReadLine())) + { + if ("".Equals(strLine)) continue; + String[] rowData = StringParser.ParseDelimitedString(strLine); + if (1 == rowData.Length && rowData[0].Trim().ToUpper().Equals("**NOTE :")) break; + List rowDataList = rowData.ToList(); + rows.Add(rowDataList); + rowCount++; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loaded {0} rows from {1}", rows.Count, strPathFileName)); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return false; + } + finally + { + if (null != streamReader) streamReader.Close(); + } + } + public virtual Dictionary LoadCSVFile(String strPathFileName, int startDataRow) + { + StreamReader streamReader = null; + try + { + DateTime modified = DateTime.Now; +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loading CSV File {0}", strPathFileName)); + streamReader = File.OpenText(strPathFileName); + String strLine = null; + ReadHeaderRows(streamReader, startDataRow); + strLine = streamReader.ReadLine(); + CreateColumns(strLine); + int rowCount = 0; + while (null != (strLine = streamReader.ReadLine())) + { + if ("".Equals(strLine)) continue; + String[] rowData = StringParser.ParseDelimitedString(strLine); + if (1 == rowData.Length && rowData[0].Trim().ToUpper().Equals("**NOTE :")) break; + List rowDataList = rowData.ToList(); + rows.Add(rowDataList); + rowCount++; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loaded {0} rows from {1}", rows.Count, strPathFileName)); + return header; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + if (null != streamReader) streamReader.Close(); + } + } + public virtual Dictionary LoadCSVFile(StreamReader streamReader, int startDataRow) + { + try + { + DateTime modified = DateTime.Now; +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loading CSV File from stream.")); + String strLine = null; + + ReadHeaderRows(streamReader, startDataRow); + strLine = streamReader.ReadLine(); + CreateColumns(strLine); + int rowCount = 0; + while (null != (strLine = streamReader.ReadLine())) + { + if ("".Equals(strLine)) continue; + String[] rowData = StringParser.ParseDelimitedString(strLine); + if (1 == rowData.Length && rowData[0].Trim().ToUpper().Equals("**NOTE :")) break; + List rowDataList = rowData.ToList(); + rows.Add(rowDataList); + rowCount++; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loaded {0} rows from file", rows.Count)); + return header; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + } + } + public virtual Dictionary LoadCSVFileNoHeader(StreamReader streamReader, int startDataRow) + { + try + { + DateTime modified = DateTime.Now; +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loading CSV File from stream.")); + String strLine = null; + + for(int index=0;index rowDataList = rowData.ToList(); + rows.Add(rowDataList); + rowCount++; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loaded {0} rows from file", rows.Count)); + return header; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + } + } + public Dictionary Header + { + get + { + return header; + } + } + public bool ContainsColumn(String columnName) + { + if (null == columns) return false; + for (int colIndex = 0; colIndex < columns.Count; colIndex++) + { + if (Columns[colIndex].Equals(columnName)) return true; + } + return false; + } + public Dictionary GetDuplicateValues(String columnName) + { + try + { + if (!ContainsColumn(columnName)) return null; + Dictionary uniqueValues = new Dictionary(); + Dictionary duplicateValues = new Dictionary(); + for (int row = 0; row < rows.Count; row++) + { + String value = GetRowData(row, columnName); + if (!uniqueValues.ContainsKey(value)) uniqueValues.Add(value, value); + else + { + if (!duplicateValues.ContainsKey(value)) duplicateValues.Add(value, 1); + else { duplicateValues[value]++; } + } + } + return duplicateValues; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + } + public void RemoveAllDuplicateValues(Dictionary valuesToRemove, String columnName) + { + try + { + if (null == valuesToRemove || 0 == valuesToRemove.Count) return; + List keys = new List(valuesToRemove.Keys); + for (int index = 0; index < keys.Count; index++) + { + String key = keys[index]; + int occurrence = valuesToRemove[key]; + for (int item = 0; item < occurrence; item++) RemoveDuplicateValue(key, columnName); + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + } + } + private void RemoveDuplicateValue(String valueToRemove, String columnName) + { + try + { + if (!ContainsColumn(columnName)) return; + for (int row = 0; row < rows.Count; row++) + { + String value = GetRowData(row, columnName); + if (!value.Equals(valueToRemove)) continue; + rows.RemoveAt(row); + break; + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + } + } + public String GetRowData(int row,int col) + { + if (row >= rows.Count) return null; + List rowData = rows[row]; + if(col>=rowData.Count)return null; + return rowData[col]; + } + public List GetRow(int row) + { + if (row >= rows.Count) return null; + return rows[row]; + } + public String GetRowData(int row, String columnName) + { + int columnIndex = -1; + if (row >= rows.Count) return null; + for (int colIndex = 0; colIndex < columns.Count; colIndex++) + { + if (Columns[colIndex].Equals(columnName)) columnIndex = colIndex; + } + if (-1 == columnIndex) return null; + List rowData = rows[row]; + return rowData[columnIndex]; + } + public void SetRowData(String columnName, String value) + { + int columnIndex = -1; + for (int colIndex = 0; colIndex < columns.Count; colIndex++) + { + if (Columns[colIndex].Equals(columnName)) columnIndex = colIndex; + } + if (-1 == columnIndex) return; + if (0 == rows.Count) rows.Add(new List()); + for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++) + { + List row = rows[rowIndex]; + row[columnIndex] = value; + } + } + public void SetRowData(String columnName,int rowIndex, String value) + { + int columnIndex = -1; + for (int colIndex = 0; colIndex < columns.Count; colIndex++) + { + if (Columns[colIndex].Equals(columnName)) columnIndex = colIndex; + } + if (-1 == columnIndex) return; + List row = rows[rowIndex]; + row[columnIndex] = value; + } + public void SetRowDataWithNewValue(String columnName,String oldValue,String newValue) + { + int columnIndex = -1; + for (int colIndex = 0; colIndex < columns.Count; colIndex++) + { + if (columns[colIndex].Equals(columnName)) columnIndex = colIndex; + } + if (-1 == columnIndex) return; + for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++) + { + List row = rows[rowIndex]; + if (row[columnIndex].Equals(oldValue)) + { + row[columnIndex] = newValue; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Replacing row data for '{0}' with value '{1}' with new value '{2}'", columnName, oldValue,newValue)); + LogRow(rowIndex); + } + } + } + public void DeleteNullOrEmptyRows(String columnName) + { + int columnIndex = -1; + for (int colIndex = 0; colIndex < columns.Count; colIndex++) + { + if (columns[colIndex].Equals(columnName)) + { + columnIndex = colIndex; + break; + } + } + if (-1 == columnIndex) return; + for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++) + { + List row = rows[rowIndex]; + if (null == row[columnIndex]||0==row[columnIndex].Length) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Removing row for '{0}' with null value.", columnName)); + LogRow(rowIndex); + rows.Remove(row); + } + } + } + public void DeleteRow(String columnName, String value) + { + int columnIndex = -1; + for (int colIndex = 0; colIndex < columns.Count; colIndex++) + { + if (columns[colIndex].Equals(columnName)) + { + columnIndex = colIndex; + break; + } + } + if (-1 == columnIndex) return; + for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++) + { + List row = rows[rowIndex]; + if (null == value && null==row[columnIndex]) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Removing row for '{0}' with value '{1}'", columnName, value)); + LogRow(rowIndex); + rows.Remove(row); + } + else if (row[columnIndex].Equals(value)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Removing row for '{0}' with value '{1}'", columnName, value)); + LogRow(rowIndex); + rows.Remove(row); + } + } + } + public int RowCount + { + get + { + if (null == rows) return 0; + return rows.Count; + } + } + public void LogRow(int row) + { + try + { + StringBuilder sb = new StringBuilder(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Contents of row {0}", row)); + for (int colIndex = 0; colIndex < columns.Count; colIndex++) + { + sb.Append(columns[colIndex]); + if (colIndex < columns.Count - 1) sb.Append(","); + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}", sb.ToString())); + sb = new StringBuilder(); + List rowData = rows[row]; + for (int colIndex = 0; colIndex < rowData.Count; colIndex++) + { + sb.Append(rowData[colIndex]); + if (colIndex < rowData.Count - 1) sb.Append(","); + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}", sb.ToString())); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}", exception.ToString())); + } + } + public String[] Columns + { + get + { + if (null == columns) return null; + return columns.ToArray(); + } + } + public void AddColumn(String columnName) + { + columns.Add(columnName); + if (null!=rows && rows.Count > 0) + for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++) + { + List row = rows[rowIndex]; + row.Add(""); + } + } + protected String FindDataRows(StreamReader streamReader, String startDataRow) + { + String strLine = null; + while (null!=(strLine=streamReader.ReadLine())) + { + strLine = streamReader.ReadLine(); + if (strLine.Contains(startDataRow)) + { + String[] columns = strLine.Split(','); + if (columns.Length == 2) header.Add(columns[0].ToUpper().Trim(), columns[1].ToUpper().Trim()); + return strLine; + } + } + return null; + } + protected bool ReadHeaderRows(StreamReader streamReader, int startDataRow) + { + String strLine = null; + for (int index = 0; index < startDataRow - 1; index++) + { + strLine = streamReader.ReadLine(); + if (null == strLine) break; + String[] columns = strLine.Split(','); + if (columns.Length == 2) + { + String key=columns[0].ToUpper().Trim(); + if(!header.ContainsKey(key))header.Add(key, columns[1].ToUpper().Trim()); + } + else if (columns.Length == 1) + { + String key=columns[0].ToUpper().Trim(); + if(!header.ContainsKey(key))header.Add(columns[0].ToUpper().Trim(), ""); + } + } + return true; + } + protected void CreateColumns(String strLine) + { + columns = strLine.Split(',').ToList(); + if(null==columns)return; + columns=columns.Where(x=>!String.IsNullOrEmpty(x)).ToList(); + for (int index = 0; index < columns.Count; index++) + { + String columnName = columns[index]; + columnName=StringParser.ParseDelimitedString(columnName)[0]; + columns[index]=columnName; + } + } + public DataTable ToDataTable() + { + return CreateDataTable(); + } + private DataTable CreateDataTable() + { + DataTable dataTable = new DataTable(); + if (null == this.columns) return null; + String[] columns = this.columns.ToArray(); + CreateDataTableColumns(ref dataTable, columns); + for (int index = 0; index < rows.Count; index++) + { + FillData(ref dataTable, rows[index]); + } + return dataTable; + } + + private void CreateDataTableColumns(ref DataTable dataTable, String[] headerCols) + { + DataColumn dataColumn = null; + try + { + foreach (String columnName in headerCols) + { + dataColumn = new DataColumn(); + dataColumn.ColumnName = columnName; + dataColumn.DataType = Type.GetType("System.String"); + dataTable.Columns.Add(dataColumn); + } + } + catch (Exception ex) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("CreateColumns :{0}", ex)); + } + } + private void FillData(ref DataTable dataTable, List rowData) + { + DataRow newRow = dataTable.NewRow(); + try + { + for (int index = 0; index < rowData.Count && index < newRow.ItemArray.Count(); index++) newRow[index] = rowData[index]; + dataTable.Rows.Add(newRow); + } + catch (Exception ex) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("FillData :{0}", ex)); + throw; + } + } + } +} diff --git a/MarketData/MarketDataLib/CSVHelper/CSVFileExt2.cs b/MarketData/MarketDataLib/CSVHelper/CSVFileExt2.cs new file mode 100755 index 0000000..8316952 --- /dev/null +++ b/MarketData/MarketDataLib/CSVHelper/CSVFileExt2.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Data; +using System.Threading.Tasks; + +namespace MarketData.CSVHelper +{ + public class CSVFileExt2 : CSVFileExt + { + public CSVFileExt2() + { + } + public override Dictionary LoadCSVFile(StreamReader streamReader,int startDataRow) + { + try + { + DateTime modified = DateTime.Now; +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loading CSV File from stream")); + String strLine = null; + ReadHeaderRows(streamReader, startDataRow); + strLine = streamReader.ReadLine(); + CreateColumns(strLine); + int rowCount = 0; + while (null != (strLine = streamReader.ReadLine())) + { + if ("".Equals(strLine)) continue; + String[] rowData = StringParser.ParseDelimitedString(strLine); + if (1 == rowData.Length && rowData[0].Trim().ToUpper().Equals("**NOTE :")) break; + List rowDataList = rowData.ToList(); + rows.Add(rowDataList); + rowCount++; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loaded {0} rows from stream", rows.Count)); + return header; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + } + } + public override Dictionary LoadCSVFile(String strPathFileName, int startDataRow) + { + StreamReader streamReader = null; + try + { + DateTime modified = DateTime.Now; +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loading CSV File {0}", strPathFileName)); + streamReader = File.OpenText(strPathFileName); + String strLine = null; + ReadHeaderRows(streamReader, startDataRow); + strLine = streamReader.ReadLine(); + CreateColumns(strLine); + int rowCount = 0; + while (null != (strLine = streamReader.ReadLine())) + { + if ("".Equals(strLine)) continue; + String[] rowData = StringParser.ParseDelimitedString(strLine); + if (1 == rowData.Length && rowData[0].Trim().ToUpper().Equals("**NOTE :")) break; + List rowDataList = rowData.ToList(); + rows.Add(rowDataList); + rowCount++; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Loaded {0} rows from {1}", rows.Count, strPathFileName)); + return header; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + if (null != streamReader) streamReader.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/CSVHelper/ExtractFileHelper.cs b/MarketData/MarketDataLib/CSVHelper/ExtractFileHelper.cs new file mode 100755 index 0000000..cf76202 --- /dev/null +++ b/MarketData/MarketDataLib/CSVHelper/ExtractFileHelper.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; +using System.IO; +using System.IO.Compression; + +namespace MarketData.CSVHelper +{ + public class ExtractFileHelper + { + public static List GetExtractFiles(String extractFolder) + { + try + { + List fileList = new List(); + String[] arFileList = Directory.GetFiles(extractFolder, "*.csv"); + for (int index = 0; index < arFileList.Length; index++) fileList.Add(arFileList[index]); + return fileList; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception: {0}",exception.ToString())); + return null; + } + } + public static List ExtractToFolder(String strPathFileName, String extractToFolder) + { + List strPathExtractedFiles = new List(); + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Extracting contents of {0} to {1}", strPathFileName, extractToFolder)); + using (ZipArchive archive = ZipFile.OpenRead(strPathFileName)) + { + foreach (ZipArchiveEntry entry in archive.Entries) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Extracting {0}", entry.FullName)); + String strPathFullName = extractToFolder + "\\" + entry.FullName; + String strDirectoryName = null; + if (entry.FullName.Contains('\\') || entry.FullName.Contains('/')) strDirectoryName = Path.GetDirectoryName(entry.FullName); + if (null != strDirectoryName) + { + if (!Directory.Exists(extractToFolder + "\\" + strDirectoryName)) + { + Directory.CreateDirectory(extractToFolder + "\\" + strDirectoryName); + } + } + if (File.Exists(strPathFullName)) + { + try { File.Delete(strPathFullName); } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception removing file {0}, exception was {1}, continuing with extraction.", strPathFullName, exception.Message)); + } + } + try { entry.ExtractToFile(strPathFullName, true); } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Unable to extract the file {0} from {1}, exception was {2}", strPathFullName, strPathFileName, exception.Message)); + continue; + } + strPathExtractedFiles.Add(strPathFullName); + } + } + return strPathExtractedFiles; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return strPathExtractedFiles; + } + } + public static void RemoveZipFile(String strPathFileName) + { + try + { + File.Delete(strPathFileName); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + } + } + } +} diff --git a/MarketData/MarketDataLib/CSVHelper/StringParser.cs b/MarketData/MarketDataLib/CSVHelper/StringParser.cs new file mode 100755 index 0000000..34df927 --- /dev/null +++ b/MarketData/MarketDataLib/CSVHelper/StringParser.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace MarketData.CSVHelper +{ + public class StringParser + { + private StringParser() + { + } + public static string[] ParseDelimitedString(string arguments, char delim = ',') + { + var regex = new Regex("(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)"); + List values = new List(); + foreach (Match m in regex.Matches(arguments)) + { + String value = m.Value; + if (null != value && value.StartsWith("\"") && value.EndsWith("\"")) + { + value = value.Substring(1, value.Length - 2); + } + values.Add(value); + } + return values.ToArray(); + } + } +} diff --git a/MarketData/MarketDataLib/Cache/DividendHistoryCache.cs b/MarketData/MarketDataLib/Cache/DividendHistoryCache.cs new file mode 100755 index 0000000..cca6017 --- /dev/null +++ b/MarketData/MarketDataLib/Cache/DividendHistoryCache.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData; +using MarketData.Utils; +using MarketData.DataAccess; + +namespace MarketData.Cache +{ + // cache by symbol + div_ex_date + public class DividendHistoryByDixExYear:Dictionary + { + private int maxYear=int.MinValue; + private int minYear=int.MaxValue; + + public DividendHistoryByDixExYear() + { + } + public new void Add(int key,DividendHistory dividendHistory) + { + base.Add(key,dividendHistory); + if(key>maxYear) maxYear=key; + if(key dividendHistoryCache=new Dictionary(); + private static DividendHistoryCache instance=null; + private Object thisLock=new Object(); + + private DividendHistoryCache() + { + } + public void Dispose() + { + lock(thisLock) + { + MDTrace.WriteLine(LogLevel.DEBUG,"[DividendHistoryCache:Dispose]Joined..."); + instance=null; + } + } + public static DividendHistoryCache GetInstance() + { + lock(typeof(DividendHistoryCache)) + { + if(null==instance) instance=new DividendHistoryCache(); + return instance; + } + } + public void ClearCache() + { + lock(typeof(DividendHistoryCache)) + { + dividendHistoryCache.Clear(); + } + } + public void Add(DividendHistory dividendHistory) + { + lock(typeof(DividendHistoryCache)) + { + int[] divExYears=dividendHistory.Select(x=>x.DivExDate.Year).Distinct().ToArray(); + String[] symbols=dividendHistory.Select(x=>x.Symbol).Distinct().ToArray(); + + foreach(String symbol in symbols) + { + foreach(int divExYear in divExYears) + { + DividendHistory historyList=new DividendHistory(dividendHistory.Where(x => x.DivExDate.Year.Equals(divExYear)&&x.Symbol.Equals(symbol)).ToList()); + Add(symbol,divExYear,historyList); + } + } + } + } + private void Add(String symbol,int divExYear,DividendHistory dividendHistory) + { + lock(typeof(DividendHistoryCache)) + { + if(!dividendHistoryCache.ContainsKey(symbol)) + { + DividendHistoryByDixExYear dividendHistoryByDivExYear=new DividendHistoryByDixExYear(); + dividendHistoryByDivExYear.Add(divExYear,dividendHistory); + dividendHistoryCache.Add(symbol,dividendHistoryByDivExYear); + } + else + { + DividendHistoryByDixExYear dividendHistoryByDixExYear=dividendHistoryCache[symbol]; + if(!dividendHistoryByDixExYear.ContainsKey(divExYear)) + { + dividendHistoryByDixExYear.Add(divExYear,dividendHistory); + } + } + } + } + public DividendHistory GetDividendHistory(String symbol, int[] divExYears) + { + DividendHistory dividendHistory=new DividendHistory(); + + foreach(int divExYear in divExYears) + { + if(!DividendHistoryCache.GetInstance().ContainsDividendHistory(symbol,divExYear)) + { + DividendHistory dividendHistoryList=DividendHistoryDA.GetDividendHistory(symbol,new int[] { divExYear }); + if(0==dividendHistoryList.Count) DividendHistoryCache.GetInstance().Add(symbol,divExYear,dividendHistoryList); + else DividendHistoryCache.GetInstance().Add(dividendHistoryList); + dividendHistory.AddRange(dividendHistoryList); + } + else + { + dividendHistory.AddRange(DividendHistoryCache.GetInstance().GetDividendHistory(symbol,divExYear)); + } + } + return dividendHistory; + } + private DividendHistory GetDividendHistory(String symbol,int divExYear) + { + lock(typeof(DividendHistoryCache)) + { + if(!dividendHistoryCache.ContainsKey(symbol)) return null; + DividendHistoryByDixExYear dividendHistoryByDixExYear=dividendHistoryCache[symbol]; + if(!dividendHistoryByDixExYear.ContainsKey(divExYear)) return null; + return dividendHistoryByDixExYear[divExYear]; + } + } + public bool ContainsDividendHistory(String symbol,int divExYear) + { + lock(typeof(DividendHistoryCache)) + { + if(!dividendHistoryCache.ContainsKey(symbol)) return false; + DividendHistoryByDixExYear dividendHistoryByDixExYear=dividendHistoryCache[symbol]; + if(!dividendHistoryByDixExYear.ContainsKey(divExYear)) return false; + return true; + } + } + } +} diff --git a/MarketData/MarketDataLib/Cache/GBPriceCache.cs b/MarketData/MarketDataLib/Cache/GBPriceCache.cs new file mode 100755 index 0000000..bb3b03b --- /dev/null +++ b/MarketData/MarketDataLib/Cache/GBPriceCache.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; +using System.Linq; +using MarketData.Helper; +using MarketData.Numerical; +using System.Threading; + + +// This cache is mainly used by the models. It is a short lived cache that gets cleared out every 2 minutes. +// This cache will attempt to load a price from the database if it is found in the cache. +namespace MarketData.Cache +{ + public class GBPriceCache + { + private Thread cacheMonitorThread=null; + private volatile bool threadRun=true; + private Object thisLock=new Object(); + private Dictionary priceCache=new Dictionary(); // the main cache + private Dictionary realTimePriceCache=new Dictionary(); // short lived cache of realtime prices gets cleared out every cacheRefreshAfter(ms) + private Dictionary nullCache=new Dictionary(); + private DateGenerator dateGenerator=new DateGenerator(); + private static GBPriceCache priceCacheInstance=null; + private int cacheRefreshAfter=120000; // the cache will be cleaned up after 2 minutes + + protected GBPriceCache() + { + cacheMonitorThread=new Thread(new ThreadStart(ThreadProc)); + cacheMonitorThread.Start(); + } + public static GBPriceCache GetInstance() + { + lock(typeof(GBPriceCache)) + { + if(null==priceCacheInstance) + { + priceCacheInstance=new GBPriceCache(); + } + return priceCacheInstance; + } + } + public void Clear() + { + lock(thisLock) + { + priceCache=new Dictionary(); + realTimePriceCache=new Dictionary(); + nullCache=new Dictionary(); + } + } + public void Dispose() + { + lock(thisLock) + { + if(null==priceCacheInstance || false==threadRun)return; + threadRun=false; + if(null!=cacheMonitorThread) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[GBPriceCache:Dispose]Thread state is '{0}'. Joining main thread...",Utility.ThreadStateToString(cacheMonitorThread))); + cacheMonitorThread.Join(5000); + this.cacheMonitorThread=null; + } + MDTrace.WriteLine(LogLevel.DEBUG,"[GBPriceCache:Dispose] End."); + priceCacheInstance=null; + } + } + public void ClearCacheOnOrBefore(DateTime onOrBeforeDate,bool collect=false) + { + lock(thisLock) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Clearing GBPriceCache cache."); + List symbols=new List(priceCache.Keys); + foreach(String symbol in symbols) + { + PricesByDate pricesByDate=priceCache[symbol]; + List symbolDates=new List(pricesByDate.Keys); + foreach(DateTime symbolDate in symbolDates) + { + if(symbolDate datesList = dateGenerator.GenerateHistoricalDates(earlierDate, laterDate); + datesList = datesList.Where(x => x >= earlierDate).ToList(); + return GetPrices(symbol, laterDate, datesList.Count); + } + +// The most recent price is returned at the lowest index + public Prices GetPrices(String symbol,DateTime startDate,int dayCount) + { + lock(thisLock) + { + List historicalDates=dateGenerator.GenerateHistoricalDates(startDate,dayCount+60); + Prices prices=null; + List missingDates=null; + foreach(DateTime historicalDate in historicalDates) + { + if(!ContainsPrice(symbol,historicalDate)) + { + String key=symbol+Utility.DateTimeToStringMMHDDHYYYY(historicalDate); + if(nullCache.ContainsKey(key)) continue; + if(null==missingDates)missingDates=new List(); + missingDates.Add(historicalDate); + } + } + if(null!=missingDates) + { + DateTime minDate=(from DateTime date in missingDates select date).Min(); + DateTime maxDate=(from DateTime date in missingDates select date).Max(); + prices=PricingDA.GetPrices(symbol,maxDate,minDate); + foreach(Price price in prices) AddPrice(price); + prices=new Prices(); + foreach(DateTime historicalDate in historicalDates) + { + if(!ContainsPrice(symbol,historicalDate)) + { + String key=symbol+Utility.DateTimeToStringMMHDDHYYYY(historicalDate); + if(!nullCache.ContainsKey(key)) nullCache.Add(key,true); + } + else + { + if(!priceCache.ContainsKey(symbol)) continue; + PricesByDate pricesByDate=priceCache[symbol]; + if(!pricesByDate.ContainsKey(historicalDate.Date)) continue; + prices.Add(pricesByDate[historicalDate]); + } + } + } + else + { + prices=new Prices(); + foreach(DateTime historicalDate in historicalDates) + { + if(!priceCache.ContainsKey(symbol)) continue; + if(!priceCache[symbol].ContainsKey(historicalDate.Date)) + { + continue; + } + prices.Add((priceCache[symbol])[historicalDate]); + } + } + return new Prices(prices.OrderByDescending(x => x.Date).ToList().Take(dayCount).ToList()); + } + } + private void AddPrice(Price price) + { + lock(thisLock) + { + if(null==price) return; + PricesByDate pricesByDate=null; + if(!priceCache.ContainsKey(price.Symbol)) + { + pricesByDate=new PricesByDate(); + pricesByDate.Add(price.Date,price); + priceCache.Add(price.Symbol,pricesByDate); + } + else + { + pricesByDate=priceCache[price.Symbol]; + if(pricesByDate.ContainsKey(price.Date.Date)) return; + pricesByDate.Add(price.Date.Date,price); + } + } + } + public bool ContainsPrice(String symbol,DateTime date) + { + if(!priceCache.ContainsKey(symbol)) return false; + PricesByDate pricesByDate=priceCache[symbol]; + if(!pricesByDate.ContainsKey(date.Date)) return false; + return true; + } + private void ThreadProc() + { + int quantums=0; + int quantumInterval=1000; + while(threadRun) + { + Thread.Sleep(quantumInterval); + if(!threadRun) break; + quantums+=quantumInterval; + if(quantums>cacheRefreshAfter) + { + quantums=0; + lock(thisLock) + { + realTimePriceCache.Clear(); + MDTrace.WriteLine(LogLevel.DEBUG,"Clearing GBPriceCache price cache."); + } + } + } + MDTrace.WriteLine(LogLevel.DEBUG,"[GBPriceCache:ThreadProc]Thread ended."); + } + } +} + diff --git a/MarketData/MarketDataLib/Cache/LocalPriceCache.cs b/MarketData/MarketDataLib/Cache/LocalPriceCache.cs new file mode 100755 index 0000000..4ef3294 --- /dev/null +++ b/MarketData/MarketDataLib/Cache/LocalPriceCache.cs @@ -0,0 +1,306 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using MarketData; +using MarketData.MarketDataModel; +using MarketData.Utils; +using MarketData.DataAccess; +using System.Threading; + +// This cache is mainly used by gainloss generator. This cache is intended to be front loaded and then used. +// This cache will not attempt to load an item that is not found. It does have a Refresh() that will reload only the most recent pricing data from the database in order to +// maintain the most updated pricing. +namespace MarketData.Cache +{ + public class LocalPriceCache + { + private Dictionary priceCache=new Dictionary(); + private static LocalPriceCache instance=null; + private Thread cacheMonitorThread=null; + private volatile bool threadRun=true; + private int cacheCycle=300000; +// private int cacheRefreshAfter=60000; + private Object thisLock=new Object(); + + private LocalPriceCache() + { + cacheMonitorThread=new Thread(new ThreadStart(ThreadProc)); + cacheMonitorThread.Start(); + } + public void Clear() + { + lock(thisLock) + { + priceCache=new Dictionary(); + } + } + public void Dispose() + { + lock(thisLock) + { + if(null==instance || false==threadRun)return; + threadRun=false; + if(null!=cacheMonitorThread) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LocalPriceCache:Dispose]Thread state is '{0}'. Joining main thread...",Utility.ThreadStateToString(cacheMonitorThread))); + cacheMonitorThread.Join(5000); + this.cacheMonitorThread=null; + } + MDTrace.WriteLine(LogLevel.DEBUG,"[LocalPriceCache:Dispose] End"); + instance=null; + } + } + public static LocalPriceCache GetInstance() + { + lock(typeof(LocalPriceCache)) + { + if(null==instance)instance=new LocalPriceCache(); + return instance; + } + } + + public void Refresh() + { + lock(typeof(LocalPriceCache)) + { + List symbols=new List(priceCache.Keys); + foreach(String symbol in symbols) + { + PricesByDate symbolPrices=priceCache[symbol]; + DateTime maxDateDb=PricingDA.GetLatestDate(symbol); // get the latest date in the database + DateTime maxDate=symbolPrices.MaxDate; // get the latest date in the cache + if(!maxDateDb.Date.Equals(maxDate.Date)) // if the cache date and the database date are not equal then reload the cache + { + Prices prices=PricingDA.GetPrices(symbol,symbolPrices.MinDate); // reload the prices for this symbol using the current minDate in the cache as a lower boundary + if(null==prices)continue; // if we can't load any prices for symbol then just continue + priceCache.Remove(symbol); // remove the pricing entries in the price cache for the symbol + priceCache.Add(symbol,prices.GetPricesByDate()); // reload the cache + } + else + { + Price price=PricingDA.GetPrice(symbol,maxDate); // the max date from the cache equals the max date from the database so just reload the latest price from the database + if(null==price)continue; // if no latest price then just continue + symbolPrices.Remove(maxDate); // remove the current price associated with the max date + symbolPrices.Add(maxDate,price); // reload the latest price for maxDate(symbol) into the cache + } + } + } + } + //public void Add(PortfolioTrades portfolioTrades) + //{ + // lock(typeof(LocalPriceCache)) + // { + // Profiler profiler=new Profiler(); + // profiler.Start(); + // List symbols=portfolioTrades.Symbols; + // foreach(String symbol in symbols) + // { + // if(ContainsSymbol(symbol))continue; + // DateTime minDate=portfolioTrades.GetMinTradeDate(symbol); + // Prices prices=PricingDA.GetPrices(symbol,minDate); + // if(null==prices)continue; + // if(!priceCache.ContainsKey(symbol))priceCache.Add(symbol,prices.GetPricesByDate()); + // } + // } + //} +// This version of Add(PortfolioTrades) will account for adding multiple lots at different times. So instead of just checking for the existance of the symbol in the cache +// we look to see if the symbol is in the cache and what dates are available. If the date range specified in the trade are not available then we load those date ranges. +// This is a brute force approach always maintaining the gap between successive TradeDates in th.e portfolio trades and the maximum date for the symbol in the database. +// So while it is inefficient in terms of memory usage it alleviates the need for figuring out contiguous price sections + public void Add(PortfolioTrades portfolioTrades) + { + lock(typeof(LocalPriceCache)) + { + Profiler profiler=new Profiler(); + profiler.Start(); + List symbols=portfolioTrades.Symbols; + foreach(String symbol in symbols) + { + DateTime minPortfolioTradeDate=portfolioTrades.GetMinTradeDate(symbol); + if(!ContainsSymbol(symbol)) + { + Prices prices=PricingDA.GetPrices(symbol,minPortfolioTradeDate); + if(null==prices)continue; + foreach(Price price in prices)Add(price); + } + else + { + DateTime minCacheDate=GetMinCacheDate(symbol); + if(minPortfolioTradeDate symbols=portfolioTrades.Symbols; + // foreach(String symbol in symbols) + // { + // DateTime minPortfolioTradeDate=portfolioTrades.GetMinTradeDate(symbol); + // DateTime maxPortfolioTradeDate=portfolioTrades.GetMaxTradeDate(symbol); + // if(!ContainsSymbol(symbol)) + // { + // Prices prices=null; + // if(Utility.IsEpoch(maxPortfolioTradeDate))prices=PricingDA.GetPrices(symbol,minPortfolioTradeDate); + // else prices=PricingDA.GetPrices(symbol,maxPortfolioTradeDate,minPortfolioTradeDate); + // if(null==prices)continue; + // foreach(Price price in prices)Add(price); + // } + // else + // { + // DateTime minCacheDate=GetMinCacheDate(symbol); + // if(minPortfolioTradeDate symbols,DateTime pricingDate) + { + foreach(String symbol in symbols) + { + if(ContainsPrice(symbol,pricingDate))continue; + Price price=PricingDA.GetPrice(symbol,pricingDate); + if(null==price)continue; + Add(price); + } + } + public void Add(Price price) + { + lock(typeof(LocalPriceCache)) + { + if(null==price)return; + if(ContainsPrice(price.Symbol,price.Date))return; + PricesByDate pricesByDate=null; + if(!priceCache.ContainsKey(price.Symbol)) + { + pricesByDate=new PricesByDate(); + pricesByDate.Add(price.Date,price); + priceCache.Add(price.Symbol,pricesByDate); + return; + } + pricesByDate=priceCache[price.Symbol]; + if(pricesByDate.ContainsKey(price.Date))return; + pricesByDate.Add(price.Date,price); + } + } + public DateTime GetMinCacheDate(String symbol) + { + if(!ContainsSymbol(symbol))return Utility.Epoch; + PricesByDate symbolPrices=priceCache[symbol]; + return symbolPrices.MinDate; + } + public void RemoveDate(DateTime date) + { + lock(typeof(LocalPriceCache)) + { + List symbols=new List(priceCache.Keys); + foreach(String key in symbols) + { + PricesByDate pricesByDate=priceCache[key]; + if(pricesByDate.ContainsKey(date))pricesByDate.Remove(date); + } + } + } + public Price GetPrice(String symbol,DateTime date) + { + lock(typeof(LocalPriceCache)) + { + if(!priceCache.ContainsKey(symbol))return null; + PricesByDate pricesByDate=priceCache[symbol]; + if(!pricesByDate.ContainsKey(date))return null; + return pricesByDate[date]; + } + } + public bool ContainsPrice(String symbol,DateTime date) + { + lock(typeof(LocalPriceCache)) + { + if(!priceCache.ContainsKey(symbol))return false; + PricesByDate pricesByDate=priceCache[symbol]; + if(!pricesByDate.ContainsKey(date))return false; + return true; + } + } + public bool ContainsPrice(List symbols,DateTime date) + { + lock(typeof(LocalPriceCache)) + { + foreach(String symbol in symbols)if(!ContainsPrice(symbol,date))return false; + return true; + } + } + public bool ContainsSymbol(String symbol) + { + lock(typeof(LocalPriceCache)) + { + if(priceCache.ContainsKey(symbol))return true; + return false; + } + } + public long Count() + { + long count=0; + List symbols=priceCache.Keys.ToList(); + foreach(String symbol in symbols) + { + PricesByDate pricesByDate=priceCache[symbol]; + count+=pricesByDate.Count; + } + return count; + } + private void ThreadProc() + { + int quantums=0; + int quantumInterval=1000; + long lastCount=0; + while(threadRun) + { + Thread.Sleep(quantumInterval); + quantums+=quantumInterval; + if(quantums>cacheCycle) + { + quantums=0; + lock(thisLock) + { + lastCount=Count(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("LocalPriceCache Symbols: {0}. Items in cache: {1}.",priceCache.Keys.Count,Utility.FormatNumber(lastCount,0,true))); + } + } + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LocalPriceCache:ThreadProc]Thread ended. Items in cache:{0}",Utility.FormatNumber(lastCount,0,true))); + } + } +} diff --git a/MarketData/MarketDataLib/Configuration/GlobalConfig.cs b/MarketData/MarketDataLib/Configuration/GlobalConfig.cs new file mode 100755 index 0000000..1983b99 --- /dev/null +++ b/MarketData/MarketDataLib/Configuration/GlobalConfig.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.Configuration; + +namespace MarketData.Configuration +{ + /// + /// This is a class that allows my legacy code to interact with the jsonsettings.config without requiring a complete rewrite of everything into dependency injection + /// The class need to be instantiated at program entry point and initilized with IConfigurationRoot + /// + public class GlobalConfig + { + private static GlobalConfig globalConfig = default; + + private GlobalConfig() + { + } + + public static GlobalConfig Instance + { + get + { + lock (typeof(GlobalConfig)) + { + if (null == globalConfig) + { + globalConfig = new GlobalConfig(); + } + return globalConfig; + } + } + } + + public IConfiguration Configuration { get; set; } = default; + } +} diff --git a/MarketData/MarketDataLib/DataAccess/AnalystPriceTargetDA.cs b/MarketData/MarketDataLib/DataAccess/AnalystPriceTargetDA.cs new file mode 100755 index 0000000..18d494b --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/AnalystPriceTargetDA.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class AnalystPriceTargetDA + { + private AnalystPriceTargetDA() + { + } + public static bool CheckAnalystPriceTargetModifiedOn(String symbol,DateTime modified) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + DateTime maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from analystpricetarget").Append(" "); + sb.Append("where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append("and date='").Append(Utility.DateTimeToStringYYYYHMMHDD(modified)).Append("'"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + sqlDataReader.Read(); + int recordCount = sqlDataReader.GetInt32(0); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static AnalystPriceTarget GetAnalystPriceTarget(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,mean_target,median_target,high_target,low_target from analystpricetarget where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and date=").Append(" (select max(date) from analystpricetarget where symbol='").Append(symbol).Append("')"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + AnalystPriceTarget analystPriceTarget = new AnalystPriceTarget(); + analystPriceTarget.Date = sqlDataReader.GetDateTime(0); + analystPriceTarget.Symbol = sqlDataReader.GetString(1); + if (!sqlDataReader.IsDBNull(2))analystPriceTarget.MeanTargetPrice = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(2))analystPriceTarget.MedianTargetPrice = sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(2))analystPriceTarget.HighTargetPrice = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(2))analystPriceTarget.LowTargetPrice = sqlDataReader.GetDouble(5); + return analystPriceTarget; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertAnalystPriceTarget(AnalystPriceTarget analystPriceTarget) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteAnalystPriceTarget(analystPriceTarget, sqlConnection, sqlTransaction); + sqlTransaction.Commit(); + sqlTransaction = sqlConnection.BeginTransaction(); + StringBuilder sb = new StringBuilder(); + sb.Append("insert into analystpricetarget (date,symbol,mean_target,median_target,high_target,low_target) "); + sb.Append("values("); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(analystPriceTarget.Date)).Append("'").Append(","); + sb.Append("'").Append(analystPriceTarget.Symbol).Append("'").Append(","); + if (!Double.IsNaN(analystPriceTarget.MeanTargetPrice)) sb.Append(analystPriceTarget.MeanTargetPrice).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(analystPriceTarget.MedianTargetPrice)) sb.Append(analystPriceTarget.MedianTargetPrice).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(analystPriceTarget.HighTargetPrice)) sb.Append(analystPriceTarget.HighTargetPrice).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(analystPriceTarget.LowTargetPrice)) sb.Append(analystPriceTarget.LowTargetPrice); + else sb.Append("null"); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteAnalystPriceTarget(AnalystPriceTarget analystPriceTarget, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from analystpricetarget where "); + sb.Append("symbol='").Append(analystPriceTarget.Symbol).Append("'"); + sb.Append(" and "); + sb.Append("date='").Append(Utility.DateTimeToStringYYYYHMMHDD(analystPriceTarget.Date)).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/AnalystRatingsDA.cs b/MarketData/MarketDataLib/DataAccess/AnalystRatingsDA.cs new file mode 100755 index 0000000..f086d19 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/AnalystRatingsDA.cs @@ -0,0 +1,653 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class AnalystRatingsDA + { + private AnalystRatingsDA() + { + } + public static AnalystRatings GetAnalystRatings() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + AnalystRatings analystRatings = new AnalystRatings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select A.* from "); + sb.Append("(select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings "); + sb.Append(" union "); + sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + sb.Append(" where zr.symbol=@symbol and zr.type is not null "); + sb.Append(" )A "); + sb.Append(" order by date desc "); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + AnalystRating analystRating = new AnalystRating(); + analystRating.Date = sqlDataReader.GetDateTime(0); + analystRating.Symbol = sqlDataReader.GetString(1); + analystRating.CompanyName = sqlDataReader.GetString(2); + analystRating.BrokerageFirm = sqlDataReader.GetString(3); + analystRating.Type = sqlDataReader.GetString(4); + analystRating.RatingsChange = sqlDataReader.GetString(5); + if (!sqlDataReader.IsDBNull(6)) analystRating.PriceTarget = sqlDataReader.GetDouble(6); + analystRatings.Add(analystRating); + } + analystRatings.CalculateUpdatePercentiles(); + return analystRatings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static AnalystRatings GetAnalystRatings(String symbol, DateTime minDate,DateTime maxDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + AnalystRatings analystRatings = new AnalystRatings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("set @symbol='").Append(symbol).Append("';"); + sb.Append("set @minDate='").Append(Utility.DateTimeToStringYYYYHMMHDD(minDate)).Append("';"); + sb.Append("set @maxDate='").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate)).Append("';"); + sb.Append(" select A.* from "); + sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=@symbol "); + sb.Append(" union "); + sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + sb.Append(" where zr.symbol=@symbol and zr.type is not null "); + sb.Append(" )A "); + sb.Append(" where A.date>=@minDate and A.date<=@maxDate "); + sb.Append(" order by date "); + + + //sb.Append(" select A.* from "); + //sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=").Append(SqlUtils.ToSqlString(symbol)); + //sb.Append(" union "); + //sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + //sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + //sb.Append(" where zr.symbol=").Append(SqlUtils.ToSqlString(symbol)).Append(" and zr.type is not null "); + //sb.Append(" )A "); + //sb.Append(" where A.date>=").Append(SqlUtils.SqlDate(minDate,true)).Append(" and A.date<=").Append(SqlUtils.SqlDate(maxDate,true)); + //sb.Append(" order by date "); + + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + AnalystRating analystRating = new AnalystRating(); + analystRating.Date = sqlDataReader.GetDateTime(0); + analystRating.Symbol = sqlDataReader.GetString(1); + analystRating.CompanyName = sqlDataReader.GetString(2); + analystRating.BrokerageFirm = sqlDataReader.GetString(3); + analystRating.Type = sqlDataReader.GetString(4); + analystRating.RatingsChange = sqlDataReader.GetString(5); + if (!sqlDataReader.IsDBNull(6)) analystRating.PriceTarget = sqlDataReader.GetDouble(6); + analystRatings.Add(analystRating); + } + analystRatings.CalculateUpdatePercentiles(); + return analystRatings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetMaxDateNoZacks() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(date) from analystratings where brokerage_firm<>'Zacks'"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return Utility.Epoch; + return sqlDataReader.GetDateTime(0); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return Utility.Epoch; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static AnalystRatings GetAnalystRatingsMaxDateNoZacks(String symbol,DateTime maxDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + AnalystRatings analystRatings = new AnalystRatings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings "); + sb.Append(" where symbol='").Append(symbol).Append("'").Append(" and "); + sb.Append(" date<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate)).Append("'").Append(" "); + sb.Append("order by date"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + AnalystRating analystRating = new AnalystRating(); + analystRating.Date = sqlDataReader.GetDateTime(0); + analystRating.Symbol = sqlDataReader.GetString(1); + analystRating.CompanyName = sqlDataReader.GetString(2); + analystRating.BrokerageFirm = sqlDataReader.GetString(3); + analystRating.Type = sqlDataReader.GetString(4); + analystRating.RatingsChange = sqlDataReader.GetString(5); + if (!sqlDataReader.IsDBNull(6)) analystRating.PriceTarget = sqlDataReader.GetDouble(6); + analystRatings.Add(analystRating); + } + analystRatings.CalculateUpdatePercentiles(); + return analystRatings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static AnalystRatings GetAnalystRatingsMaxDate(String symbol,DateTime maxDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + AnalystRatings analystRatings = new AnalystRatings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); +// sb.Append("set @symbol='").Append(symbol).Append("' COLLATE utf8mb4_unicode_ci ;"); + //sb.Append("set @symbol='").Append(symbol).Append("';"); + //sb.Append("set @maxDate='").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate)).Append("';"); + //sb.Append(" select A.* from "); + //sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=@symbol "); + //sb.Append(" union "); + //sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + //sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + //sb.Append(" where zr.symbol=@symbol and zr.type is not null "); + //sb.Append(" )A "); + //sb.Append(" where A.date<=@maxDate "); + //sb.Append(" order by date"); + + + + //sb.Append(" select A.* from "); + //sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=").Append(SqlUtils.ToSqlString(symbol)); + //sb.Append(" union "); + //sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + //sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + //sb.Append(" where zr.symbol=").Append(SqlUtils.ToSqlString(symbol)).Append(" and zr.type is not null "); + //sb.Append(" )A "); + //sb.Append(" where A.date<=").Append(SqlUtils.SqlDate(maxDate,true)); + //sb.Append(" order by date"); + + sb.Append("set @symbol='").Append(symbol).Append("';"); + sb.Append("set @maxDate='").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate)).Append("';"); + sb.Append(" select A.* from "); + sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=@symbol "); + sb.Append(" union "); + sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + sb.Append(" where zr.symbol=@symbol and zr.type is not null "); + sb.Append(" )A "); + sb.Append(" where A.date<=@maxDate "); + sb.Append(" order by date"); + + + + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + AnalystRating analystRating = new AnalystRating(); + analystRating.Date = sqlDataReader.GetDateTime(0); + analystRating.Symbol = sqlDataReader.GetString(1); + analystRating.CompanyName = sqlDataReader.GetString(2); + analystRating.BrokerageFirm = sqlDataReader.GetString(3); + analystRating.Type = sqlDataReader.GetString(4); + analystRating.RatingsChange = sqlDataReader.GetString(5); + if (!sqlDataReader.IsDBNull(6)) analystRating.PriceTarget = sqlDataReader.GetDouble(6); + analystRatings.Add(analystRating); + } + analystRatings.CalculateUpdatePercentiles(); + return analystRatings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static AnalystRatings GetAnalystRatings(String symbol, DateTime date) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + AnalystRatings analystRatings = new AnalystRatings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); +// sb.Append("set @symbol='").Append(symbol).Append("' COLLATE utf8mb4_unicode_ci ;"); + sb.Append("set @symbol='").Append(symbol).Append("';"); + sb.Append("set @date='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("';"); + sb.Append(" select A.* from "); + sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=@symbol "); + sb.Append(" union "); + sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + sb.Append(" where zr.symbol=@symbol and zr.type is not null "); + sb.Append(" )A "); + sb.Append(" where A.date=@date "); + sb.Append(" order by A.symbol"); + + //sb.Append(" select A.* from "); + //sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=").Append(SqlUtils.ToSqlString(symbol)); + //sb.Append(" union "); + //sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + //sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + //sb.Append(" where zr.symbol=@symbol and zr.type is not null "); + //sb.Append(" )A "); + //sb.Append(" where A.date=").Append(SqlUtils.SqlDate(date,true)); + //sb.Append(" order by A.symbol"); + + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + AnalystRating analystRating = new AnalystRating(); + analystRating.Date = sqlDataReader.GetDateTime(0); + analystRating.Symbol = sqlDataReader.GetString(1); + analystRating.CompanyName = sqlDataReader.GetString(2); + analystRating.BrokerageFirm = sqlDataReader.GetString(3); + analystRating.Type = sqlDataReader.GetString(4); + analystRating.RatingsChange = sqlDataReader.GetString(5); + if (!sqlDataReader.IsDBNull(6)) analystRating.PriceTarget = sqlDataReader.GetDouble(6); + analystRatings.Add(analystRating); + } + analystRatings.CalculateUpdatePercentiles(); + return analystRatings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static AnalystRatings GetAnalystRatings(DateTime date) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + AnalystRatings analystRatings = new AnalystRatings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + //sb.Append("set @date='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("';"); + //sb.Append(" select A.* from "); + //sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings "); + //sb.Append(" union "); + //sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + //sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + //sb.Append(" where zr.type is not null "); + //sb.Append(" )A "); + //sb.Append(" where A.date=@date "); + //sb.Append(" order by A.symbol; "); + + //sb.Append("set @date='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("';"); + sb.Append(" select A.* from "); + sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings "); + sb.Append(" union "); + sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + sb.Append(" where zr.type is not null "); + sb.Append(" )A "); + sb.Append(" where A.date=").Append(SqlUtils.SqlDate(date,true)); + sb.Append(" order by A.symbol; "); + + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + AnalystRating analystRating = new AnalystRating(); + analystRating.Date = sqlDataReader.GetDateTime(0); + analystRating.Symbol = sqlDataReader.GetString(1); + analystRating.CompanyName = sqlDataReader.GetString(2); + analystRating.BrokerageFirm = sqlDataReader.GetString(3); + analystRating.Type = sqlDataReader.GetString(4); + analystRating.RatingsChange = sqlDataReader.GetString(5); + if (!sqlDataReader.IsDBNull(6)) analystRating.PriceTarget = sqlDataReader.GetDouble(6); + analystRatings.Add(analystRating); + } + analystRatings.CalculateUpdatePercentiles(); + return analystRatings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static AnalystRatings GetAnalystRatings(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + AnalystRatings analystRatings = new AnalystRatings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + + //sb.Append(" set @symbol='").Append(symbol).Append("';"); + //sb.Append(" select A.* from "); + //sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=@symbol "); + //sb.Append(" union "); + //sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + //sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + //sb.Append(" where zr.symbol=@symbol and zr.type is not null "); + //sb.Append(" )A "); + //sb.Append(" order by date desc "); + + //sb.Append(" select A.* from "); + //sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=").Append(SqlUtils.ToSqlString(symbol)); + //sb.Append(" union "); + //sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + //sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + //sb.Append(" where zr.symbol=").Append(SqlUtils.ToSqlString(symbol)).Append(" and zr.type is not null "); + //sb.Append(" )A "); + //sb.Append(" order by date desc "); + + sb.Append(" set @symbol='").Append(symbol).Append("';"); + sb.Append(" select A.* from "); + sb.Append(" (select date,symbol,upper(company),brokerage_firm,type,ratings_change,price_target from analystratings where symbol=@symbol "); + sb.Append(" union "); + sb.Append(" select zr.date,zr.symbol,upper(sm.company) as company,'Zacks' as brokerage_firm,zr.type,zr.zacks_rank as ratings_change,null as price_target from zacksrank zr "); + sb.Append(" left join securitymaster sm on sm.symbol=zr.symbol "); + sb.Append(" where zr.symbol=@symbol and zr.type is not null "); + sb.Append(" )A "); + sb.Append(" order by date desc "); + + + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + AnalystRating analystRating = new AnalystRating(); + analystRating.Date = sqlDataReader.GetDateTime(0); + analystRating.Symbol = sqlDataReader.GetString(1); + analystRating.CompanyName = sqlDataReader.GetString(2); + analystRating.BrokerageFirm = sqlDataReader.GetString(3); + analystRating.Type = sqlDataReader.GetString(4); + analystRating.RatingsChange = sqlDataReader.GetString(5); + if (!sqlDataReader.IsDBNull(6)) analystRating.PriceTarget = sqlDataReader.GetDouble(6); + analystRatings.Add(analystRating); + } + analystRatings.CalculateUpdatePercentiles(); + return analystRatings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// **************************************************************************************************************************************************** + public static List GetAnalystRatingsDates() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + List analystRatingsDates = new List(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct date from analystratings order by date desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DateTime ratingDate = sqlDataReader.GetDateTime(0); + analystRatingsDates.Add(Utility.DateTimeToStringMMHDDHYYYY(ratingDate)); + } + return analystRatingsDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertAnalystRatings(AnalystRatings analystRatings) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + + try + { + if (null == analystRatings || 0 == analystRatings.Count) return true; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteAnalystRatings(analystRatings, sqlConnection, sqlTransaction); + for (int index = 0; index < analystRatings.Count; index++) + { + AnalystRating analystRating = analystRatings[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into analystratings (date,symbol,company,brokerage_firm,type,ratings_change,price_target) "); + sb.Append("values("); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(analystRating.Date)).Append("'").Append(","); + sb.Append("'").Append(analystRating.Symbol).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.SqlString(analystRating.CompanyName)).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.SqlString(analystRating.BrokerageFirm)).Append("'").Append(","); + sb.Append("'").Append(analystRating.Type).Append("'").Append(","); + sb.Append("'").Append(analystRating.RatingsChange).Append("'").Append(","); + if (!Double.IsNaN(analystRating.PriceTarget)) sb.Append(analystRating.PriceTarget); + else sb.Append("null"); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool ContainsAnalystRating(AnalystRating analystRating) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select count(*) from analystratings where "); + sb.Append("symbol='").Append(analystRating.Symbol).Append("'").Append(" and "); + sb.Append("date='").Append(Utility.DateTimeToStringYYYYHMMHDD(analystRating.Date)).Append("'").Append(" and "); + sb.Append("brokerage_firm='").Append(SqlUtils.SqlString(analystRating.BrokerageFirm)).Append("'"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return false; + int count = sqlDataReader.GetInt32(0); + return count > 0 ? true : false; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + MDTrace.WriteLine(LogLevel.DEBUG, "Query was '" + strQuery + "'"); + return false; + } + finally + { + if (null != sqlDataReader) {sqlDataReader.Close(); sqlDataReader.Dispose();} + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteAnalystRatings(AnalystRatings analystRatings, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + try + { + foreach (AnalystRating analystRating in analystRatings) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + sb.Append("delete from analystratings where "); + sb.Append("symbol='").Append(analystRating.Symbol).Append("'"); + sb.Append(" and "); + sb.Append("date='").Append(Utility.DateTimeToStringYYYYHMMHDD(analystRating.Date)).Append("'").Append(" "); + sb.Append("and brokerage_firm='").Append(SqlUtils.SqlString(analystRating.BrokerageFirm)).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + } + } + } +} + diff --git a/MarketData/MarketDataLib/DataAccess/BalanceSheetDA.cs b/MarketData/MarketDataLib/DataAccess/BalanceSheetDA.cs new file mode 100755 index 0000000..204b9b1 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/BalanceSheetDA.cs @@ -0,0 +1,618 @@ +using System; +using System.Text; +using System.Collections.Generic; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class BalanceSheetDA + { + private BalanceSheetDA() + { + } +// ********************************************* B A L A N C E S H E E T ************************************** +// get the greatest date on record that is on or before asof date + public static DateTime? GetMaxDateFromBalanceSheet(String symbol, DateTime asof,BalanceSheet.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate=null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select asof from balancesheet where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and asof<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("' "); + sb.Append("and period=").Append(periodType.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append(" order by asof desc "); + sb.Append(" limit 1").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + if(!sqlDataReader.IsDBNull(0))maxDate=sqlDataReader.GetDateTime(0); + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static double GetTotalStockHolderEquityOnOrBefore(String symbol, DateTime asof,BalanceSheet.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + double totalStockholderEquity=double.NaN; + + try + { + DateTime? maxDate=GetMaxDateFromBalanceSheet(symbol,asof,periodType); + if(null==maxDate)return double.NaN; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select total_stockholder_equity from balancesheet where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate.Value)).Append("'"); + sb.Append(" limit 1").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return double.NaN; + if(!sqlDataReader.IsDBNull(0))totalStockholderEquity=sqlDataReader.GetDouble(0); + return totalStockholderEquity; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return double.NaN; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static BalanceSheet GetBalanceSheetOnOrBefore(String symbol, DateTime asof,BalanceSheet.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + DateTime? maxDate=GetMaxDateFromBalanceSheet(symbol,asof,periodType); + if(null==maxDate)return null; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,long_term_debt,other_liabilities,deferred_long_term_liabilities,minority_interest,negative_goodwill,total_stockholder_equity,inventory,property_plant_and_equipment,intangible_assets,accumulated_amortization,goodwill,period,total_assets,total_current_assets,total_liabilities,total_current_liabilities,cash_and_cash_equivalents,modified from balancesheet where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate.Value)).Append("'"); + sb.Append(" limit 1").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + BalanceSheet balanceSheet=new BalanceSheet(); + balanceSheet.Symbol=sqlDataReader.GetString(0); + balanceSheet.AsOf=sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2))balanceSheet.LongTermDebt= sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3))balanceSheet.OtherLiabilities=sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4))balanceSheet.DeferredLongTermLiabilities=sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5))balanceSheet.MinorityInterest=sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6))balanceSheet.NegativeGoodwill=sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7)) balanceSheet.TotalStockHolderEquity = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) balanceSheet.Inventory = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) balanceSheet.PropertyPlantAndEquipment = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) balanceSheet.IntangibleAssets = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) balanceSheet.AccumulatedAmortization = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) balanceSheet.Goodwill = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) balanceSheet.Period = sqlDataReader.GetInt32(13) == 0 ? BalanceSheet.PeriodType.Annual : BalanceSheet.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(14)) balanceSheet.TotalAssets = sqlDataReader.GetDouble(14); + if (!sqlDataReader.IsDBNull(15)) balanceSheet.TotalCurrentAssets = sqlDataReader.GetDouble(15); + if (!sqlDataReader.IsDBNull(16)) balanceSheet.TotalLiabilities = sqlDataReader.GetDouble(16); + if (!sqlDataReader.IsDBNull(17)) balanceSheet.TotalCurrentLiabilities = sqlDataReader.GetDouble(17); + if (!sqlDataReader.IsDBNull(18)) balanceSheet.CashAndCashEquivalents = sqlDataReader.GetDouble(18); + if (!sqlDataReader.IsDBNull(19)) balanceSheet.Modified = sqlDataReader.GetDateTime(19); + return balanceSheet; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool CheckBalanceSheetModifiedOn(String symbol, DateTime modified,BalanceSheet.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from balancesheet"); + sb.Append(" where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and period=").Append(periodType.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append("").Append(" "); + sb.Append("and modified='").Append(Utility.DateTimeToStringYYYYHMMHDD(modified)).Append("'"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + sqlDataReader.Read(); + int recordCount = sqlDataReader.GetInt32(0); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetBalanceSheetDates(String symbol,BalanceSheet.PeriodType periodType) + { + List balanceSheetDates = new List(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select asof from balancesheet where symbol='").Append(symbol).Append("' "); + sb.Append("and period='").Append(periodType.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append("'"); + sb.Append(" order by 1 asc;"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + DateTime asof=sqlDataReader.GetDateTime(0); + balanceSheetDates.Add(asof); + } + return balanceSheetDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return balanceSheetDates; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime? GetLatestBalanceSheetDate(String symbol,BalanceSheet.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(asof) from balancesheet"); + sb.Append(" where symbol='").Append(symbol).Append("' "); + sb.Append(" and period=").Append(periodType.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (sqlDataReader.IsDBNull(0)) maxDate = null; + else maxDate = sqlDataReader.GetDateTime(0); + } + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return maxDate; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static BalanceSheet GetBalanceSheet(String symbol,BalanceSheet.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + DateTime? latestDate = GetLatestBalanceSheetDate(symbol,periodType); + if (null == latestDate) return null; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,long_term_debt,other_liabilities,deferred_long_term_liabilities,minority_interest,negative_goodwill,total_stockholder_equity,inventory,property_plant_and_equipment,intangible_assets,accumulated_amortization,goodwill,period,total_assets,total_current_assets,total_liabilities,total_current_liabilities,cash_and_cash_equivalents,modified from balancesheet where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(latestDate.Value)).Append("'").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + BalanceSheet balanceSheet=new BalanceSheet(); + balanceSheet.Symbol=sqlDataReader.GetString(0); + balanceSheet.AsOf=sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2))balanceSheet.LongTermDebt= sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3))balanceSheet.OtherLiabilities=sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4))balanceSheet.DeferredLongTermLiabilities=sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5))balanceSheet.MinorityInterest=sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6))balanceSheet.NegativeGoodwill=sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7))balanceSheet.TotalStockHolderEquity = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) balanceSheet.Inventory = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) balanceSheet.PropertyPlantAndEquipment = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) balanceSheet.IntangibleAssets = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) balanceSheet.AccumulatedAmortization = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) balanceSheet.Goodwill = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) balanceSheet.Period = sqlDataReader.GetInt32(13)==0?BalanceSheet.PeriodType.Annual:BalanceSheet.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(14)) balanceSheet.TotalAssets = sqlDataReader.GetDouble(14); + if (!sqlDataReader.IsDBNull(15)) balanceSheet.TotalCurrentAssets = sqlDataReader.GetDouble(15); + if (!sqlDataReader.IsDBNull(16)) balanceSheet.TotalLiabilities = sqlDataReader.GetDouble(16); + if (!sqlDataReader.IsDBNull(17)) balanceSheet.TotalCurrentLiabilities = sqlDataReader.GetDouble(17); + if (!sqlDataReader.IsDBNull(18)) balanceSheet.CashAndCashEquivalents = sqlDataReader.GetDouble(18); + if (!sqlDataReader.IsDBNull(19)) balanceSheet.Modified = sqlDataReader.GetDateTime(19); + return balanceSheet; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static BalanceSheet GetBalanceSheet(String symbol, DateTime asof,BalanceSheet.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,long_term_debt,other_liabilities,deferred_long_term_liabilities,minority_interest,negative_goodwill,total_stockholder_equity,inventory,property_plant_and_equipment,intangible_assets,accumulated_amortization,goodwill,period,total_assets,total_current_assets,total_liabilities,total_current_liabilities,cash_and_cash_equivalents,modified from balancesheet where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("'").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + BalanceSheet balanceSheet=new BalanceSheet(); + balanceSheet.Symbol=sqlDataReader.GetString(0); + balanceSheet.AsOf=sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2))balanceSheet.LongTermDebt= sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3))balanceSheet.OtherLiabilities=sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4))balanceSheet.DeferredLongTermLiabilities=sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5))balanceSheet.MinorityInterest=sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6))balanceSheet.NegativeGoodwill=sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7)) balanceSheet.TotalStockHolderEquity = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) balanceSheet.Inventory = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) balanceSheet.PropertyPlantAndEquipment = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) balanceSheet.IntangibleAssets = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) balanceSheet.AccumulatedAmortization = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) balanceSheet.Goodwill = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) balanceSheet.Period = sqlDataReader.GetInt32(13) == 0 ? BalanceSheet.PeriodType.Annual : BalanceSheet.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(14)) balanceSheet.TotalAssets = sqlDataReader.GetDouble(14); + if (!sqlDataReader.IsDBNull(15)) balanceSheet.TotalCurrentAssets = sqlDataReader.GetDouble(15); + if (!sqlDataReader.IsDBNull(16)) balanceSheet.TotalLiabilities = sqlDataReader.GetDouble(16); + if (!sqlDataReader.IsDBNull(17)) balanceSheet.TotalCurrentLiabilities = sqlDataReader.GetDouble(17); + if (!sqlDataReader.IsDBNull(18)) balanceSheet.CashAndCashEquivalents = sqlDataReader.GetDouble(18); + if (!sqlDataReader.IsDBNull(19)) balanceSheet.Modified = sqlDataReader.GetDateTime(19); + return balanceSheet; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static TimeSeriesCollection GetInventory(String symbol,BalanceSheet.PeriodType period) + { + TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,inventory from balancesheet where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and period=").Append(period.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append(" order by asof desc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + timeSeriesElement.Type = period.Equals(BalanceSheet.PeriodType.Quarterly) ? TimeSeriesElement.ElementType.QuarterlyInventory : TimeSeriesElement.ElementType.Inventory; + if (!sqlDataReader.IsDBNull(2)) timeSeriesElement.Value = sqlDataReader.GetDouble(2); + else continue; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static TimeSeriesCollection GetGoodwill(String symbol, BalanceSheet.PeriodType period) + { + TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,goodwill from balancesheet where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and period=").Append(period.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append(" order by asof desc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + timeSeriesElement.Type = period.Equals(BalanceSheet.PeriodType.Quarterly) ? TimeSeriesElement.ElementType.QuarterlyInventory : TimeSeriesElement.ElementType.Inventory; + if (!sqlDataReader.IsDBNull(2)) timeSeriesElement.Value = sqlDataReader.GetDouble(2); + else continue; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static TimeSeriesCollection GetTotalStockholderEquity(String symbol, BalanceSheet.PeriodType period) + { + TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,total_stockholder_equity from balancesheet where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and period=").Append(period.Equals(BalanceSheet.PeriodType.Annual) ? 0 : 1).Append(" order by asof desc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + timeSeriesElement.Type = period.Equals(BalanceSheet.PeriodType.Quarterly) ? TimeSeriesElement.ElementType.QuarterlyInventory : TimeSeriesElement.ElementType.Inventory; + if (!sqlDataReader.IsDBNull(2)) timeSeriesElement.Value = sqlDataReader.GetDouble(2); + else continue; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertBalanceSheets(List balanceSheets) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + + try + { + if(null==balanceSheets)return false; + DateTime modified = DateTime.Now; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteBalanceSheets(balanceSheets, sqlConnection, sqlTransaction); + for (int index = 0; index < balanceSheets.Count; index++) + { + BalanceSheet balanceSheet = balanceSheets[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into balancesheet (symbol,asof,long_term_debt,other_liabilities,deferred_long_term_liabilities,minority_interest,negative_goodwill,total_stockholder_equity,inventory,property_plant_and_equipment,intangible_assets,accumulated_amortization,goodwill,period,total_assets,total_current_assets,total_liabilities,total_current_liabilities,cash_and_cash_equivalents,modified) "); + sb.Append("values("); + sb.Append("'").Append(balanceSheet.Symbol).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(balanceSheet.AsOf)).Append("'").Append(","); + if (!Double.IsNaN(balanceSheet.LongTermDebt)) sb.Append(balanceSheet.LongTermDebt).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.OtherLiabilities)) sb.Append(balanceSheet.OtherLiabilities).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.DeferredLongTermLiabilities)) sb.Append(balanceSheet.DeferredLongTermLiabilities).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.MinorityInterest)) sb.Append(balanceSheet.MinorityInterest).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.NegativeGoodwill)) sb.Append(balanceSheet.NegativeGoodwill).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.TotalStockHolderEquity)) sb.Append(balanceSheet.TotalStockHolderEquity).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.Inventory)) sb.Append(balanceSheet.Inventory).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.PropertyPlantAndEquipment)) sb.Append(balanceSheet.PropertyPlantAndEquipment).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.IntangibleAssets)) sb.Append(balanceSheet.IntangibleAssets).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.AccumulatedAmortization)) sb.Append(balanceSheet.AccumulatedAmortization).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.Goodwill)) sb.Append(balanceSheet.Goodwill).Append(","); + else sb.Append("null").Append(","); + sb.Append(BalanceSheet.PeriodType.Annual.Equals(balanceSheet.Period)?0:1).Append(","); + if (!Double.IsNaN(balanceSheet.TotalAssets)) sb.Append(balanceSheet.TotalAssets).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.TotalCurrentAssets)) sb.Append(balanceSheet.TotalCurrentAssets).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.TotalLiabilities)) sb.Append(balanceSheet.TotalLiabilities).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.TotalCurrentLiabilities)) sb.Append(balanceSheet.TotalCurrentLiabilities).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(balanceSheet.CashAndCashEquivalents)) sb.Append(balanceSheet.CashAndCashEquivalents).Append(","); + else sb.Append("null").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(modified)).Append("'"); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '"+strQuery+"'"); + return false; + } + finally + { + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteBalanceSheets(List balanceSheets, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + for (int index = 0; index < balanceSheets.Count; index++) + { + DeleteBalanceSheet(balanceSheets[index], sqlConnection, sqlTransaction); + } + return true; + } + private static bool DeleteBalanceSheet(BalanceSheet balanceSheet, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from balancesheet where "); + sb.Append("symbol='").Append(balanceSheet.Symbol).Append("'"); + sb.Append(" and "); + sb.Append("asof='").Append(Utility.DateTimeToStringYYYYHMMHDD(balanceSheet.AsOf)).Append("'"); + sb.Append(" and period=").Append(balanceSheet.Period.Equals(BalanceSheet.PeriodType.Annual)?0:1); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/CashDA.cs b/MarketData/MarketDataLib/DataAccess/CashDA.cs new file mode 100755 index 0000000..8fae563 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/CashDA.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class CashDA + { + private CashDA() + { + } + public static bool AddTransaction(CashTransaction cashTransaction) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == cashTransaction) return false; + double accountBalance=GetBalance(cashTransaction.Account); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sqlTransaction = sqlConnection.BeginTransaction(); + StringBuilder sb = new StringBuilder(); + cashTransaction.Balance=accountBalance+(cashTransaction.Credit-cashTransaction.Debit); + sb.Append("insert into cash(account,date,description,credit,debit,balance) values("); + sb.Append(SqlUtils.AddQuotes(cashTransaction.Account)).Append(","); + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(cashTransaction.TransactionDate))).Append(","); + sb.Append(SqlUtils.AddQuotes(cashTransaction.Description)).Append(","); + sb.Append(cashTransaction.Credit).Append(","); + sb.Append(cashTransaction.Debit).Append(","); + sb.Append(accountBalance+cashTransaction.Credit-cashTransaction.Debit).Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + } + } +// get balance for specific account + public static double GetBalance(String account) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select balance from cash where account='").Append(account).Append("' and transaction_id=(select max(transaction_id) from cash where account='").Append(account).Append("')"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return double.NaN; + double accountBalance = sqlDataReader.GetDouble(0); + return accountBalance; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return double.NaN; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// get latest balance for all accounts + public static double GetBalance() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); +// sb.Append("select sum(a.balance) from (select account,balance,date from cash b group by account desc) a"); + sb.Append("select sum(balance) from cash"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return double.NaN; + double accountBalance = sqlDataReader.GetDouble(0); + return accountBalance; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return double.NaN; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/CashflowStatementDA.cs b/MarketData/MarketDataLib/DataAccess/CashflowStatementDA.cs new file mode 100755 index 0000000..84a6f93 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/CashflowStatementDA.cs @@ -0,0 +1,377 @@ +using System; +using System.Text; +using System.Collections.Generic; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class CashflowStatementDA + { + private CashflowStatementDA() + { + } +// ********************************************* B A L A N C E S H E E T ************************************** + public static CashflowStatement GetCashflowStatementOnOrBefore(String symbol, DateTime asof,CashflowStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,depreciation_and_amortization,deferred_income_taxes,stock_based_compensation,accounts_receivable,inventory,accounts_payable,accrued_liabilities,operating_cashflow,free_cashflow,period,modified from cashflowstatement where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(CashflowStatement.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("'"); + sb.Append(" order by asof desc");; + sb.Append(" limit 1").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + CashflowStatement cashflowStatement=new CashflowStatement(); + cashflowStatement.Symbol=sqlDataReader.GetString(0); + cashflowStatement.AsOf=sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2))cashflowStatement.DepreciationAndAmortization=sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3))cashflowStatement.DeferredIncomeTaxes=sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4))cashflowStatement.StockBasedCompensation=sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5))cashflowStatement.AccountsReceivable=sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6))cashflowStatement.Inventory=sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7))cashflowStatement.AccountsPayable=sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8))cashflowStatement.AccruedLiabilities=sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9))cashflowStatement.OperatingCashflow=sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10))cashflowStatement.FreeCashflow=sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) cashflowStatement.Period = sqlDataReader.GetInt32(11) == 0 ? CashflowStatement.PeriodType.Annual : CashflowStatement.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(12)) cashflowStatement.Modified = sqlDataReader.GetDateTime(12); + return cashflowStatement; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool CheckCashflowStatementModifiedOn(String symbol, DateTime modified,CashflowStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from cashflowstatement"); + sb.Append(" where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and period=").Append(periodType.Equals(CashflowStatement.PeriodType.Annual) ? 0 : 1).Append("").Append(" "); + sb.Append("and modified='").Append(Utility.DateTimeToStringYYYYHMMHDD(modified)).Append("'"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + sqlDataReader.Read(); + int recordCount = sqlDataReader.GetInt32(0); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetCashflowStatementDates(String symbol,CashflowStatement.PeriodType periodType) + { + List dates = new List(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select asof from cashflowstatement where symbol='").Append(symbol).Append("' "); + sb.Append("and period='").Append(periodType.Equals(CashflowStatement.PeriodType.Annual) ? 0 : 1).Append("'"); + sb.Append(" order by 1 asc;"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + DateTime asof=sqlDataReader.GetDateTime(0); + dates.Add(asof); + } + return dates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return dates; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime? GetLatestCashflowStatementDate(String symbol,CashflowStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(asof) from cashflowstatement"); + sb.Append(" where symbol='").Append(symbol).Append("' "); + sb.Append(" and period=").Append(periodType.Equals(CashflowStatement.PeriodType.Annual) ? 0 : 1); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (sqlDataReader.IsDBNull(0)) maxDate = null; + else maxDate = sqlDataReader.GetDateTime(0); + } + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return maxDate; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static CashflowStatement GetCashflowStatement(String symbol,CashflowStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + DateTime? latestDate = GetLatestCashflowStatementDate(symbol,periodType); + if (null == latestDate) return null; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,depreciation_and_amortization,deferred_income_taxes,stock_based_compensation,accounts_receivable,inventory,accounts_payable,accrued_liabilities,operating_cashflow,free_cashflow,period,modified from cashflowstatement where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(CashflowStatement.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(latestDate.Value)).Append("'").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + CashflowStatement cashflowStatement=new CashflowStatement(); + cashflowStatement.Symbol=sqlDataReader.GetString(0); + cashflowStatement.AsOf=sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2))cashflowStatement.DepreciationAndAmortization=sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3))cashflowStatement.DeferredIncomeTaxes=sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4))cashflowStatement.StockBasedCompensation=sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5))cashflowStatement.AccountsReceivable=sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6))cashflowStatement.Inventory=sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7))cashflowStatement.AccountsPayable=sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8))cashflowStatement.AccruedLiabilities=sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9))cashflowStatement.OperatingCashflow=sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10))cashflowStatement.FreeCashflow=sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) cashflowStatement.Period = sqlDataReader.GetInt32(11) == 0 ? CashflowStatement.PeriodType.Annual : CashflowStatement.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(12)) cashflowStatement.Modified = sqlDataReader.GetDateTime(12); + return cashflowStatement; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static CashflowStatement GetCashflowStatement(String symbol, DateTime asof,CashflowStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,depreciation_and_amortization,deferred_income_taxes,stock_based_compensation,accounts_receivable,inventory,accounts_payable,accrued_liabilities,operating_cashflow,free_cashflow,period,modified from cashflowstatement where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(CashflowStatement.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("'").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + CashflowStatement cashflowStatement=new CashflowStatement(); + cashflowStatement.Symbol=sqlDataReader.GetString(0); + cashflowStatement.AsOf=sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2))cashflowStatement.DepreciationAndAmortization=sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3))cashflowStatement.DeferredIncomeTaxes=sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4))cashflowStatement.StockBasedCompensation=sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5))cashflowStatement.AccountsReceivable=sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6))cashflowStatement.Inventory=sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7))cashflowStatement.AccountsPayable=sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8))cashflowStatement.AccruedLiabilities=sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9))cashflowStatement.OperatingCashflow=sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10))cashflowStatement.FreeCashflow=sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) cashflowStatement.Period = sqlDataReader.GetInt32(11) == 0 ? CashflowStatement.PeriodType.Annual : CashflowStatement.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(12)) cashflowStatement.Modified = sqlDataReader.GetDateTime(12); + return cashflowStatement; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertCashflowStatement(List cashflowStatements) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + + try + { + DateTime modified=DateTime.Now; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteCashflowStatements(cashflowStatements, sqlConnection, sqlTransaction); + for (int index = 0; index < cashflowStatements.Count; index++) + { + CashflowStatement cashflowStatement = cashflowStatements[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into cashflowstatement (symbol,asof,depreciation_and_amortization,deferred_income_taxes,stock_based_compensation,accounts_receivable,inventory,accounts_payable,accrued_liabilities,operating_cashflow,free_cashflow,period,modified) "); + sb.Append("values("); + sb.Append("'").Append(cashflowStatement.Symbol).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(cashflowStatement.AsOf)).Append("'").Append(","); + if (!Double.IsNaN(cashflowStatement.DepreciationAndAmortization)) sb.Append(cashflowStatement.DepreciationAndAmortization).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(cashflowStatement.DeferredIncomeTaxes)) sb.Append(cashflowStatement.DeferredIncomeTaxes).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(cashflowStatement.StockBasedCompensation)) sb.Append(cashflowStatement.StockBasedCompensation).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(cashflowStatement.AccountsReceivable)) sb.Append(cashflowStatement.AccountsReceivable).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(cashflowStatement.Inventory)) sb.Append(cashflowStatement.Inventory).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(cashflowStatement.AccountsPayable)) sb.Append(cashflowStatement.AccountsPayable).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(cashflowStatement.AccruedLiabilities)) sb.Append(cashflowStatement.AccruedLiabilities).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(cashflowStatement.OperatingCashflow)) sb.Append(cashflowStatement.OperatingCashflow).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(cashflowStatement.FreeCashflow)) sb.Append(cashflowStatement.FreeCashflow).Append(","); + else sb.Append("null").Append(","); + sb.Append(CashflowStatement.PeriodType.Annual.Equals(cashflowStatement.Period)?0:1).Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(modified)).Append("'"); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '"+strQuery+"'"); + return false; + } + finally + { + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteCashflowStatements(List cashflowStatements, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + for (int index = 0; index < cashflowStatements.Count; index++) + { + DeleteCashflowStatement(cashflowStatements[index], sqlConnection, sqlTransaction); + } + return true; + } + private static bool DeleteCashflowStatement(CashflowStatement cashflowStatement, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from cashflowstatement where "); + sb.Append("symbol='").Append(cashflowStatement.Symbol).Append("'"); + sb.Append(" and "); + sb.Append("asof='").Append(Utility.DateTimeToStringYYYYHMMHDD(cashflowStatement.AsOf)).Append("'"); + sb.Append(" and period=").Append(cashflowStatement.Period.Equals(CashflowStatement.PeriodType.Annual)?0:1); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/CompanyProfileDA.cs b/MarketData/MarketDataLib/DataAccess/CompanyProfileDA.cs new file mode 100755 index 0000000..36e45c4 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/CompanyProfileDA.cs @@ -0,0 +1,247 @@ +using System; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class CompanyProfileDA + { + private CompanyProfileDA() + { + } +// *********************************************************************************************************** +// ************************************** C O M P A N Y P R O F I L E ************************************* +// *********************************************************************************************************** + public static bool UpdateCompanyProfile(CompanyProfile companyProfile) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == companyProfile || null == companyProfile.Symbol) return false; + if(!PricingDA.SecurityExists(companyProfile.Symbol))return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + + if(null!=companyProfile.Industry || null!=companyProfile.Sector) + { + StringBuilder sb = new StringBuilder(); + sb.Append("update securitymaster "); + sb.Append("set "); + if((null!=companyProfile.Sector && !"".Equals(companyProfile.Sector)) && (null != companyProfile.Industry && !"".Equals(companyProfile.Industry))) + { + sb.Append("Sector=").Append(SqlUtils.AddQuotes(companyProfile.Sector)).Append(", "); + sb.Append("Industry=").Append(SqlUtils.AddQuotes(companyProfile.Industry)).Append(" "); + } + else if(null!=companyProfile.Industry && !"".Equals(companyProfile.Industry)) + { + sb.Append("Industry=").Append(SqlUtils.AddQuotes(companyProfile.Industry)).Append(" "); + } + else if(null!=companyProfile.Sector&&!"".Equals(companyProfile.Industry)) + { + sb.Append("Sector=").Append(SqlUtils.AddQuotes(companyProfile.Sector)).Append(" "); + } + sb.Append(" where symbol=").Append(SqlUtils.AddQuotes(companyProfile.Symbol)); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + if(!CompanyProfileDetailsExists(companyProfile,sqlConnection,sqlTransaction))InsertCompanyProfileDescription(companyProfile,sqlConnection,sqlTransaction); + else UpdateCompanyProfileDescription(companyProfile,sqlConnection,sqlTransaction); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static CompanyProfiles GetCompanyProfiles() + { + CompanyProfiles companyProfiles=new CompanyProfiles(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select sm.symbol,sm.sector,sm.industry,sm.security_type,sm.company,cp.description,cp.pricing_source,cp.can_roll_previous,cp.freeze_pricing from securitymaster sm left outer join companyprofile cp on sm.symbol=cp.symbol"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + CompanyProfile companyProfile = new CompanyProfile(); + companyProfile.Symbol=sqlDataReader.GetString(0); + if (!sqlDataReader.IsDBNull(1)) companyProfile.Sector = sqlDataReader.GetString(1); + if (!sqlDataReader.IsDBNull(2)) companyProfile.Industry = sqlDataReader.GetString(2); + if (!sqlDataReader.IsDBNull(3)) companyProfile.SecurityType = sqlDataReader.GetString(3); + if (!sqlDataReader.IsDBNull(4)) companyProfile.CompanyName = sqlDataReader.GetString(4); + if (!sqlDataReader.IsDBNull(5)) companyProfile.Description = sqlDataReader.GetString(5); + if (!sqlDataReader.IsDBNull(6)) companyProfile.PricingSource = sqlDataReader.GetString(6).ToUpper(); + if (!sqlDataReader.IsDBNull(7)) companyProfile.CanRollPrevious = sqlDataReader.GetBoolean(7); + if (!sqlDataReader.IsDBNull(8)) companyProfile.FreezePricing = sqlDataReader.GetBoolean(8); + companyProfiles.Add(companyProfile); + } + return companyProfiles; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static CompanyProfile GetCompanyProfile(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select sm.sector,sm.industry,sm.security_type,sm.company,cp.description,cp.pricing_source,cp.can_roll_previous,cp.freeze_pricing from securitymaster sm left outer join companyprofile cp on sm.symbol=cp.symbol where sm.symbol='"); + sb.Append(symbol).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + CompanyProfile companyProfile = new CompanyProfile(); + companyProfile.Symbol = symbol; + if (!sqlDataReader.IsDBNull(0)) companyProfile.Sector = sqlDataReader.GetString(0); + if (!sqlDataReader.IsDBNull(1)) companyProfile.Industry = sqlDataReader.GetString(1); + if (!sqlDataReader.IsDBNull(2)) companyProfile.SecurityType = sqlDataReader.GetString(2); + if (!sqlDataReader.IsDBNull(3)) companyProfile.CompanyName = sqlDataReader.GetString(3); + if (!sqlDataReader.IsDBNull(4)) companyProfile.Description = sqlDataReader.GetString(4); + if (!sqlDataReader.IsDBNull(5)) companyProfile.PricingSource = sqlDataReader.GetString(5).ToUpper(); + if (!sqlDataReader.IsDBNull(6)) companyProfile.CanRollPrevious = sqlDataReader.GetBoolean(6); + if (!sqlDataReader.IsDBNull(7)) companyProfile.FreezePricing = sqlDataReader.GetBoolean(7); + return companyProfile; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + +// This handles the actual company profile table where we store additional company related informtion + private static bool CompanyProfileDetailsExists(CompanyProfile companyProfile,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == companyProfile || null == companyProfile.Symbol) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("select count(*) from CompanyProfile where symbol=").Append(SqlUtils.AddQuotes(companyProfile.Symbol)).Append(" and description is not null and description <>''"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read())return false; + return 0==sqlDataReader.GetInt32(0)?false:true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader){sqlDataReader.Close();sqlDataReader.Dispose();} + } + } + private static bool InsertCompanyProfileDescription(CompanyProfile companyProfile,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == companyProfile || null == companyProfile.Symbol || null==companyProfile.Description || "".Equals(companyProfile.Description.Trim())) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into CompanyProfile(symbol,description)values("); + sb.Append(SqlUtils.AddQuotes(companyProfile.Symbol)).Append(","); + sb.Append(SqlUtils.ToSqlString(companyProfile.Description.Trim())); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + } + } + private static bool UpdateCompanyProfileDescription(CompanyProfile companyProfile,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == companyProfile || null == companyProfile.Symbol || null==companyProfile.Description || "".Equals(companyProfile.Description)) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("update CompanyProfile set description=").Append(SqlUtils.ToSqlString(companyProfile.Description)); + sb.Append(" where symbol=").Append(SqlUtils.AddQuotes(companyProfile.Symbol)); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/CompositeDA.cs b/MarketData/MarketDataLib/DataAccess/CompositeDA.cs new file mode 100755 index 0000000..4d3808c --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/CompositeDA.cs @@ -0,0 +1,357 @@ +using System; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class CompositeDA + { + private CompositeDA() + { + } + public static FeedStatistics GetFeedStatistics(FeedStatistic.FeedStatisticType feedStatisticType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + FeedStatistics feedStatistics = new FeedStatistics(); + String strQuery; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + switch (feedStatisticType) + { + case FeedStatistic.FeedStatisticType.ZACKS_RANK: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Zacks Rank' description,count(*) records,date from zacksrank group by 3 order by date desc"); + break; + case FeedStatistic.FeedStatisticType.VALUATIONS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Valuations' description, count(*), valuation_date from valuations group by 3 order by valuation_date desc"); + break; + case FeedStatistic.FeedStatisticType.YIELD_CURVE: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Yield Curve' description,count(*), date from yieldcurve group by 3 order by date desc"); + break; + case FeedStatistic.FeedStatisticType.SPLITS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Splits' description,count(*), modified from splits group by 3 order by modified desc"); + break; + case FeedStatistic.FeedStatisticType.SECURITY_MASTER: +// sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Security Master' description,count(*), date(create_date) from securitymaster group by 3 order by create_date desc"); + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Security Master' description,count(*), date(create_date) from securitymaster group by 3 order by 3 desc"); + break; + case FeedStatistic.FeedStatisticType.SEC_FILINGS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'SEC Filings' description,count(*), filing_date from secfilings group by 3 order by filing_date desc"); + break; + case FeedStatistic.FeedStatisticType.PRICES: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Prices' description,count(*), date from prices group by 3 order by date desc"); + break; + case FeedStatistic.FeedStatisticType.OPTIONS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Options' description,count(*), modified from options where modified is not null group by 3 order by modified desc"); + break; + case FeedStatistic.FeedStatisticType.INSIDER_TRANSACTIONS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Insider Transactions' description,count(*), filing_date from insidertransaction group by 3 order by filing_date desc"); + break; + case FeedStatistic.FeedStatisticType.FUNDAMENTALS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Fundamentals' description,count(*), asof from fundamentals group by 3 order by asof desc"); + break; + case FeedStatistic.FeedStatisticType.INCOME_STATEMENT: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Income Statement' description,count(*), modified from incomestatement group by 3 order by modified desc"); + break; + case FeedStatistic.FeedStatisticType.CASHFLOW_STATEMENT: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Cashflow Statement' description,count(*), modified from cashflowstatement group by 3 order by modified desc"); + break; + case FeedStatistic.FeedStatisticType.BALANCE_SHEET: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Balance Sheet' description,count(*), modified from balancesheet group by 3 order by modified desc"); + break; + case FeedStatistic.FeedStatisticType.HISTORICAL: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Historical' description,count(*), asof from historical group by 3 order by asof desc"); + break; + case FeedStatistic.FeedStatisticType.HEADLINES: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Headlines' description,count(*), asof from headlines group by 3 having count(*) > 10 order by asof desc"); + break; + case FeedStatistic.FeedStatisticType.ETF_HOLDINGS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'ETF Holdings' description,count(*), modified from etfholdings group by 3 order by modified desc"); + break; + case FeedStatistic.FeedStatisticType.ECONOMIC_INDICATORS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Economic Indicators' description,count(*), Date(modified) from economicindicators group by 3 order by Date(modified) desc"); + break; + case FeedStatistic.FeedStatisticType.EARNINGS_ANNOUNCEMENTS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Earnings Announcements' description,count(*), period_ending from earningsannouncements group by 3 order by period_ending desc"); + break; + case FeedStatistic.FeedStatisticType.DIVIDEND_HISTORY: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Dividend History' description,count(*), CAST(modified AS DATE) modified from dividendhistory group by 3 order by CAST(modified AS DATE) desc"); + break; + case FeedStatistic.FeedStatisticType.CURRENCY_CONVERSION: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Currency Conversion' description,count(*), asof from currencyconversion group by 3 order by asof desc"); + break; + case FeedStatistic.FeedStatisticType.ANALYST_RATINGS: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Analyst Ratings' description,count(*), date from analystratings group by 3 order by date desc"); + break; + case FeedStatistic.FeedStatisticType.ANALYST_PRICE_TARGET: + sb.Append("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;select 'Analyst Price Target' description,count(*), date from analystpricetarget group by 3 order by date desc"); + break; + default: + return null; + } + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + FeedStatistic feedStatistic = new FeedStatistic(); + feedStatistic.Feed = sqlDataReader.GetString(0); + feedStatistic.Records = sqlDataReader.GetInt32(1); + feedStatistic.Date = sqlDataReader.GetDateTime(2); + feedStatistics.Add(feedStatistic); + } + return feedStatistics; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception.ToString()); + return null; + } + finally + { + if (null != sqlCommand) { sqlCommand.Dispose(); } + if (null != sqlDataReader) { sqlDataReader.Close(); sqlDataReader.Dispose(); } + if (null != sqlConnection) { sqlConnection.Close(); sqlConnection.Dispose(); } + } + } + public static TimeSeriesCollection GetDebtToEquity(String symbol) + { + TimeSeriesCollection timeSeriesCollection=new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + double prevStockHoldersEquity=double.NaN; + double prevTotalDebt=double.NaN; + int recordCount=0; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("set @symbol='").Append(symbol).Append("';"); + sb.Append("select A.symbol,A.year,A.total_debt,B.total_stockholder_equity,A.total_debt/B.total_stockholder_equity debt_to_equity from "); + sb.Append("( "); + sb.Append("select MIN(f.symbol) symbol,MIN(YEAR(f.asof))year,AVG(f.total_debt)total_debt from fundamentals f where symbol=").Append(SqlUtils.ToSqlString(symbol)); + sb.Append(" group by YEAR(f.asof) order by 2 asc "); + sb.Append(")A "); + sb.Append("left join "); + sb.Append("( "); + sb.Append("select MIN(bs.symbol)symbol,MIN(YEAR(bs.asof)) year,AVG(bs.total_stockholder_equity) total_stockholder_equity from balancesheet bs where symbol=").Append(SqlUtils.ToSqlString(symbol)).Append(" and period=0 "); + sb.Append("group by YEAR(bs.asof) order by 2 asc "); + sb.Append(")B "); + sb.Append("on A.symbol=B.symbol and A.year=B.year order by 2 asc"); + + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + double totalDebt=double.NaN; + double totalStockholderEquity=double.NaN; + double debtToEquity=double.NaN; + symbol=sqlDataReader.GetString(0); + int year=sqlDataReader.GetInt32(1); + if(!sqlDataReader.IsDBNull(2))totalDebt=sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3))totalStockholderEquity=sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4))debtToEquity=sqlDataReader.GetDouble(4); + + if(0==recordCount&&(double.IsNaN(totalDebt)||double.IsNaN(totalStockholderEquity)))continue; + if(double.IsNaN(totalStockholderEquity))totalStockholderEquity=prevStockHoldersEquity; + if(double.IsNaN(totalDebt))totalDebt=prevTotalDebt; + + TimeSeriesElement timeSeriesElement=new TimeSeriesElement(); + timeSeriesElement.Symbol=symbol; + timeSeriesElement.AsOf=new DateTime(year,1,1); + timeSeriesElement.Type=TimeSeriesElement.ElementType.OTHER; + timeSeriesElement.OtherType="DebtToEquity"; + timeSeriesElement.Value=totalDebt/totalStockholderEquity; + timeSeriesCollection.Add(timeSeriesElement); + recordCount++; + prevStockHoldersEquity=totalStockholderEquity; + prevTotalDebt=totalDebt; + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DividendLoadCollection GetDividendLoad(String symbol) + { + DividendLoadCollection dividendLoadCollection=new DividendLoadCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("SET @symbol='").Append(symbol).Append("';"); + sb.Append("select A.symbol,A.year,A.eps,B.cash_amount,B.records,(B.cash_amount/A.eps)*100.00 as dividend_load_pct from "); + sb.Append(" (select MIN(h.symbol) symbol,MIN(YEAR(h.asof)) year,min(h.value) eps from historical h "); + sb.Append(" where h.symbol=@symbol and h.type='eps' "); + sb.Append(" group by YEAR(h.asof))A "); + sb.Append(" inner join ( "); + sb.Append(" select MIN(symbol) symbol,sum(dh.cash_amount) cash_amount,count(*) records,YEAR(dh.payment_date) year from dividendhistory dh "); + sb.Append(" where dh.symbol=@symbol group by 4 "); + sb.Append(" )B "); + sb.Append(" on A.symbol=B.symbol and A.year=B.year "); + sb.Append(" order by 2 desc"); + + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + DividendLoadElement dividendLoadElement = new DividendLoadElement(); + if(!sqlDataReader.IsDBNull(0))dividendLoadElement.Symbol=sqlDataReader.GetString(0); + if(!sqlDataReader.IsDBNull(1))dividendLoadElement.Year=sqlDataReader.GetInt32(1); + if(!sqlDataReader.IsDBNull(2))dividendLoadElement.EPS=sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3))dividendLoadElement.CashAmount=sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4))dividendLoadElement.Payments=sqlDataReader.GetInt32(4); + if(!sqlDataReader.IsDBNull(5))dividendLoadElement.DividendLoadPcnt=sqlDataReader.GetDouble(5); + dividendLoadCollection.Add(dividendLoadElement); + } + return dividendLoadCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static CompanyProfiles GetCompanyProfiles(String watchListName) + { + CompanyProfiles companyProfiles=new CompanyProfiles(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select wl.symbol,sm.sector,sm.industry,sm.security_type,sm.company,cp.description "); + sb.Append("from portfolio_data.watchlist wl "); + sb.Append("join portfolio_data.watchlists wls on wls.watch_list_id=wl.watch_list_id "); + sb.Append("join market_data.securitymaster sm on sm.symbol=wl.symbol "); + sb.Append("left outer join market_data.companyprofile cp on cp.symbol=wl.symbol "); + sb.Append("where wls.watch_list_name='").Append(watchListName).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + CompanyProfile companyProfile = new CompanyProfile(); + companyProfile.Symbol=sqlDataReader.GetString(0); + if (!sqlDataReader.IsDBNull(1)) companyProfile.Sector = sqlDataReader.GetString(1); + if (!sqlDataReader.IsDBNull(2)) companyProfile.Industry = sqlDataReader.GetString(2); + if (!sqlDataReader.IsDBNull(3)) companyProfile.SecurityType = sqlDataReader.GetString(3); + if (!sqlDataReader.IsDBNull(4)) companyProfile.CompanyName = sqlDataReader.GetString(4).ToUpper(); + if (!sqlDataReader.IsDBNull(5)) companyProfile.Description = sqlDataReader.GetString(5); + companyProfiles.Add(companyProfile); + } + return companyProfiles; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static EarningsAnnouncementModel GetEarningsAnnouncement(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + EarningsAnnouncementModel earningsAnnouncementModel=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select f.symbol,f.asof as last_updated,p.date as pricing_date,p.close,p.open,f.pe,f.peg,(f.pe/f.peg)/100.00 as anticipated_earnings_growth,"); + sb.Append("case when f.peg<1 then 'UNDERVALUED' when f.peg>1 then 'OVERVALUED' else 'EQUILIBRIUM' end as peg_valuation,f.next_earnings_date,"); + sb.Append("datediff(f.next_earnings_date,curdate())as daysfromtoday,s.company,a.high_target as upside,(a.high_target-p.close)/p.close as upside_pcnt,"); + sb.Append("a.low_target as downside,(a.low_target-p.close)/p.close as downside_pcnt,a.date as price_target_asof "); + sb.Append(" from fundamentals f "); + sb.Append(" left outer join securitymaster s on s.symbol=f.symbol "); + sb.Append(" left outer join analystpricetarget a on a.symbol=s.symbol"); + sb.Append(" left outer join prices p on a.symbol=p.symbol "); + sb.Append(" where f.symbol='").Append(symbol).Append("' and f.asof=(select max(asof) from fundamentals where symbol='").Append(symbol).Append("')"); + sb.Append(" and a.symbol='").Append(symbol).Append("' and a.date=(select max(date) from analystpricetarget where symbol='").Append(symbol).Append("')"); + sb.Append(" and p.symbol='").Append(symbol).Append("' and p.date=(select max(date) from prices where symbol='").Append(symbol).Append("')"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + earningsAnnouncementModel=new EarningsAnnouncementModel(); + if(!sqlDataReader.IsDBNull(0))earningsAnnouncementModel.Symbol = sqlDataReader.GetString(0).ToUpper(); + if(!sqlDataReader.IsDBNull(1))earningsAnnouncementModel.FundamentalDate = sqlDataReader.GetDateTime(1); + if(!sqlDataReader.IsDBNull(2))earningsAnnouncementModel.PricingDate = sqlDataReader.GetDateTime(2); + if(!sqlDataReader.IsDBNull(3))earningsAnnouncementModel.LastPrice = sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(5))earningsAnnouncementModel.PE = sqlDataReader.GetDouble(5); + if(!sqlDataReader.IsDBNull(6))earningsAnnouncementModel.PEG = sqlDataReader.GetDouble(6); + if(!sqlDataReader.IsDBNull(7))earningsAnnouncementModel.AnticipatedEarningsGrowth = sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))earningsAnnouncementModel.PEGValuation = sqlDataReader.GetString(8); + if(!sqlDataReader.IsDBNull(9))earningsAnnouncementModel.NextEarningsDate = sqlDataReader.GetDateTime(9); + if(!sqlDataReader.IsDBNull(10))earningsAnnouncementModel.DaysFromToday = sqlDataReader.GetInt32(10); + if(!sqlDataReader.IsDBNull(11))earningsAnnouncementModel.CompanyName = sqlDataReader.GetString(11).ToUpper(); + if(!sqlDataReader.IsDBNull(12))earningsAnnouncementModel.Upside = sqlDataReader.GetDouble(12); + if(!sqlDataReader.IsDBNull(13))earningsAnnouncementModel.UpsidePcnt = sqlDataReader.GetDouble(13); + if(!sqlDataReader.IsDBNull(14))earningsAnnouncementModel.Downside = sqlDataReader.GetDouble(14); + if(!sqlDataReader.IsDBNull(15))earningsAnnouncementModel.DownsidePcnt = sqlDataReader.GetDouble(15); + if(!sqlDataReader.IsDBNull(16))earningsAnnouncementModel.PriceTargetDate = sqlDataReader.GetDateTime(16); + if(Utility.IsEpoch(earningsAnnouncementModel.NextEarningsDate))return null; + return earningsAnnouncementModel; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/ConsumerPriceIndexDA.cs b/MarketData/MarketDataLib/DataAccess/ConsumerPriceIndexDA.cs new file mode 100755 index 0000000..6f98200 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/ConsumerPriceIndexDA.cs @@ -0,0 +1,276 @@ +using System; +using System.Text; +using System.Collections.Generic; +using System.Linq; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class ConsumerPriceIndexDA + { + private ConsumerPriceIndexDA() + { + } + + public static List GetDistinctIndices() + { + MySqlConnection sqlConnection=null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + List indices = new List(); + try + + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlCommand=sqlConnection.CreateCommand(); + StringBuilder sb=new StringBuilder(); + sb.Append("select distinct(index_code) from PriceIndex "); + sb.Append("ORDER BY 1 desc"); + sqlCommand.CommandText=sb.ToString(); + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + indices.Add(sqlDataReader.GetString(0).ToUpper()); + } + sqlDataReader.Close(); + sqlDataReader.Dispose(); + sqlCommand.Dispose(); + sqlConnection.Close(); + sqlConnection.Dispose(); + return indices; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return null; + } + finally + { + if(null!=sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader.Dispose(); + } + if(null!=sqlCommand) + { + sqlCommand.Dispose(); + } + if(null!=sqlConnection) + { + sqlConnection.Close(); + sqlConnection.Dispose(); + } + } + } + + public static PriceIndices GetConsumerPriceIndex(String indexCode) + { + MySqlConnection sqlConnection=null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + PriceIndices priceIndices=new PriceIndices(); + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlCommand=sqlConnection.CreateCommand(); + StringBuilder sb=new StringBuilder(); + sb.Append("select index_code, index_name, index_value, as_of, source from PriceIndex "); + sb.Append("where index_code='").Append(indexCode).Append("'"); + sb.Append("ORDER BY as_of desc"); + sqlCommand.CommandText=sb.ToString(); + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + PriceIndex priceIndex=new PriceIndex(); + if(!sqlDataReader.IsDBNull(0))priceIndex.Code=sqlDataReader.GetString(0); + if(!sqlDataReader.IsDBNull(1))priceIndex.Name=sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))priceIndex.Value=sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3))priceIndex.AsOf=sqlDataReader.GetDateTime(3); + if(!sqlDataReader.IsDBNull(4))priceIndex.Source=sqlDataReader.GetString(4); + priceIndices.Add(priceIndex); + } + sqlDataReader.Close(); + sqlDataReader.Dispose(); + sqlCommand.Dispose(); + sqlConnection.Close(); + sqlConnection.Dispose(); + return priceIndices; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return null; + } + finally + { + if(null!=sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader.Dispose(); + } + if(null!=sqlCommand) + { + sqlCommand.Dispose(); + } + if(null!=sqlConnection) + { + sqlConnection.Close(); + sqlConnection.Dispose(); + } + } + } + public static PriceIndices GetConsumerPriceIndices() + { + MySqlConnection sqlConnection=null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + PriceIndices priceIndices=new PriceIndices(); + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlCommand=sqlConnection.CreateCommand(); + StringBuilder sb=new StringBuilder(); + sb.Append("select index_code, index_name, index_value, as_of, source from PriceIndex ORDER BY as_of desc"); + sqlCommand.CommandText=sb.ToString(); + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + PriceIndex priceIndex=new PriceIndex(); + if(!sqlDataReader.IsDBNull(0))priceIndex.Code=sqlDataReader.GetString(0); + if(!sqlDataReader.IsDBNull(1))priceIndex.Name=sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))priceIndex.Value=sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3))priceIndex.AsOf=sqlDataReader.GetDateTime(3); + if(!sqlDataReader.IsDBNull(4))priceIndex.Source=sqlDataReader.GetString(4); + priceIndices.Add(priceIndex); + } + sqlDataReader.Close(); + sqlDataReader.Dispose(); + sqlCommand.Dispose(); + sqlConnection.Close(); + sqlConnection.Dispose(); + return priceIndices; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return null; + } + finally + { + if(null!=sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader.Dispose(); + } + if(null!=sqlCommand) + { + sqlCommand.Dispose(); + } + if(null!=sqlConnection) + { + sqlConnection.Close(); + sqlConnection.Dispose(); + } + } + } + public static bool InsertUpdatePriceIndices(PriceIndices priceIndices) + { + MySqlConnection sqlConnection=null; + MySqlCommand sqlCommand=null; + MySqlTransaction sqlTransaction=null; + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted); + sqlCommand=sqlConnection.CreateCommand(); + sqlCommand.Transaction=sqlTransaction; + foreach(PriceIndex priceIndex in priceIndices) + { + DeletePriceIndex(priceIndex.Code,priceIndex.AsOf,sqlCommand,sqlTransaction); + } + InsertPriceIndices(priceIndices,sqlCommand,sqlTransaction); + sqlTransaction.Commit(); + sqlTransaction.Dispose(); + sqlCommand.Dispose(); + sqlConnection.Close(); + sqlConnection.Dispose(); + sqlConnection=null; + sqlCommand=null; + sqlTransaction=null; + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return false; + } + finally + { + if(null!=sqlConnection) + { + sqlConnection.Close(); + sqlConnection.Dispose(); + } + if(null!=sqlCommand) + { + sqlCommand.Dispose(); + } + if(null!=sqlTransaction) + { + sqlTransaction.Dispose(); + } + } + } + private static bool DeletePriceIndex(String indexCode,DateTime asOf,MySqlCommand sqlCommand,MySqlTransaction sqlTransaction) + { + String strQuery=null; + try + { + StringBuilder sb=new StringBuilder(); + sb.Append("delete from PriceIndex ").Append(" where "); + sb.Append("index_code=").Append("'").Append(indexCode).Append("'").Append(" and "); + sb.Append("as_of= ").Append(SqlUtils.SqlDate(asOf,true)); + strQuery=sb.ToString(); + sqlCommand.CommandText=strQuery; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}, query was {1}",exception.ToString(),strQuery)); + return false; + } + } + private static bool InsertPriceIndices(PriceIndices priceIndices,MySqlCommand sqlCommand,MySqlTransaction sqlTransaction) + { + String strQuery=null; + DateTime modified=DateTime.Now; + try + { + StringBuilder sb=new StringBuilder(); + foreach(PriceIndex priceIndex in priceIndices) + { + sb.Append("insert into PriceIndex(index_code,index_name,index_value,as_of,source,modified)values("); + sb.Append(SqlUtils.ToSqlString(priceIndex.Code)).Append(","); + sb.Append(SqlUtils.ToSqlString(priceIndex.Name)).Append(","); + sb.Append(priceIndex.Value).Append(","); + sb.Append(SqlUtils.SqlDate(priceIndex.AsOf,true)).Append(","); + sb.Append(SqlUtils.ToSqlString(priceIndex.Source)).Append(","); + sb.Append(SqlUtils.SqlDate(modified,true)); + sb.Append(");"); + } + strQuery=sb.ToString(); + sqlCommand.CommandText=sb.ToString(); + sqlCommand.ExecuteNonQuery(); + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return false; + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/CurrencyConversionDA.cs b/MarketData/MarketDataLib/DataAccess/CurrencyConversionDA.cs new file mode 100755 index 0000000..dc7ba4d --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/CurrencyConversionDA.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class CurrencyConversionDA + { + private CurrencyConversionDA() + { + } +// get the maximum date on record on or before asof. If maxDate turns out to be less than asof then return null + public static DateTime? GetMaxDateForCurrency(String sourceCurrency,String destinationCurrency,DateTime asof) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate=null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select asof from CurrencyConversion "); + sb.Append(" where "); + sb.Append("source_currency=").Append("'").Append(sourceCurrency).Append("'").Append(" "); + sb.Append("and ").Append(" destination_currency=").Append("'").Append(destinationCurrency).Append("'").Append(" "); + sb.Append("and asof<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("'"); + sb.Append(" order by asof desc "); + sb.Append(" limit 1"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return maxDate; + if(!sqlDataReader.IsDBNull(0))maxDate=sqlDataReader.GetDateTime(0); + if(maxDate dataSourceDictionary = new Dictionary(); + private static MainDataSource mainDataSource; + + private MainDataSource() + { + } + + public static MainDataSource Instance + { + get + { + lock (typeof(MainDataSource)) + { + if (null == mainDataSource) + { + mainDataSource = new MainDataSource(); + + IConfiguration configuration = GlobalConfig.Instance.Configuration; + DataSourceEx marketDataSource = new DataSourceEx(configuration, "market_data"); + mainDataSource.dataSourceDictionary.Add("market_data",marketDataSource); + + DataSourceEx portfolioDataSource = new DataSourceEx(configuration, "portfolio_data"); + mainDataSource.dataSourceDictionary.Add("portfolio_data",portfolioDataSource); + + DataSourceEx userDataSource = new DataSourceEx(configuration, "user_data"); + mainDataSource.dataSourceDictionary.Add("user_data",userDataSource); + } + return mainDataSource; + } + } + } + + public DataSourceEx LocateDataSource(String sourceKey) + { + return mainDataSource.dataSourceDictionary[sourceKey]; + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/DataSourceEx.cs b/MarketData/MarketDataLib/DataAccess/DataSourceEx.cs new file mode 100755 index 0000000..e5eae46 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/DataSourceEx.cs @@ -0,0 +1,91 @@ +using System; +using System.Text; +using System.Configuration; +using System.Collections.Generic; +using MarketData.Utils; +using Microsoft.Extensions.Configuration; + +namespace MarketData.DataAccess +{ + [Serializable] + public sealed class DataSourceEx + { + private string key; + private string database; + private string datasource; + private string username; + private string password; + private string port; + + public DataSourceEx(IConfiguration configuration,String configurationKey) + { + Dictionary dictionary = CreateConfigurationSettings(configuration, configurationKey); + Database = dictionary["Database"]; + Datasource = dictionary["Datasource"]; + Username = dictionary["Username"]; + Password = dictionary["Password"]; + } + + private Dictionary CreateConfigurationSettings(IConfiguration configuration, String configurationKey) + { + String marketData = configuration[configurationKey]; + + String[] elements = marketData.Split(';'); + Dictionary dictionary = new Dictionary(); + foreach (String element in elements) + { + String[] valuePairs = element.Split('='); + dictionary.Add(valuePairs[0], valuePairs[1]); + } + return dictionary; + } + + public string Key + { + get { return key; } + set { key = value; } + } + + public string Database + { + get { return database; } + set { database = value; } + } + + public string Datasource + { + get { return datasource; } + set { datasource = value; } + } + + public string Port + { + get { return port; } + set { port = value; } + } + + public string Password + { + get { return password; } + set { password = value; } + } + + public string Username + { + get { return username; } + set { username = value; } + } + + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("Key='").Append(key).Append("', "); + sb.Append("Database='").Append(database).Append("', "); + sb.Append("DataSource='").Append(datasource).Append("', "); + sb.Append("Port='").Append(port).Append("', "); + sb.Append("UserName='").Append(username).Append("', "); + sb.Append("Password='").Append(Utility.AsteriskForString(password)).Append("'"); + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/DataAccess/DictionaryDA.cs b/MarketData/MarketDataLib/DataAccess/DictionaryDA.cs new file mode 100755 index 0000000..800f8b3 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/DictionaryDA.cs @@ -0,0 +1,342 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class DictionaryDA + { + private DictionaryDA() + { + } + public static bool TruncateDictionary() + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + sb.Append("truncate table dictionary"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertDictionaryElement(DictionaryElement dictionaryElement) + { + DictionaryCollection dictionaryCollection=new DictionaryCollection(); + dictionaryCollection.Add(dictionaryElement); + InsertDictionaryCollection(dictionaryCollection); + return true; + } + public static bool InsertDictionaryCollection(DictionaryCollection dictionaryCollection) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + DateTime created=modified; + foreach(DictionaryElement dictionaryElement in dictionaryCollection) + { + sb=new StringBuilder(); + if(ContainsDictionaryElement(dictionaryElement)) + { + continue; + } + sb.Append("insert into dictionary (word,part_of_speech) "); + sb.Append("values("); + sb.Append(SqlUtils.ToSqlString(dictionaryElement.Word)).Append(","); + sb.Append("'").Append(dictionaryElement.PartOfSpeech).Append("'"); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool ContainsDictionaryElement(DictionaryElement dictionaryElement) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + int recordCount = 0; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from dictionary where word=").Append(SqlUtils.ToSqlString(dictionaryElement.Word)); + sb.Append(" and part_of_speech='").Append(dictionaryElement.PartOfSpeech).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) recordCount = sqlDataReader.GetInt32(0); + } + sqlCommand.Dispose(); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool UpdateDictionaryElement(DictionaryElement dictionaryElement) + { + DictionaryCollection dictionaryCollection=new DictionaryCollection(); + dictionaryCollection.Add(dictionaryElement); + return UpdateDictionaryElements(dictionaryCollection); + } + public static bool UpdateDictionaryElements(DictionaryCollection dictionaryCollection) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + foreach(DictionaryElement dictionaryElement in dictionaryCollection) + { + if(!ContainsDictionaryElement(dictionaryElement))continue; + if(null==dictionaryElement.PartOfSpeech||0==dictionaryElement.PartOfSpeech.Length)continue; + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("update dictionary set "); + sb.Append("part_of_speech=").Append("'").Append(dictionaryElement.PartOfSpeech).Append("'"); + sb.Append(" where word=").Append(SqlUtils.ToSqlString(dictionaryElement.Word)); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DictionaryCollection GetWord(String word) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + DictionaryCollection dictionaryCollection=new DictionaryCollection(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("select word,part_of_speech from dictionary "); + sb.Append(" where word=").Append(SqlUtils.ToSqlString(word)); + sb.Append(" order by word desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + DictionaryElement dictionaryElement=new DictionaryElement(); + dictionaryElement.Word=sqlDataReader.GetString(0); + if(!sqlDataReader.IsDBNull(1))dictionaryElement.PartOfSpeech=sqlDataReader.GetString(1); + dictionaryCollection.Add(dictionaryElement); + } + return dictionaryCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DictionaryCollection GetPartsOfSpeech(String partOfSpeech) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + DictionaryCollection dictionaryCollection=new DictionaryCollection(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("select word,part_of_speech from dictionary "); + sb.Append(" where part_of_speech='").Append(partOfSpeech).Append("'"); + sb.Append(" order by word desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + DictionaryElement dictionaryElement=new DictionaryElement(); + dictionaryElement.Word=sqlDataReader.GetString(0); + if(!sqlDataReader.IsDBNull(1))dictionaryElement.PartOfSpeech=sqlDataReader.GetString(1); + dictionaryCollection.Add(dictionaryElement); + } + return dictionaryCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DictionaryCollection GetDictionaryCollection() + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + DictionaryCollection dictionaryCollection=new DictionaryCollection(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("select word,part_of_speech from dictionary "); + sb.Append(" order by word desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + DictionaryElement dictionaryElement=new DictionaryElement(); + dictionaryElement.Word=sqlDataReader.GetString(0); + dictionaryElement.PartOfSpeech=sqlDataReader.GetString(1); + dictionaryCollection.Add(dictionaryElement); + } + return dictionaryCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteDictionaryCollection(DictionaryCollection dictionaryCollection, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + foreach(DictionaryElement dictionaryElement in dictionaryCollection)DeleteDictionaryElement(dictionaryElement,sqlConnection,sqlTransaction); + return true; + } + private static bool DeleteDictionaryElement(DictionaryElement dictionaryElement, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from dictionary where "); + sb.Append("word=").Append(SqlUtils.ToSqlString(dictionaryElement.Word)); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/DividendHistoryDA.cs b/MarketData/MarketDataLib/DataAccess/DividendHistoryDA.cs new file mode 100755 index 0000000..2a18c67 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/DividendHistoryDA.cs @@ -0,0 +1,286 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class DividendHistoryDA + { + private DividendHistoryDA() + { + } + public static List GetLatestDivExDates() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + List divExDates = new List(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(div_ex_date),symbol from dividendhistory group by symbol order by symbol asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DivExDateItem divExDate = new DivExDateItem(); + divExDate.DivExDate = sqlDataReader.GetDateTime(0); + divExDate.Symbol = sqlDataReader.GetString(1); + divExDates.Add(divExDate); + } + return divExDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) {sqlDataReader.Close();sqlDataReader.Dispose();} + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DividendHistory GetDividendHistory(List divExDates) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + DividendHistory dividendHistory = new DividendHistory(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + + foreach (DivExDateItem divExDate in divExDates) + { + StringBuilder sb = new StringBuilder(); + sb.Append("select symbol,dividend_type,cash_amount,div_ex_date,declaration_date,record_date,payment_date,modified from dividendhistory where symbol="); + sb.Append(SqlUtils.AddQuotes(divExDate.Symbol)); + sb.Append(" and "); + sb.Append("div_ex_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(divExDate.DivExDate))); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + DividendHistoryItem dividendHistoryItem = new DividendHistoryItem(); + dividendHistoryItem.Symbol = sqlDataReader.GetString(0); + if (!sqlDataReader.IsDBNull(1)) dividendHistoryItem.DividendType = sqlDataReader.GetString(1); + if (!sqlDataReader.IsDBNull(2)) dividendHistoryItem.CashAmount = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3)) dividendHistoryItem.DivExDate = sqlDataReader.GetDateTime(3); + if (!sqlDataReader.IsDBNull(4)) dividendHistoryItem.DeclarationDate = sqlDataReader.GetDateTime(4); + if (!sqlDataReader.IsDBNull(5)) dividendHistoryItem.RecordDate = sqlDataReader.GetDateTime(5); + if (!sqlDataReader.IsDBNull(6)) dividendHistoryItem.PaymentDate = sqlDataReader.GetDateTime(6); + if (!sqlDataReader.IsDBNull(7)) dividendHistoryItem.Modified = sqlDataReader.GetDateTime(7); + dividendHistory.Add(dividendHistoryItem); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + } + return dividendHistory; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader){sqlDataReader.Close();sqlDataReader.Dispose();} + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DividendHistory GetDividendHistory(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + DividendHistory dividendHistory = new DividendHistory(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,dividend_type,cash_amount,div_ex_date,declaration_date,record_date,payment_date,modified from dividendhistory where symbol="); + sb.Append(SqlUtils.AddQuotes(symbol)); + sb.Append(" order by div_ex_date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DividendHistoryItem dividendHistoryItem = new DividendHistoryItem(); + dividendHistoryItem.Symbol = sqlDataReader.GetString(0); + if (!sqlDataReader.IsDBNull(1)) dividendHistoryItem.DividendType = sqlDataReader.GetString(1); + if (!sqlDataReader.IsDBNull(2)) dividendHistoryItem.CashAmount = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3)) dividendHistoryItem.DivExDate = sqlDataReader.GetDateTime(3); + if (!sqlDataReader.IsDBNull(4)) dividendHistoryItem.DeclarationDate = sqlDataReader.GetDateTime(4); + if (!sqlDataReader.IsDBNull(5)) dividendHistoryItem.RecordDate = sqlDataReader.GetDateTime(5); + if (!sqlDataReader.IsDBNull(6)) dividendHistoryItem.PaymentDate = sqlDataReader.GetDateTime(6); + if (!sqlDataReader.IsDBNull(7)) dividendHistoryItem.Modified = sqlDataReader.GetDateTime(7); + dividendHistory.Add(dividendHistoryItem); + } + return dividendHistory; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader){sqlDataReader.Close();sqlDataReader.Dispose();} + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DividendHistory GetDividendHistory(String symbol,int[] years) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + DividendHistory dividendHistory = new DividendHistory(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,dividend_type,cash_amount,div_ex_date,declaration_date,record_date,payment_date,modified from dividendhistory where symbol="); + sb.Append(SqlUtils.AddQuotes(symbol)); + sb.Append(" and year(div_ex_date) in ").Append(SqlUtils.CreateInClauseInt(years.ToList())); + sb.Append(" order by div_ex_date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DividendHistoryItem dividendHistoryItem = new DividendHistoryItem(); + dividendHistoryItem.Symbol = sqlDataReader.GetString(0); + if (!sqlDataReader.IsDBNull(1)) dividendHistoryItem.DividendType = sqlDataReader.GetString(1); + if (!sqlDataReader.IsDBNull(2)) dividendHistoryItem.CashAmount = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3)) dividendHistoryItem.DivExDate = sqlDataReader.GetDateTime(3); + if (!sqlDataReader.IsDBNull(4)) dividendHistoryItem.DeclarationDate = sqlDataReader.GetDateTime(4); + if (!sqlDataReader.IsDBNull(5)) dividendHistoryItem.RecordDate = sqlDataReader.GetDateTime(5); + if (!sqlDataReader.IsDBNull(6)) dividendHistoryItem.PaymentDate = sqlDataReader.GetDateTime(6); + if (!sqlDataReader.IsDBNull(7)) dividendHistoryItem.Modified = sqlDataReader.GetDateTime(7); + dividendHistory.Add(dividendHistoryItem); + } + return dividendHistory; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader){sqlDataReader.Close();sqlDataReader.Dispose();} + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertOrUpdate(DividendHistory dividendHistory) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + + try + { + if (null == dividendHistory || 0 == dividendHistory.Count) return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteDividendHistory(dividendHistory, sqlConnection,sqlTransaction); + DateTime modified = DateTime.Now; + for (int index = 0; index < dividendHistory.Count; index++) + { + DividendHistoryItem dividendHistoryItem = dividendHistory[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into dividendhistory(symbol,dividend_type,cash_amount,div_ex_date,declaration_date,record_date,payment_date,modified)values("); + sb.Append(SqlUtils.AddQuotes(dividendHistoryItem.Symbol)).Append(","); + sb.Append(SqlUtils.AddQuotes(dividendHistoryItem.DividendType)).Append(","); + if (null == dividendHistoryItem.CashAmount) sb.Append("null").Append(","); + else sb.Append(dividendHistoryItem.CashAmount.Value).Append(","); + + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(dividendHistoryItem.DivExDate))).Append(","); + + if (null == dividendHistoryItem.DeclarationDate) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(dividendHistoryItem.DeclarationDate.Value))).Append(","); + + if (null == dividendHistoryItem.RecordDate) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(dividendHistoryItem.RecordDate.Value))).Append(","); + + if (null == dividendHistoryItem.PaymentDate) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(dividendHistoryItem.PaymentDate.Value))).Append(","); + +// sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(modified))); + sb.Append(SqlUtils.AddQuotes(SqlUtils.ToSqlDateTime(modified))); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was.."+strQuery); + return false; + } + finally + { + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static void DeleteDividendHistory(DividendHistory dividendHistory,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + String strQuery = null; + try + { + for (int index = 0; index < dividendHistory.Count; index++) + { + StringBuilder sb = new StringBuilder(); + DividendHistoryItem dividendHistoryItem = dividendHistory[index]; + sb.Append("delete from dividendhistory where "); + sb.Append("symbol=").Append(SqlUtils.AddQuotes(dividendHistoryItem.Symbol)); + sb.Append(" and div_ex_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(dividendHistoryItem.DivExDate))); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/DividendPaymentDA.cs b/MarketData/MarketDataLib/DataAccess/DividendPaymentDA.cs new file mode 100755 index 0000000..529d888 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/DividendPaymentDA.cs @@ -0,0 +1,368 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class DividendPaymentDA + { + private DividendPaymentDA() + { + } + public static DividendPayments GetDividendPayments() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + DividendPayments dividendPayments=new DividendPayments(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select symbol,payment_date,account,amount from dividends order by payment_date desc, symbol asc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DividendPayment dividendPayment=new DividendPayment(); + dividendPayment.Symbol = sqlDataReader.GetString(0); + dividendPayment.PaymentDate=sqlDataReader.GetDateTime(1); + dividendPayment.Account=sqlDataReader.GetString(2); + dividendPayment.Amount=sqlDataReader.GetDouble(3); + dividendPayments.Add(dividendPayment); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + return dividendPayments; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader)sqlDataReader.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DividendPayments GetDividendPaymentsForSymbol(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + DividendPayments dividendPayments=new DividendPayments(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select symbol,payment_date,account,amount from dividends "); + sb.Append("where symbol=").Append("'").Append(symbol).Append("'"); + sb.Append(" order by payment_date desc, symbol asc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DividendPayment dividendPayment=new DividendPayment(); + dividendPayment.Symbol = sqlDataReader.GetString(0); + dividendPayment.PaymentDate=sqlDataReader.GetDateTime(1); + dividendPayment.Account=sqlDataReader.GetString(2); + dividendPayment.Amount=sqlDataReader.GetDouble(3); + dividendPayments.Add(dividendPayment); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + return dividendPayments; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader)sqlDataReader.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DividendPayments GetDividendPaymentsForAccount(String account) + { + List accounts = new List(); + accounts.Add(account); + return GetDividendPaymentsForAccounts(accounts); + } + public static DividendPayments GetDividendPaymentsForAccounts(List accounts) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + DividendPayments dividendPayments = new DividendPayments(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select symbol,payment_date,account,amount from dividends "); + sb.Append("where account in ").Append(SqlUtils.CreateInClause(accounts)); + sb.Append(" order by payment_date desc, symbol asc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DividendPayment dividendPayment = new DividendPayment(); + dividendPayment.Symbol = sqlDataReader.GetString(0); + dividendPayment.PaymentDate = sqlDataReader.GetDateTime(1); + dividendPayment.Account = sqlDataReader.GetString(2); + dividendPayment.Amount = sqlDataReader.GetDouble(3); + dividendPayments.Add(dividendPayment); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + return dividendPayments; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DividendPayments GetDividendPaymentsForAccountsAndSymbols(List accounts,List symbols) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + DividendPayments dividendPayments = new DividendPayments(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select symbol,payment_date,account,amount from dividends "); + if ((null == accounts || 0 == accounts.Count) && (null == symbols || 0 == symbols.Count)) return GetDividendPayments(); + if (!accounts.Contains(Constants.CONST_ALL)&&!accounts.Contains("")) + { + sb.Append("where account in ").Append(SqlUtils.CreateInClause(accounts)).Append(" "); + if (!symbols.Contains(Constants.CONST_ALL)&&0!=symbols.Count&&!symbols.Contains("")) sb.Append("and symbol in ").Append(SqlUtils.CreateInClause(symbols)).Append(" "); + } + else if (!symbols.Contains(Constants.CONST_ALL)&&0!=symbols.Count&&!symbols.Contains("")) sb.Append("where symbol in ").Append(SqlUtils.CreateInClause(symbols)).Append(" "); + sb.Append(" order by payment_date desc, account, symbol asc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DividendPayment dividendPayment = new DividendPayment(); + dividendPayment.Symbol = sqlDataReader.GetString(0); + dividendPayment.PaymentDate = sqlDataReader.GetDateTime(1); + dividendPayment.Account = sqlDataReader.GetString(2); + dividendPayment.Amount = sqlDataReader.GetDouble(3); + dividendPayments.Add(dividendPayment); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + return dividendPayments; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DividendPayments GetDividendPaymentsMaxDate(String symbol,DateTime maxDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + DividendPayments dividendPayments=new DividendPayments(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select symbol,payment_date,account,amount from dividends "); + sb.Append("where symbol=").Append("'").Append(symbol).Append("'"); + sb.Append(" and payment_date<=").Append("'").Append(SqlUtils.ToSqlDateTime(maxDate)).Append("'"); + sb.Append(" order by payment_date desc, symbol asc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DividendPayment dividendPayment=new DividendPayment(); + dividendPayment.Symbol = sqlDataReader.GetString(0); + dividendPayment.PaymentDate=sqlDataReader.GetDateTime(1); + dividendPayment.Account=sqlDataReader.GetString(2); + dividendPayment.Amount=sqlDataReader.GetDouble(3); + dividendPayments.Add(dividendPayment); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + return dividendPayments; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader)sqlDataReader.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// *********** + public static List GetDividendPaymentAccounts() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + List accounts = new List(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select distinct(account) from dividends "); + sb.Append(" order by account asc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + accounts.Add(sqlDataReader.GetString(0)); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + return accounts; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetDividendPaymentSymbols() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + List symbols = new List(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select distinct(symbol) from dividends "); + sb.Append(" order by symbol asc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + symbols.Add(sqlDataReader.GetString(0)); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + return symbols; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetDividendPaymentSymbols(String account) + { + List accounts = new List(); + accounts.Add(account); + return GetDividendPaymentSymbols(accounts); + } + public static List GetDividendPaymentSymbols(List accounts) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + List symbols = new List(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select distinct(symbol) from dividends where account in ").Append(SqlUtils.CreateInClause(accounts)); + sb.Append(" order by symbol asc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + symbols.Add(sqlDataReader.GetString(0)); + } + sqlCommand.Dispose(); + sqlDataReader.Close(); + return symbols; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/ETFHoldingsDA.cs b/MarketData/MarketDataLib/DataAccess/ETFHoldingsDA.cs new file mode 100755 index 0000000..752b75f --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/ETFHoldingsDA.cs @@ -0,0 +1,292 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ +// ********************************************************** + public class ETFHoldingsDA + { + private ETFHoldingsDA() + { + } + public static List GetETFSymbols() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + List etfSymbols=new List(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct(etf_symbol) from etfholdings "); + sb.Append(" order by 1 asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + etfSymbols.Add(sqlDataReader.GetString(0)); + } + return etfSymbols; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool HaveETFHoldings(String etfSymbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + ETFHoldings etfHoldings = new ETFHoldings(); // new ETFHoldings(etfSymbol); + String strQuery = null; + + try + { + if (null == etfSymbol) return false; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from etfholdings "); + sb.Append("where etf_symbol='").Append(etfSymbol).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return false; + int count = sqlDataReader.GetInt32(0); + sqlCommand.Dispose(); + return count==0?false:true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteETFHoldings(String etfSymbol,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + String strQuery = null; + try + { + StringBuilder sb = new StringBuilder(); + sb.Append("delete from etfholdings "); + sb.Append("where etf_symbol='").Append(etfSymbol).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection,sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + } + } + public static bool InsertOrUpdate(ETFHoldings etfHoldings) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + + try + { + if (null == etfHoldings || 0 == etfHoldings.Count) return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + List etfSymbols = etfHoldings.GetETFSymbols(); + DateTime modified = DateTime.Now; + foreach (String etfSymbol in etfSymbols) + { + if (HaveETFHoldings(etfSymbol)) DeleteETFHoldings(etfSymbol, sqlConnection, sqlTransaction); + } + for (int index = 0; index < etfHoldings.Count; index++) + { + ETFHolding etfHolding = etfHoldings[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into ETFHoldings(etf_symbol,holding_symbol,holding_symbol_sc,pcnt_of_assets,company,modified)values("); + sb.Append(SqlUtils.ToSqlString(etfHolding.ETFSymbol)).Append(","); + sb.Append(SqlUtils.ToSqlString(etfHolding.HoldingSymbol)).Append(","); + sb.Append(SqlUtils.ToSqlString(etfHolding.HoldingSymbolShareClass)).Append(","); + sb.Append(etfHolding.PercentOfAssets).Append(","); + sb.Append(SqlUtils.ToSqlString(etfHolding.HoldingCompanyName)).Append(","); + sb.Append(SqlUtils.ToSqlString(Utility.DateTimeToStringYYYYHMMHDD(modified))); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if (null != sqlConnection) sqlConnection.Close(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + } + } + public static ETFHoldings GetETFHoldings(String etfSymbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + ETFHoldings etfHoldings = new ETFHoldings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select etf_symbol,holding_symbol,holding_symbol_sc,pcnt_of_assets,company,modified from etfholdings "); + sb.Append("where etf_symbol='").Append(etfSymbol).Append("'"); + sb.Append(" order by pcnt_of_assets desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + ETFHolding etfHolding = new ETFHolding(); + etfHolding.ETFSymbol = sqlDataReader.GetString(0); + etfHolding.HoldingSymbol = sqlDataReader.GetString(1); + etfHolding.HoldingSymbolShareClass = sqlDataReader.GetString(2); + etfHolding.PercentOfAssets = sqlDataReader.GetDouble(3); + etfHolding.HoldingCompanyName = sqlDataReader.GetString(4); + etfHolding.Modified = sqlDataReader.GetDateTime(5); + etfHoldings.Add(etfHolding); + } + return etfHoldings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static ETFHoldings GetETFHoldingsWithExposureToSymbolLike(String holdingSymbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + ETFHoldings etfHoldings = new ETFHoldings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select etf_symbol,holding_symbol,holding_symbol_sc,pcnt_of_assets,company,modified from etfholdings "); + sb.Append("where holding_symbol like '%").Append(holdingSymbol).Append("%'"); + sb.Append(" order by pcnt_of_assets desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + ETFHolding etfHolding = new ETFHolding(); + etfHolding.ETFSymbol = sqlDataReader.GetString(0); + etfHolding.HoldingSymbol = sqlDataReader.GetString(1); + etfHolding.HoldingSymbolShareClass = sqlDataReader.GetString(2); + etfHolding.PercentOfAssets = sqlDataReader.GetDouble(3); + etfHolding.HoldingCompanyName = sqlDataReader.GetString(4); + etfHolding.Modified = sqlDataReader.GetDateTime(5); + etfHoldings.Add(etfHolding); + } + return etfHoldings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static ETFHoldings GetETFHoldingsWithExposureToCompanyLike(String searchValue) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + ETFHoldings etfHoldings = new ETFHoldings(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select etf_symbol,holding_symbol,holding_symbol_sc,pcnt_of_assets,company,modified from etfholdings "); + sb.Append("where company like '%").Append(searchValue).Append("%'"); + sb.Append(" order by pcnt_of_assets desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + ETFHolding etfHolding = new ETFHolding(); + etfHolding.ETFSymbol = sqlDataReader.GetString(0); + etfHolding.HoldingSymbol = sqlDataReader.GetString(1); + etfHolding.HoldingSymbolShareClass = sqlDataReader.GetString(2); + etfHolding.PercentOfAssets = sqlDataReader.GetDouble(3); + etfHolding.HoldingCompanyName = sqlDataReader.GetString(4); + etfHolding.Modified = sqlDataReader.GetDateTime(5); + etfHoldings.Add(etfHolding); + } + return etfHoldings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/EarningsAnnouncementsDA.cs b/MarketData/MarketDataLib/DataAccess/EarningsAnnouncementsDA.cs new file mode 100755 index 0000000..0009eeb --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/EarningsAnnouncementsDA.cs @@ -0,0 +1,249 @@ +using System; +using System.Text; +using System.Diagnostics; +using System.Collections.Generic; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ +// Persistence for Zacks Earnings Announcements + public class EarningsAnnouncementsDA + { + private EarningsAnnouncementsDA() + { + } + public static DateTime? GetNextEarningsDate(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List earningsDates=new List(); + DateTime currentDate=DateTime.Now.Date; + DateGenerator dateGenerator=new DateGenerator(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date from earningsannouncements where symbol=").Append(SqlUtils.AddQuotes(symbol)).Append(" order by date desc limit 2"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + earningsDates.Add(sqlDataReader.GetDateTime(0)); + } + if(2!=earningsDates.Count)return null; + DateTime latestAnnouncementDate=earningsDates[0]; + DateTime previousAnnouncementDate=earningsDates[1]; + if(latestAnnouncementDate>currentDate)return latestAnnouncementDate; + TimeSpan daysBetween=latestAnnouncementDate-previousAnnouncementDate; + return dateGenerator.GetNextBusinessDay(latestAnnouncementDate+daysBetween); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static EarningsAnnouncements GetEarningsAnnouncements(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + EarningsAnnouncements earningsAnnouncements=new EarningsAnnouncements(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,date,period_ending,estimate,reported,surprise,surprise_pct,time from earningsannouncements where symbol=").Append(SqlUtils.AddQuotes(symbol)).Append(" order by date desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + EarningsAnnouncement earningsAnnouncement=new EarningsAnnouncement(); + earningsAnnouncement.Symbol=symbol; + earningsAnnouncement.Date=sqlDataReader.GetDateTime(1); + if(!sqlDataReader.IsDBNull(2))earningsAnnouncement.PeriodEnding=sqlDataReader.GetDateTime(2); + if(!sqlDataReader.IsDBNull(3))earningsAnnouncement.Estimate=sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4))earningsAnnouncement.Reported=sqlDataReader.GetDouble(4); + if(!sqlDataReader.IsDBNull(5))earningsAnnouncement.Surprise=sqlDataReader.GetDouble(5); + if(!sqlDataReader.IsDBNull(6))earningsAnnouncement.SurprisePct=sqlDataReader.GetDouble(6); + if(!sqlDataReader.IsDBNull(7))earningsAnnouncement.Time=sqlDataReader.GetString(7); + earningsAnnouncements.Add(earningsAnnouncement); + } + return earningsAnnouncements; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return earningsAnnouncements; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static EarningsAnnouncement GetLatestEarningsAnnouncement(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + EarningsAnnouncement earningsAnnouncement=null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,date,period_ending,estimate,reported,surprise,surprise_pct,time from earningsannouncements where symbol=").Append(SqlUtils.AddQuotes(symbol)); + sb.Append("and date=(select max(date) from earningsannouncements where symbol=").Append(SqlUtils.AddQuotes(symbol)).Append(")"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read())return null; + earningsAnnouncement=new EarningsAnnouncement(); + earningsAnnouncement.Symbol=symbol; + earningsAnnouncement.Date=sqlDataReader.GetDateTime(1); + if(!sqlDataReader.IsDBNull(2))earningsAnnouncement.PeriodEnding=sqlDataReader.GetDateTime(2); + if(!sqlDataReader.IsDBNull(3))earningsAnnouncement.Estimate=sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4))earningsAnnouncement.Reported=sqlDataReader.GetDouble(4); + if(!sqlDataReader.IsDBNull(5))earningsAnnouncement.Surprise=sqlDataReader.GetDouble(5); + if(!sqlDataReader.IsDBNull(6))earningsAnnouncement.SurprisePct=sqlDataReader.GetDouble(6); + if(!sqlDataReader.IsDBNull(7))earningsAnnouncement.Time=sqlDataReader.GetString(7); + return earningsAnnouncement; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertEarningsAnnouncements(EarningsAnnouncements earningsAnnouncements) + { + MySqlCommand sqlCommand=null; + MySqlConnection sqlConnection=null; + MySqlTransaction sqlTransaction=null; + + try + { + if (null == earningsAnnouncements || 0 == earningsAnnouncements.Count) return false; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + foreach(EarningsAnnouncement earningsAnnouncement in earningsAnnouncements) + { + if(!EarningsAnnouncementExists(earningsAnnouncement,sqlConnection,sqlTransaction))InsertEarningsAnnouncement(earningsAnnouncement,sqlConnection,sqlTransaction); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + private static bool InsertEarningsAnnouncement(EarningsAnnouncement earningsAnnouncement,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == earningsAnnouncement || null == earningsAnnouncement.Symbol || Utility.IsEpoch(earningsAnnouncement.Date) || Utility.IsEpoch(earningsAnnouncement.PeriodEnding)) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into EarningsAnnouncements(symbol,date,period_ending,estimate,reported,surprise,surprise_pct,time,modified) values("); + sb.Append(SqlUtils.AddQuotes(earningsAnnouncement.Symbol)).Append(","); + sb.Append(SqlUtils.AddQuotes(SqlUtils.SqlDate(earningsAnnouncement.Date))).Append(","); + sb.Append(SqlUtils.AddQuotes(SqlUtils.SqlDate(earningsAnnouncement.PeriodEnding))).Append(","); + if(double.IsNaN(earningsAnnouncement.Estimate))sb.Append("null").Append(","); + else sb.Append(earningsAnnouncement.Estimate).Append(","); + if(double.IsNaN(earningsAnnouncement.Reported))sb.Append("null").Append(","); + else sb.Append(earningsAnnouncement.Reported).Append(","); + if(double.IsNaN(earningsAnnouncement.Surprise))sb.Append("null").Append(","); + else sb.Append(earningsAnnouncement.Surprise).Append(","); + if(double.IsNaN(earningsAnnouncement.SurprisePct))sb.Append("null").Append(","); + else sb.Append(earningsAnnouncement.SurprisePct).Append(","); + if(null==earningsAnnouncement.Time)sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(earningsAnnouncement.Time)).Append(","); + sb.Append(SqlUtils.AddQuotes(SqlUtils.ToSqlDateTime(DateTime.Now))); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was '{0}'",strQuery)); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + } + } + private static bool EarningsAnnouncementExists(EarningsAnnouncement earningsAnnouncement,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == earningsAnnouncement || null == earningsAnnouncement.Symbol) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("select count(*) from earningsannouncements where symbol=").Append(SqlUtils.AddQuotes(earningsAnnouncement.Symbol)).Append(" and "); + sb.Append(" date=").Append(SqlUtils.AddQuotes(SqlUtils.SqlDate(earningsAnnouncement.Date))); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read())return false; + return 0==sqlDataReader.GetInt32(0)?false:true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader){sqlDataReader.Close();sqlDataReader.Dispose();} + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/EconomicIndicatorDA.cs b/MarketData/MarketDataLib/DataAccess/EconomicIndicatorDA.cs new file mode 100755 index 0000000..2266d9d --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/EconomicIndicatorDA.cs @@ -0,0 +1,176 @@ +using System; +using System.Text; +using System.Collections.Generic; +using System.Linq; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class EconomicIndicatorDA + { + private EconomicIndicatorDA() + { + } + public static EconomicIndicators GetEconomicIndicators() + { + MySqlConnection sqlConnection=null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + EconomicIndicators economicIndicators=new EconomicIndicators(); + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlCommand=sqlConnection.CreateCommand(); + StringBuilder sb=new StringBuilder(); + sb.Append("select country_code,country_name,indicator_code,indicator_name,indicator_value,year,source from EconomicIndicators"); + sqlCommand.CommandText=sb.ToString(); + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + EconomicIndicator economicIndicator=new EconomicIndicator(); + if(!sqlDataReader.IsDBNull(0))economicIndicator.CountryCode=sqlDataReader.GetString(0); + if(!sqlDataReader.IsDBNull(1))economicIndicator.CountryName=sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))economicIndicator.IndicatorCode=sqlDataReader.GetString(2); + if(!sqlDataReader.IsDBNull(3))economicIndicator.IndicatorName=sqlDataReader.GetString(3); + if(!sqlDataReader.IsDBNull(4))economicIndicator.IndicatorValue=sqlDataReader.GetDouble(4); + if(!sqlDataReader.IsDBNull(5))economicIndicator.Year=sqlDataReader.GetInt32(5); + if(!sqlDataReader.IsDBNull(6))economicIndicator.Source=sqlDataReader.GetString(6); + economicIndicators.Add(economicIndicator); + } + sqlDataReader.Close(); + sqlDataReader.Dispose(); + sqlCommand.Dispose(); + sqlConnection.Close(); + sqlConnection.Dispose(); + return economicIndicators; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return null; + } + finally + { + if(null!=sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader.Dispose(); + } + if(null!=sqlCommand) + { + sqlCommand.Dispose(); + } + if(null!=sqlConnection) + { + sqlConnection.Close(); + sqlConnection.Dispose(); + } + } + } + public static bool InsertUpdateEconomicIndicators(EconomicIndicators economicIndicators) + { + MySqlConnection sqlConnection=null; + MySqlCommand sqlCommand=null; + MySqlTransaction sqlTransaction=null; + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted); + sqlCommand=sqlConnection.CreateCommand(); + sqlCommand.Transaction=sqlTransaction; + List distinctCountryCodes=(from EconomicIndicator economicIndicator in economicIndicators select economicIndicator.CountryCode).Distinct().ToList(); + for(int index=0;index years=(from EconomicIndicator economicIndicator in economicIndicators select economicIndicator.Year).Distinct().ToList(); + DeleteEconomicIndicator(countryCode,years,sqlCommand,sqlTransaction); + } + InsertEconomicIndicators(economicIndicators,sqlCommand,sqlTransaction); + sqlTransaction.Commit(); + sqlTransaction.Dispose(); + sqlCommand.Dispose(); + sqlConnection.Close(); + sqlConnection.Dispose(); + sqlConnection=null; + sqlCommand=null; + sqlTransaction=null; + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return false; + } + finally + { + if(null!=sqlConnection) + { + sqlConnection.Close(); + sqlConnection.Dispose(); + } + if(null!=sqlCommand) + { + sqlCommand.Dispose(); + } + if(null!=sqlTransaction) + { + sqlTransaction.Dispose(); + } + } + } + public static bool DeleteEconomicIndicator(String countryCode,List years,MySqlCommand sqlCommand,MySqlTransaction sqlTransaction) + { + String strQuery=null; + try + { + StringBuilder sb=new StringBuilder(); + sb.Append("delete from EconomicIndicators ").Append(" where "); + sb.Append("country_code=").Append("'").Append(countryCode).Append("'").Append(" and "); + sb.Append("year in ").Append(SqlUtils.CreateInClause(years)); + strQuery=sb.ToString(); + sqlCommand.CommandText=strQuery; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}, query was {1}",exception.ToString(),strQuery)); + return false; + } + } + public static bool InsertEconomicIndicators(EconomicIndicators economicIndicators,MySqlCommand sqlCommand,MySqlTransaction sqlTransaction) + { + String strQuery=null; + try + { + StringBuilder sb=new StringBuilder(); + foreach(EconomicIndicator economicIndicator in economicIndicators) + { + sb.Append("insert into EconomicIndicators(country_code,country_name,indicator_code,indicator_name,indicator_value,year,source)values("); + sb.Append(SqlUtils.ToSqlString(economicIndicator.CountryCode)).Append(","); + sb.Append(SqlUtils.ToSqlString(economicIndicator.CountryName)).Append(","); + sb.Append(SqlUtils.ToSqlString(economicIndicator.IndicatorCode)).Append(","); + sb.Append(SqlUtils.ToSqlString(economicIndicator.IndicatorName)).Append(","); + sb.Append(economicIndicator.IndicatorValue).Append(","); + sb.Append(economicIndicator.Year).Append(","); + sb.Append(SqlUtils.ToSqlString(economicIndicator.Source)); + sb.Append(");"); + } + strQuery=sb.ToString(); + sqlCommand.CommandText=sb.ToString(); + sqlCommand.ExecuteNonQuery(); + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/FundamentalDA.cs b/MarketData/MarketDataLib/DataAccess/FundamentalDA.cs new file mode 100755 index 0000000..6a74edf --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/FundamentalDA.cs @@ -0,0 +1,766 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class FundamentalDA + { + private FundamentalDA() + { + } + public static bool CheckFundamentalModifiedOn(String symbol,DateTime modified) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + DateTime maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from fundamentals").Append(" "); + sb.Append("where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append("and asof='").Append(Utility.DateTimeToStringYYYYHMMHDD(modified)).Append("'"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + sqlDataReader.Read(); + int recordCount = sqlDataReader.GetInt32(0); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetLatestDate(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(asof) from fundamentals").Append(" "); + sb.Append("where symbol='").Append(symbol).Append("'"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0))maxDate=sqlDataReader.GetDateTime(0); + } + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return maxDate; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader)sqlDataReader.Close(); + if(null != sqlConnection) sqlConnection.Close(); + } + } + public static TimeSeriesCollection GetTotalCashMils(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + TimeSeriesCollection timeSeriesCollection=new TimeSeriesCollection(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,total_cash from fundamentals where symbol='").Append(symbol).Append("' order by asof desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement=new TimeSeriesElement(); + timeSeriesElement.Symbol=sqlDataReader.GetString(0); + timeSeriesElement.AsOf=sqlDataReader.GetDateTime(1); + if(!sqlDataReader.IsDBNull(2))timeSeriesElement.Value=sqlDataReader.GetDouble(2)/1000000.00; + else timeSeriesElement.Value=double.NaN; + timeSeriesElement.Type=TimeSeriesElement.ElementType.OTHER; + timeSeriesElement.OtherType="Total_Cash"; + if(double.IsNaN(timeSeriesElement.Value))continue; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static TimeSeriesCollection GetPERatio(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + TimeSeriesCollection timeSeriesCollection=new TimeSeriesCollection(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,pe from fundamentals where symbol='").Append(symbol).Append("' order by asof desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement=new TimeSeriesElement(); + timeSeriesElement.Symbol=sqlDataReader.GetString(0); + timeSeriesElement.AsOf=sqlDataReader.GetDateTime(1); + if(!sqlDataReader.IsDBNull(2))timeSeriesElement.Value=sqlDataReader.GetDouble(2); + else timeSeriesElement.Value=double.NaN; + timeSeriesElement.Type=TimeSeriesElement.ElementType.OTHER; + timeSeriesElement.OtherType="PE"; + if(double.IsNaN(timeSeriesElement.Value))continue; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static TimeSeriesCollection GetEPS(String symbol,DateTime? maxDate=null) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + if(null==maxDate)sb.Append("select symbol,asof,eps from fundamentals where symbol='").Append(symbol).Append("' order by asof desc"); + else sb.Append("select symbol,asof,eps from fundamentals where symbol='").Append(symbol).Append("'").Append(" and asof<=").Append(SqlUtils.AddQuotes(SqlUtils.ToSqlDateTime(maxDate.Value))).Append(" order by asof desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2)) timeSeriesElement.Value = sqlDataReader.GetDouble(2); + else timeSeriesElement.Value = double.NaN; + timeSeriesElement.Type = TimeSeriesElement.ElementType.OTHER; + timeSeriesElement.OtherType = "EPS"; + if (double.IsNaN(timeSeriesElement.Value)) continue; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Fundamental GetFundamental(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,next_earnings_date,beta,low52,high52,volume,market_cap,pe,eps,peg,return_on_assets,return_on_equity,total_cash,total_debt,shares_outstanding,revenue,revenue_per_share,qtrly_revenue_growth,gross_profit,ebitda,net_income_available_to_common,book_value_per_share,operating_cashflow,leveraged_free_cashflow,book_value_per_share*shares_outstanding as equity,trailing_pe,ebit,enterprise_value,source from fundamentals where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and asof=(select max(asof) from fundamentals where symbol='").Append(symbol).Append("')"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + Fundamental fundamental = new Fundamental(); + fundamental.Symbol=sqlDataReader.GetString(0); + fundamental.AsOf = sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2)) fundamental.NextEarningsDate = sqlDataReader.GetDateTime(2); + if (!sqlDataReader.IsDBNull(3)) fundamental.Beta = sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4)) fundamental.Low52 = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5)) fundamental.High52 = sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6)) fundamental.Volume = sqlDataReader.GetInt64(6); + if (!sqlDataReader.IsDBNull(7)) fundamental.MarketCap = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) fundamental.PE = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) fundamental.EPS = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) fundamental.PEG = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) fundamental.ReturnOnAssets = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) fundamental.ReturnOnEquity = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) fundamental.TotalCash = sqlDataReader.GetDouble(13); + if (!sqlDataReader.IsDBNull(14)) fundamental.TotalDebt = sqlDataReader.GetDouble(14); + if (!sqlDataReader.IsDBNull(15)) fundamental.SharesOutstanding = sqlDataReader.GetDouble(15); + if (!sqlDataReader.IsDBNull(16)) fundamental.Revenue = sqlDataReader.GetDouble(16); + if (!sqlDataReader.IsDBNull(17)) fundamental.RevenuePerShare = sqlDataReader.GetDouble(17); + if (!sqlDataReader.IsDBNull(18)) fundamental.QtrlyRevenueGrowth = sqlDataReader.GetDouble(18); + if (!sqlDataReader.IsDBNull(19)) fundamental.GrossProfit = sqlDataReader.GetDouble(19); + if (!sqlDataReader.IsDBNull(20)) fundamental.EBITDA = sqlDataReader.GetDouble(20); + if (!sqlDataReader.IsDBNull(21)) fundamental.NetIncomeAvailableToCommon = sqlDataReader.GetDouble(21); + if (!sqlDataReader.IsDBNull(22)) fundamental.BookValuePerShare = sqlDataReader.GetDouble(22); + if (!sqlDataReader.IsDBNull(23)) fundamental.OperatingCashflow = sqlDataReader.GetDouble(23); + if (!sqlDataReader.IsDBNull(24)) fundamental.LeveragedFreeCashflow = sqlDataReader.GetDouble(24); + if (!sqlDataReader.IsDBNull(25)) fundamental.Equity = sqlDataReader.GetDouble(25); + if (!sqlDataReader.IsDBNull(26)) fundamental.TrailingPE = sqlDataReader.GetDouble(26); + if (!sqlDataReader.IsDBNull(27)) fundamental.EBIT = sqlDataReader.GetDouble(27); + if (!sqlDataReader.IsDBNull(28)) fundamental.EnterpriseValue = sqlDataReader.GetDouble(28); + if (!sqlDataReader.IsDBNull(29)) fundamental.Source = sqlDataReader.GetString(29); + BalanceSheet balanceSheet=BalanceSheetDA.GetBalanceSheetOnOrBefore(symbol,fundamental.AsOf,BalanceSheet.PeriodType.Annual); + if(null!=balanceSheet&&!double.IsNaN(balanceSheet.TotalStockHolderEquity)&&!double.IsNaN(fundamental.TotalDebt)&&0!=fundamental.TotalDebt)fundamental.DebtToEquity=fundamental.TotalDebt/balanceSheet.TotalStockHolderEquity; + return fundamental; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Fundamental GetFundamental(String symbol, DateTime asof) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,next_earnings_date,beta,low52,high52,volume,market_cap,pe,eps,peg,return_on_assets,return_on_equity,total_cash,total_debt,shares_outstanding,revenue,revenue_per_share,qtrly_revenue_growth,gross_profit,ebitda,net_income_available_to_common,book_value_per_share,operating_cashflow,leveraged_free_cashflow,book_value_per_share*shares_outstanding as equity,trailing_pe,ebit,enterprise_value,source from fundamentals where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("'").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + BalanceSheet balanceSheet=BalanceSheetDA.GetBalanceSheetOnOrBefore(symbol,asof,BalanceSheet.PeriodType.Annual); + Fundamental fundamental = new Fundamental(); + fundamental.Symbol = sqlDataReader.GetString(0); + fundamental.AsOf = sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2)) fundamental.NextEarningsDate = sqlDataReader.GetDateTime(2); + if (!sqlDataReader.IsDBNull(3)) fundamental.Beta = sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4)) fundamental.Low52 = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5)) fundamental.High52 = sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6)) fundamental.Volume = sqlDataReader.GetInt64(6); + if (!sqlDataReader.IsDBNull(7)) fundamental.MarketCap = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) fundamental.PE = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) fundamental.EPS = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) fundamental.PEG = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) fundamental.ReturnOnAssets = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) fundamental.ReturnOnEquity = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) fundamental.TotalCash = sqlDataReader.GetDouble(13); + if (!sqlDataReader.IsDBNull(14)) fundamental.TotalDebt = sqlDataReader.GetDouble(14); + if (!sqlDataReader.IsDBNull(15)) fundamental.SharesOutstanding = sqlDataReader.GetDouble(15); + if (!sqlDataReader.IsDBNull(16)) fundamental.Revenue = sqlDataReader.GetDouble(16); + if (!sqlDataReader.IsDBNull(17)) fundamental.RevenuePerShare = sqlDataReader.GetDouble(17); + if (!sqlDataReader.IsDBNull(18)) fundamental.QtrlyRevenueGrowth = sqlDataReader.GetDouble(18); + if (!sqlDataReader.IsDBNull(19)) fundamental.GrossProfit = sqlDataReader.GetDouble(19); + if (!sqlDataReader.IsDBNull(20)) fundamental.EBITDA = sqlDataReader.GetDouble(20); + if (!sqlDataReader.IsDBNull(21)) fundamental.NetIncomeAvailableToCommon = sqlDataReader.GetDouble(21); + if (!sqlDataReader.IsDBNull(22)) fundamental.BookValuePerShare = sqlDataReader.GetDouble(22); + if (!sqlDataReader.IsDBNull(23)) fundamental.OperatingCashflow = sqlDataReader.GetDouble(23); + if (!sqlDataReader.IsDBNull(24)) fundamental.LeveragedFreeCashflow = sqlDataReader.GetDouble(24); + if (!sqlDataReader.IsDBNull(25)) fundamental.Equity = sqlDataReader.GetDouble(25); + if (!sqlDataReader.IsDBNull(26)) fundamental.TrailingPE = sqlDataReader.GetDouble(26); + if (!sqlDataReader.IsDBNull(27)) fundamental.EBIT = sqlDataReader.GetDouble(27); + if (!sqlDataReader.IsDBNull(28)) fundamental.EnterpriseValue = sqlDataReader.GetDouble(28); + if (!sqlDataReader.IsDBNull(29)) fundamental.Source = sqlDataReader.GetString(29); + if (null != balanceSheet && !double.IsNaN(balanceSheet.TotalStockHolderEquity) && !double.IsNaN(fundamental.TotalDebt) && 0 != fundamental.TotalDebt) + { + fundamental.DebtToEquity=fundamental.TotalDebt/balanceSheet.TotalStockHolderEquity; + } + return fundamental; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// get the maximum date on record on or before asof + public static DateTime? GetMaxDateFromFundamental(String symbol,DateTime asof) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate=null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select asof from fundamentals where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and asof<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("'"); + sb.Append(" order by asof desc "); + sb.Append(" limit 1"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return maxDate; + if(!sqlDataReader.IsDBNull(0))maxDate=sqlDataReader.GetDateTime(0); + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Fundamental GetFundamentalMaxDate(String symbol, DateTime asof) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + DateTime? maxDate=GetMaxDateFromFundamental(symbol,asof); // get the maximum date on record on or before max date + if(null==maxDate)return null; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,next_earnings_date,beta,low52,high52,volume,market_cap,pe,eps,peg,return_on_assets,return_on_equity,total_cash,total_debt,shares_outstanding,revenue,revenue_per_share,qtrly_revenue_growth,gross_profit,ebitda,net_income_available_to_common,book_value_per_share,operating_cashflow,leveraged_free_cashflow,book_value_per_share*shares_outstanding as equity,trailing_pe,ebit,enterprise_value,source from fundamentals where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate.Value)).Append("'"); + sb.Append(" limit 1"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + double totalStockHolderEquity=BalanceSheetDA.GetTotalStockHolderEquityOnOrBefore(symbol,asof,BalanceSheet.PeriodType.Annual); + Fundamental fundamental = new Fundamental(); + fundamental.Symbol = sqlDataReader.GetString(0); + fundamental.AsOf = sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2)) fundamental.NextEarningsDate = sqlDataReader.GetDateTime(2); + if (!sqlDataReader.IsDBNull(3)) fundamental.Beta = sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4)) fundamental.Low52 = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5)) fundamental.High52 = sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6)) fundamental.Volume = sqlDataReader.GetInt64(6); + if (!sqlDataReader.IsDBNull(7)) fundamental.MarketCap = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) fundamental.PE = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) fundamental.EPS = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) fundamental.PEG = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) fundamental.ReturnOnAssets = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) fundamental.ReturnOnEquity = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) fundamental.TotalCash = sqlDataReader.GetDouble(13); + if (!sqlDataReader.IsDBNull(14)) fundamental.TotalDebt = sqlDataReader.GetDouble(14); + if (!sqlDataReader.IsDBNull(15)) fundamental.SharesOutstanding = sqlDataReader.GetDouble(15); + if (!sqlDataReader.IsDBNull(16)) fundamental.Revenue = sqlDataReader.GetDouble(16); + if (!sqlDataReader.IsDBNull(17)) fundamental.RevenuePerShare = sqlDataReader.GetDouble(17); + if (!sqlDataReader.IsDBNull(18)) fundamental.QtrlyRevenueGrowth = sqlDataReader.GetDouble(18); + if (!sqlDataReader.IsDBNull(19)) fundamental.GrossProfit = sqlDataReader.GetDouble(19); + if (!sqlDataReader.IsDBNull(20)) fundamental.EBITDA = sqlDataReader.GetDouble(20); + if (!sqlDataReader.IsDBNull(21)) fundamental.NetIncomeAvailableToCommon = sqlDataReader.GetDouble(21); + if (!sqlDataReader.IsDBNull(22)) fundamental.BookValuePerShare = sqlDataReader.GetDouble(22); + if (!sqlDataReader.IsDBNull(23)) fundamental.OperatingCashflow = sqlDataReader.GetDouble(23); + if (!sqlDataReader.IsDBNull(24)) fundamental.LeveragedFreeCashflow = sqlDataReader.GetDouble(24); + if (!sqlDataReader.IsDBNull(25)) fundamental.Equity = sqlDataReader.GetDouble(25); + if (!sqlDataReader.IsDBNull(26)) fundamental.TrailingPE = sqlDataReader.GetDouble(26); + if (!sqlDataReader.IsDBNull(27)) fundamental.EBIT = sqlDataReader.GetDouble(27); + if (!sqlDataReader.IsDBNull(28)) fundamental.EnterpriseValue = sqlDataReader.GetDouble(28); + if (!sqlDataReader.IsDBNull(29)) fundamental.Source = sqlDataReader.GetString(29); + if (!double.IsNaN(totalStockHolderEquity) && !double.IsNaN(fundamental.TotalDebt)) + { + if(0.00==totalStockHolderEquity)fundamental.TotalDebt=0.00; + else fundamental.DebtToEquity=fundamental.TotalDebt/totalStockHolderEquity; + } + return fundamental; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + + public static Fundamentals GetFundamentalMaxDateTop(String symbol, DateTime asof, int top) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Fundamentals fundamentals = new Fundamentals(); + + try + { + DateTime? maxDate=GetMaxDateFromFundamental(symbol,asof); // get the maximum date on record on or before max date + if(null==maxDate)return null; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,next_earnings_date,beta,low52,high52,volume,market_cap,pe,eps,peg,return_on_assets,return_on_equity,total_cash,total_debt,shares_outstanding,revenue,revenue_per_share,qtrly_revenue_growth,gross_profit,ebitda,net_income_available_to_common,book_value_per_share,operating_cashflow,leveraged_free_cashflow,book_value_per_share*shares_outstanding as equity,trailing_pe,ebit,enterprise_value,source from fundamentals where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and asof<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate.Value)).Append("'"); + sb.Append(" order by asof desc "); + sb.Append(" limit ").Append(top); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + + double totalStockHolderEquity=BalanceSheetDA.GetTotalStockHolderEquityOnOrBefore(symbol,asof,BalanceSheet.PeriodType.Annual); + Fundamental fundamental = new Fundamental(); + fundamental.Symbol = sqlDataReader.GetString(0); + fundamental.AsOf = sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2)) fundamental.NextEarningsDate = sqlDataReader.GetDateTime(2); + if (!sqlDataReader.IsDBNull(3)) fundamental.Beta = sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4)) fundamental.Low52 = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5)) fundamental.High52 = sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6)) fundamental.Volume = sqlDataReader.GetInt64(6); + if (!sqlDataReader.IsDBNull(7)) fundamental.MarketCap = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) fundamental.PE = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) fundamental.EPS = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) fundamental.PEG = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) fundamental.ReturnOnAssets = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) fundamental.ReturnOnEquity = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) fundamental.TotalCash = sqlDataReader.GetDouble(13); + if (!sqlDataReader.IsDBNull(14)) fundamental.TotalDebt = sqlDataReader.GetDouble(14); + if (!sqlDataReader.IsDBNull(15)) fundamental.SharesOutstanding = sqlDataReader.GetDouble(15); + if (!sqlDataReader.IsDBNull(16)) fundamental.Revenue = sqlDataReader.GetDouble(16); + if (!sqlDataReader.IsDBNull(17)) fundamental.RevenuePerShare = sqlDataReader.GetDouble(17); + if (!sqlDataReader.IsDBNull(18)) fundamental.QtrlyRevenueGrowth = sqlDataReader.GetDouble(18); + if (!sqlDataReader.IsDBNull(19)) fundamental.GrossProfit = sqlDataReader.GetDouble(19); + if (!sqlDataReader.IsDBNull(20)) fundamental.EBITDA = sqlDataReader.GetDouble(20); + if (!sqlDataReader.IsDBNull(21)) fundamental.NetIncomeAvailableToCommon = sqlDataReader.GetDouble(21); + if (!sqlDataReader.IsDBNull(22)) fundamental.BookValuePerShare = sqlDataReader.GetDouble(22); + if (!sqlDataReader.IsDBNull(23)) fundamental.OperatingCashflow = sqlDataReader.GetDouble(23); + if (!sqlDataReader.IsDBNull(24)) fundamental.LeveragedFreeCashflow = sqlDataReader.GetDouble(24); + if (!sqlDataReader.IsDBNull(25)) fundamental.Equity = sqlDataReader.GetDouble(25); + if (!sqlDataReader.IsDBNull(26)) fundamental.TrailingPE = sqlDataReader.GetDouble(26); + if (!sqlDataReader.IsDBNull(27)) fundamental.EBIT = sqlDataReader.GetDouble(27); + if (!sqlDataReader.IsDBNull(28)) fundamental.EnterpriseValue = sqlDataReader.GetDouble(28); + if (!sqlDataReader.IsDBNull(29)) fundamental.Source = sqlDataReader.GetString(29); + if (!double.IsNaN(totalStockHolderEquity) && !double.IsNaN(fundamental.TotalDebt)) + { + if(0.00==totalStockHolderEquity)fundamental.TotalDebt=0.00; + else fundamental.DebtToEquity=fundamental.TotalDebt/totalStockHolderEquity; + } + fundamentals.Add(fundamental); + } + return fundamentals; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + + public static bool InsertFundamentals(Fundamentals fundamentals) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteFundamentals(fundamentals, sqlConnection, sqlTransaction); + for (int index = 0; index < fundamentals.Count; index++) + { + Fundamental fundamental = fundamentals[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into fundamentals (symbol,asof,next_earnings_date,beta,low52,high52,volume,market_cap,pe,eps,peg,return_on_assets,return_on_equity,total_cash,total_debt,shares_outstanding,revenue,revenue_per_share,qtrly_revenue_growth,gross_profit,ebitda,net_income_available_to_common,book_value_per_share,operating_cashflow,leveraged_free_cashflow,trailing_pe,ebit,enterprise_value,source) "); + sb.Append("values("); + sb.Append("'").Append(fundamental.Symbol).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(fundamental.AsOf)).Append("'").Append(","); + if (Utility.IsEpoch(fundamental.NextEarningsDate)) sb.Append("null").Append(","); + else sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(fundamental.NextEarningsDate)).Append("'").Append(","); + if (!Double.IsNaN(fundamental.Beta)) sb.Append(fundamental.Beta).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.Low52)) sb.Append(fundamental.Low52).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.High52)) sb.Append(fundamental.High52).Append(","); + else sb.Append("null").Append(","); + sb.Append(fundamental.Volume).Append(","); + if (!Double.IsNaN(fundamental.MarketCap)) sb.Append(fundamental.MarketCap).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.PE)) sb.Append(fundamental.PE).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.EPS)) sb.Append(fundamental.EPS).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.PEG)) sb.Append(fundamental.PEG).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.ReturnOnAssets))sb.Append(fundamental.ReturnOnAssets).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.ReturnOnEquity)) sb.Append(fundamental.ReturnOnEquity).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.TotalCash)) sb.Append(fundamental.TotalCash).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.TotalDebt)) sb.Append(fundamental.TotalDebt).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.SharesOutstanding)) sb.Append(fundamental.SharesOutstanding).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.Revenue)) sb.Append(fundamental.Revenue).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.RevenuePerShare)) sb.Append(fundamental.RevenuePerShare).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.QtrlyRevenueGrowth)) sb.Append(fundamental.QtrlyRevenueGrowth).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.GrossProfit)) sb.Append(fundamental.GrossProfit).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.EBITDA)) sb.Append(fundamental.EBITDA).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.NetIncomeAvailableToCommon)) sb.Append(fundamental.NetIncomeAvailableToCommon).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.BookValuePerShare)) sb.Append(fundamental.BookValuePerShare).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.OperatingCashflow)) sb.Append(fundamental.OperatingCashflow).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.LeveragedFreeCashflow)) sb.Append(fundamental.LeveragedFreeCashflow).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.TrailingPE)) sb.Append(fundamental.TrailingPE).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.EBIT)) sb.Append(fundamental.EBIT).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.EnterpriseValue)) sb.Append(fundamental.EnterpriseValue).Append(","); + else sb.Append("null").Append(","); + if (null != fundamental.Source) sb.Append(SqlUtils.AddQuotes(fundamental.Source)); + else sb.Append("null"); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '"+strQuery+"'"); + return false; + } + finally + { + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + + public static bool InsertFundamental(Fundamental fundamental) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteFundamental(fundamental, sqlConnection, sqlTransaction); + StringBuilder sb = new StringBuilder(); + sb.Append("insert into fundamentals (symbol,asof,next_earnings_date,beta,low52,high52,volume,market_cap,pe,eps,peg,return_on_assets,return_on_equity,total_cash,total_debt,shares_outstanding,revenue,revenue_per_share,qtrly_revenue_growth,gross_profit,ebitda,net_income_available_to_common,book_value_per_share,operating_cashflow,leveraged_free_cashflow,trailing_pe,ebit,enterprise_value,source) "); + sb.Append("values("); + sb.Append("'").Append(fundamental.Symbol).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(fundamental.AsOf)).Append("'").Append(","); + if (Utility.IsEpoch(fundamental.NextEarningsDate)) sb.Append("null").Append(","); + else sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(fundamental.NextEarningsDate)).Append("'").Append(","); + if (!Double.IsNaN(fundamental.Beta)) sb.Append(fundamental.Beta).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.Low52)) sb.Append(fundamental.Low52).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.High52)) sb.Append(fundamental.High52).Append(","); + else sb.Append("null").Append(","); + sb.Append(fundamental.Volume).Append(","); + if (!Double.IsNaN(fundamental.MarketCap)) sb.Append(fundamental.MarketCap).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.PE)) sb.Append(fundamental.PE).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.EPS)) sb.Append(fundamental.EPS).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.PEG)) sb.Append(fundamental.PEG).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.ReturnOnAssets))sb.Append(fundamental.ReturnOnAssets).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.ReturnOnEquity)) sb.Append(fundamental.ReturnOnEquity).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.TotalCash)) sb.Append(fundamental.TotalCash).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.TotalDebt)) sb.Append(fundamental.TotalDebt).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.SharesOutstanding)) sb.Append(fundamental.SharesOutstanding).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.Revenue)) sb.Append(fundamental.Revenue).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.RevenuePerShare)) sb.Append(fundamental.RevenuePerShare).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.QtrlyRevenueGrowth)) sb.Append(fundamental.QtrlyRevenueGrowth).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.GrossProfit)) sb.Append(fundamental.GrossProfit).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.EBITDA)) sb.Append(fundamental.EBITDA).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.NetIncomeAvailableToCommon)) sb.Append(fundamental.NetIncomeAvailableToCommon).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.BookValuePerShare)) sb.Append(fundamental.BookValuePerShare).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.OperatingCashflow)) sb.Append(fundamental.OperatingCashflow).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.LeveragedFreeCashflow)) sb.Append(fundamental.LeveragedFreeCashflow).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.TrailingPE)) sb.Append(fundamental.TrailingPE).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.EBIT)) sb.Append(fundamental.EBIT).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(fundamental.EnterpriseValue)) sb.Append(fundamental.EnterpriseValue).Append(","); + else sb.Append("null").Append(","); + if (null != fundamental.Source) sb.Append(SqlUtils.AddQuotes(fundamental.Source)); + else sb.Append("null"); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '"+strQuery+"'"); + return false; + } + finally + { + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteFundamentals(Fundamentals fundamentals, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + for (int index = 0; index < fundamentals.Count; index++) + { + DeleteFundamental(fundamentals[index], sqlConnection, sqlTransaction); + } + return true; + } + private static bool DeleteFundamental(Fundamental fundamental, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from fundamentals where "); + sb.Append("symbol='").Append(fundamental.Symbol).Append("'"); + sb.Append(" and "); + sb.Append("asof='").Append(Utility.DateTimeToStringYYYYHMMHDD(fundamental.AsOf)).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/HeadlinesDA.cs b/MarketData/MarketDataLib/DataAccess/HeadlinesDA.cs new file mode 100755 index 0000000..0f15b6e --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/HeadlinesDA.cs @@ -0,0 +1,434 @@ +using System; +using System.Text; +using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class HeadlinesDA + { + private HeadlinesDA() + { + } + public static DateTime GetMaxHeadlineDate() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + DateTime maxDate = Utility.Epoch; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(asof) from headlines"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + maxDate=sqlDataReader.GetDateTime(0); + } + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return Utility.Epoch; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetHeadlineDates() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List headlineDates=new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct asof from headlines order by 1 desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + headlineDates.Add(sqlDataReader.GetDateTime(0).ToShortDateString()); + } + return headlineDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return headlineDates; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Headlines GetHeadlines(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Headlines headlines=new Headlines(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select h.symbol, h.asof, h.headline, h.source, h.modified,sm.company from headlines h left outer join securitymaster sm on h.symbol=sm.symbol where h.symbol=").Append(SqlUtils.AddQuotes(symbol)); + sb.Append(" order by h.asof desc, h.modified desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Headline headline=new Headline(); + headline.Symbol=symbol; + headline.Date=sqlDataReader.GetDateTime(1); + headline.Entry=sqlDataReader.GetString(2); + headline.Source=sqlDataReader.GetString(3); + headline.Modified=sqlDataReader.GetDateTime(4); + headline.CompanyName=sqlDataReader.GetString(5); + headlines.Add(headline); + } + return headlines; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return headlines; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Headlines GetHeadlines() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Headlines headlines=new Headlines(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select h.symbol, h.asof, h.headline, h.source, h.modified, sm.company from headlines h left outer join securitymaster sm on h.symbol=sm.symbol"); + sb.Append(" order by h.asof desc,h.symbol,h.modified desc;"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Headline headline=new Headline(); + headline.Symbol=sqlDataReader.GetString(0); + headline.Date=sqlDataReader.GetDateTime(1); + headline.Entry=sqlDataReader.GetString(2); + headline.Source=sqlDataReader.GetString(3); + headline.Modified=sqlDataReader.GetDateTime(4); + headline.CompanyName=sqlDataReader.GetString(5); + headlines.Add(headline); + } + return headlines; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return headlines; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// This was authored for mobile app. It wants the sorting to match the WPF app. + public static Headlines GetLatestHeadlines() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + Headlines headlines = new Headlines(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select h.symbol, h.asof, h.headline, h.source, h.modified, sm.company from headlines h left outer join securitymaster sm on h.symbol=sm.symbol"); + sb.Append(" where h.asof=(select max(asof) from headlines)"); + sb.Append(" order by h.asof desc,h.modified desc,h.symbol desc;"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Headline headline = new Headline(); + headline.Symbol = sqlDataReader.GetString(0); + headline.Date = sqlDataReader.GetDateTime(1); + headline.Entry = sqlDataReader.GetString(2); + headline.Source = sqlDataReader.GetString(3); + headline.Modified = sqlDataReader.GetDateTime(4); + headline.CompanyName = sqlDataReader.GetString(5); + headlines.Add(headline); + } + return headlines; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return headlines; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Headlines GetHeadlines(String symbol,DateTime dateTime) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Headlines headlines=new Headlines(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select h.symbol, h.asof, h.headline, h.source, h.modified, sm.company from headlines h left outer join securitymaster sm on h.symbol=sm.symbol where h.asof=").Append(SqlUtils.AddQuotes(SqlUtils.SqlDate(dateTime))); + sb.Append(" and h.symbol=").Append(SqlUtils.AddQuotes(symbol)); + sb.Append("order by h.asof desc, h.modified desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Headline headline=new Headline(); + headline.Symbol=sqlDataReader.GetString(0); + headline.Date=sqlDataReader.GetDateTime(1); + headline.Entry=sqlDataReader.GetString(2); + headline.Source=sqlDataReader.GetString(3); + headline.Modified=sqlDataReader.GetDateTime(4); + headline.CompanyName=sqlDataReader.GetString(5); + headlines.Add(headline); + } + return headlines; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return headlines; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Headlines GetHeadlines(DateTime dateTime) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Headlines headlines=new Headlines(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select h.symbol, h.asof, h.headline, h.source, h.modified, sm.company from headlines h left outer join securitymaster sm on h.symbol=sm.symbol where h.asof=").Append(SqlUtils.AddQuotes(SqlUtils.SqlDate(dateTime))); + sb.Append("order by h.modified desc,h.symbol"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Headline headline=new Headline(); + headline.Symbol=sqlDataReader.GetString(0); + headline.Date=sqlDataReader.GetDateTime(1); + headline.Entry=sqlDataReader.GetString(2); + headline.Source=sqlDataReader.GetString(3); + headline.Modified=sqlDataReader.GetDateTime(4); + headline.CompanyName=sqlDataReader.GetString(5); + headlines.Add(headline); + } + return headlines; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return headlines; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertHeadlines(Headlines headlines) + { + MySqlCommand sqlCommand=null; + MySqlConnection sqlConnection=null; + MySqlTransaction sqlTransaction=null; + + try + { + if (null == headlines || 0 == headlines.Count) return false; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + headlines=new Headlines(headlines.Distinct(new HeadlinesEqualityComparer()).ToList()); + foreach(Headline headline in headlines) + { + if(!HeadlineExists(headline,sqlConnection,sqlTransaction))InsertHeadline(headline,sqlConnection,sqlTransaction); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + private static bool InsertHeadline(Headline headline,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == headline || null == headline.Symbol || null==headline.Entry) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into Headlines(symbol,asof,headline,source,modified) values("); + sb.Append(SqlUtils.AddQuotes(headline.Symbol)).Append(","); + sb.Append(SqlUtils.AddQuotes(SqlUtils.SqlDate(headline.Date))).Append(","); + sb.Append(SqlUtils.AddQuotes(SqlUtils.SqlString(headline.Entry))).Append(","); + sb.Append(SqlUtils.AddQuotes(SqlUtils.SqlString(headline.Source))).Append(","); + if(Utility.IsEpoch(headline.Modified))sb.Append(SqlUtils.AddQuotes(SqlUtils.ToSqlDateTime(DateTime.Now))); + else sb.Append(SqlUtils.AddQuotes(SqlUtils.ToSqlDateTime(headline.Modified))); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was '{0}'",strQuery)); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + } + } + private static bool HeadlineExists(Headline headline,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == headline || null == headline.Symbol) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("select count(*) from headlines where "); + sb.Append(" asof=").Append(SqlUtils.AddQuotes(SqlUtils.SqlDate(headline.Date))).Append(" and "); + sb.Append(" headline=").Append(SqlUtils.AddQuotes(SqlUtils.SqlString(headline.Entry))); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read())return false; + return 0==sqlDataReader.GetInt32(0)?false:true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlDataReader){sqlDataReader.Close();sqlDataReader.Dispose();} + } + } + //private static bool HeadlineExists(Headline headline,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + //{ + // MySqlDataReader sqlDataReader=null; + // MySqlCommand sqlCommand=null; + // String strQuery = null; + + // try + // { + // if (null == headline || null == headline.Symbol) return false; + // StringBuilder sb = new StringBuilder(); + // sb.Append("select count(*) from headlines where symbol=").Append(SqlUtils.AddQuotes(headline.Symbol)).Append(" and "); + // sb.Append(" asof=").Append(SqlUtils.AddQuotes(SqlUtils.SqlDate(headline.Date))).Append(" and "); + // sb.Append(" headline=").Append(SqlUtils.AddQuotes(SqlUtils.SqlString(headline.Entry))); + // strQuery = sb.ToString(); + // sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + // sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + // sqlDataReader=sqlCommand.ExecuteReader(); + // if(!sqlDataReader.Read())return false; + // return 0==sqlDataReader.GetInt32(0)?false:true; + // } + // catch (Exception exception) + // { + // MDTrace.WriteLine(LogLevel.DEBUG,exception); + // return false; + // } + // finally + // { + // if(null!=sqlCommand)sqlCommand.Dispose(); + // if(null!=sqlDataReader){sqlDataReader.Close();sqlDataReader.Dispose();} + // } + //} + } +} diff --git a/MarketData/MarketDataLib/DataAccess/HistoricalDA.cs b/MarketData/MarketDataLib/DataAccess/HistoricalDA.cs new file mode 100755 index 0000000..bd7ad21 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/HistoricalDA.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class HistoricalDA + { + private HistoricalDA() + { + } + public static TimeSeriesCollection GetTimeSeriesMaxAsOf(String symbol,DateTime asOf,TimeSeriesElement.ElementType elementType) + { + TimeSeriesCollection timeSeriesCollection =new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,value,modified from historical where symbol="); + sb.Append("'").Append(symbol).Append("'"); + sb.Append(" and type='").Append(TimeSeriesElement.StringForType(elementType)).Append("'"); + sb.Append(" and asof<='").Append(SqlUtils.FormatDate(asOf)).Append("'"); + sb.Append(" order by asof desc"); + sb.Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + timeSeriesElement.Type = elementType; + if (!sqlDataReader.IsDBNull(2)) timeSeriesElement.Value = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3)) timeSeriesElement.Modified = sqlDataReader.GetDateTime(3); + else timeSeriesElement.Modified=Utility.Epoch; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static TimeSeriesCollection GetTimeSeries(String symbol,TimeSeriesElement.ElementType elementType) + { + TimeSeriesCollection timeSeriesCollection =new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,value,modified from historical where symbol="); + sb.Append("'").Append(symbol).Append("'"); + sb.Append(" and type='").Append(TimeSeriesElement.StringForType(elementType)).Append("'").Append(" order by asof desc"); + sb.Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + timeSeriesElement.Type = elementType; + if (!sqlDataReader.IsDBNull(2)) timeSeriesElement.Value = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3)) timeSeriesElement.Modified = sqlDataReader.GetDateTime(3); + else timeSeriesElement.Modified=Utility.Epoch; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertTimeSeries(TimeSeriesCollection timeSeriesCollection) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + DateTime modified=DateTime.Now; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteTimeSeries(timeSeriesCollection, sqlConnection, sqlTransaction); + for (int index = 0; index < timeSeriesCollection.Count; index++) + { + TimeSeriesElement timeSeriesElement = timeSeriesCollection[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into historical (symbol,asof,type,value,modified) "); + sb.Append("values("); + sb.Append("'").Append(timeSeriesElement.Symbol).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(timeSeriesElement.AsOf)).Append("'").Append(","); + sb.Append("'").Append(TimeSeriesElement.StringForType(timeSeriesElement.Type)).Append("'").Append(","); + sb.Append(timeSeriesElement.Value).Append(","); + sb.Append("'").Append(SqlUtils.ToSqlDateTime(modified)).Append("'"); + sb.Append(");"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '"+strQuery+"'"); + return false; + } + finally + { + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteTimeSeries(TimeSeriesCollection timeSeriesCollection, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + for (int index = 0; index < timeSeriesCollection.Count; index++) + { + DeleteTimeSeries(timeSeriesCollection[index], sqlConnection, sqlTransaction); + } + return true; + } + private static bool DeleteTimeSeries(TimeSeriesElement timeSeriesElement, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from historical where "); + sb.Append("symbol='").Append(timeSeriesElement.Symbol).Append("'"); + sb.Append(" and "); + sb.Append("asof='").Append(Utility.DateTimeToStringYYYYHMMHDD(timeSeriesElement.AsOf)).Append("'"); + sb.Append(" and type='").Append(TimeSeriesElement.StringForType(timeSeriesElement.Type)).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/HolidayDA.cs b/MarketData/MarketDataLib/DataAccess/HolidayDA.cs new file mode 100755 index 0000000..0b899b1 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/HolidayDA.cs @@ -0,0 +1,159 @@ +using System; +using System.Text; +using System.Diagnostics; +using System.Collections.Generic; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class HolidayDA + { + private HolidayDA() + { + } + public static String GetHolidayDescription(DateTime date) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + String description=""; + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select description from MarketHolidays where date='").Append(Utils.SqlUtils.SqlDate(date)).Append("'"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(sqlDataReader.Read()) + { + if(!sqlDataReader.IsDBNull(0)) description=sqlDataReader.GetString(0); + } + return description; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return description; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetMaxHolidayDate() + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + DateTime maxHolidayDate=Utility.Epoch; + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(date) from MarketHolidays"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(sqlDataReader.Read()) + { + if(!sqlDataReader.IsDBNull(0)) maxHolidayDate=sqlDataReader.GetDateTime(0); + } + return maxHolidayDate; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return maxHolidayDate; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + + public static bool IsMarketHoliday(DateTime date) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + int recordCount=0; + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from MarketHolidays where date='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("' "); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(sqlDataReader.Read()) + { + if(!sqlDataReader.IsDBNull(0)) recordCount=sqlDataReader.GetInt32(0); + } + return 0==recordCount?false:true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static Dictionary GetHolidays() + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + Dictionary holidays=new Dictionary(); + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date from MarketHolidays order by date desc"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + DateTime holiday=sqlDataReader.GetDateTime(0); + if(!holidays.ContainsKey(holiday))holidays.Add(holiday,holiday); + } + return holidays; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/IncomeStatementDA.cs b/MarketData/MarketDataLib/DataAccess/IncomeStatementDA.cs new file mode 100755 index 0000000..a8788ef --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/IncomeStatementDA.cs @@ -0,0 +1,522 @@ +using System; +using System.Text; +using System.Collections.Generic; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class IncomeStatementDA + { +// ********************************************* I N C O M E S T A T E M E N T ************************************** + public static bool CheckIncomeStatementModifiedOn(String symbol, DateTime modified,IncomeStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from incomestatement"); + sb.Append(" where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and period=").Append(periodType.Equals(IncomeStatement.PeriodType.Annual)?0:1).Append("").Append(" "); + sb.Append("and modified='").Append(Utility.DateTimeToStringYYYYHMMHDD(modified)).Append("'"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + sqlDataReader.Read(); + int recordCount = sqlDataReader.GetInt32(0); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetIncomeStatementDates(String symbol,IncomeStatement.PeriodType periodType) + { + List incomeStatementDates = new List(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select asof from incomestatement where symbol='").Append(symbol).Append("' "); + sb.Append("and period='").Append(periodType.Equals(IncomeStatement.PeriodType.Annual)?0:1).Append("'"); + sb.Append(" order by 1 asc;"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + DateTime asof = sqlDataReader.GetDateTime(0); + incomeStatementDates.Add(asof); + } + return incomeStatementDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return incomeStatementDates; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime? GetLatestIncomeStatementDate(String symbol,IncomeStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(asof) from incomestatement"); + sb.Append(" where symbol='").Append(symbol).Append("' "); + sb.Append(" and period=").Append(periodType.Equals(IncomeStatement.PeriodType.Annual)?0:1); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (sqlDataReader.IsDBNull(0)) maxDate = null; + else maxDate = sqlDataReader.GetDateTime(0); + } + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return maxDate; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static IncomeStatement GetIncomeStatement(String symbol,IncomeStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + DateTime? latestDate = GetLatestIncomeStatementDate(symbol,periodType); + if(null==latestDate)return null; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,total_revenue,cost_of_revenue,income_tax_expense,gross_profit,net_income,sga,net_income_applicable_to_common_shares,ebit,operating_expenses,research_and_development,interest_expense,period,modified from incomestatement where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(IncomeStatement.PeriodType.Annual)?0:1).Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(latestDate.Value)).Append("'").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + IncomeStatement incomeStatement = new IncomeStatement(); + incomeStatement.Symbol = sqlDataReader.GetString(0); + incomeStatement.AsOf = sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2)) incomeStatement.TotalRevenue = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3)) incomeStatement.CostOfRevenue = sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4)) incomeStatement.IncomeTaxExpense = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5)) incomeStatement.GrossProfit = sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6)) incomeStatement.NetIncome = sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7)) incomeStatement.SGA = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) incomeStatement.NetIncomeApplicableToCommonShares = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) incomeStatement.EBIT = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) incomeStatement.OperatingExpenses = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) incomeStatement.ResearchAndDevelopment = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) incomeStatement.InterestExpense = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) incomeStatement.Period = sqlDataReader.GetInt32(13)==0?IncomeStatement.PeriodType.Annual:IncomeStatement.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(14)) incomeStatement.Modified = sqlDataReader.GetDateTime(14); + return incomeStatement; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static TimeSeriesCollection GetRevenue(String symbol,IncomeStatement.PeriodType period) + { + TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,total_revenue from incomestatement where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and period=").Append(period.Equals(IncomeStatement.PeriodType.Annual)?0:1).Append(" order by asof desc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + timeSeriesElement.Type = period.Equals(IncomeStatement.PeriodType.Quarterly)?TimeSeriesElement.ElementType.QuarterlyRevenue:TimeSeriesElement.ElementType.Revenue; + if (!sqlDataReader.IsDBNull(2)) timeSeriesElement.Value = sqlDataReader.GetDouble(2); + else continue; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// Profit Margin is calculated as a percentage. + public static TimeSeriesCollection GetProfitMargin(String symbol,IncomeStatement.PeriodType period=IncomeStatement.PeriodType.Annual) + { + TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,total_revenue,gross_profit from incomestatement where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and period=").Append(period.Equals(IncomeStatement.PeriodType.Annual)?0:1).Append(" order by asof desc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + timeSeriesElement.Type = period.Equals(IncomeStatement.PeriodType.Quarterly)?TimeSeriesElement.ElementType.QuarterlyRevenue:TimeSeriesElement.ElementType.Revenue; + + if(sqlDataReader.IsDBNull(2))continue; + double total_revenue=sqlDataReader.GetDouble(2); + if(sqlDataReader.IsDBNull(3))continue; + double gross_profit=sqlDataReader.GetDouble(3); + if(0==gross_profit)continue; + timeSeriesElement.Value=(gross_profit/total_revenue)*100.00; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + // Profit Margin is calculated as a percentage. + public static TimeSeriesCollection GetProfitMarginMaxAsOf(String symbol,DateTime maxDate, IncomeStatement.PeriodType period = IncomeStatement.PeriodType.Annual) + { + TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,total_revenue,gross_profit from incomestatement where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and asof<='").Append(SqlUtils.SqlDate(maxDate)).Append("' "); + sb.Append(" and period=").Append(period.Equals(IncomeStatement.PeriodType.Annual) ? 0 : 1).Append(" order by asof desc;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Symbol = sqlDataReader.GetString(0); + timeSeriesElement.AsOf = sqlDataReader.GetDateTime(1); + timeSeriesElement.Type = period.Equals(IncomeStatement.PeriodType.Quarterly) ? TimeSeriesElement.ElementType.QuarterlyRevenue : TimeSeriesElement.ElementType.Revenue; + + if (sqlDataReader.IsDBNull(2)) continue; + double total_revenue = sqlDataReader.GetDouble(2); + if (sqlDataReader.IsDBNull(3)) continue; + double gross_profit = sqlDataReader.GetDouble(3); + if (0 == gross_profit) continue; + timeSeriesElement.Value = (gross_profit / total_revenue) * 100.00; + timeSeriesCollection.Add(timeSeriesElement); + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static IncomeStatement GetIncomeStatement(String symbol,DateTime asof,IncomeStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,total_revenue,cost_of_revenue,income_tax_expense,gross_profit,net_income,net_income_applicable_to_common_shares,sga,ebit,operating_expenses,research_and_development,interest_expense,period,modified from incomestatement where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(IncomeStatement.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("'").Append(";"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + IncomeStatement incomeStatement = new IncomeStatement(); + incomeStatement.Symbol = sqlDataReader.GetString(0); + incomeStatement.AsOf = sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2)) incomeStatement.TotalRevenue = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3)) incomeStatement.CostOfRevenue = sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4)) incomeStatement.IncomeTaxExpense = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5)) incomeStatement.GrossProfit = sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6)) incomeStatement.NetIncome = sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7)) incomeStatement.SGA = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) incomeStatement.NetIncomeApplicableToCommonShares = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) incomeStatement.EBIT = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) incomeStatement.OperatingExpenses = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) incomeStatement.ResearchAndDevelopment = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) incomeStatement.InterestExpense = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) incomeStatement.Period = 0 == sqlDataReader.GetInt32(13) ? IncomeStatement.PeriodType.Annual : IncomeStatement.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(14)) incomeStatement.Modified = sqlDataReader.GetDateTime(14); + return incomeStatement; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static IncomeStatement GetIncomeStatementMaxAsOf(String symbol,DateTime asof,IncomeStatement.PeriodType periodType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,asof,total_revenue,cost_of_revenue,income_tax_expense,gross_profit,net_income,net_income_applicable_to_common_shares,sga,ebit,operating_expenses,research_and_development,interest_expense,period,modified from incomestatement where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and period=").Append(periodType.Equals(IncomeStatement.PeriodType.Annual) ? 0 : 1).Append(" "); + sb.Append("and asof<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(asof)).Append("'"); + sb.Append(" order by asof desc limit 1;"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + IncomeStatement incomeStatement = new IncomeStatement(); + incomeStatement.Symbol = sqlDataReader.GetString(0); + incomeStatement.AsOf = sqlDataReader.GetDateTime(1); + if (!sqlDataReader.IsDBNull(2)) incomeStatement.TotalRevenue = sqlDataReader.GetDouble(2); + if (!sqlDataReader.IsDBNull(3)) incomeStatement.CostOfRevenue = sqlDataReader.GetDouble(3); + if (!sqlDataReader.IsDBNull(4)) incomeStatement.IncomeTaxExpense = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5)) incomeStatement.GrossProfit = sqlDataReader.GetDouble(5); + if (!sqlDataReader.IsDBNull(6)) incomeStatement.NetIncome = sqlDataReader.GetDouble(6); + if (!sqlDataReader.IsDBNull(7)) incomeStatement.SGA = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) incomeStatement.NetIncomeApplicableToCommonShares = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) incomeStatement.EBIT = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) incomeStatement.OperatingExpenses = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) incomeStatement.ResearchAndDevelopment = sqlDataReader.GetDouble(11); + if (!sqlDataReader.IsDBNull(12)) incomeStatement.InterestExpense = sqlDataReader.GetDouble(12); + if (!sqlDataReader.IsDBNull(13)) incomeStatement.Period = 0 == sqlDataReader.GetInt32(13) ? IncomeStatement.PeriodType.Annual : IncomeStatement.PeriodType.Quarterly; + if (!sqlDataReader.IsDBNull(14)) incomeStatement.Modified = sqlDataReader.GetDateTime(14); + return incomeStatement; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertIncomeStatements(List incomeStatements) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + + try + { + DateTime modified = DateTime.Now; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteIncomeStatements(incomeStatements, sqlConnection, sqlTransaction); + for (int index = 0; index < incomeStatements.Count; index++) + { + IncomeStatement incomeStatement = incomeStatements[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into incomestatement (symbol,asof,total_revenue,cost_of_revenue,income_tax_expense,gross_profit,net_income,sga,net_income_applicable_to_common_shares,ebit,operating_expenses,research_and_development,interest_expense,period,modified) "); + sb.Append("values("); + sb.Append("'").Append(incomeStatement.Symbol).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(incomeStatement.AsOf)).Append("'").Append(","); + if (!Double.IsNaN(incomeStatement.TotalRevenue)) sb.Append(incomeStatement.TotalRevenue).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.CostOfRevenue)) sb.Append(incomeStatement.CostOfRevenue).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.IncomeTaxExpense)) sb.Append(incomeStatement.IncomeTaxExpense).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.GrossProfit)) sb.Append(incomeStatement.GrossProfit).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.NetIncome)) sb.Append(incomeStatement.NetIncome).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.SGA)) sb.Append(incomeStatement.SGA).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.NetIncomeApplicableToCommonShares))sb.Append(incomeStatement.NetIncomeApplicableToCommonShares).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.EBIT)) sb.Append(incomeStatement.EBIT).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.OperatingExpenses)) sb.Append(incomeStatement.OperatingExpenses).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.ResearchAndDevelopment)) sb.Append(incomeStatement.ResearchAndDevelopment).Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(incomeStatement.InterestExpense)) sb.Append(incomeStatement.InterestExpense).Append(","); + else sb.Append("null").Append(","); + sb.Append(IncomeStatement.PeriodType.Annual.Equals(incomeStatement.Period)?0:1).Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(modified)).Append("'"); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteIncomeStatements(List incomeStatements, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + for (int index = 0; index < incomeStatements.Count; index++) + { + DeleteIncomeStatement(incomeStatements[index], sqlConnection, sqlTransaction); + } + return true; + } + private static bool DeleteIncomeStatement(IncomeStatement incomeStatement, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from incomestatement where "); + sb.Append("symbol='").Append(incomeStatement.Symbol).Append("'"); + sb.Append(" and "); + sb.Append("asof='").Append(Utility.DateTimeToStringYYYYHMMHDD(incomeStatement.AsOf)).Append("'"); + sb.Append(" and period=").Append(incomeStatement.Period.Equals(IncomeStatement.PeriodType.Annual) ? 0 : 1); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/InsiderTransactionDA.cs b/MarketData/MarketDataLib/DataAccess/InsiderTransactionDA.cs new file mode 100755 index 0000000..2baca59 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/InsiderTransactionDA.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class InsiderTransactionDA + { + private InsiderTransactionDA() + { + } + public static InsiderTransactionSummaries GetInsiderTransactionSummaries(String symbol,DateTime? minDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + InsiderTransactionSummaries insiderTransactionSummaries =new InsiderTransactionSummaries(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select transaction_date,sum(number_or_value_acquired_disposed) from InsiderTransaction where "); + sb.Append(" symbol=").Append("'").Append(symbol).Append("' "); + if(null!=minDate)sb.Append(" and transaction_date>=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(minDate.Value)).Append("'"); + sb.Append(" and number_or_value_acquired_disposed is not null group by transaction_date order by transaction_date desc "); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + InsiderTransactionSummary insiderTransactionSummary=new InsiderTransactionSummary(); + insiderTransactionSummary.Symbol=symbol; + insiderTransactionSummary.TransactionDate=sqlDataReader.GetDateTime(0); + insiderTransactionSummary.NumberOfSharesAcquiredDisposed=sqlDataReader.GetDouble(1); + insiderTransactionSummaries.Add(insiderTransactionSummary); + } + return insiderTransactionSummaries; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactionSummaries Exception: {0}",exception.ToString())); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + + public static InsiderTransactions GetLatestInsiderTransactions() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + InsiderTransactions insiderTransactions=new InsiderTransactions(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("SELECT symbol,filing_date,transaction_date,insider_name,ownership_type,securities,nature_of_transaction,number_or_value_acquired_disposed,price,form,sec_accession_number,form_row_number,modified FROM insidertransaction WHERE TRANSACTION_DATE=(SELECT MAX(TRANSACTION_DATE) FROM insidertransaction WHERE TRANSACTION_DATE<=NOW() LIMIT 1)"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + InsiderTransaction insiderTransaction=new InsiderTransaction(); + insiderTransaction.Symbol=sqlDataReader.GetString(0); + insiderTransaction.FilingDate=sqlDataReader.GetDateTime(1); + insiderTransaction.TransactionDate=sqlDataReader.GetDateTime(2); + insiderTransaction.InsiderName=sqlDataReader.GetString(3); + insiderTransaction.OwnershipType=sqlDataReader.GetString(4); + insiderTransaction.Securities=sqlDataReader.GetString(5); + insiderTransaction.NatureOfTransaction=sqlDataReader.GetString(6); + if(!sqlDataReader.IsDBNull(7))insiderTransaction.NumberOrValueAcquiredDisposed=sqlDataReader.GetDouble(7); + else insiderTransaction.NumberOrValueAcquiredDisposed=Double.NaN; + if(!sqlDataReader.IsDBNull(8))insiderTransaction.Price=sqlDataReader.GetDouble(8); + else insiderTransaction.Price=Double.NaN; + insiderTransaction.Form=sqlDataReader.GetString(9); + insiderTransaction.SECAccessionNumber=sqlDataReader.GetString(10); + insiderTransaction.FormRowNumber=sqlDataReader.GetString(11); + insiderTransaction.Modified=sqlDataReader.GetDateTime(12); + insiderTransactions.Add(insiderTransaction); + } + return insiderTransactions; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetLatestInsiderTransactions Exception: {0}",exception.ToString())); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + + public static InsiderTransactions GetInsiderTransactions(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + InsiderTransactions insiderTransactions=new InsiderTransactions(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,filing_date,transaction_date,insider_name,ownership_type,securities,nature_of_transaction,number_or_value_acquired_disposed,price,form,sec_accession_number,form_row_number,modified from InsiderTransaction where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" order by filing_date desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + InsiderTransaction insiderTransaction=new InsiderTransaction(); + insiderTransaction.Symbol=sqlDataReader.GetString(0); + insiderTransaction.FilingDate=sqlDataReader.GetDateTime(1); + insiderTransaction.TransactionDate=sqlDataReader.GetDateTime(2); + insiderTransaction.InsiderName=sqlDataReader.GetString(3); + insiderTransaction.OwnershipType=sqlDataReader.GetString(4); + insiderTransaction.Securities=sqlDataReader.GetString(5); + insiderTransaction.NatureOfTransaction=sqlDataReader.GetString(6); + if(!sqlDataReader.IsDBNull(7))insiderTransaction.NumberOrValueAcquiredDisposed=sqlDataReader.GetDouble(7); + else insiderTransaction.NumberOrValueAcquiredDisposed=Double.NaN; + if(!sqlDataReader.IsDBNull(8))insiderTransaction.Price=sqlDataReader.GetDouble(8); + else insiderTransaction.Price=Double.NaN; + insiderTransaction.Form=sqlDataReader.GetString(9); + insiderTransaction.SECAccessionNumber=sqlDataReader.GetString(10); + insiderTransaction.FormRowNumber=sqlDataReader.GetString(11); + insiderTransaction.Modified=sqlDataReader.GetDateTime(12); + insiderTransactions.Add(insiderTransaction); + } + return insiderTransactions; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactions Exception: {0}",exception.ToString())); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + + + public static bool InsertInsiderTransactions(InsiderTransactions insiderTransactions) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + Dictionary insiderTransactionsUniqueKey = new Dictionary(); + String strQuery = null; + DateTime modified=DateTime.Now; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + if (!DeleteInsiderTransactions(insiderTransactions, sqlConnection)) return false; + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + foreach (InsiderTransaction insiderTransaction in insiderTransactions) + { + String insiderTransactionKey = insiderTransaction.Form + insiderTransaction.SECAccessionNumber + insiderTransaction.FormRowNumber; + if (insiderTransactionsUniqueKey.ContainsKey(insiderTransactionKey)) + { + MDTrace.WriteLine(LogLevel.DEBUG,"*********************************************************************************************************"); + + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Collection already contains a value for Form:{0} SECAccessionNumber:{1} FormRowNumber:{2}", + insiderTransaction.Form,insiderTransaction.SECAccessionNumber,insiderTransaction.FormRowNumber)); + + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Item attempting to add: Symbol:{0} InsiderName:{1} OwnershipType:{2} Securities:{3} NatureOfTransaction:{4} NumberOrValueAcquiredDisposed:{5} Price:{7} FilingDate:{7} TransactionDate:{8}", + insiderTransaction.Symbol, insiderTransaction.InsiderName,insiderTransaction.OwnershipType,insiderTransaction.Securities,insiderTransaction.NatureOfTransaction,insiderTransaction.NumberOrValueAcquiredDisposed,insiderTransaction.Price, + Utility.DateTimeToStringMMHDDHYYYY(insiderTransaction.FilingDate),Utility.DateTimeToStringMMSDDSYYYY(insiderTransaction.TransactionDate))); + + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Item already in collection: Symbol:{0} InsiderName:{1} OwnershipType:{2} Securities:{3} NatureOfTransaction:{4} NumberOrValueAcquiredDisposed:{5} Price:{6} FilingDate:{7} TransactionDate:{8}", + insiderTransaction.Symbol,insiderTransaction.InsiderName,insiderTransaction.OwnershipType,insiderTransaction.Securities,insiderTransaction.NatureOfTransaction,insiderTransaction.NumberOrValueAcquiredDisposed,insiderTransaction.Price, + Utility.DateTimeToStringMMHDDHYYYY(insiderTransaction.FilingDate),Utility.DateTimeToStringMMSDDSYYYY(insiderTransaction.TransactionDate))); + + MDTrace.WriteLine(LogLevel.DEBUG,"*********************************************************************************************************"); + + continue; + } + StringBuilder sb = new StringBuilder(); + sb.Append("insert into InsiderTransaction (symbol,filing_date,transaction_date,insider_name,ownership_type,securities,nature_of_transaction,number_or_value_acquired_disposed,price,form,sec_accession_number,form_row_number,modified) "); + sb.Append("values("); + sb.Append("'").Append(insiderTransaction.Symbol).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(insiderTransaction.FilingDate)).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(insiderTransaction.TransactionDate)).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.SqlString(insiderTransaction.InsiderName)).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.SqlString(insiderTransaction.OwnershipType)).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.SqlString(insiderTransaction.Securities)).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.SqlString(insiderTransaction.NatureOfTransaction)).Append("'").Append(","); + if (!Double.IsNaN(insiderTransaction.NumberOrValueAcquiredDisposed)) sb.Append("'").Append(insiderTransaction.NumberOrValueAcquiredDisposed).Append("'").Append(","); + else sb.Append("null").Append(","); + if (!Double.IsNaN(insiderTransaction.Price)) sb.Append("'").Append(insiderTransaction.Price).Append("'").Append(","); + else sb.Append("null").Append(","); + sb.Append("'").Append(insiderTransaction.Form).Append("'").Append(","); + sb.Append("'").Append(insiderTransaction.SECAccessionNumber).Append("'").Append(","); + sb.Append("'").Append(insiderTransaction.FormRowNumber).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.ToSqlDateTime(modified)).Append("'"); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + insiderTransactionsUniqueKey.Add(insiderTransactionKey, insiderTransaction); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("InsertInsiderTransactions Exception: {0}",exception.ToString())); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if (null != sqlConnection) sqlConnection.Close(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + } + } + private static bool DeleteInsiderTransactions(InsiderTransactions insiderTransactions, MySqlConnection sqlConnection) + { + StringBuilder sb = null; + String strQuery = null; + MySqlTransaction sqlTransaction = null; + + try + { + if (null == insiderTransactions) return false; + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + foreach (InsiderTransaction insiderTransaction in insiderTransactions) + { + sb = new StringBuilder(); + sb.Append("delete from InsiderTransaction where "); + sb.Append("symbol='").Append(insiderTransaction.Symbol).Append("'").Append(" and "); + sb.Append("form='").Append(insiderTransaction.Form).Append("'").Append(" and "); + sb.Append("sec_accession_number='").Append(insiderTransaction.SECAccessionNumber).Append("'").Append(" and "); + sb.Append("form_row_number='").Append(insiderTransaction.FormRowNumber).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("DeleteInsiderTransactions Exception: {0}",exception.ToString())); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + if(null!=sqlTransaction)sqlTransaction.Dispose(); + } + } + /// + /// Delete InsiderTransaction for given symbol for all years>=given year. + /// + /// The symbol. + /// All years greater then or equal to the year. + public static bool DeleteInsiderTransactionsYearsGreaterEqual(String symbol, int yearsGreaterEqual) + { + MySqlConnection sqlConnection = null; + StringBuilder sb = null; + String strQuery = null; + MySqlTransaction sqlTransaction = null; + + try + { + if (null == symbol) return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + sb = new StringBuilder(); + sb.Append("DELETE FROM InsiderTransaction WHERE symbol="); + sb.Append("'").Append(symbol).Append("'"); + sb.Append(" AND YEAR(filing_date)>=").Append(yearsGreaterEqual); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("DeleteInsiderTransactionsYearsGreaterEqual Exception: {0}",exception.ToString())); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if(null!=sqlConnection)sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/LexicalDA.cs b/MarketData/MarketDataLib/DataAccess/LexicalDA.cs new file mode 100755 index 0000000..3974d46 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/LexicalDA.cs @@ -0,0 +1,305 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class LexicalDA + { + private LexicalDA() + { + } + public static bool TruncateLexicon() + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + sb.Append("truncate table lexicon"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertLexicalElement(LexicalElement lexicalElement) + { + LexicalCollection lexicalCollection=new LexicalCollection(); + lexicalCollection.Add(lexicalElement); + InsertLexicalCollection(lexicalCollection); + return true; + } + public static bool InsertLexicalCollection(LexicalCollection lexicalCollection) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + DateTime created=modified; + foreach(LexicalElement lexicalElement in lexicalCollection) + { + sb=new StringBuilder(); + if(ContainsLexicalElement(lexicalElement))continue; + sb.Append("insert into lexicon (word,sentiment,part_of_speech) "); + sb.Append("values("); + sb.Append("'").Append(lexicalElement.Word).Append("'").Append(","); + sb.Append("'").Append(lexicalElement.Sentiment).Append("'").Append(","); + if(null!=lexicalElement.PartOfSpeech)sb.Append("'").Append(lexicalElement.PartOfSpeech).Append("'"); + else sb.Append("null"); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool ContainsLexicalElement(LexicalElement lexicalElement) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + int recordCount = 0; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from lexicon where word='").Append(lexicalElement.Word).Append("' "); + sb.Append("and sentiment='").Append(lexicalElement.Sentiment).Append("' "); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) recordCount = sqlDataReader.GetInt32(0); + } + sqlCommand.Dispose(); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool UpdateLexicalElement(LexicalElement lexicalElement) + { + LexicalCollection lexicalCollection=new LexicalCollection(); + lexicalCollection.Add(lexicalElement); + return UpdateLexicalElements(lexicalCollection); + } + public static bool UpdateLexicalElements(LexicalCollection lexicalCollection) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + foreach(LexicalElement lexicalElement in lexicalCollection) + { + if(!ContainsLexicalElement(lexicalElement))continue; + if(null==lexicalElement.PartOfSpeech||0==lexicalElement.PartOfSpeech.Length)continue; + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("update lexicon set "); + sb.Append("part_of_speech=").Append("'").Append(lexicalElement.PartOfSpeech).Append("'"); + sb.Append(" where word='").Append(lexicalElement.Word).Append("'").Append(" and "); + sb.Append("sentiment='").Append(lexicalElement.Sentiment).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static LexicalCollection GetLexicalCollection(String sentiment) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + LexicalCollection lexicalCollection=new LexicalCollection(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("select word,sentiment,part_of_speech from lexicon "); + sb.Append(" where sentiment='").Append(sentiment).Append("'"); + sb.Append(" order by word desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + LexicalElement lexicalElement=new LexicalElement(); + lexicalElement.Word=sqlDataReader.GetString(0); + lexicalElement.Sentiment=sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))lexicalElement.PartOfSpeech=sqlDataReader.GetString(2); + lexicalCollection.Add(lexicalElement); + } + return lexicalCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static LexicalCollection GetLexicalCollection() + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + LexicalCollection lexicalCollection=new LexicalCollection(); + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("select word,sentiment,part_of_speech from lexicon "); + sb.Append(" order by word desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + LexicalElement lexicalElement=new LexicalElement(); + lexicalElement.Word=sqlDataReader.GetString(0); + lexicalElement.Sentiment=sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))lexicalElement.PartOfSpeech=sqlDataReader.GetString(2); + lexicalCollection.Add(lexicalElement); + } + return lexicalCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteLexicalCollection(LexicalCollection lexicalCollection, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + foreach(LexicalElement lexicalElement in lexicalCollection)DeleteLexicalElement(lexicalElement,sqlConnection,sqlTransaction); + return true; + } + private static bool DeleteLexicalElement(LexicalElement lexicalElement, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from lexicon where "); + sb.Append("word='").Append(lexicalElement.Word).Append("'"); + sb.Append(" and "); + sb.Append("sentiment='").Append(lexicalElement.Sentiment).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/MStarSecurityDA.cs b/MarketData/MarketDataLib/DataAccess/MStarSecurityDA.cs new file mode 100755 index 0000000..0557a85 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/MStarSecurityDA.cs @@ -0,0 +1,181 @@ +using System; +using System.Text; +using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class MStarSecurityDA + { + private MStarSecurityDA() + { + } + public static String GetSecurityId(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + String securityIdentifier=null; + + try + { + if(!HasSecurityId(symbol))return null; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select security_identifier from mstarsecurityid where symbol=").Append(Utility.AddQuotes(symbol)); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + securityIdentifier=sqlDataReader.GetString(0); + } + return securityIdentifier; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static void PutSecurityId(String symbol,String securityId) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction=null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + if(!HasSecurityId(symbol))InsertSecurityId(symbol,securityId,sqlConnection,sqlTransaction); + else UpdateSecurityId(symbol,securityId,sqlConnection,sqlTransaction); + sqlTransaction= sqlConnection.BeginTransaction(); + sqlTransaction.Commit(); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + } + finally + { + if(null!=sqlTransaction) + { + sqlTransaction.Dispose(); + } + if(null!=sqlConnection) + { + sqlConnection.Close(); + sqlConnection.Dispose(); + } + } + } + + private static bool UpdateSecurityId(String symbol,String securityIdentifier, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == securityIdentifier || null == symbol) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("update mstarsecurityid set security_identifier=").Append(Utility.AddQuotes(securityIdentifier)); + sb.Append(" where symbol=").Append(Utility.AddQuotes(symbol)); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was '{0}'",strQuery)); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + } + } + + private static bool InsertSecurityId(String symbol,String securityIdentifier, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if (null == securityIdentifier || null == symbol) return false; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into mstarsecurityid(symbol,security_identifier,modified) values("); + sb.Append(SqlUtils.AddQuotes(symbol)).Append(","); + sb.Append(SqlUtils.AddQuotes(securityIdentifier)).Append(","); + sb.Append(SqlUtils.AddQuotes(SqlUtils.ToSqlDateTime(DateTime.Now))); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was '{0}'",strQuery)); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + } + } + + public static bool HasSecurityId(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + int count = 0; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from mstarsecurityid where symbol="); + sb.Append(Utility.AddQuotes(symbol)); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + sqlDataReader.Read(); + count=sqlDataReader.GetInt32(0); + return count>0?true:false; + + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return false; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/OptionsDA.cs b/MarketData/MarketDataLib/DataAccess/OptionsDA.cs new file mode 100755 index 0000000..2dc31a9 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/OptionsDA.cs @@ -0,0 +1,433 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; +using MarketData.Numerical; + +namespace MarketData.DataAccess +{ + public class OptionsDA + { + private OptionsDA() + { + } + public static List GetOptionsSymbolIn(List symbols) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List optionSymbols = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct symbol from options where symbol in ").Append(SqlUtils.CreateInClause(symbols)).Append(" order by symbol asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + optionSymbols.Add(sqlDataReader.GetString(0)); + } + return optionSymbols; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Options GetOptions(String symbol, DateTime earliestDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Options options = new Options(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol, expiration_date,option_type,strike,bid,ask,volume,open_interest,modified from options "); + sb.Append("where symbol='").Append(symbol).Append("'"); + sb.Append(" and expiration_date>='").Append(Utility.DateTimeToStringYYYYHMMHDD(earliestDate)).Append("'"); + sb.Append(" order by option_type,expiration_date asc, strike desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Option option = new Option(); + option.Symbol = sqlDataReader.GetString(0); + option.Expiration = sqlDataReader.GetDateTime(1); + option.Type = ("C".Equals(sqlDataReader.GetString(2)) ? OptionTypeEnum.CallOption : OptionTypeEnum.PutOption); + if (!sqlDataReader.IsDBNull(3)) option.Strike = sqlDataReader.GetDouble(3); + else option.Strike = double.NaN; + if (!sqlDataReader.IsDBNull(4)) option.Bid = sqlDataReader.GetDouble(4); + else option.Bid = double.NaN; + if (!sqlDataReader.IsDBNull(5)) option.Ask = sqlDataReader.GetDouble(5); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(6)) option.Volume = sqlDataReader.GetInt32(6); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(7)) option.OpenInterest = sqlDataReader.GetDouble(7); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(8)) option.Modified = sqlDataReader.GetDateTime(8); + else option.Modified = Utility.Epoch; + options.Add(option); + } + return options; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Options GetOptions(String symbol, DateTime earliestDate,OptionTypeEnum optionType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Options options = new Options(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol, expiration_date,option_type,strike,bid,ask,volume,open_interest,modified from options "); + sb.Append("where symbol='").Append(symbol).Append("'"); + sb.Append(" and expiration_date>='").Append(Utility.DateTimeToStringYYYYHMMHDD(earliestDate)).Append("'"); + sb.Append(" and option_type='").Append(optionType.Equals(OptionTypeEnum.CallOption) ? "C" : "P").Append("'"); + sb.Append(" order by option_type,expiration_date asc, strike desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Option option = new Option(); + option.Symbol = sqlDataReader.GetString(0); + option.Expiration = sqlDataReader.GetDateTime(1); + option.Type = ("C".Equals(sqlDataReader.GetString(2)) ? OptionTypeEnum.CallOption : OptionTypeEnum.PutOption); + if (!sqlDataReader.IsDBNull(3)) option.Strike = sqlDataReader.GetDouble(3); + else option.Strike = double.NaN; + if (!sqlDataReader.IsDBNull(4)) option.Bid = sqlDataReader.GetDouble(4); + else option.Bid = double.NaN; + if (!sqlDataReader.IsDBNull(5)) option.Ask = sqlDataReader.GetDouble(5); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(6)) option.Volume = sqlDataReader.GetInt32(6); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(7)) option.OpenInterest = sqlDataReader.GetDouble(7); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(8)) option.Modified = sqlDataReader.GetDateTime(8); + else option.Modified = Utility.Epoch; + options.Add(option); + } + return options; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Options GetOptions(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Options options = new Options(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol, expiration_date,option_type,strike,bid,ask,volume,open_interest,modified from options where symbol='").Append(symbol).Append("' order by option_type,expiration_date asc, strike desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Option option = new Option(); + option.Symbol = sqlDataReader.GetString(0); + option.Expiration = sqlDataReader.GetDateTime(1); + option.Type = ("C".Equals(sqlDataReader.GetString(2)) ?OptionTypeEnum.CallOption : OptionTypeEnum.PutOption); + if (!sqlDataReader.IsDBNull(3)) option.Strike = sqlDataReader.GetDouble(3); + else option.Strike = double.NaN; + if (!sqlDataReader.IsDBNull(4)) option.Bid = sqlDataReader.GetDouble(4); + else option.Bid = double.NaN; + if (!sqlDataReader.IsDBNull(5)) option.Ask = sqlDataReader.GetDouble(5); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(6)) option.Volume = sqlDataReader.GetInt32(6); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(7)) option.OpenInterest = sqlDataReader.GetDouble(7); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(8)) option.Modified = sqlDataReader.GetDateTime(8); + else option.Modified = Utility.Epoch; + options.Add(option); + } + return options; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Options GetOptions(String symbol,OptionTypeEnum optionType) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Options options = new Options(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol, expiration_date,option_type,strike,bid,ask,volume,open_interest,modified from options where symbol='").Append(symbol).Append("'"); + sb.Append(" and option_type='").Append(optionType.Equals(OptionTypeEnum.CallOption)?"C":"P").Append("'"); + sb.Append(" order by option_type,expiration_date asc, strike desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Option option = new Option(); + option.Symbol = sqlDataReader.GetString(0); + option.Expiration = sqlDataReader.GetDateTime(1); + option.Type = ("C".Equals(sqlDataReader.GetString(2)) ? OptionTypeEnum.CallOption : OptionTypeEnum.PutOption); + if (!sqlDataReader.IsDBNull(3)) option.Strike = sqlDataReader.GetDouble(3); + else option.Strike = double.NaN; + if (!sqlDataReader.IsDBNull(4)) option.Bid = sqlDataReader.GetDouble(4); + else option.Bid = double.NaN; + if (!sqlDataReader.IsDBNull(5)) option.Ask = sqlDataReader.GetDouble(5); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(6)) option.Volume = sqlDataReader.GetInt32(6); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(7)) option.OpenInterest = sqlDataReader.GetDouble(7); + else option.Ask = double.NaN; + if (!sqlDataReader.IsDBNull(8)) option.Modified = sqlDataReader.GetDateTime(8); + else option.Modified = Utility.Epoch; + options.Add(option); + } + return options; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool DeleteOptions(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("delete from options where symbol='").Append(symbol).Append("' "); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + sqlCommand = null; + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return false; + } + finally + { + if (null != sqlCommand) { sqlCommand.Dispose(); sqlCommand = null; } + if (null != sqlConnection) { sqlConnection.Close(); sqlConnection = null; } + } + } + private static bool DeleteOption(Option option, MySqlTransaction sqlTransaction) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("delete from options where symbol=").Append(SqlUtils.AddQuotes(option.Symbol)); + sb.Append(" and expiration_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(option.Expiration))); + sb.Append(" and strike=").Append(Utility.FormatNumber(option.Strike,2)); + sb.Append(" and option_type=").Append(SqlUtils.AddQuotes(option.Type.Equals(OptionTypeEnum.CallOption) ? "C" : "P")); + strQuery = sb.ToString(); +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("DeleteOption {0},{1},{2},{3}",option.Symbol,Utility.DateTimeToStringMMHDDHYYYY(option.Expiration),option.Type.Equals(OptionTypeEnum.CallOption)?"Call":"Put",option.Strike)); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + sqlCommand = null; + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if (null != sqlCommand) { sqlCommand.Dispose(); sqlCommand = null; } + if (null != sqlConnection) { sqlConnection.Close(); sqlConnection = null; } + } + } +// private static bool DeleteOption(Option option) +// { +// MySqlConnection sqlConnection = null; +// MySqlCommand sqlCommand = null; +// MySqlTransaction sqlTransaction=null; +// String strQuery = null; +// try +// { +// StringBuilder sb = new StringBuilder(); +// sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); +// sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); +// sb.Append("delete from options where symbol=").Append(SqlUtils.AddQuotes(option.Symbol)); +// sb.Append(" and expiration_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(option.Expiration))); +// sb.Append(" and strike=").Append(Utility.FormatNumber(option.Strike,2)); +// sb.Append(" and option_type=").Append(SqlUtils.AddQuotes(option.Type.Equals(OptionTypeEnum.CallOption) ? "C" : "P")); +// strQuery = sb.ToString(); +//// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("DeleteOption {0},{1},{2},{3}",option.Symbol,Utility.DateTimeToStringMMHDDHYYYY(option.Expiration),option.Type.Equals(OptionTypeEnum.CallOption)?"Call":"Put",option.Strike)); +// sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); +// sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; +// sqlCommand.ExecuteNonQuery(); +// sqlTransaction.Commit(); +// sqlCommand.Dispose(); +// sqlCommand = null; +// return true; +// } +// catch (Exception exception) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,exception); +// return false; +// } +// finally +// { +// if (null != sqlCommand) { sqlCommand.Dispose(); sqlCommand = null; } +// if (null != sqlConnection) { sqlConnection.Close(); sqlConnection.Dispose();sqlConnection = null; } +// if(null!=sqlTransaction){sqlTransaction.Dispose();sqlTransaction=null;} +// } +// } + public static bool AddOptions(Options options) + { + foreach (Option option in options) + { + AddOption(option); + } + return true; + } + public static bool AddOption(Option option) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { +// MDTrace.WriteLine(LogLevel.DEBUG,"[AddOption]Enter"); + DateTime modified = DateTime.Now; + if (null == option) return false; +// DeleteOption(option); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteOption(option,sqlTransaction); + StringBuilder sb=new StringBuilder(); + sb.Append("insert into options(symbol,expiration_date,option_type,strike,last_price,change_price,bid,ask,volume,open_interest,modified)values("); + sb.Append(SqlUtils.AddQuotes(option.Symbol)).Append(","); + sb.Append(SqlUtils.AddQuotes((Utility.DateTimeToStringYYYYHMMHDD(option.Expiration)))).Append(","); + sb.Append(SqlUtils.AddQuotes(option.Type.Equals(OptionTypeEnum.CallOption)?"C":"P")).Append(","); + if (!double.IsNaN(option.Strike)) sb.Append(Utility.FormatNumber(option.Strike,2)).Append(","); + else sb.Append("null").Append(","); + if (!double.IsNaN(option.Last)) sb.Append(option.Last).Append(","); + else sb.Append("null").Append(","); + if (!double.IsNaN(option.Change)) sb.Append(option.Change).Append(","); + else sb.Append("null").Append(","); + if (!double.IsNaN(option.Bid)) sb.Append(option.Bid).Append(","); + else sb.Append("null").Append(","); + if (!double.IsNaN(option.Ask)) sb.Append(option.Ask).Append(","); + else sb.Append("null").Append(","); + if (!double.IsNaN(option.Volume)) sb.Append(option.Volume).Append(","); + else sb.Append("null").Append(","); + if (!double.IsNaN(option.OpenInterest)) sb.Append(option.OpenInterest).Append(","); + else sb.Append("null").Append(","); + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(modified))); + sb.Append(")"); + strQuery = sb.ToString(); +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("AddOption {0},{1},{2},{3}",option.Symbol,Utility.DateTimeToStringMMHDDHYYYY(option.Expiration),option.Type.Equals(OptionTypeEnum.CallOption)?"Call":"Put",option.Strike)); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + sqlTransaction.Dispose(); + sqlTransaction=null; + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + if (null != sqlTransaction) sqlTransaction.Dispose(); +// MDTrace.WriteLine(LogLevel.DEBUG,"[AddOption]LEAVE"); + } + } + } +} + diff --git a/MarketData/MarketDataLib/DataAccess/PortfolioDA.cs b/MarketData/MarketDataLib/DataAccess/PortfolioDA.cs new file mode 100755 index 0000000..69ff829 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/PortfolioDA.cs @@ -0,0 +1,933 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class PortfolioDA + { + private PortfolioDA() + { + } +// ********************************************************************************************************************************************************************************** +// ****************************************************************************************** S T O P L I M I T S **************************************************************** +// ********************************************************************************************************************************************************************************** + public static StopLimit GetStopLimit(String symbol) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + + try + { + StringBuilder sb=new StringBuilder(); + if(null==symbol)return null; + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select symbol,stop_limit,shares,stop_type,active from stoplimits "); + sb.Append("where symbol='").Append(symbol).Append("'"); + sb.Append(" and active=1"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read())return null; + StopLimit stopLimit=new StopLimit(); + stopLimit.Symbol=sqlDataReader.GetString(0); + stopLimit.StopPrice=sqlDataReader.GetDouble(1); + stopLimit.Shares=sqlDataReader.GetDouble(2); + stopLimit.StopType=sqlDataReader.GetString(3); + stopLimit.Active=sqlDataReader.GetInt32(4); + return stopLimit; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertUpdateStopLimit(StopLimit stopLimit) + { + if(null==stopLimit||null==stopLimit.Symbol||double.IsNaN(stopLimit.StopPrice))return false; + if(!HasStopLimit(stopLimit.Symbol))return InsertStopLimit(stopLimit); + return UpdateStopLimit(stopLimit); + } + private static bool InsertStopLimit(StopLimit stopLimit) + { + MySqlConnection sqlConnection=null; + MySqlTransaction sqlTransaction=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + + try + { + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sqlTransaction=sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb=new StringBuilder(); + sb.Append("insert into stoplimits(symbol,stop_limit,shares,stop_type,active)values("); + sb.Append(SqlUtils.AddQuotes(stopLimit.Symbol)).Append(","); + sb.Append(stopLimit.StopPrice).Append(","); + sb.Append(stopLimit.Shares).Append(","); + if(null!=stopLimit.StopType) sb.Append(SqlUtils.AddQuotes(stopLimit.StopType)).Append(","); + else sb.Append("null").Append(","); + sb.Append(stopLimit.Active); + sb.Append(")"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection,sqlTransaction); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlTransaction) sqlTransaction.Dispose(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + private static bool UpdateStopLimit(StopLimit stopLimit) + { + MySqlConnection sqlConnection=null; + MySqlTransaction sqlTransaction=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + + try + { + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sqlTransaction=sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb=new StringBuilder(); + sb.Append("update stoplimits "); + sb.Append("set "); + if(null!=stopLimit.StopType) sb.Append("stop_type=").Append(SqlUtils.AddQuotes(stopLimit.StopType)).Append(", "); + sb.Append("stop_limit=").Append(stopLimit.StopPrice).Append(", "); + sb.Append("shares=").Append(stopLimit.Shares).Append(", "); + sb.Append("active=").Append(stopLimit.Active).Append(""); + sb.Append(" where symbol=").Append(SqlUtils.AddQuotes(stopLimit.Symbol)); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection,sqlTransaction); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlConnection) sqlConnection.Close(); + if(null!=sqlTransaction) sqlTransaction.Dispose(); + } + } + public static bool HasStopLimit(String symbol) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + + try + { + StringBuilder sb=new StringBuilder(); + if(null==symbol) return false; + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select count(*) from stoplimits "); + sb.Append("where symbol='").Append(symbol).Append("'"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read()) return false; + int count=sqlDataReader.GetInt32(0); + return count>0?true:false; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static bool DeleteStopLimit(String symbol) + { + MySqlConnection sqlConnection=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + + try + { + StringBuilder sb=new StringBuilder(); + if(null==symbol) return false; + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("delete from stoplimits "); + sb.Append("where symbol='").Append(symbol).Append("'"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } +// ********************************************************************************************************************************************************************** + public static bool UpdateTrade(PortfolioTrade trade) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + sb.Append("update trades "); + sb.Append("set "); + sb.Append("symbol=").Append(SqlUtils.AddQuotes(trade.Symbol)).Append(", "); + sb.Append("trade_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(trade.TradeDate))).Append(", "); + sb.Append("shares=").Append(trade.Shares).Append(", "); + sb.Append("price=").Append(trade.Price).Append(", "); + sb.Append("buysell=").Append(SqlUtils.AddQuotes(trade.BuySell)).Append(", "); + sb.Append("account=").Append(SqlUtils.AddQuotes(trade.Account)).Append(", "); + sb.Append("status=").Append(SqlUtils.AddQuotes(trade.Status)).Append(", "); + sb.Append("commission=").Append(trade.Commission); + if (!Utility.IsEpoch(trade.SellDate))sb.Append(", date_sold=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(trade.SellDate))).Append(" "); + if (!double.IsNaN(trade.SellPrice) && !double.IsInfinity(trade.SellPrice))sb.Append(", sell_price=").Append(trade.SellPrice).Append(" "); + sb.Append(" where trade_id=").Append(trade.TradeId); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + } + } + public static int AddTrade(PortfolioTrade trade) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + sb.Append("insert into trades(symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price)values("); + sb.Append(SqlUtils.AddQuotes(trade.Symbol)).Append(","); + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(trade.TradeDate))).Append(","); + sb.Append(trade.Shares).Append(","); + sb.Append(trade.Price).Append(","); + sb.Append(SqlUtils.AddQuotes(trade.BuySell)).Append(","); + sb.Append("'").Append(trade.Account).Append("'").Append(","); + sb.Append("'").Append(trade.Status).Append("'").Append(","); + sb.Append("'").Append(trade.Commission).Append("'").Append(","); + if (!Utility.IsEpoch(trade.SellDate)) sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(trade.SellDate))).Append(","); + else sb.Append("null").Append(","); + if (!double.IsNaN(trade.SellPrice)&&!double.IsInfinity(trade.SellPrice)) sb.Append(trade.SellPrice); + else sb.Append("null"); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return GetMaxTradeId(); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return -1; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static PortfolioTrades GetTrades(String symbol=null) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + PortfolioTrades portfolioTrades = new PortfolioTrades(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select trade_id,symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price from trades "); + if(null!=symbol)sb.Append("where symbol='").Append(symbol).Append("'"); + sb.Append(" order by trade_date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + PortfolioTrade portfolioTrade = new PortfolioTrade(); + portfolioTrade.TradeId = sqlDataReader.GetInt32(0); + portfolioTrade.Symbol = sqlDataReader.GetString(1); + portfolioTrade.TradeDate = sqlDataReader.GetDateTime(2); + portfolioTrade.Shares = sqlDataReader.GetDouble(3); + portfolioTrade.Price = sqlDataReader.GetDouble(4); + portfolioTrade.BuySell = sqlDataReader.GetString(5); + portfolioTrade.Account = sqlDataReader.GetString(6); + portfolioTrade.Status = sqlDataReader.GetString(7); + portfolioTrade.Commission = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) portfolioTrade.SellDate = sqlDataReader.GetDateTime(9); + else portfolioTrade.SellDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(10)) portfolioTrade.SellPrice = sqlDataReader.GetDouble(10); + else portfolioTrade.SellPrice = double.NaN; + portfolioTrades.Add(portfolioTrade); + } + return portfolioTrades; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static PortfolioTrades GetTradesForAccount(String account) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + PortfolioTrades portfolioTrades = new PortfolioTrades(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select trade_id,symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price from trades "); + sb.Append("where account='").Append(account).Append("'"); + sb.Append(" order by trade_date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + PortfolioTrade portfolioTrade = new PortfolioTrade(); + portfolioTrade.TradeId = sqlDataReader.GetInt32(0); + portfolioTrade.Symbol = sqlDataReader.GetString(1); + portfolioTrade.TradeDate = sqlDataReader.GetDateTime(2); + portfolioTrade.Shares = sqlDataReader.GetDouble(3); + portfolioTrade.Price = sqlDataReader.GetDouble(4); + portfolioTrade.BuySell = sqlDataReader.GetString(5); + portfolioTrade.Account = sqlDataReader.GetString(6); + portfolioTrade.Status = sqlDataReader.GetString(7); + portfolioTrade.Commission = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) portfolioTrade.SellDate = sqlDataReader.GetDateTime(9); + else portfolioTrade.SellDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(10)) portfolioTrade.SellPrice = sqlDataReader.GetDouble(10); + else portfolioTrade.SellPrice = double.NaN; + portfolioTrades.Add(portfolioTrade); + } + return portfolioTrades; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static PortfolioTrades GetTradesForAccounts(List accounts) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + PortfolioTrades portfolioTrades = new PortfolioTrades(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select trade_id,symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price from trades "); + sb.Append("where account in ").Append(SqlUtils.CreateInClause(accounts)); + sb.Append(" order by trade_date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + PortfolioTrade portfolioTrade = new PortfolioTrade(); + portfolioTrade.TradeId = sqlDataReader.GetInt32(0); + portfolioTrade.Symbol = sqlDataReader.GetString(1); + portfolioTrade.TradeDate = sqlDataReader.GetDateTime(2); + portfolioTrade.Shares = sqlDataReader.GetDouble(3); + portfolioTrade.Price = sqlDataReader.GetDouble(4); + portfolioTrade.BuySell = sqlDataReader.GetString(5); + portfolioTrade.Account = sqlDataReader.GetString(6); + portfolioTrade.Status = sqlDataReader.GetString(7); + portfolioTrade.Commission = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) portfolioTrade.SellDate = sqlDataReader.GetDateTime(9); + else portfolioTrade.SellDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(10)) portfolioTrade.SellPrice = sqlDataReader.GetDouble(10); + else portfolioTrade.SellPrice = double.NaN; + portfolioTrades.Add(portfolioTrade); + } + return portfolioTrades; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static PortfolioTrades GetOpenTrades() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + PortfolioTrades portfolioTrades = new PortfolioTrades(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select trade_id,symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price from trades "); + sb.Append(" where status='").Append("OPEN").Append("'"); + sb.Append(" order by trade_date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + PortfolioTrade portfolioTrade = new PortfolioTrade(); + portfolioTrade.TradeId = sqlDataReader.GetInt32(0); + portfolioTrade.Symbol = sqlDataReader.GetString(1); + portfolioTrade.TradeDate = sqlDataReader.GetDateTime(2); + portfolioTrade.Shares = sqlDataReader.GetDouble(3); + portfolioTrade.Price = sqlDataReader.GetDouble(4); + portfolioTrade.BuySell = sqlDataReader.GetString(5); + portfolioTrade.Account = sqlDataReader.GetString(6); + portfolioTrade.Status = sqlDataReader.GetString(7); + portfolioTrade.Commission = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) portfolioTrade.SellDate = sqlDataReader.GetDateTime(9); + else portfolioTrade.SellDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(10)) portfolioTrade.SellPrice = sqlDataReader.GetDouble(10); + else portfolioTrade.SellPrice = double.NaN; + portfolioTrades.Add(portfolioTrade); + } + return portfolioTrades; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// Retrieves the symbols for open trades + public static List GetOpenSymbols() + { + try + { + PortfolioTrades portfolioTrades=GetOpenTrades(); + if(null==portfolioTrades)return null; + return portfolioTrades.Symbols; + } + catch(Exception) + { + return null; + } + } +// This is used by ValueAtRisk +// Notes: Added the conditional after "OR" clause. The reason being that the query was not returning trades which are CLOSED but OPEN on the asOf date. +// The behaviour was observed while running the VaR and examining 07/30/2019 vs 07/31/2019 and noticing that ENSG, which was still OPEN on 07/30, was not being included in the VaR + public static PortfolioTrades GetOpenTradesAsOf(DateTime asOf) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + PortfolioTrades portfolioTrades = new PortfolioTrades(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select trade_id,symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price from trades "); + sb.Append(" where (trade_date<='").Append(Utility.DateTimeToStringYYYYHMMHDD(asOf)).Append("' ").Append(" and status='").Append("OPEN").Append("')"); + sb.Append(" or (trade_date<='").Append(Utility.DateTimeToStringYYYYHMMHDD(asOf)).Append("' and status='CLOSED' and date_sold is not null and date_sold>='").Append(Utility.DateTimeToStringYYYYHMMHDD(asOf)).Append("')"); + sb.Append(" order by trade_date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + PortfolioTrade portfolioTrade = new PortfolioTrade(); + portfolioTrade.TradeId = sqlDataReader.GetInt32(0); + portfolioTrade.Symbol = sqlDataReader.GetString(1); + portfolioTrade.TradeDate = sqlDataReader.GetDateTime(2); + portfolioTrade.Shares = sqlDataReader.GetDouble(3); + portfolioTrade.Price = sqlDataReader.GetDouble(4); + portfolioTrade.BuySell = sqlDataReader.GetString(5); + portfolioTrade.Account = sqlDataReader.GetString(6); + portfolioTrade.Status = sqlDataReader.GetString(7); + portfolioTrade.Commission = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) portfolioTrade.SellDate = sqlDataReader.GetDateTime(9); + else portfolioTrade.SellDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(10)) portfolioTrade.SellPrice = sqlDataReader.GetDouble(10); + else portfolioTrade.SellPrice = double.NaN; + portfolioTrades.Add(portfolioTrade); + } + return portfolioTrades; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static PortfolioTrades GetOpenTradesSymbolBetween(String symbol,DateTime minDate,DateTime maxDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + PortfolioTrades portfolioTrades = new PortfolioTrades(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select trade_id,symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price from trades "); + sb.Append(" where trade_date>='").Append(Utility.DateTimeToStringYYYYHMMHDD(minDate)).Append("' "); + sb.Append(" and trade_date<='").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate)).Append("' "); + sb.Append(" and symbol='").Append(symbol).Append("'"); + sb.Append(" and status='").Append("OPEN").Append("'"); + sb.Append(" order by trade_date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + PortfolioTrade portfolioTrade = new PortfolioTrade(); + portfolioTrade.TradeId = sqlDataReader.GetInt32(0); + portfolioTrade.Symbol = sqlDataReader.GetString(1); + portfolioTrade.TradeDate = sqlDataReader.GetDateTime(2); + portfolioTrade.Shares = sqlDataReader.GetDouble(3); + portfolioTrade.Price = sqlDataReader.GetDouble(4); + portfolioTrade.BuySell = sqlDataReader.GetString(5); + portfolioTrade.Account = sqlDataReader.GetString(6); + portfolioTrade.Status = sqlDataReader.GetString(7); + portfolioTrade.Commission = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) portfolioTrade.SellDate = sqlDataReader.GetDateTime(9); + else portfolioTrade.SellDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(10)) portfolioTrade.SellPrice = sqlDataReader.GetDouble(10); + else portfolioTrade.SellPrice = double.NaN; + portfolioTrades.Add(portfolioTrade); + } + return portfolioTrades; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static PortfolioTrades GetOpenTradesSymbol(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + PortfolioTrades portfolioTrades = new PortfolioTrades(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select trade_id,symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price from trades "); + sb.Append(" where symbol='").Append(symbol).Append("'"); + sb.Append(" and status='").Append("OPEN").Append("'"); + sb.Append(" order by trade_date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + PortfolioTrade portfolioTrade = new PortfolioTrade(); + portfolioTrade.TradeId = sqlDataReader.GetInt32(0); + portfolioTrade.Symbol = sqlDataReader.GetString(1); + portfolioTrade.TradeDate = sqlDataReader.GetDateTime(2); + portfolioTrade.Shares = sqlDataReader.GetDouble(3); + portfolioTrade.Price = sqlDataReader.GetDouble(4); + portfolioTrade.BuySell = sqlDataReader.GetString(5); + portfolioTrade.Account = sqlDataReader.GetString(6); + portfolioTrade.Status = sqlDataReader.GetString(7); + portfolioTrade.Commission = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) portfolioTrade.SellDate = sqlDataReader.GetDateTime(9); + else portfolioTrade.SellDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(10)) portfolioTrade.SellPrice = sqlDataReader.GetDouble(10); + else portfolioTrade.SellPrice = double.NaN; + portfolioTrades.Add(portfolioTrade); + } + return portfolioTrades; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static PortfolioTrades GetTradesSymbol(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + PortfolioTrades portfolioTrades = new PortfolioTrades(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select trade_id,symbol,trade_date,shares,price,buysell,account,status,commission,date_sold,sell_price from trades "); + sb.Append(" where symbol='").Append(symbol).Append("'"); + sb.Append(" order by trade_date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + PortfolioTrade portfolioTrade = new PortfolioTrade(); + portfolioTrade.TradeId = sqlDataReader.GetInt32(0); + portfolioTrade.Symbol = sqlDataReader.GetString(1); + portfolioTrade.TradeDate = sqlDataReader.GetDateTime(2); + portfolioTrade.Shares = sqlDataReader.GetDouble(3); + portfolioTrade.Price = sqlDataReader.GetDouble(4); + portfolioTrade.BuySell = sqlDataReader.GetString(5); + portfolioTrade.Account = sqlDataReader.GetString(6); + portfolioTrade.Status = sqlDataReader.GetString(7); + portfolioTrade.Commission = sqlDataReader.GetDouble(8); + if (!sqlDataReader.IsDBNull(9)) portfolioTrade.SellDate = sqlDataReader.GetDateTime(9); + else portfolioTrade.SellDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(10)) portfolioTrade.SellPrice = sqlDataReader.GetDouble(10); + else portfolioTrade.SellPrice = double.NaN; + portfolioTrades.Add(portfolioTrade); + } + return BreakoutTrades(portfolioTrades); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static PortfolioTrades BreakoutTrades(PortfolioTrades portfolioTrades) + { + PortfolioTrades allTrades = new PortfolioTrades(); + foreach (PortfolioTrade portfolioTrade in portfolioTrades) + { + if (portfolioTrade.IsOpen) allTrades.Add(portfolioTrade); + else + { + PortfolioTrade openTrade = new PortfolioTrade(); + PortfolioTrade closedTrade = new PortfolioTrade(); + openTrade.Symbol = portfolioTrade.Symbol; + openTrade.Shares = portfolioTrade.Shares; + openTrade.Account = portfolioTrade.Account; + openTrade.BuySell = "B"; + openTrade.Status = "OPEN"; + openTrade.Commission = 0; + openTrade.Price = portfolioTrade.Price; + openTrade.TradeDate = portfolioTrade.TradeDate; + openTrade.TradeId=portfolioTrade.TradeId; + allTrades.Add(openTrade); + closedTrade.Symbol = portfolioTrade.Symbol; + closedTrade.Shares = portfolioTrade.Shares; + closedTrade.Account = portfolioTrade.Account; + closedTrade.BuySell = "S"; + closedTrade.Status = "CLOSED"; + closedTrade.Commission = 0; + closedTrade.Price = portfolioTrade.SellPrice; // closed trade gets a price of the sell price + closedTrade.SellPrice = portfolioTrade.SellPrice; // closed trade also gets a sell price of sell price. Ref:CombineLots() function depends on the SellPrice being set. + closedTrade.TradeDate = portfolioTrade.SellDate; + closedTrade.TradeId=portfolioTrade.TradeId; + allTrades.Add(closedTrade); + } + } + return allTrades; + } + public static List GetOpenTradeDates() + { + Profiler profiler = new Profiler(); + List openTradeDates = new List(); + try + { + DateGenerator dateGenerator = new DateGenerator(); + DateTime minTradeDate = GetMinTradeDate(); + DateTime maxTradeDate = PricingDA.GetLatestDate(); // use the latest date for which we have pricing information + List historicalDates = PricingDA.GetPricingDates(minTradeDate); + foreach (DateTime historicalDate in historicalDates) + { + PortfolioTrades portfolioTrades = GetOpenTradesAsOf(historicalDate); + if (null == portfolioTrades || 0 == portfolioTrades.Count) continue; + openTradeDates.Add(historicalDate); + } + return openTradeDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return openTradeDates; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("PortfolioDA.GetOpenTradeDates: Done, took {0}(ms)", profiler.End())); + } + } + public static DateTime GetMinTradeDate() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + DateTime minTradeDate=Utility.Epoch; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select min(trade_date) from trades"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) minTradeDate = sqlDataReader.GetDateTime(0); + return minTradeDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return minTradeDate; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static int GetMaxTradeId() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + int tradeId = -1; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select max(trade_id) from trades"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) tradeId = sqlDataReader.GetInt32(0); + return tradeId; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return -1; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool DeleteTrade(int tradeId) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("delete from trades where trade_id="); + sb.Append(tradeId.ToString()); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetAccounts() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + List watchList = new List(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select account from accounts order by 1 desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + String symbol = sqlDataReader.GetString(0); + watchList.Add(symbol); + } + return watchList; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetAccountsWithOpenTrades() + { + try + { + PortfolioTrades portfolioTrades=GetOpenTrades(); + List accounts=(from portfolioTrade in portfolioTrades select portfolioTrade.Account).Distinct().ToList(); + return accounts; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/PremarketDA.cs b/MarketData/MarketDataLib/DataAccess/PremarketDA.cs new file mode 100755 index 0000000..9a01829 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/PremarketDA.cs @@ -0,0 +1,281 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class PremarketDA + { + private PremarketDA() + { + } +//SELECT market, change_value,change_percent,timestamp, STR_TO_DATE(SUBSTRING(TIMESTAMP,12,11),'%h:%i:%s %p') time_of_day,CONVERT(TIMESTAMP,DATE) AS the_day +//FROM premarket WHERE market='S&P' ORDER BY the_day DESC, time_of_day DESC + + public static bool AddElements(PremarketElements premarketElements) + { + MySqlConnection sqlConnection=null; + MySqlTransaction sqlTransaction=null; + String strQuery=null; + + try + { + if(null==premarketElements||0==premarketElements.Count) return false; + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction=sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + for(int index=0;index markets=GetDistinctMarkets(); + if(null==markets)return null; + foreach(String market in markets) + { + PremarketElement premarketElement=GetLatestPremarketData(market); + if(null==premarketElement)continue; + premarketElements.Add(premarketElement); + + } + return premarketElements; + } + public static PremarketElement GetLatestPremarketData(String market) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + PremarketElement premarketElement=new PremarketElement(); + + try + { + List availableMarketDates=GetAvailableMarketDates(market); + if(null==availableMarketDates || 0==availableMarketDates.Count)return null; + DateTime marketDate=availableMarketDates.Take(1).FirstOrDefault(); + + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select market,change_value,change_percent,timestamp,STR_TO_DATE(SUBSTRING(TIMESTAMP,12,11),'%h:%i:%s %p') MILITARY_TIME,CONVERT(TIMESTAMP,DATE) DATE from premarket "); + sb.Append("WHERE MARKET='").Append(market).Append("' and CONVERT(TIMESTAMP,DATE)=").Append(SqlUtils.AddQuotes(SqlUtils.SqlString(SqlUtils.FormatDate(marketDate)))); + sb.Append("ORDER BY MILITARY_TIME DESC LIMIT 10"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read())return null; + if(!sqlDataReader.IsDBNull(0)) premarketElement.Market=sqlDataReader.GetString(0); + if(!sqlDataReader.IsDBNull(1)) premarketElement.ChangeValue=sqlDataReader.GetDouble(1); + if(!sqlDataReader.IsDBNull(2)) premarketElement.ChangePercent=sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3)) premarketElement.Timestamp=Utility.ParseDate(sqlDataReader.GetString(3)); + if(String.IsNullOrEmpty(premarketElement.Market)) return null; + return premarketElement; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetLatestMarketDate() + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + DateTime latestMarketDate=Utility.Epoch; + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("SELECT MAX(CONVERT(TIMESTAMP,DATE)) FROM premarket "); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(sqlDataReader.Read()) + { + latestMarketDate=sqlDataReader.GetDateTime(0); + } + return latestMarketDate; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return latestMarketDate; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static List GetAvailableMarketDates(String market) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + List availableMarketDates=new List(); + DateGenerator dateGenerator=new DateGenerator(); + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("SELECT DISTINCT(CONVERT(TIMESTAMP,DATE)) FROM premarket where market=").Append(SqlUtils.AddQuotes(market)).Append(" ORDER BY 1 DESC"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + DateTime marketDate=sqlDataReader.GetDateTime(0); + if(!dateGenerator.IsMarketOpen(marketDate)) continue; + availableMarketDates.Add(marketDate); + } + return availableMarketDates; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static PremarketElements GetLatestPremarketData(String market,DateTime date,bool constrainToMarketHours=true) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + PremarketElements premarketElements=new PremarketElements(); + DateGenerator dateGenerator=new DateGenerator(); + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select market,change_value,change_percent,timestamp,STR_TO_DATE(SUBSTRING(TIMESTAMP,12,11),'%h:%i:%s %p') MILITARY_TIME,CONVERT(TIMESTAMP,DATE) DATE from premarket "); + sb.Append("WHERE MARKET='").Append(market).Append("' and CONVERT(TIMESTAMP,DATE)=").Append(SqlUtils.AddQuotes(SqlUtils.FormatDate(date))); + if(constrainToMarketHours)sb.Append(" AND STR_TO_DATE(SUBSTRING(TIMESTAMP,12,11),'%h:%i:%s %p')<'16:30:00' "); + sb.Append(" ORDER BY MILITARY_TIME ASC"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + PremarketElement premarketElement=new PremarketElement(); + if(!sqlDataReader.IsDBNull(0)) premarketElement.Market=sqlDataReader.GetString(0); + if(!sqlDataReader.IsDBNull(1)) premarketElement.ChangeValue=sqlDataReader.GetDouble(1); + if(!sqlDataReader.IsDBNull(2)) premarketElement.ChangePercent=sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3)) premarketElement.Timestamp=Utility.ParseDate(sqlDataReader.GetString(3)); + if(String.IsNullOrEmpty(premarketElement.Market)) continue; + if(!dateGenerator.IsMarketOpen(premarketElement.Timestamp))continue; + premarketElements.Add(premarketElement); + } + return premarketElements; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static List GetDistinctMarkets() + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + List markets=new List(); + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct market from premarket order by 1 asc"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + markets.Add(sqlDataReader.GetString(0)); + } + return markets; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + } +} + diff --git a/MarketData/MarketDataLib/DataAccess/PricingDA.cs b/MarketData/MarketDataLib/DataAccess/PricingDA.cs new file mode 100755 index 0000000..065ce33 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/PricingDA.cs @@ -0,0 +1,1518 @@ +using System; +using System.Text; +using System.Diagnostics; +using System.Collections.Generic; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class PricingDA + { + private PricingDA() + { + } + public static bool AddSecurity(String symbol,String companyName) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if(null==symbol)return false; + symbol=symbol.Trim(); + if (SecurityExists(symbol)) return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + sb.Append("insert into securitymaster (symbol,company,security_type)values("); + sb.Append(SqlUtils.AddQuotes(symbol)).Append(","); + sb.Append(SqlUtils.AddQuotes(SqlUtils.SqlString(companyName))).Append(","); + sb.Append("'EQUITY'"); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool SecurityExists(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + int recordCount = 0; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from securitymaster where symbol='").Append(symbol).Append("' "); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) recordCount = sqlDataReader.GetInt32(0); + } + sqlCommand.Dispose(); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetSymbolsNotIn(List symbols) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List selectedSymbols = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + if (null == symbols || 0 == symbols.Count) return symbols; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol from SecurityMaster where symbol in ").Append(SqlUtils.CreateInClause(symbols)); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + selectedSymbols.Add(sqlDataReader.GetString(0)); + } + for (int index = 0; index < selectedSymbols.Count; index++) + { + symbols.RemoveAll(x => x.Equals(selectedSymbols[index])); + } + sqlCommand.Dispose(); + return symbols; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return selectedSymbols; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static int GetPriceCountOn(DateTime date) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + int recordCount=0; + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from prices where date='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("' "); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(sqlDataReader.Read()) + { + if(!sqlDataReader.IsDBNull(0)) recordCount=sqlDataReader.GetInt32(0); + } + return recordCount; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return 0; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + + public static bool CheckPricingOn(String symbol,DateTime date) + { + List symbols=new List(); + symbols.Add(symbol); + return CheckPricingOn(symbols,date); + } + + public static bool CheckPricingOn(List symbols,DateTime date) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + int recordCount = 0; + + try + { + StringBuilder sb = new StringBuilder(); + if (null == symbols || 0 == symbols.Count) return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from prices where date='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("' "); + sb.Append("and symbol in ").Append(SqlUtils.CreateInClause(symbols)); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) recordCount = sqlDataReader.GetInt32(0); + } + return 0==recordCount?false:true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetEarliestDate() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime earliestDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select min(date) from prices"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) earliestDate = sqlDataReader.GetDateTime(0); + } + return earliestDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return earliestDate; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetLatestDate(String symbol) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + DateTime maxDate=DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(date) from prices"); + sb.Append(" where symbol='").Append(symbol).Append("'"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(sqlDataReader.Read()) + { + if(!sqlDataReader.IsDBNull(0)) maxDate=sqlDataReader.GetDateTime(0); + } + return maxDate; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return maxDate; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetLatestDate(List symbols) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + DateTime maxDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append(" WITH CTE AS "); + sb.Append(" ( "); + sb.Append(" select symbol, max(date) as date "); + sb.Append(" from prices where symbol in").Append(SqlUtils.CreateInClause(symbols)); + sb.Append(" group by symbol "); + sb.Append(" ) "); + sb.Append(" select min(date) from CTE "); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) maxDate = sqlDataReader.GetDateTime(0); + } + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return maxDate; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetLatestDate() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + DateTime earliestDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(date) from prices"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) earliestDate = sqlDataReader.GetDateTime(0); + } + return earliestDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return earliestDate; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetLatestDateOnOrBefore(String symbol,DateTime date) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + DateTime maxDate=DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(date) from prices"); + sb.Append(" where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append(" and date<='").Append(SqlUtils.SqlDate(date)).Append("'"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + if(sqlDataReader.Read()) + { + if(!sqlDataReader.IsDBNull(0)) maxDate=sqlDataReader.GetDateTime(0); + } + return maxDate; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return maxDate; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetEarliestDate(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime earliestDate = DateTime.Parse("01-01-0001"); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select min(date) from prices"); + sb.Append(" where symbol='").Append(symbol).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) earliestDate = sqlDataReader.GetDateTime(0); + } + return earliestDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return earliestDate; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// selects dates for symbol ordered earliest to latest + public static List GetPricingDatesForSymbol(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List pricingDates=new List(); + + try + { + if(null==symbol)return pricingDates; + symbol=symbol.ToUpper(); + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date from prices where symbol='").Append(symbol).Append("' order by date asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + pricingDates.Add(sqlDataReader.GetDateTime(0)); + } + return pricingDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return pricingDates; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// Get pricing dates from lowerBoundary (historical date ) to mosr recent + public static List GetPricingDates(DateTime lowerBoundary) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + List pricingDates = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct(date) from prices where date>='").Append(SqlUtils.ToSqlDateTime(lowerBoundary)).Append("' order by date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + pricingDates.Add(sqlDataReader.GetDateTime(0)); + } + return pricingDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return pricingDates; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetPricingDatesBetween(DateTime lowerBoundary,DateTime upperBoundary) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + List pricingDates=new List(); + + try + { + StringBuilder sb=new StringBuilder(); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct(date) from prices where date>='").Append(SqlUtils.ToSqlDateTime(lowerBoundary)).Append("' "); + sb.Append("and date<='").Append(SqlUtils.ToSqlDateTime(upperBoundary)).Append("'"); + sb.Append(" order by date desc"); + strQuery=sb.ToString(); + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + pricingDates.Add(sqlDataReader.GetDateTime(0)); + } + return pricingDates; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return pricingDates; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static List GetSymbols() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List symbols = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct symbol from securitymaster "); + sb.Append("order by symbol;"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + symbols.Add(sqlDataReader.GetString(0)); + } + return symbols; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return symbols; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetSymbolsETF() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List symbols = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct symbol from securitymaster where security_type in ('ETF','ETN')"); + sb.Append("order by symbol;"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + symbols.Add(sqlDataReader.GetString(0)); + } + return symbols; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return symbols; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static String GetNameForSymbol(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List symbols = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select company from securitymaster where symbol='"); + sb.Append(symbol).Append("';"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read())return null; + String companyName=sqlDataReader.GetString(0); + if (null != companyName) companyName=companyName.ToUpper(); + return companyName; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static String GetSectorForSymbol(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List symbols = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select sector from securitymaster where symbol='"); + sb.Append(symbol).Append("';"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + String sector = null; + if(!sqlDataReader.IsDBNull(0))sector=sqlDataReader.GetString(0); + return sector; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static String GetIndustryForSymbol(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List symbols = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select industry from securitymaster where symbol='"); + sb.Append(symbol).Append("';"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + String industry = null; + if(!sqlDataReader.IsDBNull(0))industry=sqlDataReader.GetString(0); + return industry; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// ********************************************************************************* +// ****************************** Manage Central Index Key ************************* +// ********************************************************************************* + public static List GetSymbolsForNullCIK() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List unmapped = new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct symbol from securitymaster where cik is null"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + String symbol = sqlDataReader.GetString(0); + unmapped.Add(symbol); + } + return unmapped; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static String GetCIKForSymbol(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + String cik; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct cik from securitymaster where symbol='"); + sb.Append(symbol); + sb.Append("' and cik is not null;"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + cik=sqlDataReader.GetString(0); + return cik; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery));; + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool UpdateCIKForSymbol(String symbol,String cik) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + + try + { + if (null == symbol || null == cik) return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + sb.Append("update securitymaster "); + sb.Append("set "); + sb.Append("cik=").Append(SqlUtils.AddQuotes(cik)).Append(" "); + sb.Append(" where symbol=").Append(SqlUtils.AddQuotes(symbol)); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Price GetPrice(String symbol,DateTime pricingDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Price price = null; + + try + { + if(Utility.IsEpoch(pricingDate))return null; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append("and date='").Append(Utility.DateTimeToStringYYYYHMMHDD(pricingDate)).Append("'").Append(" "); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + price = new Price(); + price.Date = sqlDataReader.GetDateTime(0); + price.Symbol = sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))price.Open = sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3))price.High = sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4))price.Low = sqlDataReader.GetDouble(4); + if(!sqlDataReader.IsDBNull(5))price.Close = sqlDataReader.GetDouble(5); + if(!sqlDataReader.IsDBNull(6))price.Volume = sqlDataReader.GetInt64(6); + if(!sqlDataReader.IsDBNull(7))price.AdjClose = sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + } + return price; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return price; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Price GetPrice(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + Price price = null; + + try + { + StringBuilder sb = new StringBuilder(); + DateTime latestDate = GetLatestDate(symbol); + if(Utility.IsEpoch(latestDate))return null; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append("and date='").Append(Utility.DateTimeToStringYYYYHMMHDD(latestDate)).Append("'").Append(" "); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + price = new Price(); + price.Date = sqlDataReader.GetDateTime(0); + price.Symbol = sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))price.Open = sqlDataReader.GetDouble(2); + else price.Open=double.NaN; + if(!sqlDataReader.IsDBNull(3))price.High = sqlDataReader.GetDouble(3); + else price.High=double.NaN; + if(!sqlDataReader.IsDBNull(4))price.Low = sqlDataReader.GetDouble(4); + else price.Low=double.NaN; + if(!sqlDataReader.IsDBNull(5))price.Close = sqlDataReader.GetDouble(5); + else price.Close=double.NaN; + price.Volume = sqlDataReader.GetInt64(6); + price.AdjClose = sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + } + return price; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return price; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Prices GetPrices(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Prices prices = new Prices(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("' order by date desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + Price price = new Price(); + if(!sqlDataReader.IsDBNull(0))price.Date = sqlDataReader.GetDateTime(0); + else throw new Exception("Date cannot be null"); + if(!sqlDataReader.IsDBNull(1))price.Symbol = sqlDataReader.GetString(1); + else throw new Exception("Symbol cannot be null"); + if(!sqlDataReader.IsDBNull(2))price.Open = sqlDataReader.GetDouble(2); + else price.Open=double.NaN; + if(!sqlDataReader.IsDBNull(3))price.High = sqlDataReader.GetDouble(3); + else price.High=double.NaN; + if(!sqlDataReader.IsDBNull(4))price.Low = sqlDataReader.GetDouble(4); + else price.Low=double.NaN; + if(!sqlDataReader.IsDBNull(5))price.Close = sqlDataReader.GetDouble(5); + else price.Close=double.NaN; + if(!sqlDataReader.IsDBNull(6))price.Volume = sqlDataReader.GetInt64(6); + else price.Volume=0; + if(!sqlDataReader.IsDBNull(7))price.AdjClose = sqlDataReader.GetDouble(7); + else price.AdjClose=double.NaN; + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + prices.Add(price); + } + return prices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return prices; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Prices GetPrices(String symbol, int days) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Prices prices = new Prices(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("'"); + sb.Append(" order by date desc"); + sb.Append(" limit ").Append(days); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + int count = 0; + while (sqlDataReader.Read() && count < days) + { + Price price = new Price(); + price.Date = sqlDataReader.GetDateTime(0); + price.Symbol = sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))price.Open = sqlDataReader.GetDouble(2); + else price.Open=double.NaN; + if(!sqlDataReader.IsDBNull(3))price.High = sqlDataReader.GetDouble(3); + else price.High=double.NaN; + if(!sqlDataReader.IsDBNull(4))price.Low = sqlDataReader.GetDouble(4); + else price.Low=double.NaN; + if(!sqlDataReader.IsDBNull(5))price.Close = sqlDataReader.GetDouble(5); + else price.Close=double.NaN; + price.Volume = sqlDataReader.GetInt64(6); + price.AdjClose = sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + prices.Add(price); + count++; + } + return prices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return prices; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// Prices are returned with the latest (most current) price in the lowest index location + public static Prices GetPrices(String symbol,DateTime startDate, int days) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Prices prices = new Prices(); + + try + { + StringBuilder sb = new StringBuilder(); + DateGenerator dateGenerator = new DateGenerator(); + DateTime maxHistoricalDate = dateGenerator.GenerateHistoricalDate(startDate, days * 2); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("'"); + sb.Append(" and date<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(startDate)).Append("'"); + sb.Append(" and date>=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(maxHistoricalDate)).Append("'"); + sb.Append(" order by date desc"); + sb.Append(" limit ").Append(days); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Price price = new Price(); + price.Date = sqlDataReader.GetDateTime(0); + price.Symbol = sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))price.Open = sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3))price.High = sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4))price.Low = sqlDataReader.GetDouble(4); + if(!sqlDataReader.IsDBNull(5))price.Close = sqlDataReader.GetDouble(5); + if(!sqlDataReader.IsDBNull(6))price.Volume = sqlDataReader.GetInt64(6); + if(!sqlDataReader.IsDBNull(7))price.AdjClose = sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + prices.Add(price); + } + return prices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return prices; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// Get prices starting at "startDate" and "days" number of days going into future + public static Prices GetPricesForward(String symbol,DateTime startDate,int days) + { + MySqlConnection sqlConnection=null; + MySqlDataReader sqlDataReader=null; + MySqlCommand sqlCommand=null; + String strQuery=null; + Prices prices=new Prices(); + + try + { + StringBuilder sb=new StringBuilder(); + DateGenerator dateGenerator=new DateGenerator(); + DateTime maxDate=dateGenerator.GenerateFutureBusinessDate(startDate,days); + sqlConnection=SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("'"); + sb.Append(" and date>=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(startDate)).Append("'"); + sb.Append(" and date<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate)).Append("'"); + sb.Append(" order by date asc"); + sb.Append(" limit ").Append(days); + strQuery=sb.ToString(); ; + sqlCommand=new MySqlCommand(strQuery,sqlConnection); + sqlCommand.CommandTimeout=SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + Price price=new Price(); + price.Date=sqlDataReader.GetDateTime(0); + price.Symbol=sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2)) price.Open=sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3)) price.High=sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4)) price.Low=sqlDataReader.GetDouble(4); + if(!sqlDataReader.IsDBNull(5)) price.Close=sqlDataReader.GetDouble(5); + if(!sqlDataReader.IsDBNull(6)) price.Volume=sqlDataReader.GetInt64(6); + if(!sqlDataReader.IsDBNull(7)) price.AdjClose=sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + prices.Add(price); + } + return prices; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return prices; + } + finally + { + if(null!=sqlCommand) sqlCommand.Dispose(); + if(null!=sqlDataReader) sqlDataReader.Close(); + if(null!=sqlConnection) sqlConnection.Close(); + } + } + public static Prices GetPricesOnOrBefore(String symbol,DateTime startDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Prices prices = new Prices(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("'"); + sb.Append(" and date<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(startDate)).Append("'"); + sb.Append(" order by date desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Price price = new Price(); + price.Date = sqlDataReader.GetDateTime(0); + price.Symbol = sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))price.Open = sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3))price.High = sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4))price.Low = sqlDataReader.GetDouble(4); + if(!sqlDataReader.IsDBNull(5))price.Close = sqlDataReader.GetDouble(5); + if(!sqlDataReader.IsDBNull(6))price.Volume = sqlDataReader.GetInt64(6); + if(!sqlDataReader.IsDBNull(7))price.AdjClose = sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + prices.Add(price); + } + return prices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return prices; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// StartDate: The most recent date +// EndDate: The most historical date + public static Prices GetPrices(String symbol,DateTime startDate,DateTime endDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Prices prices = new Prices(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("'"); + sb.Append(" "); + sb.Append("and date<='").Append(Utility.DateTimeToStringYYYYHMMHDD(startDate)).Append("'"); + sb.Append(" and date>='").Append(Utility.DateTimeToStringYYYYHMMHDD(endDate)).Append("'"); + sb.Append(" order by date desc"); + strQuery = sb.ToString(); ; + // MDTrace.WriteLine(LogLevel.DEBUG,strQuery); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Price price = new Price(); + price.Date = sqlDataReader.GetDateTime(0); + price.Symbol = sqlDataReader.GetString(1); + if(sqlDataReader.IsDBNull(2))price.Open=double.NaN; + else price.Open = sqlDataReader.GetDouble(2); + if(sqlDataReader.IsDBNull(3))price.High=double.NaN; + else price.High = sqlDataReader.GetDouble(3); + if(sqlDataReader.IsDBNull(4))price.Low=double.NaN; + else price.Low = sqlDataReader.GetDouble(4); + if(sqlDataReader.IsDBNull(5))price.Close=double.NaN; + else price.Close = sqlDataReader.GetDouble(5); + price.Volume = sqlDataReader.GetInt64(6); + price.AdjClose = sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + prices.Add(price); + } + return prices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return prices; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Prices GetPrices(String symbol, DateTime endDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + Prices prices = new Prices(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,open,high,low,close,volume,adjclose,source from prices where symbol='").Append(symbol).Append("'"); + sb.Append(" "); + sb.Append(" and date>='").Append(Utility.DateTimeToStringYYYYHMMHDD(endDate)).Append("'"); + sb.Append(" order by date desc"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + Price price = new Price(); + price.Date = sqlDataReader.GetDateTime(0); + price.Symbol = sqlDataReader.GetString(1); + if(!sqlDataReader.IsDBNull(2))price.Open = sqlDataReader.GetDouble(2); + if(!sqlDataReader.IsDBNull(3))price.High = sqlDataReader.GetDouble(3); + if(!sqlDataReader.IsDBNull(4))price.Low = sqlDataReader.GetDouble(4); + if(!sqlDataReader.IsDBNull(5))price.Close = sqlDataReader.GetDouble(5); + if(!sqlDataReader.IsDBNull(6))price.Volume = sqlDataReader.GetInt64(6); + if(!sqlDataReader.IsDBNull(7))price.AdjClose = sqlDataReader.GetDouble(7); + if(!sqlDataReader.IsDBNull(8))price.Source = (Price.PriceSource)Utility.CharToNum(sqlDataReader.GetChar(8)); + else price.Source=Price.PriceSource.Other; + prices.Add(price); + } + return prices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return prices; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertPrice(Price price) + { + Prices prices = new Prices(); + prices.Add(price); + DeletePrice(price.Symbol, price.Date); + return InsertPrices(prices); + } + public static bool InsertPrices(Prices prices) + { + MySqlConnection sqlConnection=null; + MySqlTransaction sqlTransaction=null; + String strQuery=null; + + try + { + if(null==prices||0==prices.Count)return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction=sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeletePrices(prices,sqlConnection,sqlTransaction); + for(int index=0;index='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return false; + } + finally + { + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool DeletePriceOnOrBefore(String symbol, DateTime date) + { + MySqlConnection sqlConnection = null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("delete from prices where symbol='").Append(symbol).Append("'").Append(" "); + sb.Append("and date>='").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query was {0}",strQuery)); + return false; + } + finally + { + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeletePrices(Prices prices, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + for(int index=0;index GetDistinctFilingSymbols() + { + List distinctSymbols = new List(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select distinct(symbol) from secfilings order by symbol asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + distinctSymbols.Add(sqlDataReader.GetString(0)); + } + return distinctSymbols; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + if (null != sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader = null; + } + } + } + public static List GetDistinctFilingDatesForSymbol(String symbol) + { + List distinctFilingDates = new List(); + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select distinct(filing_date) from secfilings where symbol="); + sb.Append(SqlUtils.AddQuotes(symbol)); + sb.Append(" order by 1 desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + distinctFilingDates.Add(sqlDataReader.GetDateTime(0)); + } + return distinctFilingDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + if (null != sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader = null; + } + } + } + public static SEC13Info GetSEC13Info(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + SEC13Info sec13Info=new SEC13Info(); + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + sec13Info.Symbol=symbol; + sb.Append(" select symbol,max(filing_date),count(*) from secfilings where symbol='").Append(symbol).Append("' and (form like '%13D%' or form like '%13G%')"); + sb.Append(" group by symbol having datediff(curdate(),max(filing_date))<180"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return sec13Info; + sec13Info.SEC13=true; + sec13Info.MostRecentFilingDate=sqlDataReader.GetDateTime(1); + sec13Info.Filings=sqlDataReader.GetInt32(2); + return sec13Info; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return sec13Info; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + if (null != sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader = null; + } + } + } + public static bool HaveSECFiling(SECFiling secFiling) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select count(*) from secfilings "); + sb.Append("where symbol=").Append(SqlUtils.AddQuotes(secFiling.Symbol)).Append(" "); + sb.Append("and filing_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(secFiling.FilingDate))).Append(" "); + sb.Append("and sec_accession_number=").Append(SqlUtils.AddQuotes(secFiling.SECAccessionNumber)).Append(" "); + sb.Append("and sequence=").Append(secFiling.Sequence).Append(" "); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return false; + int recordCount = sqlDataReader.GetInt32(0); + return recordCount > 0 ? true : false; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + if (null != sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader = null; + } + } + } + public static bool DeleteSECFiling(SECFiling secFiling,MySqlTransaction sqlTransaction) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand =null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("delete from secfilings "); + sb.Append("where symbol=").Append(SqlUtils.AddQuotes(secFiling.Symbol)).Append(" "); + sb.Append("and filing_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(secFiling.FilingDate))); + sb.Append("and sec_accession_number=").Append(SqlUtils.AddQuotes(secFiling.SECAccessionNumber)); + sb.Append("and sequence=").Append(secFiling.Sequence); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection,sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + if (null != sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader = null; + } + } + } + public static bool InsertOrUpdateSECFilings(SECFilings secFilings) + { + MySqlTransaction sqlTransaction = null; + MySqlConnection sqlConnection = null; + + try + { + secFilings=secFilings.Distinct(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + for (int index = 0; index < secFilings.Count; index++) + { + SECFiling secFiling = secFilings[index]; + if (HaveSECFiling(secFiling)) DeleteSECFiling(secFiling,sqlTransaction); + InsertSECFiling(secFiling,sqlConnection,sqlTransaction); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if (null != sqlTransaction) + { + sqlTransaction.Dispose(); + sqlTransaction = null; + } + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + } + } + public static bool InsertSECFilings(SECFilings secFilings) + { + MySqlTransaction sqlTransaction = null; + MySqlConnection sqlConnection = null; + + try + { + secFilings=secFilings.Distinct(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + for (int index = 0; index < secFilings.Count; index++) + { + SECFiling secFiling = secFilings[index]; + if (HaveSECFiling(secFiling)) continue; + InsertSECFiling(secFiling, sqlConnection, sqlTransaction); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if (null != sqlTransaction) + { + sqlTransaction.Dispose(); + sqlTransaction = null; + } + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + } + } + private static bool InsertSECFiling(SECFiling secFiling,MySqlConnection sqlConnection,MySqlTransaction sqlTransaction) + { + MySqlCommand sqlCommand = null; + try + { + StringBuilder sb = new StringBuilder(); + sqlCommand = new MySqlCommand(); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.Connection = sqlConnection; + sb.Append("insert into secfilings(sec_accession_number,sequence,symbol,filing_date,form,form_text,description,sec_filing_url)"); + sb.Append(" values(?sec_accession_number,?sequence,?symbol,?filing_date,?form,?form_text,?description,?secFilingUrl);"); + MySqlParameter secAccessionNumberParameter = new MySqlParameter("?sec_accession_number", MySqlDbType.VarChar,50); + MySqlParameter sequenceParameter = new MySqlParameter("?sequence", MySqlDbType.Int32); + MySqlParameter symbolParameter = new MySqlParameter("?symbol", MySqlDbType.VarChar, 15); + MySqlParameter filingDateParameter = new MySqlParameter("?filing_date", MySqlDbType.DateTime); + MySqlParameter formParameter = new MySqlParameter("?form", MySqlDbType.VarChar,25); + MySqlParameter formTextParameter = new MySqlParameter("?form_text", MySqlDbType.Blob, secFiling.FormText.Length); + MySqlParameter descriptionParameter = new MySqlParameter("?description", MySqlDbType.VarChar, 128); + MySqlParameter secFilingUrlParameter = new MySqlParameter("?secFilingUrl", MySqlDbType.VarChar, 255); + secAccessionNumberParameter.Value = secFiling.SECAccessionNumber; + sequenceParameter.Value = secFiling.Sequence; + symbolParameter.Value = secFiling.Symbol; + filingDateParameter.Value=Utility.DateTimeToStringYYYYHMMHDD(secFiling.FilingDate); + formParameter.Value=secFiling.Form; + formTextParameter.Value = Utility.Compress(secFiling.FormText); + descriptionParameter.Value = secFiling.Description; + secFilingUrlParameter.Value = secFiling.SecFilingUrl; + sqlCommand.Parameters.Add(secAccessionNumberParameter); + sqlCommand.Parameters.Add(symbolParameter); + sqlCommand.Parameters.Add(filingDateParameter); + sqlCommand.Parameters.Add(formParameter); + sqlCommand.Parameters.Add(formTextParameter); + sqlCommand.Parameters.Add(descriptionParameter); + sqlCommand.Parameters.Add(secFilingUrlParameter); + sqlCommand.Parameters.Add(sequenceParameter); + sqlCommand.CommandText = sb.ToString(); + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if (null != sqlCommand) + { + sqlCommand.Dispose(); + sqlCommand = null; + } + } + } + public static SECFilings GetSECFilings(String symbol) + { + MySqlCommand sqlCommand = null; + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + SECFilings secFilings = new SECFilings(); + try + { + StringBuilder sb = new StringBuilder(); + sqlCommand = null; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,filing_date,form,length(form_text),form_text,description,sec_filing_url,sequence,sec_accession_number from secfilings "); + sb.Append("where symbol='").Append(symbol).Append("' order by filing_date desc"); + String strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + SECFiling secFiling = new SECFiling(); + secFiling.Symbol = sqlDataReader.GetString(0); + secFiling.FilingDate = sqlDataReader.GetDateTime(1); + secFiling.Form = sqlDataReader.GetString(2); + int lengthFormText=sqlDataReader.GetInt32(3); + byte[] formTextBytes=new byte[lengthFormText]; + sqlDataReader.GetBytes(4,0,formTextBytes,0,lengthFormText); + secFiling.FormText=Utility.Decompress(formTextBytes); + secFiling.Description = sqlDataReader.GetString(5); + secFiling.SecFilingUrl = sqlDataReader.GetString(6); + secFiling.Sequence = sqlDataReader.GetInt32(7); + secFiling.SECAccessionNumber = sqlDataReader.GetString(8); + secFilings.Add(secFiling); + } + return secFilings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + if (null != sqlCommand) + { + sqlCommand.Dispose(); + sqlCommand = null; + } + if (null != sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader = null; + } + } + } + public static SECFilings GetSECFilings(String symbol,DateTime filingDate) + { + MySqlCommand sqlCommand = null; + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + SECFilings secFilings = new SECFilings(); + try + { + StringBuilder sb = new StringBuilder(); + sqlCommand = null; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,filing_date,form,length(form_text),form_text,description,sec_filing_url,sequence,sec_accession_number from secfilings "); + sb.Append("where symbol=").Append(SqlUtils.AddQuotes(symbol)); + sb.Append(" and filing_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(filingDate))); + sb.Append(" order by filing_date desc"); + String strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + SECFiling secFiling = new SECFiling(); + secFiling.Symbol = sqlDataReader.GetString(0); + secFiling.FilingDate = sqlDataReader.GetDateTime(1); + secFiling.Form = sqlDataReader.GetString(2); + int lengthFormText = sqlDataReader.GetInt32(3); + byte[] formTextBytes = new byte[lengthFormText]; + sqlDataReader.GetBytes(4, 0, formTextBytes, 0, lengthFormText); + secFiling.FormText = Utility.Decompress(formTextBytes); + secFiling.Description = sqlDataReader.GetString(5); + secFiling.SecFilingUrl = sqlDataReader.GetString(6); + secFiling.Sequence = sqlDataReader.GetInt32(7); + secFiling.SECAccessionNumber = sqlDataReader.GetString(8); + secFilings.Add(secFiling); + } + return secFilings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if (null != sqlConnection) + { + sqlConnection.Close(); + sqlConnection = null; + } + if (null != sqlCommand) + { + sqlCommand.Dispose(); + sqlCommand = null; + } + if (null != sqlDataReader) + { + sqlDataReader.Close(); + sqlDataReader = null; + } + } + } + } +} + diff --git a/MarketData/MarketDataLib/DataAccess/SplitsDA.cs b/MarketData/MarketDataLib/DataAccess/SplitsDA.cs new file mode 100755 index 0000000..e4b0897 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/SplitsDA.cs @@ -0,0 +1,335 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class SplitsDA + { + private SplitsDA() + { + } + public static bool InsertSplit(Split split) + { + Splits splits=new Splits(); + splits.Add(split); + InsertSplits(splits); + return true; + } + public static bool ContainsSplit(Split split) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + int recordCount = 0; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select count(*) from splits where symbol='").Append(split.Symbol).Append("' "); + sb.Append("and effective_date='").Append(SqlUtils.SqlDate(split.EffectiveDate)).Append("' "); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + if (!sqlDataReader.IsDBNull(0)) recordCount = sqlDataReader.GetInt32(0); + } + sqlCommand.Dispose(); + return 0 == recordCount ? false : true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool UpdateSplit(Split split) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if(!ContainsSplit(split))return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + if(split.Applied&&(Utility.IsEpoch(split.AppliedLeastRecent)||Utility.IsEpoch(split.AppliedMostRecent))) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Applied split requires AppliedRecent and AppliedMostRecent dates."); + return false; + } + if(!split.Applied)return false; + sb.Append("update splits set "); + sb.Append("applied=").Append(split.Applied).Append(", "); + sb.Append("applied_least_recent='").Append(SqlUtils.SqlDate(split.AppliedLeastRecent)).Append("'").Append(", "); + sb.Append("applied_most_recent='").Append(SqlUtils.SqlDate(split.AppliedMostRecent)).Append("'").Append(", "); + sb.Append("modified='").Append(SqlUtils.SqlDate(modified)).Append("'").Append(" "); + sb.Append(" where symbol='").Append(split.Symbol).Append("'").Append(" and "); + sb.Append("effective_date='").Append(SqlUtils.SqlDate(split.EffectiveDate)).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Splits GetUnappliedSplits() + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + String strQuery = null; + Splits splits=new Splits(); + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("select symbol,effective_date,ratio,applied,applied_least_recent,applied_most_recent,modified,created from splits where Symbol in(select symbol from securitymaster) and applied=0 order by symbol,effective_date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + Split split=new Split(); + split.Symbol=sqlDataReader.GetString(0); + split.EffectiveDate=sqlDataReader.GetDateTime(1); + split.StrRatio=sqlDataReader.GetString(2); + split.Applied=sqlDataReader.GetInt32(3)==0?false:true; + if(!sqlDataReader.IsDBNull(4))split.AppliedLeastRecent=sqlDataReader.GetDateTime(4); + if(!sqlDataReader.IsDBNull(5))split.AppliedMostRecent=sqlDataReader.GetDateTime(5); + if(!sqlDataReader.IsDBNull(6))split.Modified=sqlDataReader.GetDateTime(6); + if(!sqlDataReader.IsDBNull(7))split.Created=sqlDataReader.GetDateTime(7); + splits.Add(split); + } + return splits; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Splits GetSplits(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + String strQuery = null; + Splits splits=new Splits(); + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("select symbol,effective_date,ratio,applied,applied_least_recent,applied_most_recent,modified,created from splits "); + sb.Append(" where symbol='").Append(symbol).Append("'"); + sb.Append(" order by symbol,effective_date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + Split split=new Split(); + split.Symbol=sqlDataReader.GetString(0); + split.EffectiveDate=sqlDataReader.GetDateTime(1); + split.StrRatio=sqlDataReader.GetString(2); + split.Applied=sqlDataReader.GetInt32(3)==0?false:true; + if(!sqlDataReader.IsDBNull(4))split.AppliedLeastRecent=sqlDataReader.GetDateTime(4); + if(!sqlDataReader.IsDBNull(5))split.AppliedMostRecent=sqlDataReader.GetDateTime(5); + if(!sqlDataReader.IsDBNull(6))split.Modified=sqlDataReader.GetDateTime(6); + if(!sqlDataReader.IsDBNull(7))split.Created=sqlDataReader.GetDateTime(7); + splits.Add(split); + } + return splits; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Splits GetSplits() + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader=null; + String strQuery = null; + Splits splits=new Splits(); + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + sb.Append("select symbol,effective_date,ratio,applied,applied_least_recent,applied_most_recent,modified,created from splits order by symbol,effective_date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader=sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + Split split=new Split(); + split.Symbol=sqlDataReader.GetString(0); + split.EffectiveDate=sqlDataReader.GetDateTime(1); + split.StrRatio=sqlDataReader.GetString(2); + split.Applied=sqlDataReader.GetInt32(3)==0?false:true; + if(!sqlDataReader.IsDBNull(4))split.AppliedLeastRecent=sqlDataReader.GetDateTime(4); + if(!sqlDataReader.IsDBNull(5))split.AppliedMostRecent=sqlDataReader.GetDateTime(5); + if(!sqlDataReader.IsDBNull(6))split.Modified=sqlDataReader.GetDateTime(6); + if(!sqlDataReader.IsDBNull(7))split.Created=sqlDataReader.GetDateTime(7); + splits.Add(split); + } + return splits; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool InsertSplits(Splits splits) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + DateTime modified=DateTime.Now; + DateTime created=modified; + foreach(Split split in splits) + { + sb=new StringBuilder(); + if(ContainsSplit(split))continue; + sb.Append("insert into splits (symbol,effective_date,ratio,applied,applied_least_recent,applied_most_recent,modified,created) "); + sb.Append("values("); + sb.Append("'").Append(split.Symbol).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.SqlDate(split.EffectiveDate)).Append("'").Append(","); + sb.Append("'").Append(split.StrRatio).Append("'").Append(","); + sb.Append("").Append(split.Applied).Append("").Append(","); + if(split.Applied&&(Utility.IsEpoch(split.AppliedLeastRecent)||Utility.IsEpoch(split.AppliedMostRecent))) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Applied split requires LeastRecentDate and MostRecentDate to be set."); + continue; + } + if(!Utility.IsEpoch(split.AppliedLeastRecent))sb.Append("'").Append(SqlUtils.SqlDate(split.AppliedLeastRecent)).Append("'").Append(","); + else sb.Append("null,"); + if(!Utility.IsEpoch(split.AppliedLeastRecent))sb.Append("'").Append(SqlUtils.SqlDate(split.AppliedMostRecent)).Append("'").Append(","); + else sb.Append("null,"); + sb.Append("'").Append(SqlUtils.SqlDate(modified)).Append("'").Append(","); + sb.Append("'").Append(SqlUtils.SqlDate(modified)).Append("'").Append(""); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static bool DeleteSplits(Splits splits, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + foreach(Split split in splits)DeleteSplit(split,sqlConnection,sqlTransaction); + return true; + } + private static bool DeleteSplit(Split split, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + StringBuilder sb = new StringBuilder(); + String strQuery = null; + + try + { + sb.Append("delete from splits where "); + sb.Append("symbol='").Append(split.Symbol).Append("'"); + sb.Append(" and "); + sb.Append("effective_date='").Append(SqlUtils.SqlDate(split.EffectiveDate)).Append("'"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + sqlTransaction.Rollback(); + MDTrace.WriteLine(LogLevel.DEBUG,exception); + if (null != strQuery) MDTrace.WriteLine(LogLevel.DEBUG,"Query was " + strQuery); + return false; + } + finally + { + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/UserDA.cs b/MarketData/MarketDataLib/DataAccess/UserDA.cs new file mode 100755 index 0000000..e91d05e --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/UserDA.cs @@ -0,0 +1,135 @@ +using System; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.Utils; +using MarketData.MarketDataModel.User; + +namespace MarketData.DataAccess +{ + public class UserDA + { + private UserDA() + { + } + + public static bool UserExists(String username) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader = null; + String strQuery = null; + + try + { + if(String.IsNullOrEmpty(username))return false; + username = username.ToLower(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("user_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select count(*) from users where username=").Append("'").Append(username).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if(!sqlDataReader.Read())return false; + int count = sqlDataReader.GetInt32(0); + return count>0?true:false; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null != sqlDataReader)sqlDataReader.Dispose(); + if(null != sqlCommand)sqlCommand.Dispose(); + if(null != sqlConnection) sqlConnection.Close(); + } + } + + public static User GetUser(String username) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlDataReader sqlDataReader = null; + String strQuery = null; + User user = new User(); + + try + { + if(null == username)return null; + if(!UserExists(username))return null; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("user_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select username, salt, hash from users where "); + sb.Append("username=").Append("'").Append(username).Append("'"); + sb.Append(";"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if(sqlDataReader.Read()) + { + user.Username = sqlDataReader.GetString(0); + user.Salt = sqlDataReader.GetString(1); + user.Hash = sqlDataReader.GetString(2); + } + return user; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlDataReader)sqlDataReader.Dispose(); + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + + public static bool AddUser(User user) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if(null == user || null == user.Username || null == user.Hash || null == user.Salt)return false; + if(UserExists(user.Username))return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("user_data")); + sqlTransaction = sqlConnection.BeginTransaction(); + StringBuilder sb = new StringBuilder(); + sb.Append("insert into users(username,hash,salt,created_by,created_on,modified_by,modified_on) values("); + sb.Append(SqlUtils.AddQuotes(user.Username)).Append(","); + sb.Append(SqlUtils.AddQuotes(user.Hash)).Append(","); + sb.Append(SqlUtils.AddQuotes(user.Salt)).Append(","); + sb.Append("CURRENT_USER").Append(","); + sb.Append("CURRENT_TIMESTAMP").Append(","); + sb.Append("CURRENT_USER").Append(","); + sb.Append("CURRENT_TIMESTAMP").Append(""); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/ValuationDA.cs b/MarketData/MarketDataLib/DataAccess/ValuationDA.cs new file mode 100755 index 0000000..db82915 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/ValuationDA.cs @@ -0,0 +1,437 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class ValuationDA + { + private ValuationDA() + { + } + public static List GetValuationDates() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + List valuationDates = new List(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select distinct(valuation_date) from valuations order by valuation_date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + valuationDates.Add(sqlDataReader.GetDateTime(0)); + } + return valuationDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static DateTime GetLatestValuationDate() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + DateTime valuationDate=Utility.Epoch; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select max(valuation_date) from valuations"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) valuationDate = sqlDataReader.GetDateTime(0); + return valuationDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return valuationDate; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static Valuations GetValuation(DateTime valuationDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + Valuations valuations = new Valuations(); + String strQuery = null; + + try + { + if (Utility.IsEpoch(valuationDate)) return null; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + StringBuilder sb = new StringBuilder(); + sb.Append("select valuation_date,symbol,company,next_earnings_date,long_term_debt,revenue,debt_load,roic_avg,bvps_dates,avg_equity_growth,avg_equity_growth_2y,avg_equity_growth_4y,eps_dates,avg_eps_growth,avg_eps_growth_2y,avg_eps_growth_4y,revenue_dates,avg_revenue_growth,avg_revenue_growth_2y,avg_revenue_growth_4y,avg_freecashflow_growth,avg_operating_cashflow,avg_working_capital,bvps,eps,pe,low_pe,trailing_pe,avg_low_trailing,current_stock_estimate_price,price_estimate_10y,todays_price_for_required_return,mos,mos_80,intrinsic_value,rgv,latest_price,upside_pcnt,downside_pcnt,mean_target_price,low_target_price,high_target_price,bargain_mos,bargain_mos_80,price_to_book,peg,implied_earnings_growth,beta90,beta2y,roic_slope,roic_dates,market_cap,earnings_yield,ebit,enterprise_value,tlb_rank_roic,fundamental_value,net_current_asset_value_per_share,roic_latest,sector,industry,debt_to_equity,sec_13,sec_13_filing_date,roc_latest,tlb_rank_roc,operating_earnings,am_rank,acquirers_multiple,dividend_yield,operating_cashflow,shares_outstanding,modified").Append(" "); + sb.Append("from valuations where valuation_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(valuationDate))); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + valuations.ValuationDate = valuationDate; + while (sqlDataReader.Read()) + { + Valuation valuation = new Valuation(); + valuation.Symbol = sqlDataReader.GetString(1); + valuation.Company = sqlDataReader.GetString(2); + if (!sqlDataReader.IsDBNull(3)) valuation.NextEarningsDate = sqlDataReader.GetDateTime(3); + else valuation.NextEarningsDate = Utility.Epoch; + if (!sqlDataReader.IsDBNull(4)) valuation.LongTermDebt = sqlDataReader.GetDouble(4); + if (!sqlDataReader.IsDBNull(5)) valuation.Revenue = sqlDataReader.GetDouble(5); + valuation.DebtLoad = sqlDataReader.GetString(6); + if (!sqlDataReader.IsDBNull(7)) valuation.AverageROIC = sqlDataReader.GetDouble(7); + if (!sqlDataReader.IsDBNull(8)) valuation.BVPSDates = sqlDataReader.GetString(8); + if (!sqlDataReader.IsDBNull(9)) valuation.AverageEquityGrowth = sqlDataReader.GetDouble(9); + if (!sqlDataReader.IsDBNull(10)) valuation.AverageEquityGrowth2Y = sqlDataReader.GetDouble(10); + if (!sqlDataReader.IsDBNull(11)) valuation.AverageEquityGrowth4Y = sqlDataReader.GetDouble(11); + valuation.EPSDates = sqlDataReader.GetString(12); + if (!sqlDataReader.IsDBNull(13)) valuation.AverageEPSGrowth = sqlDataReader.GetDouble(13); + if (!sqlDataReader.IsDBNull(14)) valuation.AverageEPSGrowth2Y = sqlDataReader.GetDouble(14); + if (!sqlDataReader.IsDBNull(15)) valuation.AverageEPSGrowth4Y = sqlDataReader.GetDouble(15); + valuation.RevenueDates = sqlDataReader.GetString(16); + if (!sqlDataReader.IsDBNull(17)) valuation.AverageRevenueGrowth = sqlDataReader.GetDouble(17); + if (!sqlDataReader.IsDBNull(18)) valuation.AverageRevenueGrowth2Y = sqlDataReader.GetDouble(18); + if (!sqlDataReader.IsDBNull(19)) valuation.AverageRevenueGrowth4Y = sqlDataReader.GetDouble(19); + if (!sqlDataReader.IsDBNull(20)) valuation.AverageFreeCashflowGrowth = sqlDataReader.GetDouble(20); + if (!sqlDataReader.IsDBNull(21)) valuation.AverageOperatingCashflow = sqlDataReader.GetDouble(21); + if (!sqlDataReader.IsDBNull(22)) valuation.AverageWorkingCapital = sqlDataReader.GetDouble(22); + if (!sqlDataReader.IsDBNull(23)) valuation.BVPS = sqlDataReader.GetDouble(23); + if (!sqlDataReader.IsDBNull(24)) valuation.EPS = sqlDataReader.GetDouble(24); + if (!sqlDataReader.IsDBNull(25)) valuation.PE = sqlDataReader.GetDouble(25); + if (!sqlDataReader.IsDBNull(26)) valuation.LowPE = sqlDataReader.GetDouble(26); + if (!sqlDataReader.IsDBNull(27)) valuation.TrailingPE = sqlDataReader.GetDouble(27); + if (!sqlDataReader.IsDBNull(28)) valuation.AverageLowTrailing = sqlDataReader.GetDouble(28); + if (!sqlDataReader.IsDBNull(29)) valuation.CurrentStockEstimatePrice = sqlDataReader.GetDouble(29); + if (!sqlDataReader.IsDBNull(30)) valuation.PriceEstimate10Y = sqlDataReader.GetDouble(30); + if (!sqlDataReader.IsDBNull(31)) valuation.TodaysPriceForRequiredReturn = sqlDataReader.GetDouble(31); + if (!sqlDataReader.IsDBNull(32)) valuation.MOS = sqlDataReader.GetDouble(32); + if (!sqlDataReader.IsDBNull(33)) valuation.MOS80 = sqlDataReader.GetDouble(33); + if (!sqlDataReader.IsDBNull(34)) valuation.IntrinsicValue = sqlDataReader.GetDouble(34); + if (!sqlDataReader.IsDBNull(35)) valuation.RGV = sqlDataReader.GetDouble(35); + if (!sqlDataReader.IsDBNull(36)) valuation.LatestPrice = sqlDataReader.GetDouble(36); + if (!sqlDataReader.IsDBNull(37)) valuation.UpsidePcnt = sqlDataReader.GetDouble(37); + if (!sqlDataReader.IsDBNull(38)) valuation.DownsidePcnt = sqlDataReader.GetDouble(38); + if (!sqlDataReader.IsDBNull(39)) valuation.MeanTargetPrice = sqlDataReader.GetDouble(39); + if (!sqlDataReader.IsDBNull(40)) valuation.LowTargetPrice = sqlDataReader.GetDouble(40); + if (!sqlDataReader.IsDBNull(41)) valuation.HighTargetPrice = sqlDataReader.GetDouble(41); + valuation.Bargain = sqlDataReader.GetBoolean(42); + valuation.Bargain80 = sqlDataReader.GetBoolean(43); + if (!sqlDataReader.IsDBNull(44)) valuation.PBVPS = sqlDataReader.GetDouble(44); + if (!sqlDataReader.IsDBNull(45)) valuation.PEG = sqlDataReader.GetDouble(45); + if (!sqlDataReader.IsDBNull(46)) valuation.ImpliedEarningsGrowth = sqlDataReader.GetDouble(46); + if (!sqlDataReader.IsDBNull(47)) valuation.Beta90 = sqlDataReader.GetDouble(47); + if (!sqlDataReader.IsDBNull(48)) valuation.Beta720 = sqlDataReader.GetDouble(48); + if (!sqlDataReader.IsDBNull(49)) valuation.ROICSlope = sqlDataReader.GetDouble(49); + if (!sqlDataReader.IsDBNull(50)) valuation.ROICDates = sqlDataReader.GetString(50); + if (!sqlDataReader.IsDBNull(51)) valuation.MarketCap = sqlDataReader.GetDouble(51); + if (!sqlDataReader.IsDBNull(52)) valuation.EarningsYield = sqlDataReader.GetDouble(52); + if (!sqlDataReader.IsDBNull(53)) valuation.EBIT = sqlDataReader.GetDouble(53); + if (!sqlDataReader.IsDBNull(54)) valuation.EnterpriseValue = sqlDataReader.GetDouble(54); + if (!sqlDataReader.IsDBNull(55)) valuation.TLBRankROIC = sqlDataReader.GetDouble(55); + if (!sqlDataReader.IsDBNull(56)) valuation.FundamentalValue = sqlDataReader.GetDouble(56); + if (!sqlDataReader.IsDBNull(57)) valuation.NetCurrentAssetValuePerShare = sqlDataReader.GetDouble(57); + if (!sqlDataReader.IsDBNull(58)) valuation.LatestROIC = sqlDataReader.GetDouble(58); + if (!sqlDataReader.IsDBNull(59)) valuation.Sector=sqlDataReader.GetString(59); + if (!sqlDataReader.IsDBNull(60)) valuation.Industry = sqlDataReader.GetString(60); + if (!sqlDataReader.IsDBNull(61)) valuation.DebtToEquity = sqlDataReader.GetDouble(61); + if (!sqlDataReader.IsDBNull(62)) valuation.SEC13 = sqlDataReader.GetBoolean(62); + if (!sqlDataReader.IsDBNull(63)) valuation.SEC13FilingDate = sqlDataReader.GetDateTime(63); + if (!sqlDataReader.IsDBNull(64)) valuation.LatestROC = sqlDataReader.GetDouble(64); + if (!sqlDataReader.IsDBNull(65)) valuation.TLBRankROC = sqlDataReader.GetDouble(65); + if (!sqlDataReader.IsDBNull(66)) valuation.OperatingEarnings = sqlDataReader.GetDouble(66); + if (!sqlDataReader.IsDBNull(67)) valuation.AMRank = sqlDataReader.GetDouble(67); + if (!sqlDataReader.IsDBNull(68)) valuation.AcquirersMultiple = sqlDataReader.GetDouble(68); + if (!sqlDataReader.IsDBNull(69)) valuation.DividendYield = sqlDataReader.GetDouble(69); + if (!sqlDataReader.IsDBNull(70)) valuation.OperatingCashflow = sqlDataReader.GetDouble(70); + if (!sqlDataReader.IsDBNull(71)) valuation.SharesOutstanding = sqlDataReader.GetDouble(71); + valuation.Modified = sqlDataReader.GetDateTime(72); + valuations.Add(valuation); + } + return valuations; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool AddValuations(Valuations valuations) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + DateTime modified = DateTime.Now; + + try + { + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + RemoveValuation(valuations.ValuationDate,sqlTransaction); + foreach(Valuation valuation in valuations) + { + StringBuilder sb = new StringBuilder(); + sb.Append("insert into valuations(valuation_date,symbol,company,next_earnings_date,long_term_debt,revenue,debt_load,roic_avg,roic_slope,roic_dates,bvps_dates,avg_equity_growth,avg_equity_growth_2y,avg_equity_growth_4y,eps_dates,avg_eps_growth,avg_eps_growth_2y,avg_eps_growth_4y,revenue_dates,avg_revenue_growth,avg_revenue_growth_2y,avg_revenue_growth_4y,avg_freecashflow_growth,avg_operating_cashflow,avg_working_capital,bvps,eps,pe,low_pe,trailing_pe,avg_low_trailing,current_stock_estimate_price,price_estimate_10y,todays_price_for_required_return,mos,mos_80,intrinsic_value,rgv,latest_price,upside_pcnt,downside_pcnt,mean_target_price,low_target_price,high_target_price,bargain_mos,bargain_mos_80,price_to_book,peg,implied_earnings_growth,beta90,beta2y,market_cap,earnings_yield,ebit,enterprise_value,tlb_rank_roic,fundamental_value,net_current_asset_value_per_share,roic_latest,sector,industry,debt_to_equity,sec_13,sec_13_filing_date,roc_latest,tlb_rank_roc,operating_earnings,am_rank,acquirers_multiple,dividend_yield,operating_cashflow,shares_outstanding,modified)values("); + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(valuations.ValuationDate))).Append(","); + sb.Append(SqlUtils.AddQuotes(valuation.Symbol)).Append(","); + if (null == valuation.Company) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(SqlUtils.SqlString(valuation.Company))).Append(","); + if (Utility.IsEpoch(valuation.NextEarningsDate)) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(valuation.NextEarningsDate))).Append(","); + if (double.IsNaN(valuation.LongTermDebt) || double.IsInfinity(valuation.LongTermDebt)) sb.Append("null").Append(","); + else sb.Append(valuation.LongTermDebt).Append(","); + if (double.IsNaN(valuation.Revenue) || double.IsInfinity(valuation.Revenue)) sb.Append("null").Append(","); + else sb.Append(valuation.Revenue).Append(","); + if (null == valuation.DebtLoad) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(valuation.DebtLoad)).Append(","); + if (double.IsNaN(valuation.AverageROIC) || double.IsInfinity(valuation.AverageROIC)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageROIC).Append(","); + if (double.IsNaN(valuation.ROICSlope) || double.IsInfinity(valuation.ROICSlope)) sb.Append("null").Append(","); + else sb.Append(valuation.ROICSlope).Append(","); + if (null == valuation.ROICDates) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(valuation.ROICDates)).Append(","); + if (null == valuation.BVPSDates) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(valuation.BVPSDates)).Append(","); + if (double.IsNaN(valuation.AverageEquityGrowth) || double.IsInfinity(valuation.AverageEquityGrowth)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageEquityGrowth).Append(","); + if (double.IsNaN(valuation.AverageEquityGrowth2Y) || double.IsInfinity(valuation.AverageEquityGrowth2Y)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageEquityGrowth2Y).Append(","); + if (double.IsNaN(valuation.AverageEquityGrowth4Y) || double.IsInfinity(valuation.AverageEquityGrowth4Y)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageEquityGrowth4Y).Append(","); + if (null == valuation.EPSDates) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(valuation.EPSDates)).Append(","); + if (double.IsNaN(valuation.AverageEPSGrowth) || double.IsInfinity(valuation.AverageEPSGrowth)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageEPSGrowth).Append(","); + if (double.IsNaN(valuation.AverageEPSGrowth2Y) || double.IsInfinity(valuation.AverageEPSGrowth2Y)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageEPSGrowth2Y).Append(","); + if (double.IsNaN(valuation.AverageEPSGrowth4Y) || double.IsInfinity(valuation.AverageEPSGrowth4Y)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageEPSGrowth4Y).Append(","); + if (null == valuation.RevenueDates) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(valuation.RevenueDates)).Append(","); + if (double.IsNaN(valuation.AverageRevenueGrowth) || double.IsInfinity(valuation.AverageRevenueGrowth)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageRevenueGrowth).Append(","); +// if (double.IsNaN(valuation.AverageRevenueGrowthQtr) || double.IsInfinity(valuation.AverageRevenueGrowthQtr)) sb.Append("null").Append(","); +// else sb.Append(valuation.AverageRevenueGrowthQtr).Append(","); + if (double.IsNaN(valuation.AverageRevenueGrowth2Y) || double.IsInfinity(valuation.AverageRevenueGrowth2Y)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageRevenueGrowth2Y).Append(","); + if (double.IsNaN(valuation.AverageRevenueGrowth4Y) || double.IsInfinity(valuation.AverageRevenueGrowth4Y)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageRevenueGrowth4Y).Append(","); + if (double.IsNaN(valuation.AverageFreeCashflowGrowth) || double.IsInfinity(valuation.AverageFreeCashflowGrowth)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageFreeCashflowGrowth).Append(","); + if (double.IsNaN(valuation.AverageOperatingCashflow) || double.IsInfinity(valuation.AverageOperatingCashflow)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageOperatingCashflow).Append(","); + if (double.IsNaN(valuation.AverageWorkingCapital) || double.IsInfinity(valuation.AverageWorkingCapital)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageWorkingCapital).Append(","); + if (double.IsNaN(valuation.BVPS) || double.IsInfinity(valuation.BVPS)) sb.Append("null").Append(","); + else sb.Append(valuation.BVPS).Append(","); + if (double.IsNaN(valuation.EPS) || double.IsInfinity(valuation.EPS)) sb.Append("null").Append(","); + else sb.Append(valuation.EPS).Append(","); + if (double.IsNaN(valuation.PE) || double.IsInfinity(valuation.PE)) sb.Append("null").Append(","); + else sb.Append(valuation.PE).Append(","); + if (double.IsNaN(valuation.LowPE) || double.IsInfinity(valuation.LowPE)) sb.Append("null").Append(","); + else sb.Append(valuation.LowPE).Append(","); + if (double.IsNaN(valuation.TrailingPE) || double.IsInfinity(valuation.TrailingPE)) sb.Append("null").Append(","); + else sb.Append(valuation.TrailingPE).Append(","); + if (double.IsNaN(valuation.AverageLowTrailing) || double.IsInfinity(valuation.AverageLowTrailing)) sb.Append("null").Append(","); + else sb.Append(valuation.AverageLowTrailing).Append(","); + if (double.IsNaN(valuation.CurrentStockEstimatePrice) || double.IsInfinity(valuation.CurrentStockEstimatePrice)) sb.Append("null").Append(","); + else sb.Append(valuation.CurrentStockEstimatePrice).Append(","); + if (valuation.PriceEstimate10Y<0 || double.IsNaN(valuation.PriceEstimate10Y) || double.IsInfinity(valuation.PriceEstimate10Y) || Utility.OutOfRange(valuation.PriceEstimate10Y)) sb.Append("null").Append(","); + else sb.Append(valuation.PriceEstimate10Y).Append(","); + if (double.IsNaN(valuation.TodaysPriceForRequiredReturn) || double.IsInfinity(valuation.TodaysPriceForRequiredReturn) || Utility.OutOfRange(valuation.TodaysPriceForRequiredReturn)) sb.Append("null").Append(","); + else sb.Append(valuation.TodaysPriceForRequiredReturn).Append(","); + if (double.IsNaN(valuation.MOS) || double.IsInfinity(valuation.MOS) || Utility.OutOfRange(valuation.MOS)) sb.Append("null").Append(","); + else sb.Append(valuation.MOS).Append(","); + if (double.IsNaN(valuation.MOS80) || double.IsInfinity(valuation.MOS80) || Utility.OutOfRange(valuation.MOS80)) sb.Append("null").Append(","); + else sb.Append(valuation.MOS80).Append(","); + if (double.IsNaN(valuation.IntrinsicValue) || double.IsInfinity(valuation.IntrinsicValue) || Utility.OutOfRange(valuation.IntrinsicValue)) sb.Append("null").Append(","); + else sb.Append(valuation.IntrinsicValue).Append(","); + if (double.IsNaN(valuation.RGV) || double.IsInfinity(valuation.RGV) || Utility.OutOfRange(valuation.RGV)) sb.Append("null").Append(","); + else sb.Append(valuation.RGV).Append(","); + if (double.IsNaN(valuation.LatestPrice) || double.IsInfinity(valuation.LatestPrice)) sb.Append("null").Append(","); + else sb.Append(valuation.LatestPrice).Append(","); + if (double.IsNaN(valuation.UpsidePcnt) || double.IsInfinity(valuation.UpsidePcnt)) sb.Append("null").Append(","); + else sb.Append(valuation.UpsidePcnt).Append(","); + if (double.IsNaN(valuation.DownsidePcnt) || double.IsInfinity(valuation.DownsidePcnt)) sb.Append("null").Append(","); + else sb.Append(valuation.DownsidePcnt).Append(","); + if (double.IsNaN(valuation.MeanTargetPrice) || double.IsInfinity(valuation.MeanTargetPrice)) sb.Append("null").Append(","); + else sb.Append(valuation.MeanTargetPrice).Append(","); + if (double.IsNaN(valuation.LowTargetPrice) || double.IsInfinity(valuation.LowTargetPrice)) sb.Append("null").Append(","); + else sb.Append(valuation.LowTargetPrice).Append(","); + if (double.IsNaN(valuation.HighTargetPrice) || double.IsInfinity(valuation.HighTargetPrice)) sb.Append("null").Append(","); + else sb.Append(valuation.HighTargetPrice).Append(","); + sb.Append(valuation.Bargain).Append(","); + sb.Append(valuation.Bargain80).Append(","); + if (double.IsNaN(valuation.PBVPS) || double.IsInfinity(valuation.PBVPS)) sb.Append("null").Append(","); + else sb.Append(valuation.PBVPS).Append(","); + if (double.IsNaN(valuation.PEG) || double.IsInfinity(valuation.PEG)) sb.Append("null").Append(","); + else sb.Append(valuation.PEG).Append(","); + if (double.IsNaN(valuation.ImpliedEarningsGrowth) || double.IsInfinity(valuation.ImpliedEarningsGrowth)) sb.Append("null").Append(","); + else sb.Append(valuation.ImpliedEarningsGrowth).Append(","); + if (double.IsNaN(valuation.Beta90) || double.IsInfinity(valuation.Beta90)) sb.Append("null").Append(","); + else sb.Append(valuation.Beta90).Append(","); + if (double.IsNaN(valuation.Beta720) || double.IsInfinity(valuation.Beta720)) sb.Append("null").Append(","); + else sb.Append(valuation.Beta720).Append(","); + if (double.IsNaN(valuation.MarketCap) || double.IsInfinity(valuation.MarketCap)) sb.Append("null").Append(","); + else sb.Append(valuation.MarketCap).Append(","); + if (double.IsNaN(valuation.EarningsYield) || double.IsInfinity(valuation.EarningsYield)) sb.Append("null").Append(","); + else sb.Append(valuation.EarningsYield).Append(","); + if (double.IsNaN(valuation.EBIT) || double.IsInfinity(valuation.EBIT)) sb.Append("null").Append(","); + else sb.Append(valuation.EBIT).Append(","); + if (double.IsNaN(valuation.EnterpriseValue) || double.IsInfinity(valuation.EnterpriseValue)) sb.Append("null").Append(","); + else sb.Append(valuation.EnterpriseValue).Append(","); + if (double.IsNaN(valuation.TLBRankROIC) || double.IsInfinity(valuation.TLBRankROIC)) sb.Append("null").Append(","); + else sb.Append(valuation.TLBRankROIC).Append(","); + if (double.IsNaN(valuation.FundamentalValue) || double.IsInfinity(valuation.FundamentalValue)) sb.Append("null").Append(","); + else sb.Append(valuation.FundamentalValue).Append(","); + if (double.IsNaN(valuation.NetCurrentAssetValuePerShare) || double.IsInfinity(valuation.NetCurrentAssetValuePerShare)) sb.Append("null").Append(","); + else sb.Append(valuation.NetCurrentAssetValuePerShare).Append(","); + if (double.IsNaN(valuation.LatestROIC) || double.IsInfinity(valuation.LatestROIC)) sb.Append("null").Append(","); + else sb.Append(valuation.LatestROIC).Append(","); + if (null==valuation.Sector) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(valuation.Sector)).Append(","); + if (null==valuation.Industry) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(valuation.Industry)).Append(","); + if (double.IsNaN(valuation.DebtToEquity) || double.IsInfinity(valuation.DebtToEquity)) sb.Append("null").Append(","); + else sb.Append(valuation.DebtToEquity).Append(","); + sb.Append(valuation.SEC13).Append(","); + if (Utility.IsEpoch(valuation.SEC13FilingDate)) sb.Append("null").Append(","); + else sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(valuation.SEC13FilingDate))).Append(","); + if (double.IsNaN(valuation.LatestROC) || double.IsInfinity(valuation.LatestROC)) sb.Append("null").Append(","); + else sb.Append(valuation.LatestROC).Append(","); + if (double.IsNaN(valuation.TLBRankROC) || double.IsInfinity(valuation.TLBRankROC)) sb.Append("null").Append(","); + else sb.Append(valuation.TLBRankROC).Append(","); + if (double.IsNaN(valuation.OperatingEarnings) || double.IsInfinity(valuation.OperatingEarnings)) sb.Append("null").Append(","); + else sb.Append(valuation.OperatingEarnings).Append(","); + if (double.IsNaN(valuation.AMRank) || double.IsInfinity(valuation.AMRank)) sb.Append("null").Append(","); + else sb.Append(valuation.AMRank).Append(","); + if (double.IsNaN(valuation.AcquirersMultiple) || double.IsInfinity(valuation.AcquirersMultiple)) sb.Append("null").Append(","); + else sb.Append(valuation.AcquirersMultiple).Append(","); + if (double.IsNaN(valuation.DividendYield) || double.IsInfinity(valuation.DividendYield)) sb.Append("null").Append(","); + else sb.Append(valuation.DividendYield).Append(","); + if (double.IsNaN(valuation.OperatingCashflow) || double.IsInfinity(valuation.OperatingCashflow)) sb.Append("null").Append(","); + else sb.Append(valuation.OperatingCashflow).Append(","); + if (double.IsNaN(valuation.SharesOutstanding) || double.IsInfinity(valuation.SharesOutstanding)) sb.Append("null").Append(","); + else sb.Append(valuation.SharesOutstanding).Append(","); + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(modified))).Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,strQuery); + + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static void RemoveValuationBySymbol(String symbol,DateTime valuationDate) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + MySqlTransaction sqlTransaction=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction=sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + sb.Append("delete from valuations where symbol='").Append(symbol).Append("'"); + sb.Append(" and valuation_date=").Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(valuationDate))); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection,sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool RemoveValuation(DateTime valuationDate,MySqlTransaction sqlTransaction) + { + MySqlConnection sqlConnection = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("delete from valuations where valuation_date="); + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(valuationDate))); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection,sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/WatchListDA.cs b/MarketData/MarketDataLib/DataAccess/WatchListDA.cs new file mode 100755 index 0000000..30a20c4 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/WatchListDA.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class WatchListDA + { + private WatchListDA() + { + } + public static bool AddToWatchList(String symbol, String watchListName = "Valuations") + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + + try + { + if (null == symbol) return false; + symbol = symbol.ToUpper(); + WatchListItem watchListItem = GetWatchListItem(watchListName); + if (null == watchListItem) return false; + if (IsInWatchList(symbol, watchListName)) return true; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + sb.Append("insert into watchlist(watch_list_id,symbol)values("); + sb.Append(watchListItem.WatchListId).Append(","); + sb.Append(SqlUtils.AddQuotes(symbol)); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return false; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool RemoveFromWatchList(String symbol, String watchListName = "Valuations") + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + + try + { + if (null == symbol) return false; + symbol = symbol.ToUpper(); + WatchListItem watchListItem = GetWatchListItem(watchListName); + if (null == watchListItem) return false; + List watchListSymbols = GetWatchList(watchListName); + if (null == watchListSymbols.Find(x => x.Equals(symbol))) return true; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + StringBuilder sb = new StringBuilder(); + sb.Append("delete from watchlist where watch_list_id=").Append(watchListItem.WatchListId).Append(" and ").Append("symbol='").Append(symbol).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return false; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static bool IsInWatchList(String symbol, String watchListName = "Valuations") + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select count(*) from watchlist wl, watchlists wls where wl.watch_list_id=wls.watch_list_id and wls.watch_list_name="); + sb.Append("'").Append(watchListName).Append("'").Append(" "); + sb.Append("and wl.symbol=").Append("'").Append(symbol).Append("'").Append(" "); + sb.Append(" order by 1 asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return false; + int count = sqlDataReader.GetInt32(0); + return count > 0 ? true : false; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return false; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetWatchList(String watchListName) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + List watchList = new List(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select wl.symbol from watchlist wl, watchlists wls where wl.watch_list_id=wls.watch_list_id and wls.watch_list_name="); + sb.Append("'").Append(watchListName).Append("'").Append(" order by 1 asc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + String symbol = sqlDataReader.GetString(0); + watchList.Add(symbol); + } + return watchList; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static WatchListItem GetWatchListItem(String watchListName) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + WatchListItem watchListItem = null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select watch_list_name,watch_list_id from watchlists where watch_list_name='").Append(watchListName).Append("'"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (sqlDataReader.Read()) + { + watchListItem = new WatchListItem(); + watchListItem.WatchListName = sqlDataReader.GetString(0); + watchListItem.WatchListId = sqlDataReader.GetInt32(1); + } + return watchListItem; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static List GetWatchLists() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand = null; + List watchList = new List(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("portfolio_data")); + sb.Append("select watch_list_name from watchlists"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + String symbol = sqlDataReader.GetString(0); + watchList.Add(symbol); + } + return watchList; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != sqlCommand) sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/YieldCurveDA.cs b/MarketData/MarketDataLib/DataAccess/YieldCurveDA.cs new file mode 100755 index 0000000..8e44528 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/YieldCurveDA.cs @@ -0,0 +1,454 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class YieldCurveDA + { + private YieldCurveDA() + { + } + private static bool DeleteYieldCurve(YieldCurve yieldCurve, MySqlConnection sqlConnection, MySqlTransaction sqlTransaction) + { + String strQuery = null; + try + { + StringBuilder sb = new StringBuilder(); + sb.Append("delete from yieldcurve "); + sb.Append("where date in ").Append(SqlUtils.CreateInClauseYear(yieldCurve.GetDistinctDates())); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + } + } + public static bool InsertOrUpdate(YieldCurve yieldCurve) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + String strQuery = null; + + try + { + if (null == yieldCurve || 0 == yieldCurve.Count) return false; + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteYieldCurve(yieldCurve,sqlConnection,sqlTransaction); + DateTime modified = DateTime.Now; + for (int index = 0; index < yieldCurve.Count; index++) + { + YieldCurveData yieldCurveData = yieldCurve[index]; + StringBuilder sb = new StringBuilder(); + sb.Append("insert into yieldcurve(date,1mo,3mo,6mo,1yr,2yr,3yr,5yr,7yr,10yr,20yr,30yr,modified)values("); + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(yieldCurveData.Date))).Append(","); + if(!double.IsNaN(yieldCurveData.Mo1))sb.Append(yieldCurveData.Mo1).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Mo3))sb.Append(yieldCurveData.Mo3).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Mo3))sb.Append(yieldCurveData.Mo6).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Yr1))sb.Append(yieldCurveData.Yr1).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Yr2))sb.Append(yieldCurveData.Yr2).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Yr3))sb.Append(yieldCurveData.Yr3).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Yr5))sb.Append(yieldCurveData.Yr5).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Yr7))sb.Append(yieldCurveData.Yr7).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Yr10))sb.Append(yieldCurveData.Yr10).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Yr20))sb.Append(yieldCurveData.Yr20).Append(","); + else sb.Append("null").Append(","); + if(!double.IsNaN(yieldCurveData.Yr30))sb.Append(yieldCurveData.Yr30).Append(","); + else sb.Append("null").Append(","); + sb.Append(SqlUtils.AddQuotes(Utility.DateTimeToStringYYYYHMMHDD(modified))); + sb.Append(")"); + strQuery = sb.ToString(); + MySqlCommand sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlCommand.Dispose(); + } + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if (null != sqlTransaction) sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static YieldCurve GetYieldCurve(DateTime startDate, int days) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + YieldCurve yieldCurve = new YieldCurve(); + + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + DateGenerator dateGenerator = new DateGenerator(); + DateTime maxHistoricalDate = dateGenerator.GenerateHistoricalDate(startDate, days * 2); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,1mo,3mo,6mo,1yr,2yr,3yr,5yr,7yr,10yr,20yr,30yr from yieldcurve "); + sb.Append("where date<='").Append(Utility.DateTimeToStringYYYYHMMHDD(startDate)).Append("' "); + sb.Append("and date>='").Append(Utility.DateTimeToStringYYYYHMMHDD(maxHistoricalDate)).Append("' "); + sb.Append(" order by date desc"); + sb.Append(" limit ").Append(days); + + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + YieldCurveData yieldCurveData = new YieldCurveData(); + yieldCurveData.Date = sqlDataReader.GetDateTime(0); + yieldCurveData.Mo1 = sqlDataReader.GetDouble(1); + yieldCurveData.Mo3 = sqlDataReader.GetDouble(2); + yieldCurveData.Mo6 = sqlDataReader.GetDouble(3); + yieldCurveData.Yr1 = sqlDataReader.GetDouble(4); + yieldCurveData.Yr2 = sqlDataReader.GetDouble(5); + yieldCurveData.Yr3 = sqlDataReader.GetDouble(6); + yieldCurveData.Yr5 = sqlDataReader.GetDouble(7); + yieldCurveData.Yr7 = sqlDataReader.GetDouble(8); + yieldCurveData.Yr10 = sqlDataReader.GetDouble(9); + yieldCurveData.Yr20 = sqlDataReader.GetDouble(10); + yieldCurveData.Yr30 = sqlDataReader.GetDouble(11); + yieldCurve.Add(yieldCurveData); + } + return yieldCurve; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static YieldCurveData GetYieldCurve(DateTime effectiveDate) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + YieldCurveData yieldCurveData = null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,1mo,3mo,6mo,1yr,2yr,3yr,5yr,7yr,10yr,20yr,30yr from yieldcurve "); + sb.Append("where date='").Append(Utility.DateTimeToStringYYYYHMMHDD(effectiveDate)).Append("' "); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read())return null; + yieldCurveData = new YieldCurveData(); + yieldCurveData.Date = sqlDataReader.GetDateTime(0); + yieldCurveData.Mo1 = sqlDataReader.GetDouble(1); + yieldCurveData.Mo3 = sqlDataReader.GetDouble(2); + yieldCurveData.Mo6 = sqlDataReader.GetDouble(3); + yieldCurveData.Yr1 = sqlDataReader.GetDouble(4); + yieldCurveData.Yr2 = sqlDataReader.GetDouble(5); + yieldCurveData.Yr3 = sqlDataReader.GetDouble(6); + yieldCurveData.Yr5 = sqlDataReader.GetDouble(7); + yieldCurveData.Yr7 = sqlDataReader.GetDouble(8); + yieldCurveData.Yr10 = sqlDataReader.GetDouble(9); + yieldCurveData.Yr20 = sqlDataReader.GetDouble(10); + yieldCurveData.Yr30 = sqlDataReader.GetDouble(11); + return yieldCurveData; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static YieldCurve GetYieldCurve(int dayCount) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + YieldCurve yieldCurve = new YieldCurve(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,1mo,3mo,6mo,1yr,2yr,3yr,5yr,7yr,10yr,20yr,30yr from yieldcurve "); + sb.Append(" order by date desc"); + sb.Append(" limit ").Append(dayCount); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + YieldCurveData yieldCurveData = new YieldCurveData(); + yieldCurveData.Date = sqlDataReader.GetDateTime(0); + yieldCurveData.Mo1 = sqlDataReader.GetDouble(1); + yieldCurveData.Mo3 = sqlDataReader.GetDouble(2); + yieldCurveData.Mo6 = sqlDataReader.GetDouble(3); + yieldCurveData.Yr1 = sqlDataReader.GetDouble(4); + yieldCurveData.Yr2 = sqlDataReader.GetDouble(5); + yieldCurveData.Yr3 = sqlDataReader.GetDouble(6); + yieldCurveData.Yr5 = sqlDataReader.GetDouble(7); + yieldCurveData.Yr7 = sqlDataReader.GetDouble(8); + yieldCurveData.Yr10 = sqlDataReader.GetDouble(9); + yieldCurveData.Yr20 = sqlDataReader.GetDouble(10); + yieldCurveData.Yr30 = sqlDataReader.GetDouble(11); + yieldCurve.Add(yieldCurveData); + } + return yieldCurve; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static YieldCurve GetYieldCurve() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + YieldCurve yieldCurve = new YieldCurve(); + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,1mo,3mo,6mo,1yr,2yr,3yr,5yr,7yr,10yr,20yr,30yr from yieldcurve "); + sb.Append(" order by date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while (sqlDataReader.Read()) + { + YieldCurveData yieldCurveData = new YieldCurveData(); + yieldCurveData.Date=sqlDataReader.GetDateTime(0); + yieldCurveData.Mo1=sqlDataReader.GetDouble(1); + yieldCurveData.Mo3=sqlDataReader.GetDouble(2); + yieldCurveData.Mo6=sqlDataReader.GetDouble(3); + yieldCurveData.Yr1=sqlDataReader.GetDouble(4); + yieldCurveData.Yr2=sqlDataReader.GetDouble(5); + yieldCurveData.Yr3=sqlDataReader.GetDouble(6); + yieldCurveData.Yr5=sqlDataReader.GetDouble(7); + yieldCurveData.Yr7=sqlDataReader.GetDouble(8); + yieldCurveData.Yr10=sqlDataReader.GetDouble(9); + yieldCurveData.Yr20=sqlDataReader.GetDouble(10); + yieldCurveData.Yr30 = sqlDataReader.GetDouble(11); + yieldCurve.Add(yieldCurveData); + } + return yieldCurve; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null != sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + public static double GetRiskFreeRate1Yr(DateTime effectiveDate,int lookAhead) + { + DateGenerator dateGenerator=new DateGenerator(); + YieldCurveData yieldCurveData=null; + for(int index=0;index GetYieldCurveDates() + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + List yieldCurveDates=new List(); + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date from yieldcurve order by date desc"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + while(sqlDataReader.Read()) + { + yieldCurveDates.Add(sqlDataReader.GetDateTime(0)); + } + return yieldCurveDates; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return new List(); + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + } +} diff --git a/MarketData/MarketDataLib/DataAccess/ZacksRankDA.cs b/MarketData/MarketDataLib/DataAccess/ZacksRankDA.cs new file mode 100755 index 0000000..ac15010 --- /dev/null +++ b/MarketData/MarketDataLib/DataAccess/ZacksRankDA.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MySql.Data.MySqlClient; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.DataAccess +{ + public class ZacksRankDA + { + private ZacksRankDA() + { + } +// Get the latest rank for symbol that falls on or before the specified date + public static ZacksRank GetZacksRankOnOrBefore(String symbol, DateTime date) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + DateTime? maxDate=GetMaxDateOnOrBefore(symbol,date); + if(null==maxDate)return null; + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select symbol,zacks_rank,date,type from zacksrank where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and date=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(maxDate.Value)).Append("'"); + sb.Append(" limit 1").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + ZacksRank zacksRank=new ZacksRank(); + zacksRank.Symbol=sqlDataReader.GetString(0); + zacksRank.Rank=sqlDataReader.GetString(1); + zacksRank.Date=sqlDataReader.GetDateTime(2); + if(!sqlDataReader.IsDBNull(3))zacksRank.Type=sqlDataReader.GetString(3); + return zacksRank; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// Get the most recent rank date on or before the given date for specified symbol + private static DateTime? GetMaxDateOnOrBefore(String symbol, DateTime date) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + DateTime? maxDate=null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date from zacksrank where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and date<=").Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(date)).Append("' "); + sb.Append(" order by date desc "); + sb.Append(" limit 1").Append(";"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + if(!sqlDataReader.IsDBNull(0))maxDate=sqlDataReader.GetDateTime(0); + return maxDate; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// Get the latest rank for symbol + public static ZacksRank GetZacksRank(String symbol) + { + MySqlConnection sqlConnection = null; + MySqlDataReader sqlDataReader = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + StringBuilder sb = new StringBuilder(); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sb.Append("select date,symbol,zacks_rank,type from zacksrank where symbol="); + sb.Append("'").Append(symbol).Append("'").Append(" "); + sb.Append("and date=").Append(" (select max(date) from zacksrank where symbol='").Append(symbol).Append("')"); + strQuery = sb.ToString(); ; + sqlCommand = new MySqlCommand(strQuery, sqlConnection); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlDataReader = sqlCommand.ExecuteReader(); + if (!sqlDataReader.Read()) return null; + ZacksRank zacksRank=new ZacksRank(); + zacksRank.Date=sqlDataReader.GetDateTime(0); + zacksRank.Symbol=sqlDataReader.GetString(1); + zacksRank.Rank=sqlDataReader.GetString(2); + if(!sqlDataReader.IsDBNull(3))zacksRank.Type=sqlDataReader.GetString(3); + return zacksRank; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if (null != sqlDataReader) sqlDataReader.Close(); + if (null != sqlConnection) sqlConnection.Close(); + } + } +// Insert a rank if the latest rank that we have is different from the one to be added or we do not have a rank + public static bool InsertZacksRank(ZacksRank zacksRank) + { + MySqlConnection sqlConnection = null; + MySqlTransaction sqlTransaction = null; + MySqlCommand sqlCommand=null; + String strQuery = null; + + try + { + if(null==zacksRank||null==zacksRank.Symbol||null==zacksRank.Rank||"".Equals(zacksRank.Rank))return false; + ZacksRank latestRank=GetZacksRank(zacksRank.Symbol); + if(null!=latestRank&&latestRank.Rank.Equals(zacksRank.Rank))return true; + zacksRank.Type=GetChangeType(latestRank,zacksRank); + sqlConnection = SqlUtils.CreateMySqlConnection(MainDataSource.Instance.LocateDataSource("market_data")); + sqlTransaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted); + DeleteZacksRank(zacksRank, sqlConnection, sqlTransaction); + sqlTransaction.Commit(); + sqlTransaction = sqlConnection.BeginTransaction(); + StringBuilder sb = new StringBuilder(); + sb.Append("insert into zacksrank (symbol,date,zacks_rank,type) "); + sb.Append("values("); + sb.Append("'").Append(zacksRank.Symbol).Append("'").Append(","); + sb.Append("'").Append(Utility.DateTimeToStringYYYYHMMHDD(zacksRank.Date)).Append("'").Append(","); + sb.Append("'").Append(zacksRank.Rank).Append("'").Append(","); + if(null==zacksRank.Type)sb.Append("null"); + else sb.Append("'").Append(zacksRank.Type).Append("'"); + sb.Append(")"); + strQuery = sb.ToString(); + sqlCommand = new MySqlCommand(strQuery, sqlConnection, sqlTransaction); + sqlCommand.CommandTimeout = SqlUtils.COMMAND_TIMEOUT; + sqlCommand.ExecuteNonQuery(); + sqlTransaction.Commit(); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + MDTrace.WriteLine(LogLevel.DEBUG,"Query was '" + strQuery + "'"); + return false; + } + finally + { + if(null!=sqlCommand)sqlCommand.Dispose(); + if(null!=sqlTransaction)sqlTransaction.Dispose(); + if (null != sqlConnection) sqlConnection.Close(); + } + } + private static String GetChangeType(ZacksRank latestRank,ZacksRank newRank) + { + if(null==latestRank)return "Initial"; + if(null==latestRank.Rank||null==newRank||null==newRank.Rank)return null; + int latestRankNumber=int.Parse(latestRank.Rank.Substring(0,1)); + int newRankNumber=int.Parse(newRank.Rank.Substring(0,1)); + if(newRankNumber>latestRankNumber)return "Downgrades"; + else if(newRankNumber + { + public AcquirersMultipleCollection() + { + } + public AcquirersMultipleCollection(AcquirersMultipleCollection collection) + { + foreach(AcquirersMultipleItem acquirersMultipleItem in collection)Add(acquirersMultipleItem); + } + } + public class AcquirersMultipleItem + { + public AcquirersMultipleItem() + { + } + public String Symbol{get;set;} + public double AcquirersMultiple{get;set;} + public double MarketCapitalization{get;set;} + public double EnterpriseValue{get;set;} + public double OperatingEarnings{get;set;} + public double DepreciationAndAmortization{get;set;} + public double TotalRevenue{get;set;} + public double CostOfRevenue{get;set;} + public double SGA{get;set;} + public double Rank{get;set;} + public static String Heading + { + get{return "Symbol,MarketCapitalization,AcquirersMultiple,EnterpriseValue,OperatingEarnings,DepreciationAndAmortization,TotalRevenue,CostOfRevenue,SGA,Rank";} + } + public override string ToString() + { + StringBuilder sb=new StringBuilder(); + sb.Append(Symbol).Append(",").Append(Utility.FormatNumber(MarketCapitalization,2,false)).Append(",").Append(Utility.FormatNumber(AcquirersMultiple,2,false)).Append(",").Append(Utility.FormatNumber(EnterpriseValue,2,false)).Append(","); + sb.Append(Utility.FormatNumber(OperatingEarnings,2,false)).Append(",").Append(Utility.FormatNumber(DepreciationAndAmortization,2,false)).Append(","); + sb.Append(Utility.FormatNumber(TotalRevenue,2,false)).Append(",").Append(Utility.FormatNumber(CostOfRevenue,2,false)).Append(","); + sb.Append(Utility.FormatNumber(SGA,2,false)).Append(",").Append(Utility.FormatNumber(Rank,2,false)).Append(","); + return sb.ToString(); + } + } + public class AcquirersMultipleItemSorter : IComparer + { + public int Compare(AcquirersMultipleItem v1,AcquirersMultipleItem v2) // here we want to sort by lowest positive non NaN item + { + if(double.IsNaN(v1.AcquirersMultiple)&&double.IsNaN(v2.AcquirersMultiple))return 0; + else if(double.IsNaN(v1.AcquirersMultiple))return -1; + else if(double.IsNaN(v2.AcquirersMultiple))return 1; + else if(v1.AcquirersMultiple.Equals(v2.AcquirersMultiple))return 0; + else if(v1.AcquirersMultiple symbols=PricingDA.GetSymbols(); + return ApplyRanks(symbols); + } + public static AcquirersMultipleCollection ApplyRanks(String symbol) + { + List symbols=new List(); + symbols.Add(symbol); + return ApplyRanks(symbols); + } + public static AcquirersMultipleCollection ApplyRanks(List symbols) + { +// List symbols=PricingDA.GetSymbols(); + AcquirersMultipleCollection acquirersMultipleCollection=new AcquirersMultipleCollection(); + IncomeStatement incomeStatement=null; + CashflowStatement cashflowStatement=null; + BalanceSheet balanceSheet=null; +// pull in the data for all symbols + foreach(String symbol in symbols) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Working on {0}",symbol)); + incomeStatement=IncomeStatementDA.GetIncomeStatement(symbol,IncomeStatement.PeriodType.Annual); + cashflowStatement=CashflowStatementDA.GetCashflowStatement(symbol,CashflowStatement.PeriodType.Annual); + balanceSheet = BalanceSheetDA.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual); + Fundamental fundamental = FundamentalDA.GetFundamental(symbol); + AcquirersMultipleItem acquirersMultipleItem=new AcquirersMultipleItem(); + acquirersMultipleItem.Symbol=symbol; + if(null!=fundamental&&!double.IsNaN(fundamental.EnterpriseValue)&&null!=cashflowStatement&&!double.IsNaN(cashflowStatement.DepreciationAndAmortization)&&null!=incomeStatement&&!double.IsNaN(incomeStatement.TotalRevenue)&&!double.IsNaN(incomeStatement.CostOfRevenue)&&!double.IsNaN(incomeStatement.SGA)) + { + acquirersMultipleItem.MarketCapitalization=fundamental.MarketCap; + acquirersMultipleItem.OperatingEarnings=incomeStatement.TotalRevenue-(cashflowStatement.DepreciationAndAmortization+incomeStatement.CostOfRevenue+incomeStatement.SGA); + acquirersMultipleItem.AcquirersMultiple=fundamental.EnterpriseValue/acquirersMultipleItem.OperatingEarnings; + acquirersMultipleItem.EnterpriseValue=fundamental.EnterpriseValue; + acquirersMultipleItem.DepreciationAndAmortization=cashflowStatement.DepreciationAndAmortization; + acquirersMultipleItem.TotalRevenue=incomeStatement.TotalRevenue; + acquirersMultipleItem.CostOfRevenue=incomeStatement.CostOfRevenue; + acquirersMultipleItem.SGA=incomeStatement.SGA; + } + else + { + if(null==fundamental)MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} missing fundamental.",symbol)); +// if(null==balanceSheet)MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} missing balance sheet.",symbol)); + if(null==cashflowStatement)MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} missing cashflow statement.",symbol)); + if(null==incomeStatement)MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} missing income statement.",symbol)); + if(null!=fundamental&&double.IsNaN(fundamental.EnterpriseValue))MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} missing fundamental data point (EnterpriseValue).",symbol)); + if(null!=cashflowStatement&&double.IsNaN(cashflowStatement.DepreciationAndAmortization))MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} missing cashflow statement data point (DepreciationAndAmortization).",symbol)); + if(null!=incomeStatement&&double.IsNaN(incomeStatement.CostOfRevenue))MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} missing income statement data point (Cost of Revenue).",symbol)); + if(null!=incomeStatement&&double.IsNaN(incomeStatement.SGA))MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} missing income statement data point (SGA).",symbol)); + acquirersMultipleItem.MarketCapitalization=double.NaN; + acquirersMultipleItem.OperatingEarnings=double.NaN; + acquirersMultipleItem.AcquirersMultiple=double.NaN; + acquirersMultipleItem.EnterpriseValue=double.NaN; + acquirersMultipleItem.DepreciationAndAmortization=double.NaN; + acquirersMultipleItem.TotalRevenue=double.NaN; + acquirersMultipleItem.CostOfRevenue=double.NaN; + acquirersMultipleItem.SGA=double.NaN; + } + acquirersMultipleCollection.Add(acquirersMultipleItem); + } +// Build the rankings + Dictionary acquirersMultipleCollectionBySymbol=new Dictionary(); + Dictionary acquirersMultipleRankedByAcquirersMultiple=new Dictionary(); + foreach(AcquirersMultipleItem acquirersMultipleItem in acquirersMultipleCollection) + { + if(!acquirersMultipleCollectionBySymbol.ContainsKey(acquirersMultipleItem.Symbol))acquirersMultipleCollectionBySymbol.Add(acquirersMultipleItem.Symbol,acquirersMultipleItem); + } + acquirersMultipleCollection.Sort(new AcquirersMultipleItemSorter()); + for(int index=0;index valuationsBySymbol=new Dictionary(); + Dictionary valuationsRankedByAcquirersMultiple=new Dictionary(); + + foreach(Valuation valuation in valuations) + { + if(!valuationsBySymbol.ContainsKey(valuation.Symbol))valuationsBySymbol.Add(valuation.Symbol,valuation); + } + Valuations valuationsCopyByAcquirersMultiple=new Valuations(valuations); + valuationsCopyByAcquirersMultiple.Sort(new ValuationsByAcquirersMultiple()); + for(int index=0;indexGenerateBollingerBands - Bollinger band generator utility class + public class BollingerBandGenerator + { + private BollingerBandGenerator() + { + } + public static BollingerBands GenerateBollingerBands(Prices prices,int movingAverageDays=20) + { + try + { + double standardDeviations = 2.00; + BollingerBands bollingerBands = new BollingerBands(); + Dictionary deviationsByDate = new Dictionary(); + Dictionary averagesByDate = new Dictionary(); + + if (movingAverageDays < 20) standardDeviations = 1.9; + else if (movingAverageDays >= 20) standardDeviations = 2.1; + if (null == prices || prices.Count < movingAverageDays * 2) return null; + DMAPrices dmaPrices = MovingAverageGenerator.GenerateMovingAverage(prices, movingAverageDays); + DMADeviations dmaDeviations = MovingDeviation.GenerateMovingDeviation(prices, movingAverageDays); + for (int index = 0; index < dmaPrices.Count; index++) + { + DMAPrice dmaPrice = dmaPrices[index]; + if (!averagesByDate.ContainsKey(dmaPrice.Date)) averagesByDate.Add(dmaPrice.Date, dmaPrice); + } + for (int index = 0; index < dmaDeviations.Count; index++) + { + DMADeviation dmaDeviation = dmaDeviations[index]; + if (!deviationsByDate.ContainsKey(dmaDeviation.Date)) deviationsByDate.Add(dmaDeviation.Date, dmaDeviation); + } + for (int index = 0; index < prices.Count; index++) + { + Price price = prices[index]; + if (!deviationsByDate.ContainsKey(price.Date) || !averagesByDate.ContainsKey(price.Date)) continue; + DMADeviation dmaDeviation = deviationsByDate[price.Date]; + DMAPrice dmaPrice = averagesByDate[price.Date]; + BollingerBandElement bollingerBandElement = new BollingerBandElement(); + bollingerBandElement.Symbol = price.Symbol; + bollingerBandElement.Date = price.Date; + bollingerBandElement.Open = price.Open; + bollingerBandElement.High = price.High; + bollingerBandElement.Low = price.Low; + bollingerBandElement.Close = price.Close; + bollingerBandElement.Volume = price.Volume; + bollingerBandElement.SMAN = dmaPrice.AVGPrice; + bollingerBandElement.StDevN = dmaDeviation.StDevPrice; + bollingerBandElement.K = bollingerBandElement.SMAN + (standardDeviations * bollingerBandElement.StDevN); + bollingerBandElement.L = bollingerBandElement.SMAN - (standardDeviations * bollingerBandElement.StDevN); + bollingerBandElement.KL1 = bollingerBandElement.SMAN + ((standardDeviations - 1) * bollingerBandElement.StDevN); + bollingerBandElement.LP1 = bollingerBandElement.SMAN - ((standardDeviations - 1) * bollingerBandElement.StDevN); + bollingerBands.Add(bollingerBandElement); + } + return bollingerBands; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + } +} diff --git a/MarketData/MarketDataLib/Generator/DCFGenerator.cs b/MarketData/MarketDataLib/Generator/DCFGenerator.cs new file mode 100755 index 0000000..873e941 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/DCFGenerator.cs @@ -0,0 +1,310 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MarketData.DataAccess; +using MarketData.Numerical; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.Generator +{ + public class DCFGenerator + { + private DCFGenerator() + { + } +// This just calculates the WACC + public static double CalculateWACC(String symbol,DateTime asOf) + { + try + { + DCFValuation dcfValuation = new DCFValuation(); + dcfValuation.Symbol = symbol; + Fundamental fundamental = FundamentalDA.GetFundamentalMaxDate(symbol,asOf); + if (null == fundamental) {return double.NaN; } + if (!CalculateCostOfEquity(dcfValuation,asOf)) return double.NaN; + if (!CalculateCostOfDebt(dcfValuation,fundamental.TotalDebt,asOf)) return double.NaN; + dcfValuation.MarketValueOfDebt = fundamental.TotalDebt; + dcfValuation.MarketValueOfEquity = fundamental.MarketCap; + dcfValuation.OutstandingShares = fundamental.SharesOutstanding; + dcfValuation.TotalCapitalInvested = dcfValuation.MarketValueOfDebt + dcfValuation.MarketValueOfEquity; + if (!CalculateWACC(dcfValuation)) return double.NaN; + return dcfValuation.WACC; + } + catch(Exception) + { + return double.NaN; + } + } +// This calculates the full discounted cashflow + public static DCFValuation GenerateDCFValuation(String symbol) + { + DCFValuation dcfValuation = new DCFValuation(); + dcfValuation.Symbol = symbol; + + Fundamental fundamental = FundamentalDA.GetFundamental(symbol); + if (null == fundamental) { dcfValuation.Message = "Missing fundamental data."; return dcfValuation; } + if (!CalculateCostOfEquity(dcfValuation)) return dcfValuation; + if (!CalculateCostOfDebt(dcfValuation, fundamental.TotalDebt)) return dcfValuation; + dcfValuation.MarketValueOfDebt = fundamental.TotalDebt; + dcfValuation.MarketValueOfEquity = fundamental.MarketCap; + dcfValuation.OutstandingShares = fundamental.SharesOutstanding; + dcfValuation.TotalCapitalInvested = dcfValuation.MarketValueOfDebt + dcfValuation.MarketValueOfEquity; + if (!CalculateWACC(dcfValuation)) return dcfValuation; + if (!Discount(dcfValuation)) return dcfValuation; + EnhanceValuation(dcfValuation,fundamental); // add ROIC, EPSGrowth, EarningsGrowth + dcfValuation.success = true; + return dcfValuation; + } + public static void EnhanceValuation(DCFValuation dcfValuation,Fundamental fundamental) + { + TimeSeriesCollection bookValuePerShareCollection = HistoricalDA.GetTimeSeries(dcfValuation.Symbol, TimeSeriesElement.ElementType.BVPS); + TimeSeriesCollection roicCollection = HistoricalDA.GetTimeSeries(dcfValuation.Symbol, TimeSeriesElement.ElementType.ROIC); + TimeSeriesCollection revenueCollection = HistoricalDA.GetTimeSeries(dcfValuation.Symbol, TimeSeriesElement.ElementType.Revenue); + TimeSeriesCollection epsCollection = HistoricalDA.GetTimeSeries(dcfValuation.Symbol, TimeSeriesElement.ElementType.EPS); + YieldCurve yieldCurve=YieldCurveDA.GetYieldCurve(); + + if (null != roicCollection && 0 != roicCollection.Count) + { + dcfValuation.Enhancements.ROICGrowth = Numerics.AverageReturn(roicCollection); + dcfValuation.Enhancements.ROIC = roicCollection[0].Value/100.00; + } + dcfValuation.Enhancements.DebtLoad = fundamental.Revenue * 3 > fundamental.TotalDebt ? true : false; + dcfValuation.Enhancements.EPSGrowth = Numerics.AverageReturn(epsCollection); + dcfValuation.Enhancements.RevenueGrowth = Numerics.AverageReturn(revenueCollection); + dcfValuation.Enhancements.BVPS = fundamental.BookValuePerShare; + if (null == dcfValuation.CurrentPrice || double.NaN.Equals(dcfValuation.CurrentPrice.Close)) dcfValuation.Enhancements.PBVPS = double.NaN; + else dcfValuation.Enhancements.PBVPS = dcfValuation.CurrentPrice.Close / dcfValuation.Enhancements.BVPS; + dcfValuation.Enhancements.EPS = fundamental.EPS; + dcfValuation.Enhancements.PE = fundamental.PE; + dcfValuation.Enhancements.PEG = fundamental.PEG; + dcfValuation.Enhancements.MOS = dcfValuation.StockPriceValuation * .5; + dcfValuation.Enhancements.MOS80 = dcfValuation.StockPriceValuation * .8; + dcfValuation.Enhancements.IntrinsicValue = GrahamGenerator.IntrinsicValue(fundamental.EPS,dcfValuation.Enhancements.EPSGrowth); + if (null == yieldCurve || double.NaN.Equals(yieldCurve[0].Yr20)) dcfValuation.Enhancements.IntrinsicValueRevised = double.NaN; + else dcfValuation.Enhancements.IntrinsicValueRevised = GrahamGenerator.IntrinsicValueRevised(fundamental.EPS,dcfValuation.Enhancements.EPSGrowth,yieldCurve[0].Yr30); + if (null == dcfValuation.CurrentPrice || double.NaN.Equals(dcfValuation.CurrentPrice.Close)) dcfValuation.Enhancements.RGVIntrinsic = double.NaN; + else dcfValuation.Enhancements.RGVIntrinsic = dcfValuation.Enhancements.IntrinsicValue / dcfValuation.CurrentPrice.Close; + if (null == dcfValuation.CurrentPrice || double.NaN.Equals(dcfValuation.CurrentPrice.Close)) dcfValuation.Enhancements.RGVIntrinsicRevised = double.NaN; + else dcfValuation.Enhancements.RGVIntrinsicRevised = dcfValuation.Enhancements.IntrinsicValueRevised / dcfValuation.CurrentPrice.Close; + } + private static bool Discount(DCFValuation dcfValuation,int years=10) + { + List sourceElements = new List(); + List destElements = null; + +// pull cashflow history from database and apply filters + TimeSeriesCollection freeCashflows = HistoricalDA.GetTimeSeries(dcfValuation.Symbol, TimeSeriesElement.ElementType.FreeCashflow); + if (null == freeCashflows || 0 == freeCashflows.Count) { dcfValuation.Message = "Missing Freecashflows"; return false; } + dcfValuation.FreeCashflowGrowth = Numerics.AverageReturnWithSpline(freeCashflows,dcfValuation.ReturnItems); // if free cashflow growth > 100% perform an average throwing away all returns in the set > 100% + if (dcfValuation.FreeCashflowGrowth.Equals(double.NaN)) { dcfValuation.Message = "Freecashflow growth is undefined"; return false; } + +// set up spline parameters. Apply 3% cap to freecashflow growth in the 10th year and spline to that. + sourceElements.Add(new Element(1, dcfValuation.FreeCashflowGrowth)); + sourceElements.Add(new Element(years, .03 < dcfValuation.FreeCashflowGrowth ? .03 : dcfValuation.FreeCashflowGrowth)); + +// set the starting date and the initial freecashflow value, run interpolation + DateTime startingDate = freeCashflows[0].AsOf; + double runningCashflow = freeCashflows[0].Value; + for (int year = 1; year <= years; year++) + { + startingDate = new DateTime(startingDate.Year + 1, startingDate.Month, startingDate.Day); + destElements = new List(); + destElements.Add(new Element(year, 0)); + CatmullRom.PerformSpline((Element[])sourceElements.ToArray(), (Element[])destElements.ToArray()); + double cashflowGrowth = destElements[0].Row; + if (year < years) runningCashflow = runningCashflow * (1.00 + cashflowGrowth); + else runningCashflow = (runningCashflow * (1.00 + cashflowGrowth)) / (Math.Abs(dcfValuation.WACC - cashflowGrowth)); + dcfValuation.Cashflows.Add(new CashflowElement(startingDate, runningCashflow)); + } +// Discount cashflows by WACC + for (int index = 0; index < dcfValuation.Cashflows.Count; index++) + { + dcfValuation.Cashflows[index].Cashflow /= Math.Pow(1.00 + dcfValuation.WACC, index + 1); + } +// sum up the discounted values to get the present value; + dcfValuation.PresentValue = 0.00; + for (int index = 0; index < dcfValuation.Cashflows.Count; index++) + { + dcfValuation.PresentValue += dcfValuation.Cashflows[index].Cashflow; + } +// subtract debt + dcfValuation.PresentValue -= dcfValuation.TotalDebt; +// divide by outstanding shares + dcfValuation.StockPriceValuation=dcfValuation.PresentValue/dcfValuation.OutstandingShares; + +// Apply validation filters + if (dcfValuation.PresentValue.Equals(double.NaN)) { dcfValuation.Message = "PresentValue is undefined"; return false; } + + if (dcfValuation.StockPriceValuation.Equals(double.NaN)) { dcfValuation.Message = "Stock price valuation is undefined"; return false; } + return true; + } +// Calculate the WACC + private static bool CalculateWACC(DCFValuation dcfValuation) + { + dcfValuation.WACC=((dcfValuation.MarketValueOfEquity/dcfValuation.TotalCapitalInvested)*dcfValuation.CostOfEquity)+ + ((dcfValuation.MarketValueOfDebt/dcfValuation.TotalCapitalInvested)*dcfValuation.CostOfDebt*(1.00-dcfValuation.CorporateTaxRate)); + return true; + } + private static bool CalculateCostOfEquity(DCFValuation dcfValuation) + { + String marketSymbol = "SPY"; + Prices stockPrices = null; + Prices marketPrices=null; + +// calculate 3-year beta of stock vs SP500 + stockPrices = PricingDA.GetPrices(dcfValuation.Symbol, 365 * 3); + if (null == stockPrices || 0 == stockPrices.Count) + { + dcfValuation.Message = "Missing prices for symbol."; + return false; + } + dcfValuation.CurrentPrice = stockPrices[0]; + marketPrices=PricingDA.GetPrices(marketSymbol,stockPrices.Count); + if (null == stockPrices || 0 == stockPrices.Count || null == marketPrices || 0 == marketPrices.Count) + { + dcfValuation.Message = "Missing prices for market."; + return false; + } + dcfValuation.Beta = BetaGenerator.Beta(dcfValuation.Symbol, PricingDA.GetLatestDate(dcfValuation.Symbol)); + +// get the risk free rate, 90 day treasury note + dcfValuation.RiskFreeRate = YieldCurveDA.GetRiskFreeRate(); + dcfValuation.RiskFreeRate /= 100.00; + +// calculate historic market returns + if (dcfValuation.UseMarketReturn) + { + marketPrices = PricingDA.GetPrices(marketSymbol); + float[] marketPricesArray = marketPrices.GetPrices(); + dcfValuation.MarketReturn = Numerics.AnnualReturn(ref marketPricesArray); + } + else dcfValuation.MarketReturn = DCFValuation.MARKET_RETURN; +// calculate cost of equity + dcfValuation.CostOfEquity = dcfValuation.RiskFreeRate + dcfValuation.Beta * (dcfValuation.MarketReturn - dcfValuation.RiskFreeRate); + return true; + } + private static bool CalculateCostOfEquity(DCFValuation dcfValuation,DateTime asOf) + { + String marketSymbol = "SPY"; + Prices stockPrices = null; + Prices marketPrices=null; + +// calculate 3-year beta of stock vs SP500 + stockPrices = PricingDA.GetPrices(dcfValuation.Symbol,asOf, 365 * 3); + if (null == stockPrices || 0 == stockPrices.Count) + { + dcfValuation.Message = "Missing prices for symbol."; + return false; + } + dcfValuation.CurrentPrice = stockPrices[0]; + marketPrices=PricingDA.GetPrices(marketSymbol,asOf,stockPrices.Count); + if (null == stockPrices || 0 == stockPrices.Count || null == marketPrices || 0 == marketPrices.Count) + { + dcfValuation.Message = "Missing prices for market."; + return false; + } + //float[] stockPricesArray=stockPrices.GetPrices(); + //float[] marketPricesArray = marketPrices.GetPrices(); + //dcfValuation.Beta = Numerics.Beta(ref stockPricesArray, ref marketPricesArray); + dcfValuation.Beta = BetaGenerator.Beta(dcfValuation.Symbol, PricingDA.GetLatestDate(dcfValuation.Symbol)); + +// get the risk free rate, 90 day treasury note + dcfValuation.RiskFreeRate = YieldCurveDA.GetRiskFreeRate(asOf); + dcfValuation.RiskFreeRate /= 100.00; + +// calculate historic market returns + if (dcfValuation.UseMarketReturn) + { + marketPrices = PricingDA.GetPricesOnOrBefore(marketSymbol,asOf); + float[] marketPricesArray = marketPrices.GetPrices(); + dcfValuation.MarketReturn = Numerics.AnnualReturn(ref marketPricesArray); + } + else dcfValuation.MarketReturn = DCFValuation.MARKET_RETURN; +// calculate cost of equity + dcfValuation.CostOfEquity = dcfValuation.RiskFreeRate + dcfValuation.Beta * (dcfValuation.MarketReturn - dcfValuation.RiskFreeRate); + return true; + } +// **YAHOO InterestExpense is totally wrong for some stocks. AER is a good example +// This prioritizes MorningStar InterestExpense number over Yahoo Interest Expense number + private static bool CalculateCostOfDebt(DCFValuation dcfValuation,double totalDebt) + { + TimeSeriesCollection interestExpenseSeries = HistoricalDA.GetTimeSeries(dcfValuation.Symbol, TimeSeriesElement.ElementType.InterestExpense); + if (null == interestExpenseSeries || 0 == interestExpenseSeries.Count) + { + IncomeStatement incomeStatement = IncomeStatementDA.GetIncomeStatement(dcfValuation.Symbol, IncomeStatement.PeriodType.Annual); + if(null!=incomeStatement&&incomeStatement.InterestExpense.Equals(double.NaN)) + { + dcfValuation.InterestExpense=0.00; + } + else if(null==incomeStatement) + { + dcfValuation.Message = "Missing IncomeStatement or Interest Expense "; + return false; + } + else dcfValuation.InterestExpense=incomeStatement.InterestExpense; + } + else + { + if(interestExpenseSeries[0].Value.Equals(double.NaN))dcfValuation.InterestExpense=0.00; + else dcfValuation.InterestExpense=interestExpenseSeries[0].Value; + } + TimeSeriesCollection timeSeriesCollection = HistoricalDA.GetTimeSeries(dcfValuation.Symbol, TimeSeriesElement.ElementType.TaxRate); + if (null == timeSeriesCollection || 0 == timeSeriesCollection.Count) timeSeriesCollection.Add(new TimeSeriesElement() {Value=37 }); + TimeSeriesElement timeSeriesElement = timeSeriesCollection[0]; + dcfValuation.CorporateTaxRate = timeSeriesElement.Value / 100.00; + dcfValuation.TotalDebt = totalDebt; + if(0.00==totalDebt) + { + dcfValuation.InterestRate=0.00; + dcfValuation.CostOfDebt=0.00; + } + else + { + dcfValuation.InterestRate=dcfValuation.InterestExpense/dcfValuation.TotalDebt; + dcfValuation.CostOfDebt=dcfValuation.InterestRate*(1-dcfValuation.CorporateTaxRate); + } + return true; + } + private static bool CalculateCostOfDebt(DCFValuation dcfValuation,double totalDebt,DateTime asOf) + { + TimeSeriesCollection interestExpenseSeries = HistoricalDA.GetTimeSeriesMaxAsOf(dcfValuation.Symbol,asOf, TimeSeriesElement.ElementType.InterestExpense); + if (null == interestExpenseSeries || 0 == interestExpenseSeries.Count) + { + IncomeStatement incomeStatement = IncomeStatementDA.GetIncomeStatementMaxAsOf(dcfValuation.Symbol,asOf, IncomeStatement.PeriodType.Annual); + if(null!=incomeStatement&&incomeStatement.InterestExpense.Equals(double.NaN)) + { + dcfValuation.InterestExpense=0.00; + } + else if(null==incomeStatement) + { + dcfValuation.Message = "Missing IncomeStatement or Interest Expense "; + return false; + } + else dcfValuation.InterestExpense=incomeStatement.InterestExpense; + } + else + { + if(interestExpenseSeries[0].Value.Equals(double.NaN))dcfValuation.InterestExpense=0.00; + else dcfValuation.InterestExpense=interestExpenseSeries[0].Value; + } + TimeSeriesCollection timeSeriesCollection = HistoricalDA.GetTimeSeriesMaxAsOf(dcfValuation.Symbol,asOf, TimeSeriesElement.ElementType.TaxRate); + if (null == timeSeriesCollection || 0 == timeSeriesCollection.Count) timeSeriesCollection.Add(new TimeSeriesElement() {Value=37 }); + TimeSeriesElement timeSeriesElement = timeSeriesCollection[0]; + dcfValuation.CorporateTaxRate = timeSeriesElement.Value / 100.00; + dcfValuation.TotalDebt = totalDebt; + if(0.00==totalDebt) + { + dcfValuation.InterestRate=0.00; + dcfValuation.CostOfDebt=0.00; + } + else + { + dcfValuation.InterestRate=dcfValuation.InterestExpense/dcfValuation.TotalDebt; + dcfValuation.CostOfDebt=dcfValuation.InterestRate*(1-dcfValuation.CorporateTaxRate); + } + return true; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/DividendHistoryGenerator.cs b/MarketData/MarketDataLib/Generator/DividendHistoryGenerator.cs new file mode 100755 index 0000000..0f6bf18 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/DividendHistoryGenerator.cs @@ -0,0 +1,114 @@ +using MarketData.Cache; +using MarketData.DataAccess; +using MarketData.MarketDataModel; +using MarketData.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MarketData.Generator +{ + public class DividendHistoryGenerator + { + private DividendHistoryGenerator() + { + } + public static double GetDividendYield(String symbol) + { + try + { + Price currentPrice=PricingDA.GetPrice(symbol); + return GetDividendYield(symbol,currentPrice); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",exception.ToString())); + return double.NaN; + } + } + public static double GetDividendYield(String symbol,Price currentPrice) + { + try + { + int currentYear=DateTime.Now.Year; + int priorYear=currentYear-1; + + DividendHistory dividendHistory=DividendHistoryCache.GetInstance().GetDividendHistory(symbol,new int[]{currentYear, priorYear}); +// DividendHistory dividendHistory=DividendHistoryDA.GetDividendHistory(symbol,new int[] { currentYear,priorYear }); + + if(null==currentPrice||double.IsNaN(currentPrice.Close)||!currentPrice.Date.Year.Equals(currentYear)) return double.NaN; + DividendHistory lastYearsDividendPayments=new DividendHistory((from DividendHistoryItem item in dividendHistory where item.DivExDate.Year==priorYear&&null!=item.CashAmount select item).ToList()); + DividendHistory currentYearsDividendPayments=new DividendHistory((from DividendHistoryItem item in dividendHistory where item.DivExDate.Year==currentYear&&null!=item.CashAmount select item).ToList()); + if(currentYearsDividendPayments.HasConsecutivePayments(3)) return (currentYearsDividendPayments.Average(x => x.CashAmount.Value)*12)/currentPrice.Close; + if(0==lastYearsDividendPayments.Count&&0==currentYearsDividendPayments.Count) return double.NaN; + double lastYearsAverageDividendPayment=lastYearsDividendPayments.Count()>1?lastYearsDividendPayments.Average(x => x.CashAmount.Value):double.NaN; + + // calculate last years min and max dividend payments in order to determine if there were special payments + double lastYearMinDividendPayment=lastYearsDividendPayments.Count>0?lastYearsDividendPayments.Min(x => x.CashAmount.Value):0.00; + DividendHistory lastYearsSpecialPayments=lastYearsDividendPayments.Count>0?new DividendHistory((from DividendHistoryItem item in lastYearsDividendPayments where item.CashAmount.Value>3*lastYearMinDividendPayment select item).ToList()):new DividendHistory(); + bool lastYearHasSpecialItems=lastYearsSpecialPayments.Count()>0?true:false; + + if(0==currentYearsDividendPayments.Count) // if no dividends in current year then go back to last year + { + if(lastYearHasSpecialItems) lastYearsDividendPayments=new DividendHistory(lastYearsDividendPayments.Where(x => !lastYearsSpecialPayments.Any(z => z.DivExDate==x.DivExDate)).ToList()); + else if(1==lastYearsDividendPayments.Count) return lastYearsDividendPayments[0].CashAmount.Value/currentPrice.Close; + return lastYearsDividendPayments.Sum(x => x.CashAmount.Value)/currentPrice.Close; + } + double currentYearMaxDividendPayment=currentYearsDividendPayments.Max(x => x.CashAmount.Value); + double currentYearMinDividendPayment=currentYearsDividendPayments.Min(x => x.CashAmount.Value); + DividendHistory currentYearsSpecialPayments=new DividendHistory((from DividendHistoryItem item in currentYearsDividendPayments where item.CashAmount.Value>3*currentYearMinDividendPayment select item).ToList()); + bool currentYearhasSpecialItems=currentYearsSpecialPayments.Count()>0?true:false; + double currentYearsAverageDividendPayment=currentYearsDividendPayments.Average(x => x.CashAmount.Value); + if(1==lastYearsDividendPayments.Count&&1==currentYearsDividendPayments.Count) return currentYearsAverageDividendPayment/currentPrice.Close; + if(0==lastYearsDividendPayments.Count) // there was no dividend payment last year. check if this years is a special dividend (>25%) + { + double dividendPayment=currentYearsDividendPayments.Average(x => x.CashAmount.Value); + double dividendYield=dividendPayment/currentPrice.Close; + if(dividendYield>=.25) return dividendYield; + } + if(4==lastYearsDividendPayments.Count) + { + if(currentYearhasSpecialItems) // exclude special payments from consideration + { + currentYearsDividendPayments=new DividendHistory(currentYearsDividendPayments.Where(x => !currentYearsSpecialPayments.Any(z => z.DivExDate==x.DivExDate)).ToList()); + double dividendYield=currentYearsDividendPayments.Average(x => x.CashAmount.Value); + dividendYield*=4.00; + dividendYield/=currentPrice.Close; + return dividendYield; + } + if(1==currentYearsDividendPayments.Count&&lastYearHasSpecialItems) // if only one payment this year and last year has a special payment then use last year minus special payment + { + lastYearsDividendPayments=new DividendHistory(lastYearsDividendPayments.Where(x => !lastYearsSpecialPayments.Any(z => z.DivExDate==x.DivExDate)).ToList()); + double dividendYield=lastYearsDividendPayments.Average(x => x.CashAmount.Value); + dividendYield*=4.00; + dividendYield/=currentPrice.Close; + return dividendYield; + } + return (currentYearsAverageDividendPayment*4.00)/currentPrice.Close; + } + if(3==currentYearsDividendPayments.Count) + { + if(currentYearhasSpecialItems) // exclude special payments from consideration + { + currentYearsDividendPayments=new DividendHistory(currentYearsDividendPayments.Where(x => !currentYearsSpecialPayments.Any(z => z.DivExDate==x.DivExDate)).ToList()); + double dividendYield=currentYearsDividendPayments.Average(x => x.CashAmount.Value); + dividendYield*=4.00; + dividendYield/=currentPrice.Close; + return dividendYield; + } + else return (currentYearsAverageDividendPayment*4.00)/currentPrice.Close; + } + if(2==lastYearsDividendPayments.Count) return Math.Min(lastYearsDividendPayments.Sum(x => x.CashAmount.Value),currentYearsDividendPayments.Sum(x => x.CashAmount.Value))/currentPrice.Close; + return (currentYearsDividendPayments.Average(x => x.CashAmount.Value)*4.00)/currentPrice.Close; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",exception.ToString())); + return double.NaN; + } + } + } +} diff --git a/MarketData/MarketDataLib/Generator/GainLoss/ActiveGainLossGenerator.cs b/MarketData/MarketDataLib/Generator/GainLoss/ActiveGainLossGenerator.cs new file mode 100755 index 0000000..cfa3ecf --- /dev/null +++ b/MarketData/MarketDataLib/Generator/GainLoss/ActiveGainLossGenerator.cs @@ -0,0 +1,91 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using MarketData; +using MarketData.MarketDataModel; +using MarketData.MarketDataModel.GainLoss; +using MarketData.Utils; +using MarketData.DataAccess; +using MarketData.Cache; + +namespace MarketData.Generator.GainLoss +{ +// ***************************************************************** G A I N L O S S G E N E R A T O R ********************************************************** + public class ActiveGainLossGenerator : IActiveGainLossGenerator + { + public ActiveGainLossGenerator() + { + } + //public void RefreshPriceCache() + //{ + // LocalPriceCache.GetInstance().Refresh(); + //} +// ***************************************************************************************************************************************************************** +// ************************************************ G E N E R A T E A C T I V E G A I N L O S S / G A I N L O S S P E R C E N T ***************************** +// ***************************************************************************************************************************************************************** + public GainLossCollection GenerateGainLoss(PortfolioTrades portfolioTrades,DateTime? maxDateRef=null) + { + if (null == portfolioTrades || 0 == portfolioTrades.Count) return null; + LocalPriceCache.GetInstance().Add(portfolioTrades); + DateTime minTradeDate = portfolioTrades.GetMinTradeDate(); + DateTime maxDate = PricingDA.GetLatestDate(); + if(null!=maxDateRef)maxDate=maxDateRef.Value; + Dictionary gainLoss = new Dictionary(); + DateGenerator dateGenerator = new DateGenerator(); + List holdingDates = dateGenerator.GenerateHistoricalDates(maxDate, minTradeDate); + for (int index = holdingDates.Count - 1; index >= 0; index--) + { + DateTime holdingDate = holdingDates[index]; + double? gainLossHoldings = null; + double totalExposure = 0.00; + double totalCostBasis=0.00; + double totalMarketValue=0.00; + PortfolioTrades openTrades = portfolioTrades.GetOpenTradesOn(holdingDate); + if (null == openTrades || 0 == openTrades.Count) + { + gainLoss.Add(holdingDate, new GainLossItem(holdingDate, 0,0,false)); + continue; + } + if(!LocalPriceCache.GetInstance().ContainsPrice(openTrades.Symbols,holdingDate)) + { + if(holdingDate.Date.Equals(maxDate)) + { + LocalPriceCache.GetInstance().Add(openTrades.Symbols,holdingDate); + }else continue; + } + foreach (PortfolioTrade portfolioTrade in openTrades) + { + double? gainLossItem = null; + double? exposure = null; + double? costBasis=null; + double? marketValue=null; + + costBasis=GainLossHelper.GetCostBasis(holdingDate,portfolioTrade); + gainLossItem=GainLossHelper.GetGainLoss(holdingDate, portfolioTrade); + marketValue=GainLossHelper.GetMarketValue(holdingDate,portfolioTrade); + if (null == gainLossItem) continue; + if (null == gainLossHoldings) gainLossHoldings = gainLossItem; + else gainLossHoldings += gainLossItem; + exposure = GainLossHelper.GetExposure(holdingDate,portfolioTrade); + if (null != exposure) totalExposure += exposure.Value; + if(null!=costBasis)totalCostBasis+=costBasis.Value; + if(null!=marketValue)totalMarketValue+=marketValue.Value; + } + GainLossItem gainLossElement = null; + double totalGainLossPercent=0; + if(0!=totalCostBasis)totalGainLossPercent=((totalMarketValue-totalCostBasis)/totalCostBasis)*100.00; + if(null==gainLossHoldings) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("ActiveGainLossGenerator:GenerateGainLoss 'GainLossHoldings' is null for on {0}",Utility.DateTimeToStringMMHDDHYYYY(holdingDate))); + continue; + } + if (null == gainLossHoldings)gainLossElement = new GainLossItem(holdingDate,gainLossHoldings.Value,totalGainLossPercent,totalExposure,false); + else gainLossElement = new GainLossItem(holdingDate, gainLossHoldings.Value,totalGainLossPercent,totalExposure,false); + gainLoss.Add(holdingDate, gainLossElement); + } + GainLossCollection gainLossList = new GainLossCollection(gainLoss.Values); + gainLossList.Sort(); + return gainLossList; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/GainLoss/GainLossGenerator.cs b/MarketData/MarketDataLib/Generator/GainLoss/GainLossGenerator.cs new file mode 100755 index 0000000..de5c20e --- /dev/null +++ b/MarketData/MarketDataLib/Generator/GainLoss/GainLossGenerator.cs @@ -0,0 +1,127 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using MarketData; +using MarketData.MarketDataModel; +using MarketData.MarketDataModel.GainLoss; +using MarketData.Utils; +using MarketData.DataAccess; +using MarketData.Cache; + +namespace MarketData.Generator.GainLoss +{ +// ***************************************************************** G A I N L O S S G E N E R A T O R ********************************************************** + public class GainLossGenerator : ITotalGainLossGenerator + { + public GainLossGenerator() + { + } +// ***************************************************************************************************************************************************************** +// ************************************************ G E N E R A T E T O T A L G A I N L O S S / T O T A L G A I N L O S S P E R C E N T ******************* +// ***************************************************************************************************************************************************************** + public TotalGainLossCollection GenerateTotalGainLoss(PortfolioTrades portfolioTrades,DateTime? maxDateRef=null) + { + if (null == portfolioTrades || 0 == portfolioTrades.Count) return null; + LocalPriceCache.GetInstance().Add(portfolioTrades); + DateTime minTradeDate = portfolioTrades.GetMinTradeDate(); + DateTime maxDate = PricingDA.GetLatestDate(); + if(null!=maxDateRef)maxDate=maxDateRef.Value; + Dictionary gainLossCollection = new Dictionary(); + DateGenerator dateGenerator = new DateGenerator(); + List holdingDates = dateGenerator.GenerateHistoricalDates(maxDate, minTradeDate); + for (int index = holdingDates.Count - 1; index >= 0; index--) + { + DateTime holdingDate = holdingDates[index]; + double totalGainLoss = 0.00;; + double totalExposure = 0.00; + double totalCostBasis=0.00; + double totalMarketValue=0.00; + PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(holdingDate); + if (null == tradesOnOrBefore || 0 == tradesOnOrBefore.Count) + { + gainLossCollection.Add(holdingDate, new TotalGainLossItem(holdingDate, 0,0,0,0)); + continue; + } + foreach (PortfolioTrade portfolioTrade in tradesOnOrBefore) + { + double? gainLoss = null; + double? exposure = null; + double? costBasis=null; + double? marketValue=null; + gainLoss=GainLossHelper.GetTotalGainLoss(holdingDate,portfolioTrade); + costBasis=GainLossHelper.GetTotalCostBasis(holdingDate,portfolioTrade); + marketValue=GainLossHelper.GetTotalMarketValue(holdingDate,portfolioTrade); + exposure=GainLossHelper.GetTotalExposure(holdingDate,portfolioTrade); + if (null == gainLoss || null==costBasis || null==marketValue) continue; + if(null!=gainLoss) totalGainLoss += gainLoss.Value; + if (null != exposure) totalExposure += exposure.Value; + if(null!=costBasis)totalCostBasis+=costBasis.Value; + if(null!=marketValue)totalMarketValue+=marketValue.Value; + } + TotalGainLossItem gainLossElement = null; + double totalGainLossPercent=0; + if(0!=totalCostBasis)totalGainLossPercent=((totalMarketValue-totalCostBasis)/totalCostBasis)*100.00; + gainLossElement=new TotalGainLossItem(holdingDate,totalGainLoss,totalGainLossPercent,totalExposure,totalMarketValue); + gainLossCollection.Add(holdingDate, gainLossElement); + } + TotalGainLossCollection gainLossList = new TotalGainLossCollection(gainLossCollection.Values); + gainLossList.Sort(); + return gainLossList; + } +// ***************************************************************************************************************************************************************** +// ************************************************ G E N E R A T E T O T A L G A I N L O S S W I T H D I V I D E N D S / T O T A L G A I N L O S S P E R C E N T ******************* +// ***************************************************************************************************************************************************************** + public TotalGainLossCollection GenerateTotalGainLossWithDividends(PortfolioTrades portfolioTrades,DividendPayments dividendPayments,DateTime? maxDateRef=null) + { + if (null == portfolioTrades || 0 == portfolioTrades.Count) return null; + LocalPriceCache.GetInstance().Add(portfolioTrades); + DateTime minTradeDate = portfolioTrades.GetMinTradeDate(); + DateTime maxDate = PricingDA.GetLatestDate(); + if(null!=maxDateRef)maxDate=maxDateRef.Value; + Dictionary gainLossCollection = new Dictionary(); + DateGenerator dateGenerator = new DateGenerator(); + List holdingDates = dateGenerator.GenerateHistoricalDates(maxDate, minTradeDate); + for (int index = holdingDates.Count - 1; index >= 0; index--) + { + DateTime holdingDate = holdingDates[index]; + double totalGainLoss = 0.00;; + double totalExposure = 0.00; + double totalCostBasis=0.00; + double totalMarketValue=0.00; + PortfolioTrades tradesOnOrBefore = portfolioTrades.GetTradesOnOrBefore(holdingDate); + if (null == tradesOnOrBefore || 0 == tradesOnOrBefore.Count) + { + gainLossCollection.Add(holdingDate, new TotalGainLossItem(holdingDate, 0,0,0,0)); + continue; + } + foreach (PortfolioTrade portfolioTrade in tradesOnOrBefore) + { + double? gainLoss = null; + double? exposure = null; + double? costBasis=null; + double? marketValue=null; + gainLoss=GainLossHelper.GetTotalGainLoss(holdingDate,portfolioTrade); + costBasis=GainLossHelper.GetTotalCostBasis(holdingDate,portfolioTrade); + marketValue=GainLossHelper.GetTotalMarketValue(holdingDate,portfolioTrade); + exposure=GainLossHelper.GetTotalExposure(holdingDate,portfolioTrade); + if (null == gainLoss || null==costBasis || null==marketValue) continue; + if(null!=gainLoss) totalGainLoss += gainLoss.Value; + if (null != exposure) totalExposure += exposure.Value; + if(null!=costBasis)totalCostBasis+=costBasis.Value; + if(null!=marketValue)totalMarketValue+=marketValue.Value; + } + TotalGainLossItem gainLossElement = null; + double totalGainLossPercent=0; + double dividendPaymentsToDate=dividendPayments.GetDividendPaymentsToDate(holdingDate); + totalMarketValue+=dividendPaymentsToDate; + totalGainLoss+=dividendPaymentsToDate; + if(0!=totalCostBasis)totalGainLossPercent=((totalMarketValue-totalCostBasis)/totalCostBasis)*100.00; + gainLossElement=new TotalGainLossItem(holdingDate,totalGainLoss,totalGainLossPercent,totalExposure,totalMarketValue,dividendPaymentsToDate); + gainLossCollection.Add(holdingDate, gainLossElement); + } + TotalGainLossCollection gainLossList = new TotalGainLossCollection(gainLossCollection.Values); + gainLossList.Sort(); + return gainLossList; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/GainLoss/GainLossGeneratorCum.cs b/MarketData/MarketDataLib/Generator/GainLoss/GainLossGeneratorCum.cs new file mode 100755 index 0000000..c917efe --- /dev/null +++ b/MarketData/MarketDataLib/Generator/GainLoss/GainLossGeneratorCum.cs @@ -0,0 +1,193 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using MarketData; +using MarketData.MarketDataModel; +using MarketData.MarketDataModel.GainLoss; +using MarketData.Utils; +using MarketData.DataAccess; +using MarketData.Cache; + +namespace MarketData.Generator.GainLoss +{ + public class GainLossGeneratorCum : ITotalGainLossGenerator + { + private DateGenerator dateGenerator=new DateGenerator(); + + public TotalGainLossCollection GenerateTotalGainLoss(PortfolioTrades portfolioTrades,DateTime? maxDateRef=null) + { + DateGenerator dateGenerator=new DateGenerator(); + ModelPerformanceSeries performanceSeries=new ModelPerformanceSeries(); + List gainLossList=new List(); + LocalPriceCache.GetInstance().Add(portfolioTrades); + try + { + if(!ValidatePortfolioTrades(portfolioTrades))return null; + DateTime minDate=portfolioTrades.GetMinTradeDate(); + DateTime maxDate=PricingDA.GetLatestDate(); + if(null!=maxDateRef) maxDate=maxDateRef.Value; + double prevGainLoss=double.NaN; + List historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate); + + foreach(DateTime currentDate in historicalDates) + { + PortfolioTrades openPositions=portfolioTrades.GetOpenTradesOn(currentDate); + PortfolioTrades closedPositions=portfolioTrades.GetClosedTradesOn(currentDate); + if(0==openPositions.Count&&0==closedPositions.Count) continue; + + double gainLoss=0.00; + double gainLossClosedPositions=0.00; + double exposure=0.00; + double marketValue=0.00; + + if(!dateGenerator.IsMarketOpen(currentDate)) continue; + ModelPerformanceItem performanceItem=new ModelPerformanceItem(); + + foreach(PortfolioTrade openPosition in openPositions) + { + exposure+=openPosition.Shares*openPosition.Price; + Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate); + if(null==price) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",openPosition.Symbol,currentDate.ToShortDateString())); + continue; + } + gainLoss+=((price.Close*openPosition.Shares)-(openPosition.Price*openPosition.Shares)); + marketValue+=(price.Close*openPosition.Shares); + } + foreach(PortfolioTrade closedPosition in closedPositions) + { + double gainLossPosition=(closedPosition.SellPrice*closedPosition.Shares)-(closedPosition.Price*closedPosition.Shares); + gainLossClosedPositions+=gainLossPosition; + } + performanceItem.Date=currentDate; + performanceItem.Exposure=exposure; + performanceItem.MarketValue=marketValue; + performanceItem.GainLossDOD=double.IsNaN(prevGainLoss)?gainLoss:(gainLoss-prevGainLoss)+gainLossClosedPositions; + performanceItem.GainLoss=gainLoss+gainLossClosedPositions; + performanceItem.ClosedPositions=closedPositions.Count>0?true:false; + performanceSeries.Add(performanceItem); + prevGainLoss=gainLoss; + } + performanceSeries.CalculatePerformance(); + double totalGainLoss=double.NaN; + foreach(ModelPerformanceItem performanceItem in performanceSeries) + { + if(double.IsNaN(totalGainLoss))totalGainLoss=performanceItem.GainLossDOD; + else totalGainLoss+=performanceItem.GainLossDOD; + TotalGainLossItem totalGainLossItem=new TotalGainLossItem( + performanceItem.Date, + totalGainLoss, + performanceItem.CumProdMinusOne*100.00, + performanceItem.Exposure, + performanceItem.MarketValue); + gainLossList.Add(totalGainLossItem); + } + TotalGainLossCollection totalGainLossCollection= new TotalGainLossCollection(gainLossList); + totalGainLossCollection.Sort(); + return totalGainLossCollection; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception: {0}",exception.ToString())); + return new TotalGainLossCollection(new List()); + } + } + public TotalGainLossCollection GenerateTotalGainLossWithDividends(PortfolioTrades portfolioTrades,DividendPayments dividendPayments,DateTime? maxDateRef=null) + { + DateGenerator dateGenerator=new DateGenerator(); + ModelPerformanceSeries performanceSeries=new ModelPerformanceSeries(); + List gainLossList=new List(); + LocalPriceCache.GetInstance().Add(portfolioTrades); + try + { + if(!ValidatePortfolioTrades(portfolioTrades)) return null; + DateTime minDate=portfolioTrades.Min(x => x.TradeDate); + DateTime maxDate=PricingDA.GetLatestDate(); + double prevGainLoss=double.NaN; +// LocalPriceCache.GetInstance().RemoveDate(maxDate); + List historicalDates=dateGenerator.GenerateHistoricalDates(minDate,maxDate); + + foreach(DateTime currentDate in historicalDates) + { + PortfolioTrades openPositions=portfolioTrades.GetOpenTradesOn(currentDate); + PortfolioTrades closedPositions=portfolioTrades.GetClosedTradesOn(currentDate); + if(0==openPositions.Count&&0==closedPositions.Count) continue; + + double gainLoss=0.00; + double gainLossClosedPositions=0.00; + double exposure=0.00; + double marketValue=0.00; + if(!dateGenerator.IsMarketOpen(currentDate)) continue; + ModelPerformanceItem performanceItem=new ModelPerformanceItem(); + + foreach(PortfolioTrade openPosition in openPositions) + { + exposure+=openPosition.Shares*openPosition.Price; + //if(!LocalPriceCache.GetInstance().ContainsPrice(openPosition.Symbol,currentDate)) + //{ + // Prices prices=PricingDA.GetPricesForward(openPosition.Symbol,currentDate,90); + // LocalPriceCache.GetInstance().Add(prices); + //} + Price price=LocalPriceCache.GetInstance().GetPrice(openPosition.Symbol,currentDate); + if(null==price) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",openPosition.Symbol,currentDate.ToShortDateString())); + } + gainLoss+=((price.Close*openPosition.Shares)-(openPosition.Price*openPosition.Shares)); + marketValue+=(price.Close*openPosition.Shares); + } + foreach(PortfolioTrade closedPosition in closedPositions) + { + double gainLossPosition=(closedPosition.SellPrice*closedPosition.Shares)-(closedPosition.Price*closedPosition.Shares); + gainLossClosedPositions+=gainLossPosition; + } + double dividendPaymentsToDate=dividendPayments.GetDividendPaymentsToDate(currentDate); + marketValue+=dividendPaymentsToDate; + gainLoss+=dividendPaymentsToDate; + performanceItem.Date=currentDate; + performanceItem.Exposure=exposure; + performanceItem.MarketValue=marketValue; + performanceItem.GainLossDOD=double.IsNaN(prevGainLoss)?gainLoss:(gainLoss-prevGainLoss)+gainLossClosedPositions; + performanceItem.GainLoss=gainLoss+gainLossClosedPositions; + performanceItem.ClosedPositions=closedPositions.Count>0?true:false; + performanceSeries.Add(performanceItem); + prevGainLoss=gainLoss; + } + performanceSeries.CalculatePerformance(); + double totalGainLoss=double.NaN; + foreach(ModelPerformanceItem performanceItem in performanceSeries) + { + double dividendPaymentsToDate=dividendPayments.GetDividendPaymentsToDate(performanceItem.Date); + if(double.IsNaN(totalGainLoss))totalGainLoss=performanceItem.GainLossDOD; + else totalGainLoss+=performanceItem.GainLossDOD; + TotalGainLossItem totalGainLossItem=new TotalGainLossItem( + performanceItem.Date, + totalGainLoss, + performanceItem.CumProdMinusOne*100.00, + performanceItem.Exposure, + performanceItem.MarketValue, + dividendPaymentsToDate); + gainLossList.Add(totalGainLossItem); + } + TotalGainLossCollection totalGainLossCollection= new TotalGainLossCollection(gainLossList); + totalGainLossCollection.Sort(); + return totalGainLossCollection; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception: {0}",exception.ToString())); + return new TotalGainLossCollection(new List()); + } + } + public bool ValidatePortfolioTrades(PortfolioTrades portfolioTrades) + { + foreach(PortfolioTrade portfolioTrade in portfolioTrades) + { + if(!dateGenerator.IsMarketOpen(portfolioTrade.TradeDate))return false; + if(!dateGenerator.IsMarketOpen(portfolioTrade.SellDate)) return false; + } + return true; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/GainLoss/GainLossHelper.cs b/MarketData/MarketDataLib/Generator/GainLoss/GainLossHelper.cs new file mode 100755 index 0000000..baf7a6f --- /dev/null +++ b/MarketData/MarketDataLib/Generator/GainLoss/GainLossHelper.cs @@ -0,0 +1,111 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using MarketData; +using MarketData.MarketDataModel; +using MarketData.MarketDataModel.GainLoss; +using MarketData.Utils; +using MarketData.DataAccess; +using MarketData.Cache; + +namespace MarketData.Generator.GainLoss +{ + public class GainLossHelper + { + private GainLossHelper() + { + } + public static double? GetTotalGainLoss(DateTime holdingDate,PortfolioTrade portfolioTrade) + { + if(holdingDateholdingDate)) + { + Price price=LocalPriceCache.GetInstance().GetPrice(portfolioTrade.Symbol,holdingDate); + if(null==price) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",portfolioTrade.Symbol,Utility.DateTimeToStringMMHDDHYYYY(holdingDate))); + return null; + } + return (price.Close*portfolioTrade.Shares)-(portfolioTrade.Shares*portfolioTrade.Price); + } + return (portfolioTrade.SellPrice*portfolioTrade.Shares)-(portfolioTrade.Price*portfolioTrade.Shares); + } + public static double? GetTotalMarketValue(DateTime holdingDate,PortfolioTrade portfolioTrade) + { + if(holdingDateholdingDate)) + { + Price price=LocalPriceCache.GetInstance().GetPrice(portfolioTrade.Symbol,holdingDate); + if(null==price) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",portfolioTrade.Symbol,Utility.DateTimeToStringMMHDDHYYYY(holdingDate))); + return null; + } + return (price.Close*portfolioTrade.Shares); + } + return (portfolioTrade.SellPrice*portfolioTrade.Shares); + } + public static double? GetTotalExposure(DateTime holdingDate,PortfolioTrade portfolioTrade) + { + if(holdingDateportfolioTrade.SellDate) return null; + // check to see if we sold this on holdingDate + if(!portfolioTrade.SellDate.Equals(Utility.Epoch)&&holdingDate.Equals(portfolioTrade.SellDate)) + { + return (portfolioTrade.SellPrice*portfolioTrade.Shares)-(portfolioTrade.Price*portfolioTrade.Shares); + } + // check to see if we bought and sold on the same date. + if(portfolioTrade.SellDate.Equals(portfolioTrade.TradeDate)) + { + return (portfolioTrade.SellPrice*portfolioTrade.Shares)-(portfolioTrade.Price*portfolioTrade.Shares); + } + Price price=LocalPriceCache.GetInstance().GetPrice(portfolioTrade.Symbol,holdingDate); + if(null==price) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",portfolioTrade.Symbol,Utility.DateTimeToStringMMHDDHYYYY(holdingDate))); + return null; + } + return (price.Close*portfolioTrade.Shares)-(portfolioTrade.Shares*portfolioTrade.Price); + } + public static double? GetMarketValue(DateTime holdingDate,PortfolioTrade portfolioTrade) + { + if(holdingDateportfolioTrade.SellDate) return null; + // check to see if we bought and sold on the same date. + if(portfolioTrade.SellDate.Equals(portfolioTrade.TradeDate)) return (portfolioTrade.SellPrice*portfolioTrade.Shares); + Price price=LocalPriceCache.GetInstance().GetPrice(portfolioTrade.Symbol,holdingDate); + if(null==price) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",portfolioTrade.Symbol,Utility.DateTimeToStringMMHDDHYYYY(holdingDate))); + return null; + } + return portfolioTrade.Shares*price.Close; + } + + public static double? GetCostBasis(DateTime holdingDate,PortfolioTrade portfolioTrade) + { + if(holdingDateportfolioTrade.SellDate) return null; + return portfolioTrade.Price*portfolioTrade.Shares; + } + + public static double? GetExposure(DateTime holdingDate,PortfolioTrade portfolioTrade) + { + if(holdingDateportfolioTrade.SellDate) return null; + return portfolioTrade.Shares*portfolioTrade.Price; + } + + } +} + diff --git a/MarketData/MarketDataLib/Generator/GainLoss/IActiveGainLossGenerator.cs b/MarketData/MarketDataLib/Generator/GainLoss/IActiveGainLossGenerator.cs new file mode 100755 index 0000000..275a74c --- /dev/null +++ b/MarketData/MarketDataLib/Generator/GainLoss/IActiveGainLossGenerator.cs @@ -0,0 +1,12 @@ +using System; +using MarketData.MarketDataModel; +using MarketData.MarketDataModel.GainLoss; + +namespace MarketData.Generator.GainLoss +{ + public interface IActiveGainLossGenerator + { + GainLossCollection GenerateGainLoss(PortfolioTrades portfolioTrades,DateTime? maxDateRef=null); + } +} + diff --git a/MarketData/MarketDataLib/Generator/GainLoss/ITotalGainLossGenerator.cs b/MarketData/MarketDataLib/Generator/GainLoss/ITotalGainLossGenerator.cs new file mode 100755 index 0000000..d81c71a --- /dev/null +++ b/MarketData/MarketDataLib/Generator/GainLoss/ITotalGainLossGenerator.cs @@ -0,0 +1,12 @@ +using System; +using MarketData.MarketDataModel; +using MarketData.MarketDataModel.GainLoss; + +namespace MarketData.Generator.GainLoss +{ + public interface ITotalGainLossGenerator + { + TotalGainLossCollection GenerateTotalGainLoss(PortfolioTrades portfolioTrades,DateTime? maxDateRef=null); + TotalGainLossCollection GenerateTotalGainLossWithDividends(PortfolioTrades portfolioTrades,DividendPayments dividendPayments,DateTime? maxDateRef=null); + } +} diff --git a/MarketData/MarketDataLib/Generator/GrahamGenerator.cs b/MarketData/MarketDataLib/Generator/GrahamGenerator.cs new file mode 100755 index 0000000..286823c --- /dev/null +++ b/MarketData/MarketDataLib/Generator/GrahamGenerator.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.Generator +{ + public class GrahamGenerator + { +// EPS: Earnings per share +// Growth: eps growth in decimal percent (i.e.) .25 represents 25% +// Benjamin Graham Formula. EPS=Trailing Twelve month, 8.5=PE base for no growth company, g=reasonably expected 7-10 year growth rate + public static double IntrinsicValue(double eps,double growth) + { + return eps * (8.5 + (2 * (growth * 100))); + } +// Grahams revision which includes a required rate of return of 4.4% which is what the going risk free rate was. Today we divied by AAA Corporate Bond Rate + public static double IntrinsicValueRevised(double eps,double growth,double riskFreeRate) + { + double requiredReturn=4.4; + return (eps * (8.5 + (2 * (growth * 100))) * requiredReturn) / riskFreeRate; + } +// The Graham number is a figure that measures a stock's fundamental value by taking into account the company's earnings per share and book value per share. +// The Graham number is the upper bound of the price range that a defensive investor should pay for the stock. According to the theory, any stock price below +// the Graham number is considered undervalued and thus worth investing in. The formula is as follows: + public static double GrahamNumber(double eps,double bvps) + { + return Math.Sqrt(22.5*eps*bvps); + } + } +} diff --git a/MarketData/MarketDataLib/Generator/Indicators/BandBreakIndicator.cs b/MarketData/MarketDataLib/Generator/Indicators/BandBreakIndicator.cs new file mode 100755 index 0000000..63f4f37 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Indicators/BandBreakIndicator.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MarketData.Numerical; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Cache; +using MarketData.Utils; + +namespace MarketData.Generator.Indicators +{ +// *********************************************************************************** + public class BandBreakIndicator + { + private BandBreakIndicator() + { + } +// This Indicator determines if a high price exceeds the K band (+2SSD) of the bollinger band over the past "dayCount" days. +// If high price breaks the K band then we consider that to be a true indication. + public static bool IsUpperBandBreakHigh(String symbol,DateTime pricingDate,int dayCount=20) + { + bool isBandBreak=false; + int pricingDays=dayCount*4; + if(pricingDays<60)pricingDays=60; + Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,pricingDays); + if(null==prices || 0==prices.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*** IsUpperBandBreakHigh: Failed to retrieve prices for {0} on {1} for {2} days. ***",symbol,pricingDate.ToShortDateString(),pricingDays)); + return isBandBreak; + } + BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices); + if(null==bollingerBands)return false; + bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList()); + BollingerBandElement item=bollingerBands.Where(x => x.High > x.K).FirstOrDefault(); + if(null!=item)isBandBreak=true; + return isBandBreak; + } +// This Indicator determines if a close price is equal to or less than the L band (-2SSD) of the bollinger band over the past "dayCount" days. +// If close price breaks or is equal to the L band then we consider that to be a true indication. +// If there is a violation then the date of the violation is return otherwise we return Epoch + public static DateTime IsLowerBandBreakClose(String symbol,DateTime pricingDate,int dayCount=20) + { + DateTime bandBreakDate=Utility.Epoch; + int pricingDays=dayCount*4; + if(pricingDays<60)pricingDays=60; + Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,pricingDays); + if(null==prices || 0==prices.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*** IsLowerBandBreakClose: Failed to retrieve prices for {0} on {1} for {2} days. ***",symbol,pricingDate.ToShortDateString(),pricingDays)); + return bandBreakDate; + } + BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices); + if(null==bollingerBands || bollingerBands.Count x.Close <= x.L).FirstOrDefault(); + if(null!=item) + { + bandBreakDate=item.Date; + } + return bandBreakDate; + } + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/Generator/Indicators/ChannelBreakoutIndicator.cs b/MarketData/MarketDataLib/Generator/Indicators/ChannelBreakoutIndicator.cs new file mode 100755 index 0000000..7c34e2d --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Indicators/ChannelBreakoutIndicator.cs @@ -0,0 +1,32 @@ +using MarketData.MarketDataModel; +using MarketData.Numerical; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +// Richard Donchian Channel Breakout. Donchian used 20 days. + +namespace MarketData.Generator.Indicators +{ + public class ChannelBreakoutIndicator + { + private ChannelBreakoutIndicator() + { + } + public static bool IsChannelBreakOut(DateTime tradeDate,Prices prices,int dayCount) + { + if(null==prices||prices.Count !(x.Date.Date.Equals(currentPrice.Date.Date))).ToList()); // make sure currentPrice is not in the list of prices + int count=prices.Count(x => x.Close>=currentPrice.Close); // count how many closing prices are above or equal to our closing price + return 0==count?true:false; // if no records then currentPrice is the max over the period so return true, otherwise return false; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/Indicators/MVPIndicator.cs b/MarketData/MarketDataLib/Generator/Indicators/MVPIndicator.cs new file mode 100755 index 0000000..2e99ed0 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Indicators/MVPIndicator.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MarketData.Numerical; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Cache; +using MarketData.Utils; + +namespace MarketData.Generator.Indicators +{ + // *********************************************************************************** + public class MVPIndicator + { + private static readonly double DAY_COUNT=15.00; + private static readonly double MOMENTUM_MIN_DAYS=12.00; + private MVPIndicator() // Marc Minervini "M"omentum, "V"olume, "P"rice + { + } + public static bool IsTrue(String symbol,DateTime pricingDate) + { + Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,(int)DAY_COUNT+1); + if(null==prices||DAY_COUNT+1>prices.Count) return false; + double daysUp=0; + double daysDown=0; + bool qualifiesOnPrice=false; + bool qualifiesOnVolume=false; + bool qualifiesOnMomentum=false; + +// Momentum Check + for(int index=prices.Count-2;index>=0;index--) + { + Price currentPrice=prices[index]; + Price prevPrice=prices[index+1]; + if(currentPrice.Close>prevPrice.Close)daysUp++; + else daysDown++; + } + if(0.00==daysDown) qualifiesOnMomentum=true; + else qualifiesOnMomentum=daysUp>=MOMENTUM_MIN_DAYS?true:false; + if(!qualifiesOnMomentum) return false; + +// Volume Check + double baseVolume=prices[prices.Count-1].Volume; + for(int index=prices.Count-2;index>=0 && !qualifiesOnVolume;index--) + { + Price currentPrice=prices[index]; + double percentChangeInVolume=((double)currentPrice.Volume-baseVolume)/baseVolume; + if(percentChangeInVolume>=.25)qualifiesOnVolume=true; + } + if(!qualifiesOnVolume)return false; + +// Price check + double cumulativeReturn=prices.GetCumulativeReturn(); + if(cumulativeReturn>=.20) qualifiesOnPrice=true; + if(!qualifiesOnPrice) return false; + + return true; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/Indicators/NarrowRangeIndicator.cs b/MarketData/MarketDataLib/Generator/Indicators/NarrowRangeIndicator.cs new file mode 100755 index 0000000..48f6d26 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Indicators/NarrowRangeIndicator.cs @@ -0,0 +1,47 @@ +using MarketData.MarketDataModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.Generator.Indicators +{ + public class NarrowRangeIndicator + { + private NarrowRangeIndicator() + { + } +// It is assumed that prices are in descending date order. (i.e.) The most recent price is in the lowest index position + public static bool IsNarrowRangeEntry(DateTime date,Prices prices,int dayCount) + { + if(!IsInsideDay(date,prices))return false; + if(!IsNarrowestRange(date,prices,dayCount))return false; + return true; + } + private static bool IsInsideDay(DateTime date,Prices prices) + { + int index=prices.FindIndex(x=>x.Date.Date.Equals(date)); + if(-1==index||index+1>=prices.Count)return false; + if(!(prices[index].High<=prices[index+1].High&&prices[index].Low>=prices[index+1].Low))return false; + return true; + } + private static bool IsNarrowestRange(DateTime date,Prices prices,int dayCount) + { + int index=prices.FindIndex(x => x.Date.Date.Equals(date)); + double range=GetRange(prices,index); + if(index+dayCount>=prices.Count-1)return false; + for(int dayIndex=index+1;dayIndex2021 + private OverExtendedIndicator() // Also, regarding VioaltionThresshold below.... the best results were obtained with MarginePercent=1.5 and ViolationThresshol=1.00 + { + } +// UseOverExtendedIndicator:true/false +// UseOverExtendedIndicatorDays:45 +// UseOverExtendedViolationThreshhold:2 breaks >=2 this number are considered to be violations +// This Indicator determines if a price is overextended by looking at the K band of the bollinger band over the past "dayCount" days. +// If closing price breaks the K band by more than 1.00% then we consider that to be an indication that the price is overextended. + public static bool? IsOverextended(String symbol,DateTime pricingDate,int dayCount=20) + { + bool isOverExtended=false; + Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,dayCount*4); + if(null==prices || 0==prices.Count)return null; + BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices,dayCount); + if(null==bollingerBands)return false; + bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList()); + BollingerBandElement item=bollingerBands.Where(x => x.Close>x.K && (((x.Close-x.K)/x.K)*100.00)>marginPercent).FirstOrDefault(); + if(null!=item)isOverExtended=true; + return isOverExtended; + } +// This method considers an overextended condition based upon an allowable number of upper band breaks + public static bool? IsOverextended(String symbol,DateTime pricingDate,int dayCount=20,int violationThreshhold=1) + { + bool isOverExtended=false; + Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,dayCount*4); + if(null==prices||0==prices.Count) return null; + BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices,dayCount); + if(null==bollingerBands) return false; + bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList()); + List items=bollingerBands.Where(x => x.Close>x.K&&(((x.Close-x.K)/x.K)*100.00)>marginPercent).ToList(); + if(null==items)return null; + if(items.Count>violationThreshhold)isOverExtended=true; + return isOverExtended; + } + // This method considers an overextended condition based upon an allowable number of upper band breaks and user supplied marginPercent + public static bool? IsOverextended(String symbol,DateTime pricingDate,int dayCount=20,int violationThreshhold=1,double paramMarginPercent=1.00) + { + bool isOverExtended=false; + Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,dayCount*4); + if(null==prices||0==prices.Count) return null; + BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices,dayCount); + if(null==bollingerBands) return false; + bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList()); + List items=bollingerBands.Where(x => x.Close>x.K&&(((x.Close-x.K)/x.K)*100.00)>paramMarginPercent).ToList(); + if(null==items) return null; + if(items.Count>violationThreshhold) isOverExtended=true; + return isOverExtended; + } + public static int? OverExtendedCount(String symbol,DateTime pricingDate,int dayCount=20) + { + Prices prices=GBPriceCache.GetInstance().GetPrices(symbol,pricingDate,dayCount*4); + if(null==prices||0==prices.Count) return null; + BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices,dayCount); + if(null==bollingerBands) return null; + bollingerBands=new BollingerBands(bollingerBands.Take(dayCount).ToList()); + List items=bollingerBands.Where(x => x.Close>x.K).ToList(); + if(null==items)return null; + return items.Count; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/Indicators/PriceTrendIndicator.cs b/MarketData/MarketDataLib/Generator/Indicators/PriceTrendIndicator.cs new file mode 100755 index 0000000..9a3943e --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Indicators/PriceTrendIndicator.cs @@ -0,0 +1,44 @@ +using MarketData.MarketDataModel; +using MarketData.Numerical; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.Generator.Indicators +{ + public class PriceTrendIndicatorResult + { + public PriceTrendIndicatorResult(bool isUptrend,double highPriceSlope=double.NaN,double lowPriceSlope=double.NaN) + { + this.IsUpTrend=isUptrend; + this.HighPriceSlope=highPriceSlope; + this.LowPriceSlope=lowPriceSlope; + } + public bool IsUpTrend{get;private set;} + public double HighPriceSlope{get;private set;} + public double LowPriceSlope{get; private set;} + } + public class PriceTrendIndicator + { + private PriceTrendIndicator() + { + } + public static PriceTrendIndicatorResult IsUptrend(Prices prices,int dayCount) + { + if(null==prices||prices.Count0.00?true:false; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/Interface/IPosition.cs b/MarketData/MarketDataLib/Generator/Interface/IPosition.cs new file mode 100755 index 0000000..bc2c16b --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Interface/IPosition.cs @@ -0,0 +1,13 @@ +using System; + +namespace MarketData.Generator.Interface +{ + public interface IPosition : IPurePosition + { + double TrailingStopLimit {get; set;} + + double InitialStopLimit {get; set;} + + double PositionRiskPercentDecimal {get; set;} + } +} diff --git a/MarketData/MarketDataLib/Generator/Interface/IPurePosition.cs b/MarketData/MarketDataLib/Generator/Interface/IPurePosition.cs new file mode 100755 index 0000000..1e449e4 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Interface/IPurePosition.cs @@ -0,0 +1,19 @@ +using System; + +namespace MarketData.Generator.Interface +{ + public interface IPurePosition + { + String Symbol {get; set;} + + DateTime PurchaseDate {get; set;} + + DateTime SellDate {get; set;} + + double CurrentPrice {get; set;} + + double PurchasePrice {get; set;} + + double Shares {get; set;} + } +} diff --git a/MarketData/MarketDataLib/Generator/MACDGenerator.cs b/MarketData/MarketDataLib/Generator/MACDGenerator.cs new file mode 100755 index 0000000..a1434ec --- /dev/null +++ b/MarketData/MarketDataLib/Generator/MACDGenerator.cs @@ -0,0 +1,131 @@ +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Threading; +using System.Reflection; +//using System.Runtime.Remoting.Messaging; +using System.Text; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; +using MarketData.Numerical; +using MarketData; + +namespace MarketData.Generator +{ + public class MACDGenerator + { + private MACDGenerator() + { + } + public static MACDFastSlowSignals GenerateMACD(String symbol,int dayCount=120) + { + try + { + DateGenerator dateGenerator = new DateGenerator(); + DateTime startDate = DateTime.Now; + if (null == symbol) return null; + symbol = symbol.ToUpper(); + Dictionary macdFastSlowSignalsByDate = new Dictionary(); + startDate = dateGenerator.GetPrevBusinessDay(DateTime.Now); ; + if (Utility.IsEpoch(startDate)) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No price dates for '" + symbol + "'"); + return null; + } + DateTime historicalDate = dateGenerator.GenerateHistoricalDate(startDate, dayCount); + Prices prices = PricingDA.GetPrices(symbol, startDate, historicalDate); + if (null == prices || 0 == prices.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No price dates for '" + symbol + "'"); + return null; + } + Price latestPrice = prices[0]; + String companyName = PricingDA.GetNameForSymbol(symbol); + MACDSetup macdSetupSlow = new MACDSetup(12, 26, 9); + MACDSetup macdSetupFast = new MACDSetup(8, 17, 9); + MACDSignals macdSignalsSlow = MACDGenerator.GenerateMACD(prices, macdSetupSlow); + MACDSignals macdSignalsFast = MACDGenerator.GenerateMACD(prices, macdSetupFast); + + Signals signalsSlow=SignalGenerator.GenerateSignals(macdSignalsSlow); + signalsSlow=signalsSlow.CondenseSignals(); + Signals signalsFast=SignalGenerator.GenerateSignals(macdSignalsFast); + signalsFast=signalsFast.CondenseSignals(); + + for (int index = 0; index < macdSignalsSlow.Count; index++) + { + MACDSignal macdSignal = macdSignalsSlow[index]; + if (!macdFastSlowSignalsByDate.ContainsKey(macdSignal.Date)) + { + MACDFastSlowSignal macdFastSlowSignal = new MACDFastSlowSignal(); + macdFastSlowSignal.Date = macdSignal.Date; + macdFastSlowSignal.SignalSlow = macdSignal.Signal; + macdFastSlowSignal.MACDSlow = macdSignal.MACD; + macdFastSlowSignalsByDate.Add(macdSignal.Date, macdFastSlowSignal); + } + } + for (int index = 0; index < macdSignalsFast.Count; index++) + { + MACDSignal macdSignal = macdSignalsFast[index]; + if (!macdFastSlowSignalsByDate.ContainsKey(macdSignal.Date)) continue; + MACDFastSlowSignal macdFastSlowSignal = macdFastSlowSignalsByDate[macdSignal.Date]; + macdFastSlowSignal.SignalFast = macdSignal.Signal; + macdFastSlowSignal.MACDFast = macdSignal.MACD; + } + MACDFastSlowSignals macdFastSlowSignals = new MACDFastSlowSignals(macdFastSlowSignalsByDate.Values); + macdFastSlowSignals.Symbol = symbol; + macdFastSlowSignals.FromDate = prices[prices.Count - 1].Date; + macdFastSlowSignals.ThruDate = prices[0].Date; + macdFastSlowSignals.Sort(new MACDFastSlowSignalsComparerAsc()); + macdFastSlowSignals.SlowCondensedSignals=signalsSlow; + macdFastSlowSignals.FastCondensedSignals=signalsFast; + + return macdFastSlowSignals; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + public static MACDSignals GenerateMACD(Prices prices, MACDSetup macdSetup) + { + try + { + MACDSignals macdSignals = new MACDSignals(); + for (int index = 0; index < prices.Count; index++) + { + MACDSignal macdSignal = new MACDSignal(); + float[] pricesArray = null; + Price price = prices[index]; + macdSignal.Symbol = price.Symbol; + macdSignal.Date = price.Date; + pricesArray = prices.GetPrices(index, macdSetup.Fast); // 12 + if (null == pricesArray) break; + macdSignal.Fast = Numerics.Mean(ref pricesArray); + pricesArray = prices.GetPrices(index, macdSetup.Slow); + if (null == pricesArray) break; + macdSignal.Slow = Numerics.Mean(ref pricesArray); // 26 + macdSignal.MACD = macdSignal.Fast - macdSignal.Slow; + macdSignals.Add(macdSignal); + } + for (int index = 0; index < macdSignals.Count; index++) + { + MACDSignal macdSignal = macdSignals[index]; + float[] macd = macdSignals.GetMACD(index, macdSetup.Signal); // 9 + if (null != macd) macdSignal.Signal = Numerics.Mean(ref macd); + macdSignal.Histogram = macdSignal.MACD - macdSignal.Signal; + } + return macdSignals; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + } +} diff --git a/MarketData/MarketDataLib/Generator/Model/Expectancy.cs b/MarketData/MarketDataLib/Generator/Model/Expectancy.cs new file mode 100755 index 0000000..7116869 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Model/Expectancy.cs @@ -0,0 +1,24 @@ +using MarketData.DataAccess; +using MarketData.MarketDataModel; +using MarketData.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.Generator.Model +{ + public class ModelStatistics + { + public long TotalTrades{get;set;} // The total number of trades + public long WinningTrades{get;set;} // The number of winning trades + public long LosingTrades{get;set;} // The number of losing trades + public double AverageWinningTradePercentGain{get;set;} // Average percent gain of the winning trades + public double AverageLosingTradePercentLoss{get;set;} // Average percent loss of the losing trades + public double WinningTradesPercent{get;set;} // Percentage of trades that are winners + public double LosingTradesPercent{get;set;} // Percentage of trades that are losers + public double Expectancy { get; set; } // The Expectancy. (WinningTradesPercent * AverageWinningTradePercent)/(percent losing trades * average loss) We are looking for a number greater than zero. + } +} diff --git a/MarketData/MarketDataLib/Generator/Model/StopLimits.cs b/MarketData/MarketDataLib/Generator/Model/StopLimits.cs new file mode 100755 index 0000000..336d9f4 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/Model/StopLimits.cs @@ -0,0 +1,128 @@ +using MarketData.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +/// +/// This StopLimit class is used by models and the UI +/// + +namespace MarketData.Generator.Model +{ + public class StopLimits:List + { + public StopLimits() + { + } + public StopLimits(List stopLimits) + { + foreach(StopLimit stopLimit in stopLimits)Add(stopLimit); + } + public NVPCollections ToNVPCollections() + { + NVPCollections nvpCollections=new NVPCollections(); + foreach(StopLimit stopLimit in this) + { + nvpCollections.Add(stopLimit.ToNVPCollection()); + } + return nvpCollections; + } + public static StopLimits FromNVPCollections(NVPCollections nvpCollections) + { + StopLimits stopLimits=new StopLimits(); + foreach(NVPCollection nvpCollection in nvpCollections) + { + stopLimits.Add(StopLimit.FromNVPCollection(nvpCollection)); + } + return stopLimits; + } + public void AddFromNVPCollection(NVPCollection nvpCollection) + { + Add(StopLimit.FromNVPCollection(nvpCollection)); + } + } + public class StopLimit + { + public StopLimit() + { + } + public StopLimit(StopLimit stopLimit) + { + this.Symbol=stopLimit.Symbol; + this.AnalysisDate=stopLimit.AnalysisDate; + this.PreviousStop=stopLimit.PreviousStop; + this.NewStop=stopLimit.NewStop; + this.CurrentPriceLow=stopLimit.CurrentPriceLow; + this.CurrentPriceClose=stopLimit.CurrentPriceClose; + this.PriceTrendIndicatorSlope=stopLimit.PriceTrendIndicatorSlope; + this.StopLimitId=stopLimit.StopLimitId; + } + public StopLimit(String symbol,DateTime analysisDate,double previousStop,double newStop,double currentPriceLow,double currentPriceClose,double priceTrendIndicatorSlope) + { + this.Symbol=symbol; + this.AnalysisDate=analysisDate; + this.PreviousStop=previousStop; + this.NewStop=newStop; + this.CurrentPriceLow=currentPriceLow; + this.CurrentPriceClose=currentPriceClose; + this.PriceTrendIndicatorSlope=priceTrendIndicatorSlope; + } + public String Symbol { get; set; } + public DateTime AnalysisDate{get;set;} + public double PreviousStop{get;set;} + public double NewStop{get;set;} + public double CurrentPriceLow{get;set;} + public double CurrentPriceClose{get;set;} + public double PriceTrendIndicatorSlope{get;set;} + public String StopLimitId {get;set;} + public static String Header() + { + StringBuilder sb=new StringBuilder(); + sb.Append("Id,Symbol,AnalysisDate,PreviousStop,NewStop,CurrentPriceLow,CurrentPriceClose,PriceTrendIndicatorSlope"); + return sb.ToString(); + } + public override String ToString() + { + StringBuilder sb=new StringBuilder(); + sb.Append(null==StopLimitId?"":StopLimitId).Append(","); + sb.Append(Symbol).Append(","); + sb.Append(AnalysisDate.ToShortDateString()).Append(","); + sb.Append(Utility.FormatCurrency(PreviousStop)).Append(","); + sb.Append(Utility.FormatCurrency(NewStop)).Append(","); + sb.Append(Utility.FormatCurrency(CurrentPriceLow)).Append(","); + sb.Append(Utility.FormatCurrency(CurrentPriceClose)).Append(","); + sb.Append(Utility.FormatNumber(PriceTrendIndicatorSlope,4,false)); + return sb.ToString(); + } + public virtual NVPCollection ToNVPCollection() + { + NVPCollection nvpCollection=new NVPCollection(); + nvpCollection.Add(new NVP("Symbol",Symbol.ToString())); + nvpCollection.Add(new NVP("AnalysisDate",AnalysisDate.ToString())); + nvpCollection.Add(new NVP("PreviousStop",PreviousStop.ToString())); + nvpCollection.Add(new NVP("NewStop",NewStop.ToString())); + nvpCollection.Add(new NVP("CurrentPriceLow",CurrentPriceLow.ToString())); + nvpCollection.Add(new NVP("CurrentPriceClose",CurrentPriceClose.ToString())); + nvpCollection.Add(new NVP("PriceTrendIndicatorSlope",PriceTrendIndicatorSlope.ToString())); + nvpCollection.Add(new NVP("StopLimitId",StopLimitId==null?"":StopLimitId)); + return nvpCollection; + } + public static StopLimit FromNVPCollection(NVPCollection nvpCollection) + { + StopLimit stopLimit=new StopLimit(); + + NVPDictionary nvpDictionary=nvpCollection.ToDictionary(); + stopLimit.Symbol=nvpDictionary["Symbol"].Get(); + stopLimit.AnalysisDate=nvpDictionary["AnalysisDate"].Get(); + stopLimit.PreviousStop=nvpDictionary["PreviousStop"].Get(); + stopLimit.NewStop=nvpDictionary["NewStop"].Get(); + stopLimit.CurrentPriceLow=nvpDictionary["CurrentPriceLow"].Get(); + stopLimit.CurrentPriceClose=nvpDictionary["CurrentPriceClose"].Get(); + stopLimit.PriceTrendIndicatorSlope=nvpDictionary["PriceTrendIndicatorSlope"].Get(); + if(nvpDictionary.ContainsKey("StopLimitId"))stopLimit.StopLimitId=nvpDictionary["StopLimitId"].Get(); + return stopLimit; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/ModelGenerators/EdgeRatioGenerator.cs b/MarketData/MarketDataLib/Generator/ModelGenerators/EdgeRatioGenerator.cs new file mode 100755 index 0000000..07141eb --- /dev/null +++ b/MarketData/MarketDataLib/Generator/ModelGenerators/EdgeRatioGenerator.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using MarketData.MarketDataModel; +using MarketData.Utils; +using MarketData.DataAccess; +using MarketData.Numerical; +using MarketData.Cache; + +namespace MarketData.Generator.ModelGenerators +{ + public class EdgeRatioGenerator + { + private EdgeRatioGenerator() + { + } + public static EdgeRatioResult CalculateEdgeRatio(String symbol,DateTime purchaseDate,double purchasePrice,DateTime asOf) + { + EdgeRatioResult edgeRatioResult=new EdgeRatioResult(); + DateGenerator dateGenerator=new DateGenerator(); + DateTime lastBusinesDate=dateGenerator.GetPrevBusinessDay(asOf); + Dictionary trueRangeResults=new Dictionary(); + double[] mae=null; + double[] mfe=null; + double[] atr=null; + + try + { + List seriesDates=dateGenerator.GenerateHistoricalDates(purchaseDate,asOf); + mae=new double[seriesDates.Count]; + mfe=new double[seriesDates.Count]; + atr=new double[seriesDates.Count]; + double sumMAEPlusATR=0.00; + double sumMFEPlusATR=0.00; + double averageMAE=0.00; + double averageMFE=0.00; + + asOf=dateGenerator.GetPrevBusinessDay(asOf); + for(int index=0;index {4}",symbol,purchaseDate.ToShortDateString(),Utility.FormatCurrency(purchasePrice),purchaseDate.ToShortDateString(),asOf.ToShortDateString()); + return edgeRatioResult; + } + catch(Exception exception) + { + edgeRatioResult.Message=exception.ToString(); + return edgeRatioResult; + } + } + } + + public class EdgeRatioResult + { + public EdgeRatioResult() + { + Success=false; + EdgeRatio=double.NaN; + Message=null; + } + public double EdgeRatio{get;set;} + public bool Success{get;set;} + public String Message{get;set;} + } +} diff --git a/MarketData/MarketDataLib/Generator/ModelGenerators/TrueRangeGenerator.cs b/MarketData/MarketDataLib/Generator/ModelGenerators/TrueRangeGenerator.cs new file mode 100755 index 0000000..9de30f5 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/ModelGenerators/TrueRangeGenerator.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using MarketData.MarketDataModel; +using MarketData.Utils; +using MarketData.DataAccess; +using MarketData.Numerical; + +namespace MarketData.Generator.ModelGenerators +{ + public class TrueRangeGenerator + { + private TrueRangeGenerator() + { + } + // Prices : Where most recent price is at lowest index + public static TrueRangeResult GenerateAverageTrueRange(String symbol, DateTime startDate, int atrDays = 14) + { + Prices prices = PricingDA.GetPrices(symbol, startDate, atrDays + 1); + if (null == prices || prices.Count < 2 || 0 == prices[0].Close) return null; + double[] values = new double[prices.Count - 1]; + for (int index = 0; index < prices.Count - 1; index++) + { + Price price = prices[index]; + Price prevPrice = prices[index + 1]; + double levelA = price.High - price.Low; + double levelB = Math.Abs(price.High - prevPrice.Close); + double levelC = Math.Abs(price.Low - prevPrice.Close); + values[index] = Math.Max(levelA, levelB); + values[index] = Math.Max(values[index], levelC); + } + double averageTrueRange = Numerics.Mean(ref values); + return new TrueRangeResult(averageTrueRange, (averageTrueRange / prices[0].Close) * 2.00); + } + } + public class TrueRangeResult + { + public TrueRangeResult() + { + } + public TrueRangeResult(double averageTrueRange,double shortTermVolatility) + { + AverageTrueRange=averageTrueRange; + ShortTermVolatility=shortTermVolatility; + } + public double AverageTrueRange{get;set;} + public double ShortTermVolatility{get;set;} + } +} diff --git a/MarketData/MarketDataLib/Generator/ModelGenerators/VolatilityGenerator.cs b/MarketData/MarketDataLib/Generator/ModelGenerators/VolatilityGenerator.cs new file mode 100755 index 0000000..2460d9e --- /dev/null +++ b/MarketData/MarketDataLib/Generator/ModelGenerators/VolatilityGenerator.cs @@ -0,0 +1,50 @@ +using MarketData.Generator.MovingAverage; +using MarketData.MarketDataModel; +using MarketData.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.Generator.ModelGenerators +{ +// Calculates Volatility as 3x Average True Range + public class VolatilityGenerator + { + public static double CalculateVolatility(String symbol,DateTime date,int movingAverageDays=10) + { + return CalculateVolatility(symbol,date,movingAverageDays,3.00); + } + public static double CalculateVolatility(String symbol,DateTime date,int movingAverageDays,double atrMultiplier) + { + double volatility=double.NaN; + DateGenerator dateGenerator=new DateGenerator(); + Dictionary trueRangeCollectionByDate=new Dictionary(); + List historicalDates=dateGenerator.GenerateHistoricalDates(date,(movingAverageDays+1)*2); // most recent date in lowest index, we need to generate (items+1) + for(int dateIndex=0;dateIndextrueRangeCollectionByDate.Count) return volatility; + historicalDates=new List(trueRangeCollectionByDate.Keys.OrderByDescending(x=>x.Date)); + Prices prices=new Prices(); + foreach(DateTime historicalDate in historicalDates) + { + Price price=new Price(); + price.Symbol=symbol; + price.Date=historicalDate; + price.Close=trueRangeCollectionByDate[historicalDate]; + prices.Add(price); + } + DMAPrices emaPrices=MovingAverageGenerator.GenerateExponentialMovingAverage(prices,movingAverageDays); + if(null==emaPrices||0==emaPrices.Count)return volatility; + volatility=emaPrices[0].AVGPrice*atrMultiplier; + return volatility; + } + + } +} diff --git a/MarketData/MarketDataLib/Generator/MovingAverage/ExponentialMovingAverageCrossover.cs b/MarketData/MarketDataLib/Generator/MovingAverage/ExponentialMovingAverageCrossover.cs new file mode 100755 index 0000000..09935a0 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/MovingAverage/ExponentialMovingAverageCrossover.cs @@ -0,0 +1,212 @@ +using MarketData.Cache; +using MarketData.MarketDataModel; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MarketData.Generator.MovingAverage +{ + public static class ExponentialMovingAverageCrossover + { + public static MovingAverageCrossovers GetMovingAverageCrossovers(String symbol, DateTime analysisDate,double threshholdPercentDecimal=.05, int fastCrossOverDays=9, int slowCrossoverDays=41) + { + Prices prices = GBPriceCache.GetInstance().GetPrices(symbol, analysisDate, slowCrossoverDays * 6); + if(prices == null || 0==prices.Count)return new MovingAverageCrossovers(); + + return GetMovingAverageCrossovers(prices, threshholdPercentDecimal, fastCrossOverDays, slowCrossoverDays); + } + + /// + /// GetMovingAverageCrossovers + /// Prices will be in descending order with the most recent price at index[0] and the least recent price at index[count-1] + /// + /// + /// The fast crossover. Tom Basso uses 9 + /// The slow crosser. Tom Basso uses 41 + /// The threshhold percent. 5% would be .05 + /// + public static MovingAverageCrossovers GetMovingAverageCrossovers(Prices prices, double threshholdPercentDecimal=.05, int fastCrossOverDays=9, int slowCrossoverDays=41) + { + MovingAverageCrossovers movingAverageCrossovers = new MovingAverageCrossovers(); + + if(prices == null || 0==prices.Count || prices.Count<=slowCrossoverDays)return movingAverageCrossovers; + if(fastCrossOverDays >= slowCrossoverDays)return movingAverageCrossovers; + + DMAPrices fastDMAPrices = MovingAverageGenerator.GenerateExponentialMovingAverage(prices, fastCrossOverDays); + DMAPrices slowDMAPrices = MovingAverageGenerator.GenerateExponentialMovingAverage(prices, slowCrossoverDays); + + if(null == fastDMAPrices || 0 == fastDMAPrices.Count)return movingAverageCrossovers; + if(null == slowDMAPrices || 0 == slowDMAPrices.Count)return movingAverageCrossovers; + + FindCrossovers(fastDMAPrices, slowDMAPrices, movingAverageCrossovers, threshholdPercentDecimal); + +// put the most recent item in the lowest index + movingAverageCrossovers = new MovingAverageCrossovers((movingAverageCrossovers as List).Where(x => x.IsChangeInTrend==true).OrderByDescending(x => x.EventDate).ToList()); + return movingAverageCrossovers; + } + + /// + /// If the sorter term (faster) crossed the longer term (slower) moving average then a direction change is noted. + /// If the change carried more than 5% in that direction then consider it a successful trend + /// + /// + /// + /// + private static void FindCrossovers(DMAPrices fastDMAPrices, DMAPrices slowDMAPrices,MovingAverageCrossovers movingAverageCrossovers, double threshholdPercentDecimal) + { + double trendChangePercentThreshhold = threshholdPercentDecimal*100.00; // if a change in direction carries more than 5% then consider is a successful trend + movingAverageCrossovers.Clear(); + DateTime startDate = slowDMAPrices[slowDMAPrices.Count-1].Date; + MovingAverageCrossover movingAverageCrossover = default; + + DMAPricesByDate fastDMAPricesByDate = fastDMAPrices.GetDMAPricesByDate(); + DMAPricesByDate slowDMAPricesByDate = slowDMAPrices.GetDMAPricesByDate(); + + List availableDates = new List(slowDMAPricesByDate.Keys); + + availableDates.Sort((a, b) => DateTime.Compare(a,b)); // earliest date should be in the lowest index, most recent date should be in the highest 2024[0], 2025[1], 2026[2] for example + + int currentDirection=0; // 1:fast DMA is above the slow, -1:fast DMA is below the slow, 0:slow DMA == fastDMA + + DMAPrice prevSlowDMAPrice = default; + DMAPrice prevFastDMAPrice = default; + + for(int index=0;index slowDMAPrice.AVGPrice) + { + movingAverageCrossover = new MovingAverageCrossover(); + movingAverageCrossover.EventDate = analysisDate; + movingAverageCrossover.Symbol = slowDMAPrice.Symbol; + movingAverageCrossover.CrossOverDirection = MovingAverageCrossover.CrossoverDirectionEnum.UpStart; + movingAverageCrossover.IsChangeInTrend = false; + movingAverageCrossover.SlowDMAPrice = slowDMAPrice; + movingAverageCrossover.FastDMAPrice = fastDMAPrice; + movingAverageCrossover.ChangePercent=0.00; + movingAverageCrossovers.Add(movingAverageCrossover); + currentDirection = 1; + } + else if(fastDMAPrice.AVGPrice < slowDMAPrice.AVGPrice) + { + movingAverageCrossover = new MovingAverageCrossover(); + movingAverageCrossover.EventDate = analysisDate; + movingAverageCrossover.Symbol = slowDMAPrice.Symbol; + movingAverageCrossover.CrossOverDirection = MovingAverageCrossover.CrossoverDirectionEnum.DownStart; + movingAverageCrossover.IsChangeInTrend = false; + movingAverageCrossover.SlowDMAPrice = slowDMAPrice; + movingAverageCrossover.FastDMAPrice = fastDMAPrice; + movingAverageCrossover.ChangePercent=0.00; + movingAverageCrossovers.Add(movingAverageCrossover); + currentDirection = -1; + } + else + { + movingAverageCrossover = new MovingAverageCrossover(); + movingAverageCrossover.EventDate = analysisDate; + movingAverageCrossover.Symbol = slowDMAPrice.Symbol; + movingAverageCrossover.CrossOverDirection = MovingAverageCrossover.CrossoverDirectionEnum.NeutralStart; + movingAverageCrossover.IsChangeInTrend = false; + movingAverageCrossover.SlowDMAPrice = slowDMAPrice; + movingAverageCrossover.FastDMAPrice = fastDMAPrice; + movingAverageCrossover.ChangePercent=0.00; + movingAverageCrossovers.Add(movingAverageCrossover); + currentDirection = 0; + } + prevSlowDMAPrice = slowDMAPrice; + prevFastDMAPrice = fastDMAPrice; + } + else + { + if(fastDMAPrice.AVGPrice > slowDMAPrice.AVGPrice) + { + if(1 == currentDirection) // The fast is above the slow as it was previously + { + if(movingAverageCrossovers.Count>0) // check the last change record for a threshhold break + { + MovingAverageCrossover movingAverageCrossOver = movingAverageCrossovers[movingAverageCrossovers.Count-1]; + double changePercent = ((fastDMAPrice.AVGPrice - movingAverageCrossOver.FastDMAPrice.AVGPrice)/movingAverageCrossOver.FastDMAPrice.AVGPrice)*100.00; + if(changePercent > 0.00 && changePercent > trendChangePercentThreshhold) // if the threshhold is exceeded then create a new record and mark it as a trend change + { + movingAverageCrossover = new MovingAverageCrossover(); + movingAverageCrossover.EventDate = analysisDate; + movingAverageCrossover.Symbol = slowDMAPrice.Symbol; + movingAverageCrossover.CrossOverDirection = MovingAverageCrossover.CrossoverDirectionEnum.UpCross; + movingAverageCrossover.IsChangeInTrend = true; + movingAverageCrossover.SlowDMAPrice = slowDMAPrice; + movingAverageCrossover.FastDMAPrice = fastDMAPrice; + movingAverageCrossover.ChangePercent=changePercent; + movingAverageCrossovers.Add(movingAverageCrossover); + } + } + } + else if(-1 == currentDirection || 0 == currentDirection) // The fast is above the slow and it was below the slow previously + { + currentDirection = 1; // switch directions + movingAverageCrossover = new MovingAverageCrossover(); + movingAverageCrossover.EventDate = analysisDate; + movingAverageCrossover.Symbol = slowDMAPrice.Symbol; + movingAverageCrossover.CrossOverDirection = MovingAverageCrossover.CrossoverDirectionEnum.UpCross; + movingAverageCrossover.SlowDMAPrice = slowDMAPrice; + movingAverageCrossover.FastDMAPrice = fastDMAPrice; + double changePercent = Math.Abs(((fastDMAPrice.AVGPrice - slowDMAPrice.AVGPrice)/slowDMAPrice.AVGPrice)*100.00); + movingAverageCrossover.ChangePercent=changePercent; + if(changePercent>trendChangePercentThreshhold)movingAverageCrossover.IsChangeInTrend = true; + else movingAverageCrossover.IsChangeInTrend = false; + movingAverageCrossovers.Add(movingAverageCrossover); + } + } + else if(fastDMAPrice.AVGPrice < slowDMAPrice.AVGPrice) + { + if(-1 == currentDirection) // The fast is below the slow as it was previously + { + if(movingAverageCrossovers.Count>0) // check the last change record for a threshhold break + { + movingAverageCrossover = movingAverageCrossovers[movingAverageCrossovers.Count-1]; + double changePercent = Math.Abs(((fastDMAPrice.AVGPrice - movingAverageCrossover.FastDMAPrice.AVGPrice)/movingAverageCrossover.FastDMAPrice.AVGPrice)*100.00); + if(changePercent<0.00 && Math.Abs(changePercent)>trendChangePercentThreshhold) // if the threshhold is exceeded then create a new record and mark it as a trend change + { + movingAverageCrossover = new MovingAverageCrossover(); + movingAverageCrossover.EventDate = analysisDate; + movingAverageCrossover.Symbol = slowDMAPrice.Symbol; + movingAverageCrossover.CrossOverDirection = MovingAverageCrossover.CrossoverDirectionEnum.UpCross; + movingAverageCrossover.IsChangeInTrend = true; + movingAverageCrossover.SlowDMAPrice = slowDMAPrice; + movingAverageCrossover.FastDMAPrice = fastDMAPrice; + movingAverageCrossover.ChangePercent = changePercent; + movingAverageCrossovers.Add(movingAverageCrossover); + } + } + } + else if(1 == currentDirection || 0 == currentDirection) // The fast is below the slow but it was above the slow previously so we've crossed + { + currentDirection = -1; // switch directions + movingAverageCrossover = new MovingAverageCrossover(); + movingAverageCrossover.EventDate = analysisDate; + movingAverageCrossover.Symbol = slowDMAPrice.Symbol; + movingAverageCrossover.CrossOverDirection = MovingAverageCrossover.CrossoverDirectionEnum.DownCross; + movingAverageCrossover.SlowDMAPrice = slowDMAPrice; + movingAverageCrossover.FastDMAPrice = fastDMAPrice; + double changePercent = Math.Abs(((fastDMAPrice.AVGPrice - slowDMAPrice.AVGPrice)/slowDMAPrice.AVGPrice)*100.00); + movingAverageCrossover.ChangePercent=changePercent; + if(changePercent>trendChangePercentThreshhold)movingAverageCrossover.IsChangeInTrend = true; + else movingAverageCrossover.IsChangeInTrend = false; + movingAverageCrossovers.Add(movingAverageCrossover); + } + } + else // The fast and the slow are equal. There's nothing to do here + { + + } + prevSlowDMAPrice = slowDMAPrice; + prevFastDMAPrice = fastDMAPrice; + } + } + } + } +} diff --git a/MarketData/MarketDataLib/Generator/MovingAverage/MovingAverageCrossover.cs b/MarketData/MarketDataLib/Generator/MovingAverage/MovingAverageCrossover.cs new file mode 100755 index 0000000..e79ec63 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/MovingAverage/MovingAverageCrossover.cs @@ -0,0 +1,47 @@ +using MarketData.MarketDataModel; +using MarketData.Utils; +using System; +using System.Collections.Generic; +using System.Text; + +namespace MarketData.Generator.MovingAverage +{ + public class MovingAverageCrossovers : List + { + public MovingAverageCrossovers() + { + } + + public MovingAverageCrossovers(List movingAverageCrossovers) + { + foreach(MovingAverageCrossover movingAverageCrossover in movingAverageCrossovers) + { + Add(movingAverageCrossover); + } + } + } + + public class MovingAverageCrossover + { + public enum CrossoverDirectionEnum{UpCross, DownCross, UpStart, DownStart, NeutralStart}; + public String Symbol { get; set; } + public DateTime EventDate { get; set; } + public CrossoverDirectionEnum CrossOverDirection {get; set;} + public bool IsChangeInTrend { get; set; } + public double ChangePercent { get; set; } + public DMAPrice SlowDMAPrice { get; set; } // the slow DMA price associated with this crossover + public DMAPrice FastDMAPrice { get; set; } // the fast DMA price associated with this crossover + public double CurrentPrice {get{return SlowDMAPrice.CurrentPrice;}} // it doesn't matter if sourced from slow or fast since they both refer to the same underlying price + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("Symbol:").Append(Symbol); + sb.Append(" Date:").Append(EventDate.ToShortDateString()); + sb.Append(" Direction:").Append(CrossOverDirection.ToString()); + sb.Append(" IsChangeInTrend:").Append(IsChangeInTrend.ToString()); + sb.Append(" ChangePercent:").Append(Utility.FormatNumber(ChangePercent,2)); + sb.Append(" ClosePrice:").Append(Utility.FormatCurrency(CurrentPrice)); + return sb.ToString(); + } + } +} diff --git a/MarketData/MarketDataLib/Generator/MovingAverage/MovingAverageGenerator.cs b/MarketData/MarketDataLib/Generator/MovingAverage/MovingAverageGenerator.cs new file mode 100755 index 0000000..c236e8c --- /dev/null +++ b/MarketData/MarketDataLib/Generator/MovingAverage/MovingAverageGenerator.cs @@ -0,0 +1,255 @@ +using System; +using System.Collections.Generic; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Numerical; +using MarketData.Utils; + +namespace MarketData.Generator.MovingAverage +{ + public class MovingAverageGenerator + { + public static readonly int DayCount200=200; + public static readonly int DayCount100=100; + public static readonly int DayCount55=55; + public static readonly int DayCount50=50; + public static readonly int DayCount21=21; + public static readonly int DayCount5=5; + private MovingAverageGenerator() + { + } + public static MovingAverages GenerateMovingAverages(String symbol,int dayCount=180) + { + try + { + Dictionary ma200ByDate = new Dictionary(); + Dictionary ma100ByDate = new Dictionary(); + Dictionary ma55ByDate = new Dictionary(); + Dictionary ma21ByDate = new Dictionary(); + Dictionary ma5ByDate = new Dictionary(); + if (null == symbol) return null; + String companyName = PricingDA.GetNameForSymbol(symbol); + DateGenerator dateGenerator = new DateGenerator(); + DateTime startDate = dateGenerator.GetPrevBusinessDay(DateTime.Now); + Prices prices = PricingDA.GetPrices(symbol, startDate, dayCount); + if (null == prices || 0 == prices.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No prices for symbol '" + symbol + "'"); + return null; + } + Price latestPrice = prices[0]; + DMAPrices ma200= GenerateMovingAverage(prices, DayCount200); + DMAPrices ma100 = GenerateMovingAverage(prices, DayCount100); + DMAPrices ma55 = GenerateMovingAverage(prices, DayCount55); + DMAPrices ma21 = GenerateMovingAverage(prices, DayCount21); + DMAPrices ma5 = GenerateMovingAverage(prices, DayCount5); + + for (int index = 0; index < ma200.Count; index++) ma200ByDate.Add(ma200[index].Date,ma200[index]); + for (int index = 0; index < ma100.Count; index++) ma100ByDate.Add(ma100[index].Date, ma100[index]); + for (int index = 0; index < ma55.Count; index++) ma55ByDate.Add(ma55[index].Date, ma55[index]); + for (int index = 0; index < ma21.Count; index++) ma21ByDate.Add(ma21[index].Date, ma21[index]); + for (int index = 0; index < ma5.Count; index++) ma5ByDate.Add(ma5[index].Date, ma5[index]); + MovingAverages movingAverages = new MovingAverages(); + movingAverages.ThruDate = prices[0].Date; + movingAverages.FromDate = prices[prices.Count - 1].Date; + for (int index = 0; index < prices.Count; index++) + { + Price price = prices[index]; + + DMAPrice ma200Price = null; + DMAPrice ma100Price = null; + DMAPrice ma55Price = null; + DMAPrice ma21Price = null; + DMAPrice ma5Price = null; + + if (ma55ByDate.ContainsKey(price.Date)) ma55Price=ma55ByDate[price.Date]; + if (ma21ByDate.ContainsKey(price.Date)) ma21Price = ma21ByDate[price.Date]; + if (ma5ByDate.ContainsKey(price.Date)) ma5Price = ma5ByDate[price.Date]; + if(ma200ByDate.ContainsKey(price.Date))ma200Price = ma200ByDate[price.Date]; + if(ma100ByDate.ContainsKey(price.Date)) ma100Price = ma100ByDate[price.Date]; + + MovingAverageElement movingAverageElement = new MovingAverageElement(); + movingAverageElement.Symbol = price.Symbol; + movingAverageElement.Date = price.Date; + movingAverageElement.Close = price.Close; + movingAverageElement.High = price.High; + movingAverageElement.Low = price.Low; + movingAverageElement.MA200 = null==ma200Price?double.NaN:ma200Price.AVGPrice; + movingAverageElement.MA100 = null == ma100Price ? double.NaN : ma100Price.AVGPrice; + movingAverageElement.MA55 = null==ma55Price?double.NaN:ma55Price.AVGPrice; + movingAverageElement.MA21 = null==ma21Price?double.NaN:ma21Price.AVGPrice; + movingAverageElement.MA5 = null==ma5Price?double.NaN:ma5Price.AVGPrice; + movingAverages.Add(movingAverageElement); + } + return movingAverages; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + public static DMAValues GenerateMovingAverage(DMAValues values,int dayCount) + { + try + { + DMAValues dmaValues = new DMAValues(); + for (int index = 0; index < values.Count; index++) + { + DMAValue value = values[index]; + DMAValue dmaValue = new DMAValue(); + dmaValue.Date = value.Date; + float[] pricesArray = values.GetValues(index, dayCount); + if (null == pricesArray) break; + dmaValue.MAValue = Numerics.Mean(ref pricesArray); + dmaValue.Value = value.Value; + if (double.IsNaN(dmaValue.MAValue)) continue; + dmaValues.Add(dmaValue); + } + return dmaValues; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + + /// + /// The EMA coverage shoudld be the same as the simple moving average. If you have 10 elements in the SMA then you should have 10 elements in the EMA + /// The EMA smooths the line by applying a smoothing (Beta) where Beta=1/(dayCount+1). Foe example if you are wanting to calculate the + /// 20 day exponential moving average over a series then Beta=2/(20+1)=.095 + /// The formula: EMA=prevEMA.AVGPrice+beta*(smaPrice.CurrentPrice - prevEMA.AVGPrice) + /// Tom Basso uses a 9 day(Fast) and 41 day(Slow) exponential moving average crossover to determine change in trend direction. + /// + /// + /// + /// + public static DMAPrices GenerateExponentialMovingAverage(Prices prices,int dayCount) + { + try + { + if(null==prices||prices.CountGenerates a dayCount moving average given prices. + public static DMAPrices GenerateMovingAverage(Prices prices, int dayCount) + { + try + { + DMAPrices dmaPrices = new DMAPrices(); + for (int index = 0; index < prices.Count; index++) + { + Price price = prices[index]; + DMAPrice dmaPrice = new DMAPrice(); + dmaPrice.Symbol = price.Symbol; + dmaPrice.Date = price.Date; + float[] pricesArray = prices.GetPrices(index, dayCount); + if (null == pricesArray) break; + dmaPrice.AVGPrice = Numerics.Mean(ref pricesArray); + if (double.IsNaN(dmaPrice.AVGPrice)) continue; + dmaPrice.CurrentPrice = price.Close; + dmaPrices.Add(dmaPrice); + } + return dmaPrices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + public static DMAPrices GenerateMovingMinsOnLow(Prices prices, int dayCount) + { + try + { + DMAPrices dmaPrices = new DMAPrices(); + + for (int index = 0; index < prices.Count; index++) + { + Price price = prices[index]; + DMAPrice dmaPrice = new DMAPrice(); + dmaPrice.Symbol = price.Symbol; + dmaPrice.Date = price.Date; + float[] pricesArray = prices.GetPricesLow(index, dayCount); + if (null == pricesArray) break; + dmaPrice.MinPrice = Numerics.Min(ref pricesArray); + if (double.IsNaN(dmaPrice.MinPrice)) continue; + dmaPrice.CurrentPrice = price.Low; + dmaPrices.Add(dmaPrice); + } + return dmaPrices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + } + public static DMAPrices GenerateMovingMaxOnHigh(Prices prices, int dayCount) + { + try + { + DMAPrices dmaPrices = new DMAPrices(); + + for (int index = 0; index < prices.Count; index++) + { + Price price = prices[index]; + DMAPrice dmaPrice = new DMAPrice(); + dmaPrice.Symbol = price.Symbol; + dmaPrice.Date = price.Date; + float[] pricesArray = prices.GetPricesHigh(index, dayCount); + if (null == pricesArray) break; + dmaPrice.MaxPrice = Numerics.Max(ref pricesArray); + if (double.IsNaN(dmaPrice.MaxPrice)) continue; + dmaPrice.CurrentPrice = price.High; + dmaPrices.Add(dmaPrice); + } + return dmaPrices; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + } + } +} diff --git a/MarketData/MarketDataLib/Generator/ParityGenerator.cs b/MarketData/MarketDataLib/Generator/ParityGenerator.cs new file mode 100755 index 0000000..86c2ca4 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/ParityGenerator.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; +using MarketData.MarketDataModel; +using MarketData.Utils; + + +namespace MarketData.Generator +{ + public class ParityGenerator + { + private enum Direction { Negative, Positive, None }; + private ParityGenerator() + { + } + public static ParityElement GenerateBreakEven(String symbol) + { + try + { + ParityElement parityElement=new ParityElement(); + Price zeroPrice=null; + PortfolioTrades portfolioTrades = PortfolioDA.GetTradesSymbol(symbol); + if(null==portfolioTrades||0==portfolioTrades.Count)return null; + PortfolioTrades openTrades=portfolioTrades.GetOpenTrades(); + DateTime pricingDate = PricingDA.GetLatestDate(symbol); + Price latestPrice = PricingDA.GetPrice(symbol, pricingDate); + GainLossGenerator gainLossGenerator=new GainLossGenerator(); + zeroPrice=ParityGenerator.GenerateGainLossValue(openTrades,latestPrice); + parityElement.ParityOffsetPrice=zeroPrice.Close; + parityElement.ParityOffsetPercent=((latestPrice.Close-zeroPrice.Close)/zeroPrice.Close); + parityElement.Symbol=symbol; + parityElement.PricingDate=pricingDate; + return parityElement; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",exception)); + return null; + } + } +// generate gain/loss value for portfolio of like symbols +// This funtion will return the dollar price that the stock must either rise to (when G/L is negative) or fall to (when the G/L is positive) +// in order to produce a zero return (i.e.) a wash. + public static Price GenerateGainLossValue(PortfolioTrades portfolioTrades,Price givenPrice) + { + double? lowerClamp=null; + double? upperClamp=null; + double? gainLoss=null; + double? prevGuess=null; + Direction direction=Direction.None; + int iterations=0; + + if(null==portfolioTrades||0==portfolioTrades.Count) return null; + Price price=givenPrice.Clone(); + gainLoss=portfolioTrades.GetGainLoss(price); + if(gainLoss<0) direction=Direction.Negative; + else direction=Direction.Positive; + while(true) + { + if(IsZero(gainLoss)) break; + if(null==lowerClamp&&null==upperClamp&&gainLoss<0&&direction.Equals(Direction.Negative)) + { + prevGuess=price.Close; + price.Close=price.Close+(price.Close/2.00); + iterations++; + } + else if(null==lowerClamp&&null==upperClamp&&gainLoss>=0&&direction.Equals(Direction.Positive)) + { + prevGuess=price.Close; + price.Close=price.Close-(price.Close/2.00); + iterations++; + } + else + { + if(gainLoss<0) + { + lowerClamp=price.Close; + if(null==upperClamp) upperClamp=prevGuess; + price.Close=(lowerClamp.Value+upperClamp.Value)/2.00; + prevGuess=price.Close; + iterations++; + } + else + { + upperClamp=price.Close; + if(null==lowerClamp) lowerClamp=prevGuess; + price.Close=(upperClamp.Value+lowerClamp.Value)/2.00; + prevGuess=price.Close; + iterations++; + } + } + gainLoss=portfolioTrades.GetGainLoss(price); + } + return price; + } + public static bool IsZero(double? value) + { + if(null==value) + { + return true; + } + int intValue=(int)(value*10000.00); + if(0==intValue) return true; + return false; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/RSIGenerator.cs b/MarketData/MarketDataLib/Generator/RSIGenerator.cs new file mode 100755 index 0000000..ef3c0a1 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/RSIGenerator.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; +using MarketData.MarketDataModel; +using MarketData.Utils; +using MarketData.DataAccess; + +namespace MarketData.Generator +{ + public class RSIGenerator + { + private RSIGenerator() + { + } + public static RSICollection GenerateRSI(String symbol,int priceCount,int rsiDayCount=14) + { + if(priceCount=0;index--) + { + Price price=prices[index]; + RSIElement rsiElement=new RSIElement(); + rsiElement.Symbol=price.Symbol; + rsiElement.RSIDays=rsiDayCount; + rsiElement.Date=price.Date; + rsiElement.Close=price.Close; + if(index==prices.Count-1)continue; + rsiElement.Change=price.Close-prices[index+1].Close; + if(rsiElement.Change<0){rsiElement.Loss=Math.Abs(rsiElement.Change);rsiElement.Gain=0.00;} + else if(rsiElement.Change>0){rsiElement.Gain=rsiElement.Change;rsiElement.Loss=0.00;} + else{rsiElement.Loss=0.00;rsiElement.Gain=0.00;} + rsiCollection.Add(rsiElement); + } + RSICollection topCollection=rsiCollection.Top(rsiDayCount,1); + rsiCollection[rsiDayCount].AverageGain=topCollection.AverageGain(); + rsiCollection[rsiDayCount].AverageLoss=topCollection.AverageLoss(); + if(0.00==rsiCollection[rsiDayCount].AverageLoss) + { + rsiCollection[rsiDayCount].RS=0.00; + rsiCollection[rsiDayCount].RSI=100.00; + } + else + { + rsiCollection[rsiDayCount].RS=rsiCollection[rsiDayCount].AverageGain/rsiCollection[rsiDayCount].AverageLoss; + rsiCollection[rsiDayCount].RSI=100.00-(100.00/(1.00+rsiCollection[rsiDayCount].RS)); + } + for(int index=rsiDayCount+1;index=0;index--) + { + Price price=prices[index]; + RSIElement rsiElement=new RSIElement(); + rsiElement.Symbol=price.Symbol; + rsiElement.RSIDays=rsiDayCount; + rsiElement.Date=price.Date; + rsiElement.Close=price.Close; + if(index==prices.Count-1)continue; + rsiElement.Change=price.Close-prices[index+1].Close; + if(rsiElement.Change<0){rsiElement.Loss=Math.Abs(rsiElement.Change);rsiElement.Gain=0.00;} + else if(rsiElement.Change>0){rsiElement.Gain=rsiElement.Change;rsiElement.Loss=0.00;} + else{rsiElement.Loss=0.00;rsiElement.Gain=0.00;} + rsiCollection.Add(rsiElement); + } + RSICollection topCollection=rsiCollection.Top(rsiDayCount,1); + rsiCollection[rsiDayCount].AverageGain=topCollection.AverageGain(); + rsiCollection[rsiDayCount].AverageLoss=topCollection.AverageLoss(); + if(0.00==rsiCollection[rsiDayCount].AverageLoss) + { + rsiCollection[rsiDayCount].RS=0.00; + rsiCollection[rsiDayCount].RSI=100.00; + } + else + { + rsiCollection[rsiDayCount].RS=rsiCollection[rsiDayCount].AverageGain/rsiCollection[rsiDayCount].AverageLoss; + rsiCollection[rsiDayCount].RSI=100.00-(100.00/(1.00+rsiCollection[rsiDayCount].RS)); + } + for(int index=rsiDayCount+1;index yearsToProcess=GetYearsToProcess(portfolioTrades); + foreach(int processYear in yearsToProcess) + { + cumulativePortfolioInvestment=GetInvestmentForYear(portfolioTrades,processYear,cumulativePortfolioInvestment); + if(double.NaN.Equals(cumulativePortfolioInvestment)) return null; + } + price.Close=price.Open=price.High=price.Low=price.AdjClose=cumulativePortfolioInvestment/totalShares; + price.Date=DateTime.Now; + return price; + } + private static List GetYearsToProcess(PortfolioTrades portfolioTrades) + { + List investmentYears=new List(); + int startingYear=portfolioTrades[0].TradeDate.Year; + int endingYear=DateTime.Now.Year; + + for(int processYear=startingYear;processYear<=endingYear;processYear++) + { + investmentYears.Add(processYear); + } + return investmentYears; + } + private static double GetInvestmentForYear(PortfolioTrades portfolioTrades,int investmentYear,double initialInvestment) + { + double cumulativeYearInvestment=0; + DateTime yearEnd=new DateTime(investmentYear,12,31); + DateTime startOfYear=new DateTime(investmentYear,1,1); + double riskFreeRate; + PortfolioTrades tradesInYear=new PortfolioTrades((from PortfolioTrade portfolioTrade in portfolioTrades where portfolioTrade.TradeDate.Year.Equals(investmentYear) select portfolioTrade).ToList()); + + if(0.00!=initialInvestment) + { + riskFreeRate=YieldCurveDA.GetRiskFreeRate1Yr(startOfYear,10); + if(double.NaN.Equals(riskFreeRate)) return double.NaN; + riskFreeRate/=100.00; + double fractionOfYearHeld=1.00; + if(yearEnd>DateTime.Now) + { + fractionOfYearHeld=GetFractionOfYearHeld(DateTime.Now,startOfYear); + cumulativeYearInvestment=initialInvestment*Math.Pow(1.00+riskFreeRate,fractionOfYearHeld); + } + else cumulativeYearInvestment=initialInvestment*Math.Pow(1.00+riskFreeRate,fractionOfYearHeld); + } + foreach(PortfolioTrade portfolioTrade in tradesInYear) + { + riskFreeRate=YieldCurveDA.GetRiskFreeRate1Yr(portfolioTrade.TradeDate,10); // suggestion: move this database call out of the inner loop + if(double.NaN.Equals(riskFreeRate)) return double.NaN; + riskFreeRate/=100.00; + double fractionOfYearHeld=GetFractionOfYearHeld(portfolioTrade,yearEnd); + double tradeInvestment=portfolioTrade.Exposure()*Math.Pow((1.00+riskFreeRate),fractionOfYearHeld); + cumulativeYearInvestment+=tradeInvestment; + } + return cumulativeYearInvestment; + } + private static double GetFractionOfYearHeld(PortfolioTrade portfolioTrade,DateTime yearEnd) + { + DateGenerator dateGenerator=new DateGenerator(); + double fractionOfYearHeld=dateGenerator.DaysBetween(portfolioTrade.TradeDate,yearEnd)/365.00; + return fractionOfYearHeld; + } + private static double GetFractionOfYearHeld(DateTime effectiveDate,DateTime yearEnd) + { + DateGenerator dateGenerator=new DateGenerator(); + double fractionOfYearHeld=dateGenerator.DaysBetween(effectiveDate,yearEnd)/365.00; + return fractionOfYearHeld; + } + } +} diff --git a/MarketData/MarketDataLib/Generator/SentimentGenerator.cs b/MarketData/MarketDataLib/Generator/SentimentGenerator.cs new file mode 100755 index 0000000..1952a76 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/SentimentGenerator.cs @@ -0,0 +1,417 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using MarketData.DataAccess; +using MarketData.Utils; +using MarketData.MarketDataModel; + +namespace MarketData.Generator +{ + public class SentimentGenerator + { + private LexicalDictionary negativeLexicon=null; + private LexicalDictionary positiveLexicon=null; + private WordDictionary wordDictionary=null; + private static SentimentGenerator sentimentGeneratorInstance=null; + private SentimentGenerator() + { +// InitializeLexicalDatabase(); // Initialize the lexical sentiment database +// UpdatePartsOfSpeech(); // and update the parts of speech +// InitializeWordDatabase(); // Initialize the master word dictionary + negativeLexicon=LexicalDA.GetLexicalCollection().ToDictionary(LexicalElement.NEGATIVE_SENTIMENT); + positiveLexicon=LexicalDA.GetLexicalCollection().ToDictionary(LexicalElement.POSITIVE_SENTIMENT); + wordDictionary=DictionaryDA.GetDictionaryCollection().ToDictionary(); + } + public static SentimentGenerator GetInstance() + { + lock (typeof(SentimentGenerator)) + { + if (null == sentimentGeneratorInstance) sentimentGeneratorInstance = new SentimentGenerator(); + return sentimentGeneratorInstance; + } + } +// ******************************************************************************************************************************************************************************************** +// ******************************************************************************* B O O T S T R A P P I N G ********************************************************************************** +// ******************************************************************************************************************************************************************************************** + private static void InitializeWordDatabase() + { + List verbs=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\verbs.txt").Values.ToList(); + List adjectives=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\adjectives.txt").Values.ToList(); + List adverbs=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\adverbs.txt").Values.ToList(); + List nouns=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\nouns.txt").Values.ToList(); + + DictionaryDA.TruncateDictionary(); + DictionaryCollection collection=new DictionaryCollection(); + foreach(String word in verbs)collection.Add(new DictionaryElement(word,LexicalElement.VERB)); + DictionaryDA.InsertDictionaryCollection(collection); + + collection=new DictionaryCollection(); + foreach(String word in adjectives)collection.Add(new DictionaryElement(word,LexicalElement.ADJECTIVE)); + DictionaryDA.InsertDictionaryCollection(collection); + + collection=new DictionaryCollection(); + foreach(String word in adverbs)collection.Add(new DictionaryElement(word,LexicalElement.ADVERB)); + DictionaryDA.InsertDictionaryCollection(collection); + + collection=new DictionaryCollection(); + foreach(String word in nouns)collection.Add(new DictionaryElement(word,LexicalElement.NOUN)); + DictionaryDA.InsertDictionaryCollection(collection); + } + private static void InitializeLexicalDatabase() + { + Dictionary negativeLexicon=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\negativelexicon.txt"); + Dictionary positiveLexicon=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\positivelexicon.txt"); + + List negativeItems=new List(negativeLexicon.Values); + List positiveItems=new List(positiveLexicon.Values); + + LexicalCollection positiveLexicalElements=new LexicalCollection(); + LexicalCollection negativeLexicalElements=new LexicalCollection(); + + foreach(String s in negativeItems)negativeLexicalElements.Add(new LexicalElement(s,LexicalElement.NEGATIVE_SENTIMENT)); + foreach(String s in positiveItems)positiveLexicalElements.Add(new LexicalElement(s,LexicalElement.POSITIVE_SENTIMENT)); + + LexicalDA.TruncateLexicon(); + LexicalDA.InsertLexicalCollection(negativeLexicalElements); + LexicalDA.InsertLexicalCollection(positiveLexicalElements); + } + private static void UpdatePartsOfSpeech() + { + List verbs=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\verbs.txt").Values.ToList(); + List adjectives=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\adjectives.txt").Values.ToList(); + List adverbs=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\adverbs.txt").Values.ToList(); + List nouns=LoadFile(@"C:\boneyard\marketdata\LexicalAnalysis\nouns.txt").Values.ToList(); + + LexicalDictionary negativeLexicon=LexicalDA.GetLexicalCollection().ToDictionary(LexicalElement.NEGATIVE_SENTIMENT); + LexicalDictionary positiveLexicon=LexicalDA.GetLexicalCollection().ToDictionary(LexicalElement.POSITIVE_SENTIMENT); + + ApplyList(verbs,negativeLexicon,positiveLexicon,LexicalElement.VERB); + ApplyList(adjectives,negativeLexicon,positiveLexicon,LexicalElement.ADJECTIVE); + ApplyList(adverbs,negativeLexicon,positiveLexicon,LexicalElement.ADVERB); + ApplyList(nouns,negativeLexicon,positiveLexicon,LexicalElement.NOUN); + + LexicalDA.UpdateLexicalElements(negativeLexicon.ToList()); + LexicalDA.UpdateLexicalElements(positiveLexicon.ToList()); + } + private static void ApplyList(List list,Dictionary negativeItems,Dictionary positiveItems,String partOfSpeech) + { + foreach(String item in list) + { + if(negativeItems.ContainsKey(item)) + { + LexicalElement lexicalElement=negativeItems[item]; + if(null==lexicalElement.PartOfSpeech)lexicalElement.PartOfSpeech=partOfSpeech; + } + if(positiveItems.ContainsKey(item)) + { + LexicalElement lexicalElement=positiveItems[item]; + if(null==lexicalElement.PartOfSpeech)lexicalElement.PartOfSpeech=partOfSpeech; + } + } + } + private static Dictionary LoadFile(String pathFileName) + { + StreamReader streamReader=null; + Dictionary items=new Dictionary(); + try + { + streamReader = File.OpenText(pathFileName); + String strLine = null; + while (null != (strLine = streamReader.ReadLine())) + { + if ("".Equals(strLine))continue; + if(items.ContainsKey(strLine))continue; + items.Add(strLine,strLine); + } + return items; + } + catch(Exception /*exception*/) + { + return null; + } + finally + { + if(null!=streamReader) + { + streamReader.Close(); + streamReader.Dispose(); + } + } + } +// ****************************************************************************************************************************************************************************************** +// ****************************************************************************************************************************************************************************************** +// ****************************************************************************************************************************************************************************************** + public HeadlineSentiment ProcessHeadline(Headline headline) + { + lock(this) + { + String sentiment=ProcessHeadlineEntry(headline.Entry); + return new HeadlineSentiment(headline,sentiment); + } + } + public String ProcessHeadlineEntry(String headline) + { + lock(this) + { + StringBuilder sb=new StringBuilder(); + Dictionary uniqueWords=new Dictionary(); +// String[] words=headline.Split(' '); + String[] words=headline.Split(new char[]{' ','-'}); + double positionRank=1; + double positiveRank=0.00; + double negativeRank=0.00; + + for(int index=words.Length-1;index>=0;index--) + { + String word=words[index]; + String cleanWord=word.Trim().ToLower(); + + cleanWord=CleanASCII(cleanWord); + if(!Keep(cleanWord))continue; + cleanWord=Clean(cleanWord); + cleanWord=CleanStartsWithEndsWith(cleanWord); + if(!KeepStartsWithEndsWith(cleanWord))continue; + if(IsNumber(word))continue; + cleanWord=cleanWord.Trim(); + if(0==cleanWord.Length)continue; + + bool isNegative=IsNegativeWord(cleanWord); + bool isPositive=IsPositiveWord(cleanWord); + bool isVerb=IsPartOfSpeech(cleanWord,LexicalElement.VERB); + bool isNoun=IsPartOfSpeech(cleanWord,LexicalElement.NOUN); + bool isAdjective=IsPartOfSpeech(cleanWord,LexicalElement.ADJECTIVE); + + // Console.WriteLine(String.Format("Word '{0}':{1}:{2}:Pr{3}",cleanWord,LexicalElement.VERB,isPositive?"Positive":isNegative?"Negative":"Neutral",positionRank)); + if(isNegative) + { + negativeRank+=positionRank; + if(isAdjective&&index==0) // it's describing the next word so don't adjust anything + { + negativeRank-=positionRank; + } + else if(isVerb&&index>0) // if the word is a verb check to see if previous word is an adjective thus strengthening it + { + String preceedingWord=words[index-1].Trim().ToLower(); + if(IsPartOfSpeech(preceedingWord,LexicalElement.ADJECTIVE)) + { + // Console.WriteLine(String.Format("Preceeding Word {0}:{1}",preceedingWord,LexicalElement.ADJECTIVE)); + negativeRank+=(--positionRank); + index--; + continue; + } + else if(isNoun) // if the word is also a noun and we have positive verb following the we are doing negative things to something positive + { + List nextNouns = FindNextNouns(words, index + 1); + for (int nounIndex = 0; nounIndex < nextNouns.Count; nounIndex++) + { + isNegative = IsNegativeWord(nextNouns[nounIndex]); + isPositive = IsPositiveWord(nextNouns[nounIndex]); + if (isPositive) negativeRank++; + } + } + } + else if(isNoun&&index>0) + { + List nextVerbs=FindNextVerbs(words,index+1); // if we have a negative noun then look for a following positive verb that would strengthen the negativity + for(int verbIndex=0;verbIndex0) // if the word is a verb check to see if previous word is an adjective thus strengthening it + { + String preceedingWord=words[index-1].Trim().ToLower(); + if(IsPartOfSpeech(preceedingWord,LexicalElement.ADJECTIVE)) + { + // Console.WriteLine(String.Format("Preceeding Word {0}:{1}",preceedingWord,LexicalElement.ADJECTIVE)); + positiveRank+=(--positionRank); + index--; + continue; + } + } + } + if(uniqueWords.ContainsKey(cleanWord))continue; + uniqueWords.Add(cleanWord,cleanWord); + positionRank++; + } // for each word in headline + String headlineSentiment=LexicalElement.NEUTRAL_SENTIMENT; + if(positiveRank>negativeRank)headlineSentiment=LexicalElement.POSITIVE_SENTIMENT; + else if(negativeRank>positiveRank)headlineSentiment=LexicalElement.NEGATIVE_SENTIMENT; + return headlineSentiment; + } + } + private List FindNextVerbs(String[] words, int startingIndex) + { + List verbs=new List(); + for (int index = startingIndex; index < words.Length; index++) + { + if(IsPartOfSpeech(words[index],LexicalElement.VERB))verbs.Add(words[index]); + } + return verbs; + } + private List FindNextNouns(String[] words, int startingIndex) + { + List verbs = new List(); + for (int index = startingIndex; index < words.Length; index++) + { + if (IsPartOfSpeech(words[index], LexicalElement.NOUN)) verbs.Add(words[index]); + } + return verbs; + } + public void PrintHeadlineEntry(String headline) + { + lock (this) + { + StringBuilder sb = new StringBuilder(); + Dictionary uniqueWords = new Dictionary(); + String[] words = headline.Split(new char[] { ' ', '-' }); + + for (int index = words.Length - 1; index >= 0; index--) + { + String word = words[index]; + String cleanWord = word.Trim().ToLower(); + + cleanWord = CleanASCII(cleanWord); + if (!Keep(cleanWord)) continue; + cleanWord = Clean(cleanWord); + cleanWord = CleanStartsWithEndsWith(cleanWord); + if (!KeepStartsWithEndsWith(cleanWord)) continue; + if (IsNumber(word)) continue; + cleanWord = cleanWord.Trim(); + if (0 == cleanWord.Length) continue; + + bool isNegative = IsNegativeWord(cleanWord); + bool isPositive = IsPositiveWord(cleanWord); + bool isVerb = IsPartOfSpeech(cleanWord, LexicalElement.VERB); + bool isNoun = IsPartOfSpeech(cleanWord, LexicalElement.NOUN); + String partOfSpeech = null; + + if (isNegative || isPositive) partOfSpeech = GetPartOfSpeech(cleanWord); + if (null == partOfSpeech) partOfSpeech = GetDictionaryPartOfSpeech(word); + if (null == partOfSpeech) partOfSpeech = "?"; + Console.WriteLine(String.Format("Word '{0}':{1}:{2}", cleanWord, partOfSpeech, isPositive ? "Positive" : isNegative ? "Negative" : "Neutral")); + if (uniqueWords.ContainsKey(cleanWord)) continue; + uniqueWords.Add(cleanWord, cleanWord); + } // for each word in headline + } + } + public HeadlinesSentiment ProcessHeadlines(Headlines headlines) + { + lock(this) + { + HeadlinesSentiment headlineSentimentList=new HeadlinesSentiment(); + foreach(Headline headline in headlines) + { + HeadlineSentiment headlineSentiment=ProcessHeadline(headline); + headlineSentimentList.Add(headlineSentiment); + } // for each headline + return headlineSentimentList; + } + } + private bool IsNegativeWord(String word) + { + if(negativeLexicon.ContainsKey(word))return true; + return false; + } + private bool IsPositiveWord(String word) + { + if(positiveLexicon.ContainsKey(word))return true; + return false; + } + private bool IsPartOfSpeech(String word,String partOfSpeech) + { + if(null==word||null==partOfSpeech)return false; + if (positiveLexicon.ContainsKey(word) && partOfSpeech.Equals(positiveLexicon[word].PartOfSpeech, StringComparison.OrdinalIgnoreCase)) return true; + if (negativeLexicon.ContainsKey(word) && partOfSpeech.Equals(negativeLexicon[word].PartOfSpeech, StringComparison.OrdinalIgnoreCase)) return true; + if(wordDictionary.ContainsKeyAs(word,partOfSpeech))return true; + return false; + } + private String GetPartOfSpeech(String word) + { + if(positiveLexicon.ContainsKey(word))return positiveLexicon[word].PartOfSpeech; + else if(negativeLexicon.ContainsKey(word))return negativeLexicon[word].PartOfSpeech; + return null; + } + private String GetDictionaryPartOfSpeech(String word) + { + if(!wordDictionary.ContainsKey(word))return null; + if(wordDictionary.ContainsKeyAs(word,LexicalElement.ADJECTIVE))return LexicalElement.ADJECTIVE; + if(wordDictionary.ContainsKeyAs(word,LexicalElement.ADVERB))return LexicalElement.ADVERB; + if(wordDictionary.ContainsKeyAs(word,LexicalElement.NOUN))return LexicalElement.NOUN; + if(wordDictionary.ContainsKeyAs(word,LexicalElement.VERB))return LexicalElement.VERB; + if(wordDictionary.ContainsKeyAs(word,LexicalElement.CONJUNCTION))return LexicalElement.CONJUNCTION; + return null; + } + private bool Keep(String word) + { +// String[] removeList={"/","%",",",":","-",";","$",">","+","?","_","#","&"}; +// String[] removeList={"/","%","-",";","$",">","+","?","_","#","&"}; + String[] removeList={"/","%",";","$",">","+","?","_","#","&"}; + foreach(String match in removeList) + { + if(word.Contains(match))return false; + } + return true; + } + private string CleanASCII(string s) + { + StringBuilder sb = new StringBuilder(s.Length); + foreach(char c in s) + { + if((int)c > 127)continue; + if((int)c < 32)continue; + sb.Append(c); + } + return sb.ToString(); + } + private String Clean(String word) + { + String[] replaceList={"\"","?","~","|",":",","}; +// String[] replaceList={"(",")","\"","?","~","|",":",","}; + foreach(String toReplace in replaceList) + { + word=word.Replace(toReplace,null); + } + return word; + } + private String CleanStartsWithEndsWith(String word) + { + String[] replaceList={"'","`","[","]","!"}; + foreach(String toReplace in replaceList) + { + if(word.StartsWith(toReplace))word=word.Substring(1); + if(word.EndsWith(toReplace))word=word.Substring(0,word.Length-2); + } + return word; + } + private bool KeepStartsWithEndsWith(String word) + { + String[] replaceList={".","~","1","2","3","4","5","6","7","8","9","0"}; + foreach(String toReplace in replaceList) + { + if(word.StartsWith(toReplace))return false; + if(word.EndsWith(toReplace))return false; + } + return true; + } + private bool IsNumber(String word) + { + double result=double.NaN; + return double.TryParse(word,out result); + } + } +} diff --git a/MarketData/MarketDataLib/Generator/SignalGenerator.cs b/MarketData/MarketDataLib/Generator/SignalGenerator.cs new file mode 100755 index 0000000..87202f7 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/SignalGenerator.cs @@ -0,0 +1,409 @@ +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Threading; +using System.Reflection; +//using System.Runtime.Remoting.Messaging; +using System.Text; +using MarketData.MarketDataModel; + +namespace MarketData.Generator +{ + public class SignalGenerator + { + private SignalGenerator() + { + } + public static Signals GenerateSignals(DMAPrices shortMA, DMAPrices longMA) + { + try + { + Signals signals = new Signals(); + Align(shortMA, longMA); + + for (int index = shortMA.Count - 1; index >= 0; index--) + { + Signal currSignal = new Signal(); + Signal prevSignal = null; + DMAPrice prevShortData = null; + DMAPrice currShortData = shortMA[index]; + DMAPrice prevLongData = null; + DMAPrice currLongData = longMA[index]; + + currSignal.Ticker = currShortData.Symbol; + currSignal.SignalDate = currShortData.Date; + if (index == shortMA.Count - 1) + { + if (currShortData.AVGPrice > currLongData.AVGPrice) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "Crossover."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "Crossover."; + } + signals.Add(currSignal); + continue; + } + prevSignal = (Signal)signals[signals.Count - 1]; + prevShortData = shortMA[index + 1]; + prevLongData = longMA[index + 1]; + if (currShortData.AVGPrice > currLongData.AVGPrice) + { + if (prevShortData.AVGPrice < prevLongData.AVGPrice) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "Crossover."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.WeakBuy; + currSignal.Reason = "Existing Crossover maintained."; + } + } + else + { + if (prevShortData.AVGPrice > prevLongData.AVGPrice) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "Crossover."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.WeakSell; + currSignal.Reason = "Existing Crossover maintained."; + } + } + signals.Add(currSignal); + } + return signals; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + public static Signals GenerateSignals(Stochastics stochastics) + { + try + { + Signals signals = new Signals(); + StochasticElement prevStochastic = null; + Signal prevSignal = null; + bool crossover = false; + + for (int index = stochastics.Count - 1; index >= 0; index--) + { + Signal currSignal = new Signal(); + StochasticElement currStochastic = stochastics[index]; + currSignal.Ticker = currStochastic.Symbol; + currSignal.SignalDate = currStochastic.Date; + // identify the crossover + if (currStochastic.PK > currStochastic.PD && (null != prevStochastic && prevStochastic.PK <= prevStochastic.PD)) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "currStochastic.PK>currStochastic.PD"; + crossover = true; + } + else if (currStochastic.PK <= currStochastic.PD && (null != prevStochastic && prevStochastic.PK > prevStochastic.PD)) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "currStochastic.PK <= currStochastic.PD"; + crossover = true; + } + else if (currStochastic.PKInRange(20, 50)) + { + crossover = false; + if (null != prevStochastic && prevStochastic.PK < 20) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "currStochastic.PKInRange(20, 50),prevStochastic.PK < 20 "; + } + else if (null != prevStochastic && prevStochastic.PK > 50) + { + currSignal.SignalIndicator = Signal.Indicator.WeakSell; + currSignal.Reason = "currStochastic.PKInRange(20, 50),prevStochastic.PK > 50"; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "currStochastic.PKInRange(20, 50),prevStochastic.PKInRange(20,50)"; + } + } + else if (currStochastic.PKInRange(51, 79)) + { + crossover = false; + if (null != prevStochastic && prevStochastic.PK < 51) + { + currSignal.SignalIndicator = Signal.Indicator.WeakBuy; + currSignal.Reason = "currStochastic.PKInRange(51, 79),prevStochastic.PK < 51"; + } + else if (null != prevStochastic && prevStochastic.PK > 79) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "currStochastic.PKInRange(51, 79),prevStochastic.PK > 79"; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.WeakBuy; + currSignal.Reason = "currStochastic.PKInRange(51, 79),prevStochastic.PKInRange(51,79)"; + } + } + else if (currStochastic.PKInRange(80, 100)) + { + crossover = false; + if (null != prevStochastic && prevStochastic.PK < 80) + { + currSignal.SignalIndicator = Signal.Indicator.WeakBuy; + currSignal.Reason = "currStochastic.PKInRange(80,100),prevStochastic.PK < 80"; + } + else if (null != prevStochastic && prevStochastic.PK > 90) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "currStochastic.PKInRange(80,100),prevStochastic.PK > 90"; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.WeakBuy; + currSignal.Reason = "currStochastic.PKInRange(80,100),prevStochastic.PK >80,prevStochastic.PK<90"; + } + } + else + { + if (crossover) + { + currSignal.SignalIndicator = prevSignal.SignalIndicator; + currSignal.Reason = "currStochastic<20, previous crossover holds."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "currStochastic<20, no crossover identified"; + } + } + signals.Add(currSignal); + prevStochastic = currStochastic; + prevSignal = (Signal)signals[signals.Count - 1]; + } + return signals; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + public static Signals GenerateSignals(MACDSignals macdSignals) + { + try + { + Signals signals = new Signals(); + SignHolder signMACD = new SignHolder(); + SignHolder signSignal = new SignHolder(); + + for (int index = macdSignals.Count - 1; index >= 0; index--) + { + Signal currSignal = new Signal(); + Signal prevSignal = null; + MACDSignal prevSecurityData = null; + MACDSignal currSecurityData = macdSignals[index]; + currSignal.Ticker = currSecurityData.Symbol; + currSignal.SignalDate = currSecurityData.Date; + if (index == macdSignals.Count - 1) + { + signMACD.SetValue(currSecurityData.MACD); + signSignal.SetValue(currSecurityData.Signal); + if (currSecurityData.MACD > currSecurityData.Signal) + { + if (currSecurityData.MACD < 0) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "MACD is above the signal line and the MACD is less than zero."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.WeakBuy; + currSignal.Reason = "MACD is above the signal line and the MACD is greater than or equal to zero."; + } + } + else + { + if (currSecurityData.MACD > 0) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "MACD is less than or equal to the signal line and MACD is above zero."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.WeakSell; + currSignal.Reason = "MACD is less than or equal to the signal line and MACD is less than or equal to zero"; + } + } + signals.Add(currSignal); + continue; + } + prevSignal = (Signal)signals[signals.Count - 1]; + prevSecurityData = macdSignals[index + 1]; + signMACD.SetValue(currSecurityData.MACD); + signSignal.SetValue(currSecurityData.Signal); + //MACD is above the signal line + if (currSecurityData.MACD > currSecurityData.Signal) + { + // previous MACD is above signal line + if (prevSignal.IsBuy()) + { + // the histogram is widening so keep it a strong buy + if (Math.Abs(currSecurityData.Histogram) > Math.Abs(prevSecurityData.Histogram) && currSecurityData.MACD < 0) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "The current MACD is above the signal and the histogram is widening and MACD is below zero"; + } + else if (Math.Abs(currSecurityData.Histogram) > Math.Abs(prevSecurityData.Histogram)) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "The current MACD is above the signal and the histogram is widening."; + } + else if (currSecurityData.MACD < 0) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "The current MACD is above the signal and less than zero."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.WeakBuy; + currSignal.Reason = "The current MACD is above the signal line but so was the previous MACD."; + } + } + else + { + if (currSecurityData.MACD > 0 && currSecurityData.Signal < 0) + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "The current MACD is above the signal, MACD is above zero, signal is below zero."; + } + else if (currSecurityData.MACD > 0) + { + currSignal.SignalIndicator = Signal.Indicator.WeakBuy; + currSignal.Reason = "The current MACD is above the signal but the MACD is above zero."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.StrongBuy; + currSignal.Reason = "The current MACD is above the signal and the MACD is less than zero"; + } + } + } + //MACD is below the signal line + else + { + // check previous MACD is below the signal line + // The MACD line is above the signal line but the MACD is below zero so this is considered a weaker buy signal + if (prevSignal.IsSell()) + { + if (Math.Abs(currSecurityData.Histogram) > Math.Abs(prevSecurityData.Histogram) && currSecurityData.MACD > 0) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "The current MACD is below or equal to the signal, the histogram is widening, and MACD is above zero"; + } + else if (Math.Abs(currSecurityData.Histogram) > Math.Abs(prevSecurityData.Histogram)) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "The current MACD is below or equal to the signal, the histogram is widening."; + } + else if (currSecurityData.MACD > 0) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "The current MACD is below or equal to the signal line and MACD is above zero"; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.WeakSell; + currSignal.Reason = "The current MACD is below or equal to the signal line."; + } + } + else + { + if (currSecurityData.MACD < 0 && currSecurityData.Signal > 0) + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "The current MACD is below or equal to the signal line, MACD is below zero, signal is above zero"; + } + else if (currSecurityData.MACD < 0) + { + currSignal.SignalIndicator = Signal.Indicator.WeakSell; + currSignal.Reason = "The current MACD is below or equal to the signal line and MACD is below zero."; + } + else + { + currSignal.SignalIndicator = Signal.Indicator.StrongSell; + currSignal.Reason = "The current MACD is below or equal to the signal and MACD is greater than or equal to zero."; + } + } + } + signals.Add(currSignal); + } + signals.Sort(new SignalComparatorByDateDescending()); // This was added to get the most recent dated items into the lowest position of the returned array. Users of this function were performing TAKE() on the array to get the topmost nth items and winding up with the bottommost (furthest dated) items. + return signals; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + private static void Align(DMAPrices shortMA, DMAPrices longMA) + { + Dictionary shortMADates = new Dictionary(); + Dictionary longMADates = new Dictionary(); + List shortMAPriceToRemove = new List(); + List longMAPriceToRemove = new List(); + + for (int index = 0; index < shortMA.Count; index++) + { + DMAPrice dmaPrice = shortMA[index]; + if (!shortMADates.ContainsKey(dmaPrice.Date)) shortMADates.Add(dmaPrice.Date, dmaPrice); + } + for (int index = 0; index < longMA.Count; index++) + { + DMAPrice dmaPrice = longMA[index]; + if (!longMADates.ContainsKey(dmaPrice.Date)) longMADates.Add(dmaPrice.Date, dmaPrice); + } + for (int index = 0; index < shortMA.Count; index++) + { + DMAPrice dmaPrice = shortMA[index]; + if (!longMADates.ContainsKey(dmaPrice.Date)) shortMAPriceToRemove.Add(dmaPrice.Date); + } + for (int index = 0; index < longMA.Count; index++) + { + DMAPrice dmaPrice = longMA[index]; + if (!shortMADates.ContainsKey(dmaPrice.Date)) longMAPriceToRemove.Add(dmaPrice.Date); + } + for (int index = 0; index < shortMAPriceToRemove.Count; index++) + { + DateTime dateToRemove = shortMAPriceToRemove[index]; + DMAPrice dmaPrice = shortMADates[dateToRemove]; + shortMA.Remove(dmaPrice); + } + for (int index = 0; index < longMAPriceToRemove.Count; index++) + { + DateTime dateToRemove = longMAPriceToRemove[index]; + DMAPrice dmaPrice = longMADates[dateToRemove]; + longMA.Remove(dmaPrice); + } + } + private static void PrintSignals(ArrayList signals) + { + for(int index=0;index pricesByDate = new Dictionary(); + Dictionary signalsByDate = new Dictionary(); + Portfolio portfolio = new Portfolio(initialCash); + + for (int index = 0; index < prices.Count; index++) + { + Price price = prices[index]; + pricesByDate.Add(price.Date, price); + } + for (int index = 0; index < signals.Count; index++) + { + Signal signal = signals[index]; + signalsByDate.Add(signal.SignalDate, signal); + } +// portfolio.AvailableCash = initialCash; + for (int index = 0; index < tradeDates.Count; index++) + { + DateTime tradingDate = tradeDates[index]; + if (!pricesByDate.ContainsKey(tradingDate)) continue; + if (!signalsByDate.ContainsKey(tradingDate)) continue; + Signal signal = signalsByDate[tradingDate]; + if (signal.IsStrongBuy() && !portfolio.HasOpenPosition) + { + if (portfolio.AvailableCash > 0) + { + ModelTrade trade = new ModelTrade(); + Price price = pricesByDate[signal.SignalDate]; + trade.Symbol = price.Symbol; + trade.Price = price.Close; + trade.Shares = (int)(portfolio.AvailableCash / trade.Price); + trade.TradeDate = price.Date; + trade.Exposure = trade.Shares * trade.Price; + trade.Type = ModelTrade.TradeType.Buy; + portfolio.AvailableCash -= (trade.Price * trade.Shares); + portfolio.Add(trade); + portfolio.HasOpenPosition = true; + } + } + else if (signal.IsStrongSell() && portfolio.HasOpenPosition) + { + ModelTrade trade = new ModelTrade(); + ModelTrade lastTrade = portfolio.GetLastTrade(); + Price price = pricesByDate[signal.SignalDate]; + if (0.00 == stopLossThreshold && price.Close < lastTrade.Price) continue; + int daysHeld = (price.Date - lastTrade.TradeDate).Days; + double stopLossPrice = lastTrade.Price - (lastTrade.Price * stopLossThreshold); + bool stopLossIndicator = price.Close < stopLossPrice && daysHeld > stopLossDays ? true : false; + if (!stopLossIndicator && price.Close < lastTrade.Price) continue; + else if (stopLossIndicator) trade.Comment = "Stop Loss. price decrease " + String.Format("{0:p}", stopLossThreshold) + ", holding days (" + daysHeld + ") >" + stopLossDays; + portfolio.AvailableCash += ((lastTrade.Shares * price.Close)); + trade.Symbol = price.Symbol; + trade.Price = price.Close; + trade.Shares = (int)(portfolio.AvailableCash / trade.Price); + trade.Type = ModelTrade.TradeType.Sell; + trade.TradeDate = price.Date; + double marketValue = (trade.Price * trade.Shares); +// trade.GainLoss = (trade.Price * trade.Shares) - (lastTrade.Price * lastTrade.Shares); + trade.GainLoss = marketValue - lastTrade.Exposure; + trade.Return = ((marketValue - lastTrade.Exposure) / lastTrade.Exposure); + trade.DaysHeld = daysHeld; + portfolio.Add(trade); + portfolio.HasOpenPosition = false; + } + } + return portfolio; + } + +// Add the MA(10,50) +// if (8,17,9) signals a buy and we are on the + side of the MA(10,50) then seek support from the (12,26,9) which must be a buy signal +// if (8,17,9) signals a buy and we are on the - side of the MA(10,50) then no support is necessary. +// sell when the (8,17,9) signals a sell + + public static Portfolio TradeSignals(DateRange tradeDates,Signals signals, Signals supportSignals, Signals crossoverSignals,Prices prices, double initialCash) + { + Dictionary pricesByDate = new Dictionary(); + Dictionary supportSignalsByDate = new Dictionary(); + Dictionary signalsByDate = new Dictionary(); + Dictionary crossoverSignalsByDate = new Dictionary(); + Signal prevSignal = null; + + MDTrace.WriteLine(LogLevel.DEBUG,"[SignalTrader::TradeSignals]"); + Portfolio portfolio = new Portfolio(initialCash); + int holdingDays = 0; + int tradeCount = 0; + int averageHoldingDays = 0; + for (int index = 0; index < prices.Count; index++) + { + Price price = prices[index]; + pricesByDate.Add(price.Date, price); + } + for (int index = 0; index < supportSignals.Count; index++) + { + Signal supportSignal = supportSignals[index]; + supportSignalsByDate.Add(supportSignal.SignalDate, supportSignal); + } + for (int index = 0; index < signals.Count; index++) + { + Signal signal = signals[index]; + signalsByDate.Add(signal.SignalDate, signal); + } + for (int index = 0; index < crossoverSignals.Count; index++) + { + Signal signal = crossoverSignals[index]; + crossoverSignalsByDate.Add(signal.SignalDate, signal); + } +// portfolio.AvailableCash = initialCash; + for(int index=0;index0 &&!portfolio.HasOpenPosition) + { + if (null != prevSignal && prevSignal.IsStrongBuy()) continue; + if (crossoverSignal.IsBuy() && !supportSignal.IsBuy()) continue; + ModelTrade trade = new ModelTrade(); + trade.Symbol = price.Symbol; + trade.Price = price.Close; + trade.Shares = (int)(portfolio.AvailableCash / trade.Price); + trade.TradeDate = price.Date; + trade.Type = ModelTrade.TradeType.Buy; + trade.Exposure = trade.Shares * trade.Price; + portfolio.AvailableCash -= (trade.Price * trade.Shares); + portfolio.Add(trade); + portfolio.HasOpenPosition = true; + } + else if (signal.IsStrongSell() && portfolio.HasOpenPosition) + { + ModelTrade trade = new ModelTrade(); + ModelTrade lastTrade = portfolio.GetLastTrade(); + if (price.Close < lastTrade.Price) continue; + portfolio.AvailableCash += ((lastTrade.Shares * price.Close)); + trade.Symbol = price.Symbol; + trade.Price = price.Close; + trade.Shares = (int)(portfolio.AvailableCash / trade.Price); + trade.Type = ModelTrade.TradeType.Sell; + trade.TradeDate = price.Date; + double marketValue = trade.Price * trade.Shares; + trade.GainLoss = marketValue - lastTrade.Exposure; + trade.Return = (marketValue - lastTrade.Exposure) / lastTrade.Exposure; + trade.DaysHeld = (price.Date - lastTrade.TradeDate).Days; ; + portfolio.Add(trade); + portfolio.HasOpenPosition = false; + tradeCount++; + holdingDays += (price.Date - lastTrade.TradeDate).Days; + averageHoldingDays = holdingDays / tradeCount; + } + prevSignal = signal; + } + return portfolio; + } + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/Generator/StochasticsGenerator.cs b/MarketData/MarketDataLib/Generator/StochasticsGenerator.cs new file mode 100755 index 0000000..a4ef154 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/StochasticsGenerator.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using MarketData.Generator.MovingAverage; +using MarketData.MarketDataModel; + +// Filename: StochasticsGenerator.cs +// Author:Sean Kessler +// Date:08/2013 + +namespace MarketData.Generator +{ + /// StochasticsGenerator - StochasticsGenerator utility class + public class StochasticsGenerator + { + public static Stochastics GenerateStochastics(Prices prices, int periodN=9,int periodX=3) + { + try + { + Stochastics stochastics = new Stochastics(); + DMAPricesByDate dmaLNPricesByDate = null; // these are the min(low) for the period-n + DMAPricesByDate dmaHNPricesByDate = null; // these are the max(high) for the period-n + DMAPrices dmaLN = MovingAverageGenerator.GenerateMovingMinsOnLow(prices, periodN); + DMAPrices dmaHN = MovingAverageGenerator.GenerateMovingMaxOnHigh(prices, periodN); + dmaLNPricesByDate = dmaLN.GetDMAPricesByDate(); + dmaHNPricesByDate = dmaHN.GetDMAPricesByDate(); + int stopCount; + + stopCount = Math.Max(periodN, periodX)+1; // clamp the solution set the range + for (int index = 0; index < prices.Count - stopCount; index++) + { + Price price = prices[index]; + StochasticElement stochasticElement = new StochasticElement(); + if(!dmaLNPricesByDate.ContainsKey(price.Date))continue; + if(!dmaHNPricesByDate.ContainsKey(price.Date))continue; + stochasticElement.Date = price.Date; + stochasticElement.Symbol = price.Symbol; + stochasticElement.Open = price.Open; + stochasticElement.High = price.High; + stochasticElement.Low = price.Low; + stochasticElement.Close = price.Close; + stochasticElement.LN = dmaLNPricesByDate[price.Date].MinPrice; // min low for period N + stochasticElement.HN = dmaHNPricesByDate[price.Date].MaxPrice; // max high for period N + stochasticElement.HX = CalculateHX(index, prices, dmaLN, periodX); // sum (CCL-LN) for past periodX + stochasticElement.LX = CalculateLX(index, dmaHN, dmaLN, periodX); // sum(HN-LN) for past periodX + stochasticElement.PK = 100 * (price.Close - stochasticElement.LN) / (stochasticElement.HN - stochasticElement.LN); // 100*(CCL-LN)/(HN-LN) + stochasticElement.PD = 100 * (stochasticElement.HX / stochasticElement.LX); // 100*(HX/LX) + stochastics.Add(stochasticElement); + } + return stochastics; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } +// calculate the x-period sum of (CCL-LN) + private static double CalculateHX(int startingIndex,Prices prices,DMAPrices lnPrices,int periodK) + { + try + { + double sum = 0.00; + for (int index = startingIndex; index < startingIndex + periodK; index++) + { + Price price = prices[index]; + DMAPrice lnPrice = lnPrices[index]; + sum+=(price.Close-lnPrice.MinPrice); + } + return sum; + } + catch(Exception /*exception*/) + { + return double.NaN; + } + } +//sum(HN-LN) for past period K + private static double CalculateLX(int startingIndex,DMAPrices hnPrices,DMAPrices lnPrices, int periodK) + { + try + { + double sum = 0.00; + for (int index = startingIndex; index < startingIndex + periodK; index++) + { + DMAPrice hnPrice = hnPrices[index]; + DMAPrice lnPrice = lnPrices[index]; + sum+=(hnPrice.MaxPrice-lnPrice.MinPrice); + } + return sum; + } + catch (Exception /*exception*/) + { + return double.NaN; + } + } + } +} diff --git a/MarketData/MarketDataLib/Generator/TLBRankGenerator.cs b/MarketData/MarketDataLib/Generator/TLBRankGenerator.cs new file mode 100755 index 0000000..5c2c7c0 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/TLBRankGenerator.cs @@ -0,0 +1,204 @@ +using MarketData.DataAccess; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.MarketDataModel +{ +// ******************************************************************************************************************************************************** +// ******************************************** U N I T T E S T F O R J O E L G R E E N B L A T T M E T H O D O L O G Y *************************** +// ******************************************************************************************************************************************************** + public class TLBItemList : List + { + public TLBItemList() + { + } + public TLBItemList(TLBItemList itemList) + { + foreach(TLBItem item in itemList)Add(item); + } + public static void ApplyTLBRanks(TLBItemList items) + { + Dictionary itemsBySymbol=new Dictionary(); + Dictionary itemsRankedByROC=new Dictionary(); + Dictionary itemsRankedByROIC=new Dictionary(); + Dictionary itemsRankedByEarningsYield=new Dictionary(); + + foreach(TLBItem item in items) + { + if(!itemsBySymbol.ContainsKey(item.Symbol)) + { + itemsBySymbol.Add(item.Symbol,item); + } + } + + TLBItemList itemsCopyByROC=new TLBItemList(items); + TLBItemList itemsCopyByROIC=new TLBItemList(items); + TLBItemList itemsCopyByEarningsYield=new TLBItemList(items); + itemsCopyByROC.Sort(new TLBListByROC()); + itemsCopyByROIC.Sort(new TLBListByROIC()); + itemsCopyByEarningsYield.Sort(new TLBListByEarningsYield()); + + for(int index=0;index + { + public int Compare(TLBItem v1,TLBItem v2) + { + if(double.IsNaN(v1.ROC)&&double.IsNaN(v2.ROC))return 0; + else if(double.IsNaN(v1.ROC))return -1; + else if(double.IsNaN(v2.ROC))return 1; + return v1.ROC.CompareTo(v2.ROC); + } + } + public class TLBListByROIC : IComparer + { + public int Compare(TLBItem v1,TLBItem v2) + { + if(double.IsNaN(v1.ROIC)&&double.IsNaN(v2.ROIC))return 0; + else if(double.IsNaN(v1.ROIC))return -1; + else if(double.IsNaN(v2.ROIC))return 1; + return v1.ROIC.CompareTo(v2.ROIC); + } + } + public class TLBListByEarningsYield : IComparer + { + public int Compare(TLBItem v1,TLBItem v2) + { + if(double.IsNaN(v1.EarningsYield)&&double.IsNaN(v2.EarningsYield))return 0; + else if(double.IsNaN(v1.EarningsYield))return -1; + else if(double.IsNaN(v2.EarningsYield))return 1; + return v1.EarningsYield.CompareTo(v2.EarningsYield); + } + } + public class TLBItem + { + public String Symbol{get;set;} + public double EBIT{get;set;} + public double EarningsYield{get;set;} + public double EnterpriseValue{get;set;} + public double WorkingCapital{get;set;} + public double PPE{get;set;} + public double ROIC{get;set;} + public double ROC{get;set;} + public double TLBRankROIC{get;set;} + public double TLBRankROC{get;set;} + } +// The sorting of the ranks will be from lowest to highest. The largest ROICS will have the largest ranks and the largest EarningsYields will have the largest ranks. +// This sorting is opposite to how Joel sorted his lists. Joel's lists wind up with the best candidates having the lowest ranks while this one winds up with the +// best candidates having the highest ranks. This can be seen when visiting the Valuations view and changing the sort to TLBRankROIC with the highest valued ranks +// on top. These will be the top candidates. + public class TLBRankGenerator + { + private TLBRankGenerator() + { + } +// ******************************************************************************************************************************************************************* +// ********************************************** T H E L I T T L E B O O K R A N K G E N E R A T O R U N I T T E S T **** ********************************** +// ******************************************************************************************************************************************************************* + public static TLBItemList ApplyTLBRanks() + { + List symbols=PricingDA.GetSymbols(); + TLBItemList tlbList=new TLBItemList(); + + foreach(String symbol in symbols) + { + double earningsYield=double.NaN; + double roc=double.NaN; + double roic=double.NaN; + Console.WriteLine("Working on "+symbol); + + BalanceSheet balanceSheet = BalanceSheetDA.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual); + TimeSeriesCollection workingCapitalCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.WorkingCapital); + TimeSeriesCollection roicCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.ROIC); + Fundamental fundamental=FundamentalDA.GetFundamental(symbol); + if(null==fundamental)continue; + TLBItem tlbItem=new TLBItem(); + if(!double.IsNaN(fundamental.EBIT)&&!double.IsNaN(fundamental.EnterpriseValue)&&fundamental.EnterpriseValue>0.00&&fundamental.EBIT>0.00) + { + earningsYield=fundamental.EBIT/fundamental.EnterpriseValue; + } + if(!double.IsNaN(fundamental.EBIT)&&null!=balanceSheet&&!double.IsNaN(balanceSheet.NetFixedAssets)) + { + roc=fundamental.EBIT/balanceSheet.NetFixedAssets; + } + if(null!=roicCollection && roicCollection.Count>0)roic=roicCollection[0].Value; + tlbItem.Symbol=symbol; + tlbItem.EBIT=fundamental.EBIT; + tlbItem.EarningsYield=earningsYield; + tlbItem.EnterpriseValue=fundamental.EnterpriseValue; + tlbItem.ROC=roc*100.00; + tlbItem.ROIC=roic; + tlbList.Add(tlbItem); + } + TLBItemList.ApplyTLBRanks(tlbList); + return tlbList; + } +// ******************************************************************************************************************************************************************* +// ********************************************** T H E L I T T L E B O O K R A N K G E N E R A T O R F O R V A L U A T I O N ********************************** +// ******************************************************************************************************************************************************************* + public static void ApplyTLBRanks(Valuations valuations) + { + Dictionary valuationsBySymbol=new Dictionary(); + Dictionary valuationsRankedByROIC=new Dictionary(); + Dictionary valuationsRankedByROC=new Dictionary(); + Dictionary valuationsRankedByEarningsYield=new Dictionary(); + + foreach(Valuation valuation in valuations) + { + if(!valuationsBySymbol.ContainsKey(valuation.Symbol))valuationsBySymbol.Add(valuation.Symbol,valuation); + } + Valuations valuationsCopyByROIC=new Valuations(valuations); + valuationsCopyByROIC.Sort(new ValuationsByROIC()); + Valuations valuationsCopyByROC=new Valuations(valuations); + valuationsCopyByROC.Sort(new ValuationsByROC()); + Valuations valuationsCopyByEarningsYield=new Valuations(valuations); + valuationsCopyByEarningsYield.Sort(new ValuationsByEarningsYield()); + for(int index=0;index x.Item.Equals(tenorName)); + if (-1 == index || index >= CurveTenors.Count) return null; + return CurveTenors[index].Value; + } + catch (Exception /*exception*/) + { + return null; + } + } + public void RemoveTenors(String strTenors) + { + string[] strTenorArray = strTenors.Split(','); + foreach (String strTenor in strTenorArray) + { + CurveTenors.Remove(strTenor); + } + } + } +// *************************************************************8 + public class CurveMappings : List + { + public CurveMappings() + { + } + } + public class CurveMapping + { + public CurveMapping() + { + } + public String CurveName { get; set; } + public String Currency { get; set; } + public String BloombergMnemonic { get; set; } + public String Field { get; set; } + public String AttributeName { get; set; } + public String CurveId { get; set; } + public Tenors TenorMappings{get;set;} + public DateTime PricingDate { get; set; } + public void SetTenorValues(String strValues) + { + String[] strTenorValues = strValues.Split(','); + if (strTenorValues.Length != TenorMappings.Count) throw new Exception("Tenor mapping count does not match tenor value count"); + for (int index = 0; index < TenorMappings.Count; index++) + { + TenorMappings[index].Value = strTenorValues[index]; + } + } + } + public class Tenors : List + { + public Tenors() + { + } + public void Remove(String strTenor) + { + for(int index=0;index + { + } + public class TermStructureInterpolator + { + private Dictionary splineRates = new Dictionary(); + private CurveData curveData = null; + private DateTime tradeDate; + + public TermStructureInterpolator(DateTime tradeDate) + { + this.tradeDate=tradeDate; + SetCurveData(); + } + public DateTime TradeDate { get; private set; } + public CurveData CurveData + { + get + { + return curveData; + } + } + public Dictionary SplineRates + { + get + { + return splineRates; + } + } + public double GetRate(int days) + { + int index = 0; + if (null == curveData) return double.NaN; + for (; index < curveData.CurveTenors.Count;index++ ) + { + Tenor tenor = curveData.CurveTenors[index]; + int tenorDays=Tenor.GetTenorDays(tenor.Item); + if(tenorDays == days) return double.Parse(tenor.Value); + if(tenorDays>days) break; + } + double differenceDays=days-Tenor.GetTenorDays(curveData.CurveTenors[index].Item); + double dailyRate=(curveData.CurveTenors[index].ValueNum - curveData.CurveTenors[index-1].ValueNum) / (curveData.CurveTenors[index].Days - curveData.CurveTenors[index-1].Days); + double rate = curveData.CurveTenors[index].ValueNum + (differenceDays * dailyRate); + return rate; + } + private void SetCurveData() + { + YieldCurveData yieldCurveData=YieldCurveDA.GetYieldCurve(tradeDate); + if(null==yieldCurveData)return; + curveData=new CurveData(); + Tenors tenors=new Tenors(); + curveData.CurveTenors=tenors; + tenors.Add(new Tenor("1D",Utility.FormatNumber(yieldCurveData.Mo1,2))); + tenors.Add(new Tenor("1M",Utility.FormatNumber(yieldCurveData.Mo1,2))); + tenors.Add(new Tenor("3M",Utility.FormatNumber(yieldCurveData.Mo3,2))); + tenors.Add(new Tenor("6M",Utility.FormatNumber(yieldCurveData.Mo6,2))); + tenors.Add(new Tenor("1Y",Utility.FormatNumber(yieldCurveData.Yr1,2))); + tenors.Add(new Tenor("2Y",Utility.FormatNumber(yieldCurveData.Yr2,2))); + tenors.Add(new Tenor("3Y",Utility.FormatNumber(yieldCurveData.Yr3,2))); + tenors.Add(new Tenor("5Y",Utility.FormatNumber(yieldCurveData.Yr5,2))); + tenors.Add(new Tenor("7Y",Utility.FormatNumber(yieldCurveData.Yr7,2))); + tenors.Add(new Tenor("10Y",Utility.FormatNumber(yieldCurveData.Yr10,2))); + tenors.Add(new Tenor("20Y",Utility.FormatNumber(yieldCurveData.Yr20,2))); + tenors.Add(new Tenor("30Y",Utility.FormatNumber(yieldCurveData.Yr30,2))); + + List sourcePairs = new List(); + List destPairs = new List(); + + sourcePairs.Add(new Element(0,double.Parse(curveData.GetTenorValue("1D")))); + sourcePairs.Add(new Element(30,double.Parse(curveData.GetTenorValue("1M")))); + sourcePairs.Add(new Element(90,double.Parse(curveData.GetTenorValue("3M")))); + sourcePairs.Add(new Element(180,double.Parse(curveData.GetTenorValue("6M")))); + sourcePairs.Add(new Element(360,double.Parse(curveData.GetTenorValue("1Y")))); + sourcePairs.Add(new Element(720,double.Parse(curveData.GetTenorValue("2Y")))); + sourcePairs.Add(new Element(1080,double.Parse(curveData.GetTenorValue("3Y")))); + sourcePairs.Add(new Element(1800,double.Parse(curveData.GetTenorValue("5Y")))); + sourcePairs.Add(new Element(2520,double.Parse(curveData.GetTenorValue("7Y")))); + sourcePairs.Add(new Element(3600,double.Parse(curveData.GetTenorValue("10Y")))); + sourcePairs.Add(new Element(7200,double.Parse(curveData.GetTenorValue("20Y")))); + sourcePairs.Add(new Element(10800,double.Parse(curveData.GetTenorValue("30Y")))); + + for (int index = 0; index <= 10800; index++)destPairs.Add(new Element(index, 0)); + Element[] sourcePairsArray = sourcePairs.ToArray(); + Element[] destPairsArray = destPairs.ToArray(); + CatmullRom.PerformSpline(sourcePairsArray,destPairsArray); + for (int index = 0; index < destPairsArray.Length; index++) + { + if (!splineRates.ContainsKey((int)destPairsArray[index].Column)) + { + splineRates.Add((int)destPairsArray[index].Column, destPairsArray[index].Row); + } + } + } + } + + +// ************************************************************************************************************************************************************* + + public class TermStructureRatesGenerator + { + private TermStructureInterpolatorByDate termStructureInterpolatorByDate = new TermStructureInterpolatorByDate(); + + public TermStructureRatesGenerator() + { + } + public void Add(DateTime tradeDate) + { + if (termStructureInterpolatorByDate.ContainsKey(tradeDate)) return; + termStructureInterpolatorByDate.Add(tradeDate,new TermStructureInterpolator(tradeDate)); + } + public CurveData GetTermStructureCurve(DateTime tradeDate) + { + if (null == termStructureInterpolatorByDate||!termStructureInterpolatorByDate.ContainsKey(tradeDate)) return null; + TermStructureInterpolator termStructureInterpolator = termStructureInterpolatorByDate[tradeDate]; + return termStructureInterpolator.CurveData; + } + public double GetRate(DateTime tradeDate,int days) + { + if (!termStructureInterpolatorByDate.ContainsKey(tradeDate)) return double.NaN; + TermStructureInterpolator termStructureInterpolator = termStructureInterpolatorByDate[tradeDate]; + return termStructureInterpolator.GetRate(days); + } + } +} diff --git a/MarketData/MarketDataLib/Generator/TradeSignalWatchGenerator.cs b/MarketData/MarketDataLib/Generator/TradeSignalWatchGenerator.cs new file mode 100755 index 0000000..8d49e87 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/TradeSignalWatchGenerator.cs @@ -0,0 +1,102 @@ +//using System; +//using System.Collections.Generic; +//using System.Text; +//using MarketData.MarketDataModel; +//using MarketData.DataAccess; +//using MarketData.Utils; + +//namespace MarketData.Generator +//{ +// public delegate void ProgressHandler(String symbol); +// public class TradeSignalWatchGenerator +// { +// private TradeSignalWatchGenerator() +// { +// } +// public static List GenerateTradeSignalWatchList(String watchListName, String initialInvestment, String historicalDate, String macd,ProgressHandler progressHandler) +// { +// try +// { +// List tradeResultList = new List(); +// List symbols = WatchListDA.GetWatchList(watchListName); +// foreach (String symbol in symbols) +// { +// if (null != progressHandler) progressHandler(symbol); +// TradeResult tradeResult = TradeSignalSymbolDateWithResult(symbol, initialInvestment, historicalDate, macd, null, null); +// if(null!=tradeResult)tradeResultList.Add(tradeResult); +// } +// tradeResultList.Sort(); +// return tradeResultList; +// } +// catch (Exception exception) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,exception); +// return null; +// } +// } +// private static TradeResult TradeSignalSymbolDateWithResult(String symbol, String initialInvestment, String strHistoricalDate, String macd, String strStopLossThreshold, String strStopLossDays) +// { +// try +// { +// TradeResult tradeResult = new TradeResult(); +// DateGenerator dateGenerator = new DateGenerator(); +// MACDSetup macdSetup = null; +// double stopLossThreshold = 0.00; +// int stopLossDays = 0; + +// symbol = symbol.ToUpper(); +// tradeResult.Symbol = symbol; +// DateRange tradeDates = new DateRange(DateTime.Parse(strHistoricalDate), DateTime.Now); +// if (null != strStopLossThreshold) stopLossThreshold = Double.Parse(strStopLossThreshold); +// else stopLossThreshold = 0; +// if (null != strStopLossDays) stopLossDays = Int32.Parse(strStopLossDays); +// else stopLossDays = 0; +// double initialCash = double.Parse(initialInvestment); +// DateTime historicalDate = DateTime.Parse(strHistoricalDate); +// DateTime latestPricingDate = PricingDA.GetLatestDate(symbol); +// String companyName = PricingDA.GetNameForSymbol(symbol); +// if (null == macd) macdSetup = new MACDSetup(8, 17, 9); +// else macdSetup = new MACDSetup(macd); +// historicalDate = dateGenerator.GenerateHistoricalDate(historicalDate, macdSetup.Slow); +// tradeResult.Company = companyName; +// tradeResult.MACDSetup = macdSetup; +// tradeResult.StopLossThreshold = stopLossThreshold; +// tradeResult.StopLossDays = stopLossDays; +// if (latestPricingDate < historicalDate) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,"The historical date you are trying to run is later than the latest date for which prices are available."); +// return null; +// } +// tradeResult.InitialCash = initialCash; +// Dictionary pricesByDate = new Dictionary(); +// Prices prices = PricingDA.GetPrices(symbol, DateTime.Now, historicalDate); +// Price latestPrice = prices[0]; +// DateTime startDate = prices[0].Date; +// DateTime endDate = prices[prices.Count - 1].Date; +// tradeResult.StartDate = startDate; +// tradeResult.HistoricalDate = historicalDate; +// for (int index = 0; index < prices.Count; index++) pricesByDate.Add(prices[index].Date, prices[index]); +// MACDSignals macdSignals = MACDGenerator.GenerateMACD(prices, macdSetup); +// Signals signals = SignalGenerator.GenerateSignals(macdSignals); +// Portfolio portfolio = SignalTrader.TradeSignals(tradeDates, signals, prices, initialCash, stopLossThreshold, stopLossDays); +// tradeResult.AvailableCash = portfolio.AvailableCash; +// double portfolioValue = portfolio.GetPortfolioValue(latestPrice); +// double returnOnInvestment = (portfolioValue - initialCash) / initialCash; +// tradeResult.TotalPortfolioValue = portfolioValue; +// tradeResult.TotalGainLoss = portfolioValue - initialCash; +// tradeResult.ROI = returnOnInvestment; +// tradeResult.Trades = portfolio.Trades; +// tradeResult.AverageGainLoss = portfolio.GetAverageGainLoss(); +// tradeResult.AverageHoldingDays = portfolio.GetAverageHoldingDays(); +// tradeResult.MinimumHoldingDays = portfolio.GetMinHoldingDays(); +// tradeResult.MaximumHoldingDays = portfolio.GetMaxHoldingDays(); +// return tradeResult; +// } +// catch (Exception exception) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); +// return null; +// } +// } +// } +//} diff --git a/MarketData/MarketDataLib/Generator/ValuationGenerator.cs b/MarketData/MarketDataLib/Generator/ValuationGenerator.cs new file mode 100755 index 0000000..516ea68 --- /dev/null +++ b/MarketData/MarketDataLib/Generator/ValuationGenerator.cs @@ -0,0 +1,549 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MarketData.DataAccess; +using MarketData.Numerical; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.Generator +{ + public class ValuationGenerator + { + public delegate bool OnItemCompleteHandler(Valuation valuation); + public delegate void OnErrorItemHandler(String symbol,String message); + private ValuationGenerator() + { + } + public static Valuations GenerateValuations(List symbols,OnItemCompleteHandler onItemCompleteHandler=null,OnErrorItemHandler onErrorItemHandler=null) + { + try + { + Valuations valuations = new Valuations(); + valuations.ValuationDate = DateTime.Now; + Prices pricesIndex90 = PricingDA.GetPrices("SPY",90); + Prices pricesIndex720 = PricingDA.GetPrices("SPY", 720); + for (int index = 0; index < symbols.Count; index++) + { + Valuation valuation=GenerateValuation(symbols[index],pricesIndex90,pricesIndex720,onItemCompleteHandler,onErrorItemHandler); + if (null == valuation) continue; + valuations.Add(valuation); + if (null != onItemCompleteHandler) + { + if (!onItemCompleteHandler(valuation)) break; + } + } + TLBRankGenerator.ApplyTLBRanks(valuations); + AcquirersMultipeGenerator.ApplyRanks(valuations); + return valuations; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + } + public static Valuations GenerateValuations(OnItemCompleteHandler onItemCompleteHandler=null,OnErrorItemHandler onErrorItemHandler=null) + { + try + { + List symbols = PricingDA.GetSymbols(); + Valuations valuations = new Valuations(); + valuations.ValuationDate = DateTime.Now; + Prices pricesIndex90 = PricingDA.GetPrices("SPY",90); + Prices pricesIndex720 = PricingDA.GetPrices("SPY", 720); + for (int index = 0; index < symbols.Count; index++) + { + Valuation valuation=GenerateValuation(symbols[index],pricesIndex90,pricesIndex720,onItemCompleteHandler,onErrorItemHandler); + if (null == valuation) continue; + valuations.Add(valuation); + if (null != onItemCompleteHandler) + { + if (!onItemCompleteHandler(valuation)) break; + } + } + TLBRankGenerator.ApplyTLBRanks(valuations); + AcquirersMultipeGenerator.ApplyRanks(valuations); + return valuations; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + } + public static Valuation GenerateValuation(String symbol,Prices pricesIndex90,Prices pricesIndex720,OnItemCompleteHandler onItemCompleteHandler=null,OnErrorItemHandler onErrorItemHandler=null) + { + try + { + Valuation valuation = new Valuation(); + symbol = symbol.ToUpper(); + String companyName = PricingDA.GetNameForSymbol(symbol); + Price price = PricingDA.GetPrice(symbol); + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + Prices pricesSymbol90=PricingDA.GetPrices(symbol,90); + Prices pricesSymbol720=PricingDA.GetPrices(symbol,720); + if (null == price) + { + if (null != onErrorItemHandler) onErrorItemHandler(symbol, "No Prices."); + return null; + } + IncomeStatement incomeStatement=IncomeStatementDA.GetIncomeStatement(symbol,IncomeStatement.PeriodType.Annual); + CashflowStatement cashflowStatement=CashflowStatementDA.GetCashflowStatement(symbol,CashflowStatement.PeriodType.Annual); + BalanceSheet balanceSheet = BalanceSheetDA.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual); + TimeSeriesCollection bookValuePerShareCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.BVPS); + TimeSeriesCollection epsCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.EPS); + TimeSeriesCollection roicCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.ROIC); + TimeSeriesCollection revenueCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.Revenue); + TimeSeriesCollection freeCashflowCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.FreeCashflow); + TimeSeriesCollection operatingCashflowCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.OperatingCashflow); + TimeSeriesCollection workingCapitalCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.WorkingCapital); + if (null == bookValuePerShareCollection || 0 == bookValuePerShareCollection.Count) + { + bookValuePerShareCollection=new TimeSeriesCollection(); + TimeSeriesElement timeSeriesElement=new TimeSeriesElement(); + timeSeriesElement.AsOf=DateTime.Now; + timeSeriesElement.Value=0; + bookValuePerShareCollection.Add(new TimeSeriesElement()); + } + Fundamental fundamental = FundamentalDA.GetFundamental(symbol); + if (null == fundamental) + { + if (null != onErrorItemHandler) onErrorItemHandler(symbol, "No Fundamental Data."); + return null; + } + AnalystPriceTarget analystPriceTarget = AnalystPriceTargetDA.GetAnalystPriceTarget(symbol); +// These series are ordered by date with the latest date appearing at the lowest ordinal index. + float[] bookValuesPerShareSeries = bookValuePerShareCollection.ToFloat(); + float[] epsSeries = epsCollection.ToFloat(); + float[] roicSeries = roicCollection.ToFloat(); + float[] revenueSeries = revenueCollection.ToFloat(); + float[] freeCashflowSeries = freeCashflowCollection.ToFloat(); + float[] operatingCashflowSeries = operatingCashflowCollection.ToFloat(); + float[] workingCapitalSeries = workingCapitalCollection.ToFloat(); + double averageGrowth = Numerics.AverageReturn(ref bookValuesPerShareSeries); + double averageGrowth2Year = Numerics.AverageReturnTop(ref bookValuesPerShareSeries, 2); + double averageGrowth4Year = Numerics.AverageReturnTop(ref bookValuesPerShareSeries, 4); + double epsGrowth = Numerics.AverageReturn(ref epsSeries); + double epsGrowth2Year = Numerics.AverageReturnTop(ref epsSeries, 2); + double epsGrowth4Year = Numerics.AverageReturnTop(ref epsSeries, 4); + double roic = Numerics.Mean(ref roicSeries); + double revenueGrowth = Numerics.AverageReturn(ref revenueSeries); + double revenueGrowth2Year = Numerics.AverageReturnTop(ref revenueSeries, 2); + double revenueGrowth4Year = Numerics.AverageReturnTop(ref revenueSeries, 4); + double freeCashflowGrowth = Numerics.AverageReturn(ref freeCashflowSeries); + double averageOperatingCashflow = Numerics.Mean(ref operatingCashflowSeries); + double averageWorkingCapital = Numerics.Mean(ref workingCapitalSeries); + double latestPrice = price.Close; +// Shares Oustanding + valuation.SharesOutstanding=fundamental.SharesOutstanding; +// Dividend Yield + valuation.DividendYield=DividendHistoryGenerator.GetDividendYield(symbol); +// Benjamin Graham Formula. EPS=Trailing Twelve month, 8.5=PE base for no growth company, g=reasonably expected 7-10 year growth rate + double intrinsicValue =GrahamGenerator.IntrinsicValue(fundamental.EPS,epsGrowth); + valuation.FundamentalValue=GrahamGenerator.GrahamNumber(fundamental.EPS,fundamental.BookValuePerShare); + if(0!=fundamental.SharesOutstanding&&!double.IsNaN(fundamental.SharesOutstanding)&&null!=balanceSheet&&!double.IsNaN(balanceSheet.NetCurrentAssetValue))valuation.NetCurrentAssetValuePerShare=balanceSheet.NetCurrentAssetValue/fundamental.SharesOutstanding; + else valuation.NetCurrentAssetValuePerShare=double.NaN; + valuation.DebtToEquity=fundamental.DebtToEquity; +// ************************************************************************************************************************************************** + valuation.MarketCap=fundamental.MarketCap; + valuation.EnterpriseValue=fundamental.EnterpriseValue; + valuation.EBIT=fundamental.EBIT; +// ******************************************************* T H E L I T T L E B O O K ******************************************************* +// Calculate the earnings yield to be used by TLB rankings (TLB=The Little Book) +// earnings_yield=EBIT/EnterpriseValue + if(!double.IsNaN(fundamental.EBIT)&&null!=balanceSheet&&!double.IsNaN(balanceSheet.NetFixedAssets)) + { + valuation.LatestROC=fundamental.EBIT/balanceSheet.NetFixedAssets; + } + else valuation.LatestROC=double.NaN; + if(!double.IsNaN(fundamental.EBIT)&&!double.IsNaN(fundamental.EnterpriseValue)&&fundamental.EnterpriseValue>0.00&&fundamental.EBIT>0.00) + { + valuation.EarningsYield=fundamental.EBIT/fundamental.EnterpriseValue; + } + else valuation.EarningsYield=double.NaN; +// ******************************************************** T H E A C Q U I R E R S M U L T I P L E ******************************************** + if(null!=fundamental&&!double.IsNaN(fundamental.EnterpriseValue)&&null!=cashflowStatement&&!double.IsNaN(cashflowStatement.DepreciationAndAmortization)&&null!=incomeStatement&&!double.IsNaN(incomeStatement.TotalRevenue)&&!double.IsNaN(incomeStatement.CostOfRevenue)&&!double.IsNaN(incomeStatement.SGA)) + { + valuation.OperatingEarnings=incomeStatement.TotalRevenue-(cashflowStatement.DepreciationAndAmortization+incomeStatement.CostOfRevenue+incomeStatement.SGA); + valuation.AcquirersMultiple=fundamental.EnterpriseValue/valuation.OperatingEarnings; + } + else + { + valuation.OperatingEarnings=double.NaN; + valuation.AcquirersMultiple=double.NaN; + } +// ******************************************************************** S E C F O R M 1 3 D ********************************************************************************************* + SEC13Info sec13Info=SECFilingDA.GetSEC13Info(symbol); + if(sec13Info.SEC13) + { + valuation.SEC13=true; + valuation.SEC13FilingDate=sec13Info.MostRecentFilingDate; + } +// ***************************************************************************************************************************************************************************************** + valuation.Company=companyName.Replace(",", ""); + valuation.Symbol=symbol; + valuation.NextEarningsDate=fundamental.NextEarningsDate; + valuation.Beta90 = BetaGenerator.Beta(symbol, PricingDA.GetLatestDate(symbol),3); + valuation.Beta720 = BetaGenerator.Beta(symbol, PricingDA.GetLatestDate(symbol),24); + if (null != roicSeries && roicSeries.Length > 0) + { + valuation.ROICDates = Utility.FormatDates(roicCollection[roicCollection.Count - 1].AsOf, roicCollection[0].AsOf); + TimeSeriesElement[] roicTimeSeriesElement=(from roicItem in roicCollection select roicItem).OrderBy(roicItem => roicItem.AsOf).ToArray(); + double[] orderedROICValues=(from element in roicTimeSeriesElement select element.Value).ToArray(); + valuation.ROICSlope = Numerics.Slope(orderedROICValues); + valuation.LatestROIC=roicCollection[0].Value; + } + if (null != revenueSeries && revenueSeries.Length > 0 && null != balanceSheet && !double.IsNaN(balanceSheet.LongTermDebt)) + { + double latestRevenue = revenueSeries[0]; + valuation.LongTermDebt=balanceSheet.LongTermDebt; + valuation.Revenue=latestRevenue; + if (latestRevenue * 3 > balanceSheet.LongTermDebt) valuation.DebtLoad="Pass"; + else valuation.DebtLoad="Fail"; + } + else + { + valuation.LongTermDebt=double.NaN; + valuation.Revenue=double.NaN; + valuation.DebtLoad="N/A"; + } + valuation.AverageROIC=roic / 100.00; + if (null != bookValuePerShareCollection && 0 != bookValuePerShareCollection.Count) + { + valuation.BVPS = bookValuePerShareCollection[0].Value; + valuation.BVPSDates = Utility.FormatDates(bookValuePerShareCollection[bookValuePerShareCollection.Count - 1].AsOf, bookValuePerShareCollection[0].AsOf); + } + else valuation.BVPSDates = "N/A"; + valuation.AverageEquityGrowth=averageGrowth; + valuation.AverageEquityGrowth2Y=averageGrowth2Year; + valuation.AverageEquityGrowth4Y=averageGrowth4Year; + if (null != epsCollection && epsCollection.Count > 0) valuation.EPSDates = Utility.FormatDates(epsCollection[epsCollection.Count - 1].AsOf, epsCollection[0].AsOf); + else valuation.EPSDates="N/A"; + valuation.AverageEPSGrowth=epsGrowth; + valuation.AverageEPSGrowth2Y=epsGrowth2Year; + valuation.AverageEPSGrowth4Y=epsGrowth4Year; + if (null != revenueCollection && revenueCollection.Count > 0) valuation.RevenueDates = Utility.FormatDates(revenueCollection[revenueCollection.Count - 1].AsOf, revenueCollection[0].AsOf); + else valuation.RevenueDates="N/A"; + valuation.AverageRevenueGrowth=revenueGrowth; + valuation.AverageRevenueGrowth2Y=revenueGrowth2Year; + valuation.AverageRevenueGrowth4Y=revenueGrowth4Year; + valuation.AverageFreeCashflowGrowth=freeCashflowGrowth; + valuation.AverageOperatingCashflow=averageOperatingCashflow; + valuation.OperatingCashflow=null!=operatingCashflowSeries&&operatingCashflowSeries.Length>0?operatingCashflowSeries[0]:double.NaN; + valuation.AverageWorkingCapital=averageWorkingCapital; + if(null!=companyProfile) + { + valuation.Industry=companyProfile.Industry; + valuation.Sector=companyProfile.Sector; + } + valuation.EPS=fundamental.EPS; + valuation.PE=latestPrice / fundamental.EPS; + valuation.PEG = fundamental.PEG; + if(!double.IsNaN(valuation.BVPS)&&!double.IsNaN(latestPrice))valuation.PBVPS=latestPrice/valuation.BVPS; + if (!double.IsNaN(valuation.PE) && !double.IsNaN(valuation.PEG)) valuation.ImpliedEarningsGrowth = (valuation.PE / valuation.PEG) / 100.00; + StickerPrice stickerPrice = new StickerPrice(symbol); + valuation.BVPSItems = stickerPrice.BVPSItems; + valuation.AverageBVPSGrowth = stickerPrice.AverageBVPSGrowth; + valuation.LowPE=stickerPrice.LowPE; + valuation.TrailingPE=stickerPrice.TrailingPE; + valuation.AverageLowTrailing=stickerPrice.AverageLowTrailing; + valuation.CurrentStockEstimatePrice=stickerPrice.CurrentStockEstimatePrice; + valuation.PriceEstimate10Y=stickerPrice.PriceEstimate10y; + valuation.TodaysPriceForRequiredReturn=stickerPrice.TodaysPriceForRequiredReturn; + valuation.MOS=stickerPrice.MarginOfSafety; + valuation.MOS80=stickerPrice.MarginOfSafety80Pcnt; + valuation.IntrinsicValue=intrinsicValue; + valuation.RGV=intrinsicValue/latestPrice; + valuation.LatestPrice=latestPrice; + if (null != analystPriceTarget) + { + valuation.MeanTargetPrice=analystPriceTarget.MeanTargetPrice; + valuation.LowTargetPrice=analystPriceTarget.LowTargetPrice; + valuation.HighTargetPrice=analystPriceTarget.HighTargetPrice; + } + else + { + valuation.MeanTargetPrice=double.NaN; + valuation.LowTargetPrice=double.NaN; + valuation.HighTargetPrice=double.NaN; + } + valuation.UpsidePcnt = double.IsNaN(valuation.HighTargetPrice)||0>=valuation.HighTargetPrice ? double.NaN : (valuation.HighTargetPrice - valuation.LatestPrice) / valuation.LatestPrice; + valuation.DownsidePcnt=double.IsNaN(valuation.LowTargetPrice)||0>=valuation.LowTargetPrice?double.NaN:(valuation.LowTargetPrice-valuation.LatestPrice)/valuation.LatestPrice; + valuation.Bargain=latestPrice < stickerPrice.MarginOfSafety ? true : false; + valuation.Bargain80=latestPrice < stickerPrice.MarginOfSafety80Pcnt ? true : false; + return valuation; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Error calculating sticker for '" + symbol + "', exception was " + exception.ToString()); + return null; + } + } + public static Valuation GenerateValuationWithOverride(String symbol,Prices pricesIndex90,Prices pricesIndex720,double bvpsGrowthOverride,OnItemCompleteHandler onItemCompleteHandler=null,OnErrorItemHandler onErrorItemHandler=null) + { + try + { + Valuation valuation = new Valuation(); + symbol = symbol.ToUpper(); + String companyName = PricingDA.GetNameForSymbol(symbol); + Price price = PricingDA.GetPrice(symbol); + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + Prices pricesSymbol90=PricingDA.GetPrices(symbol,90); + Prices pricesSymbol720=PricingDA.GetPrices(symbol,720); + if (null == price) + { + if (null != onErrorItemHandler) onErrorItemHandler(symbol, "No Prices."); + return null; + } + BalanceSheet balanceSheet = BalanceSheetDA.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual); + IncomeStatement incomeStatement=IncomeStatementDA.GetIncomeStatement(symbol,IncomeStatement.PeriodType.Annual); + CashflowStatement cashflowStatement=CashflowStatementDA.GetCashflowStatement(symbol,CashflowStatement.PeriodType.Annual); +// These series are ordered by date with the latest date appearing at the lowest ordinal index + TimeSeriesCollection bookValuePerShareCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.BVPS); + TimeSeriesCollection epsCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.EPS); + TimeSeriesCollection roicCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.ROIC); + TimeSeriesCollection revenueCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.Revenue); + TimeSeriesCollection freeCashflowCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.FreeCashflow); + TimeSeriesCollection operatingCashflowCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.OperatingCashflow); + TimeSeriesCollection workingCapitalCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.WorkingCapital); + if (null == bookValuePerShareCollection || 0 == bookValuePerShareCollection.Count) + { + bookValuePerShareCollection=new TimeSeriesCollection(); + TimeSeriesElement timeSeriesElement=new TimeSeriesElement(); + timeSeriesElement.AsOf=DateTime.Now; + timeSeriesElement.Value=0; + bookValuePerShareCollection.Add(new TimeSeriesElement()); + } + Fundamental fundamental = FundamentalDA.GetFundamental(symbol); + if (null == fundamental) + { + if (null != onErrorItemHandler) onErrorItemHandler(symbol, "No Fundamental Data."); + return null; + } + AnalystPriceTarget analystPriceTarget = AnalystPriceTargetDA.GetAnalystPriceTarget(symbol); + float[] bookValuesPerShareSeries = bookValuePerShareCollection.ToFloat(); + float[] epsSeries = epsCollection.ToFloat(); + float[] roicSeries = roicCollection.ToFloat(); + float[] revenueSeries = revenueCollection.ToFloat(); + float[] freeCashflowSeries = freeCashflowCollection.ToFloat(); + float[] operatingCashflowSeries = operatingCashflowCollection.ToFloat(); + float[] workingCapitalSeries = workingCapitalCollection.ToFloat(); + double averageGrowth = bvpsGrowthOverride; + double averageGrowth2Year = bvpsGrowthOverride; + double averageGrowth4Year = bvpsGrowthOverride; + double epsGrowth = Numerics.AverageReturn(ref epsSeries); + double epsGrowth2Year = Numerics.AverageReturnTop(ref epsSeries, 2); + double epsGrowth4Year = Numerics.AverageReturnTop(ref epsSeries, 4); + double roic = Numerics.Mean(ref roicSeries); + double revenueGrowth = Numerics.AverageReturn(ref revenueSeries); + double revenueGrowth2Year = Numerics.AverageReturnTop(ref revenueSeries, 2); + double revenueGrowth4Year = Numerics.AverageReturnTop(ref revenueSeries, 4); + double freeCashflowGrowth = Numerics.AverageReturn(ref freeCashflowSeries); + double averageOperatingCashflow = Numerics.Mean(ref operatingCashflowSeries); + double averageWorkingCapital = Numerics.Mean(ref workingCapitalSeries); + double latestPrice = price.Close; +// Shares Oustanding + valuation.SharesOutstanding=fundamental.SharesOutstanding; +// Dividend Yield + valuation.DividendYield=DividendHistoryGenerator.GetDividendYield(symbol); +// Benjamin Graham Formula. EPS=Trailing Twelve month, 8.5=PE base for no growth company, g=reasonably expected 7-10 year growth rate + double intrinsicValue = GrahamGenerator.IntrinsicValue(fundamental.EPS,epsGrowth); + valuation.FundamentalValue=GrahamGenerator.GrahamNumber(fundamental.EPS,fundamental.BookValuePerShare); + if(0!=fundamental.SharesOutstanding&&!double.IsNaN(fundamental.SharesOutstanding)&&null!=balanceSheet&&!double.IsNaN(balanceSheet.NetCurrentAssetValue))valuation.NetCurrentAssetValuePerShare=balanceSheet.NetCurrentAssetValue/fundamental.SharesOutstanding; + else valuation.NetCurrentAssetValuePerShare=double.NaN; + valuation.DebtToEquity=fundamental.DebtToEquity; +// ************************************************************************************************************************************************** + valuation.MarketCap=fundamental.MarketCap; + valuation.EnterpriseValue=fundamental.EnterpriseValue; + valuation.EBIT=fundamental.EBIT; +// ******************************************************* T H E L I T T L E B O O K ******************************************************* +// Calculate the earnings yield to be used by TLB rankings (TLB=The Little Book) +// earnings_yield=EBIT/EnterpriseValue + if(!double.IsNaN(fundamental.EBIT)&&!double.IsNaN(fundamental.EnterpriseValue)&&fundamental.EnterpriseValue>0.00&&fundamental.EBIT>0.00) + { + valuation.EarningsYield=fundamental.EBIT/fundamental.EnterpriseValue; + } + else valuation.EarningsYield=double.NaN; +// ******************************************************** T H E A C Q U I R E R S M U L T I P L E ******************************************** + if(null!=fundamental&&!double.IsNaN(fundamental.EnterpriseValue)&&null!=cashflowStatement&&!double.IsNaN(cashflowStatement.DepreciationAndAmortization)&&null!=incomeStatement&&!double.IsNaN(incomeStatement.TotalRevenue)&&!double.IsNaN(incomeStatement.CostOfRevenue)&&!double.IsNaN(incomeStatement.SGA)) + { + valuation.OperatingEarnings=incomeStatement.TotalRevenue-(cashflowStatement.DepreciationAndAmortization+incomeStatement.CostOfRevenue+incomeStatement.SGA); + valuation.AcquirersMultiple=fundamental.EnterpriseValue/valuation.OperatingEarnings; + } + else + { + valuation.OperatingEarnings=double.NaN; + valuation.AcquirersMultiple=double.NaN; + } +// ******************************************************************** S E C F O R M 1 3 D ********************************************************************************************* + SEC13Info sec13Info=SECFilingDA.GetSEC13Info(symbol); + if(sec13Info.SEC13) + { + valuation.SEC13=true; + valuation.SEC13FilingDate=sec13Info.MostRecentFilingDate; + } +// ***************************************************************************************************************************************************************************************** + + if(null!=companyProfile) + { + valuation.Industry=companyProfile.Industry; + valuation.Sector=companyProfile.Sector; + } + valuation.Company=companyName.Replace(",", ""); + valuation.Symbol=symbol; + valuation.NextEarningsDate=fundamental.NextEarningsDate; + valuation.Beta90 = BetaGenerator.Beta(symbol, PricingDA.GetLatestDate(symbol), 3); + valuation.Beta720 = BetaGenerator.Beta(symbol, PricingDA.GetLatestDate(symbol), 24); + if (null != roicSeries && roicSeries.Length > 0) + { + valuation.ROICDates = Utility.FormatDates(roicCollection[roicCollection.Count - 1].AsOf, roicCollection[0].AsOf); + TimeSeriesElement[] roicTimeSeriesElement=(from roicItem in roicCollection select roicItem).OrderBy(roicItem => roicItem.AsOf).ToArray(); + double[] orderedROICValues=(from element in roicTimeSeriesElement select element.Value).ToArray(); + valuation.ROICSlope = Numerics.Slope(orderedROICValues); + valuation.LatestROIC=roicCollection[0].Value; + } + if (null != revenueSeries && revenueSeries.Length > 0 && null != balanceSheet && !double.IsNaN(balanceSheet.LongTermDebt)) + { + double latestRevenue = revenueSeries[0]; + valuation.LongTermDebt=balanceSheet.LongTermDebt; + valuation.Revenue=latestRevenue; + if (latestRevenue * 3 > balanceSheet.LongTermDebt) valuation.DebtLoad="Pass"; + else valuation.DebtLoad="Fail"; + } + else + { + valuation.LongTermDebt=double.NaN; + valuation.Revenue=double.NaN; + valuation.DebtLoad="N/A"; + } + valuation.AverageROIC=roic / 100.00; + if (null != bookValuePerShareCollection && 0 != bookValuePerShareCollection.Count) + { + valuation.BVPS = bookValuePerShareCollection[0].Value; + valuation.BVPSDates = Utility.FormatDates(bookValuePerShareCollection[bookValuePerShareCollection.Count - 1].AsOf, bookValuePerShareCollection[0].AsOf); + } + else valuation.BVPSDates = "N/A"; + valuation.AverageEquityGrowth=averageGrowth; + valuation.AverageEquityGrowth2Y=averageGrowth2Year; + valuation.AverageEquityGrowth4Y=averageGrowth4Year; + if (null != epsCollection && epsCollection.Count > 0) valuation.EPSDates = Utility.FormatDates(epsCollection[epsCollection.Count - 1].AsOf, epsCollection[0].AsOf); + else valuation.EPSDates="N/A"; + valuation.AverageEPSGrowth=epsGrowth; + valuation.AverageEPSGrowth2Y=epsGrowth2Year; + valuation.AverageEPSGrowth4Y=epsGrowth4Year; + if (null != revenueCollection && revenueCollection.Count > 0) valuation.RevenueDates = Utility.FormatDates(revenueCollection[revenueCollection.Count - 1].AsOf, revenueCollection[0].AsOf); + else valuation.RevenueDates="N/A"; + valuation.AverageRevenueGrowth=revenueGrowth; +// if (null != fundamental) valuation.AverageRevenueGrowthQtr=fundamental.QtrlyRevenueGrowth / 100.00; +// else valuation.AverageRevenueGrowthQtr=double.NaN; + valuation.AverageRevenueGrowth2Y=revenueGrowth2Year; + valuation.AverageRevenueGrowth4Y=revenueGrowth4Year; + valuation.AverageFreeCashflowGrowth=freeCashflowGrowth; + valuation.AverageOperatingCashflow=averageOperatingCashflow; + valuation.OperatingCashflow=null!=operatingCashflowSeries&&operatingCashflowSeries.Length>0?operatingCashflowSeries[0]:double.NaN; + valuation.AverageWorkingCapital=averageWorkingCapital; + valuation.EPS=fundamental.EPS; + valuation.PE=latestPrice / fundamental.EPS; + valuation.PEG = fundamental.PEG; + if(!double.IsNaN(valuation.BVPS)&&!double.IsNaN(latestPrice))valuation.PBVPS=latestPrice/valuation.BVPS; + if (!double.IsNaN(valuation.PE) && !double.IsNaN(valuation.PEG)) valuation.ImpliedEarningsGrowth = (valuation.PE / valuation.PEG) / 100.00; + StickerPrice stickerPrice = new StickerPrice(symbol,bvpsGrowthOverride); + valuation.BVPSItems = stickerPrice.BVPSItems; + valuation.AverageBVPSGrowth = stickerPrice.AverageBVPSGrowth; + valuation.LowPE=stickerPrice.LowPE; + valuation.TrailingPE=stickerPrice.TrailingPE; + valuation.AverageLowTrailing=stickerPrice.AverageLowTrailing; + valuation.CurrentStockEstimatePrice=stickerPrice.CurrentStockEstimatePrice; + valuation.PriceEstimate10Y=stickerPrice.PriceEstimate10y; + valuation.TodaysPriceForRequiredReturn=stickerPrice.TodaysPriceForRequiredReturn; + valuation.MOS=stickerPrice.MarginOfSafety; + valuation.MOS80=stickerPrice.MarginOfSafety80Pcnt; + valuation.IntrinsicValue=intrinsicValue; + valuation.RGV=intrinsicValue/latestPrice; + valuation.LatestPrice=latestPrice; + if (null != analystPriceTarget) + { + valuation.MeanTargetPrice=analystPriceTarget.MeanTargetPrice; + valuation.LowTargetPrice=analystPriceTarget.LowTargetPrice; + valuation.HighTargetPrice=analystPriceTarget.HighTargetPrice; + } + else + { + valuation.MeanTargetPrice=double.NaN; + valuation.LowTargetPrice=double.NaN; + valuation.HighTargetPrice=double.NaN; + } + valuation.UpsidePcnt = double.IsNaN(valuation.HighTargetPrice)||0>=valuation.HighTargetPrice ? double.NaN : (valuation.HighTargetPrice - valuation.LatestPrice) / valuation.LatestPrice; + valuation.DownsidePcnt=double.IsNaN(valuation.LowTargetPrice)||0>=valuation.LowTargetPrice?double.NaN:(valuation.LowTargetPrice-valuation.LatestPrice)/valuation.LatestPrice; + valuation.Bargain=latestPrice < stickerPrice.MarginOfSafety ? true : false; + valuation.Bargain80=latestPrice < stickerPrice.MarginOfSafety80Pcnt ? true : false; + return valuation; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Error calculating sticker for '" + symbol + "', exception was " + exception.ToString()); + return null; + } + } + public static String ToString(Valuation valuation) + { + StringBuilder sb = new StringBuilder(); + sb.Append(valuation.Company).Append(","); + sb.Append(valuation.Symbol).Append(","); + sb.Append(Utility.DateTimeToStringMMHDDHYYYY(valuation.NextEarningsDate)).Append(","); + sb.Append(Utility.FormatNumber(valuation.LongTermDebt)).Append(","); + sb.Append(Utility.FormatNumber(valuation.Revenue)).Append(","); + sb.Append(valuation.DebtLoad).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageROIC)).Append(","); + sb.Append(valuation.BVPSDates).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageEquityGrowth)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageEquityGrowth2Y)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageEquityGrowth4Y)).Append(","); + sb.Append(valuation.EPSDates).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageEPSGrowth)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageEPSGrowth2Y)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageEPSGrowth4Y)).Append(","); + sb.Append(valuation.RevenueDates).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageRevenueGrowth)).Append(","); +// sb.Append(valuation.AverageRevenueGrowthQtr).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageRevenueGrowth2Y)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageRevenueGrowth4Y)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageFreeCashflowGrowth)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageOperatingCashflow)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageWorkingCapital)).Append(","); + sb.Append(Utility.FormatNumber(valuation.BVPS)).Append(","); + sb.Append(Utility.FormatNumber(valuation.EPS)).Append(","); + sb.Append(Utility.FormatNumber(valuation.PE)).Append(","); + sb.Append(Utility.FormatNumber(valuation.PEG)).Append(","); + sb.Append(Utility.FormatNumber(valuation.ImpliedEarningsGrowth)).Append(","); + sb.Append(Utility.FormatNumber(valuation.LowPE)).Append(","); + sb.Append(Utility.FormatNumber(valuation.TrailingPE)).Append(","); + sb.Append(Utility.FormatNumber(valuation.AverageLowTrailing)).Append(","); + sb.Append(Utility.FormatNumber(valuation.CurrentStockEstimatePrice)).Append(","); + sb.Append(Utility.FormatNumber(valuation.PriceEstimate10Y)).Append(","); + sb.Append(Utility.FormatNumber(valuation.TodaysPriceForRequiredReturn)).Append(","); + sb.Append(Utility.FormatNumber(valuation.MOS)).Append(","); + sb.Append(Utility.FormatNumber(valuation.MOS80)).Append(","); + sb.Append(Utility.FormatNumber(valuation.IntrinsicValue)).Append(","); + sb.Append(Utility.FormatNumber(valuation.RGV)).Append(","); + sb.Append(Utility.FormatNumber(valuation.LatestPrice)).Append(","); + sb.Append(Utility.FormatNumber(valuation.UpsidePcnt)).Append(","); + sb.Append(Utility.FormatNumber(valuation.DownsidePcnt)).Append(","); + sb.Append(Utility.FormatNumber(valuation.MeanTargetPrice)).Append(","); + sb.Append(Utility.FormatNumber(valuation.LowTargetPrice)).Append(","); + sb.Append(Utility.FormatNumber(valuation.HighTargetPrice)).Append(","); + sb.Append(valuation.Bargain ? true : false).Append(","); + sb.Append(valuation.Bargain80 ? true : false).Append(","); + sb.Append(Utility.FormatNumber(valuation.DividendYield)); + return sb.ToString(); + } + public static String Heading() + { + StringBuilder sb = new StringBuilder(); + sb.Append("Company,Symbol,NextEarningDate,LongTermDebt,Revenue,DebtLoad,ROIC(Avg%),BVPSDates,AvgEquityGrowth(AvgBVPS%),AvgEquityGrowth_2Y(AvgBVPS%),AvgEquityGrowth_4Y(AvgBVPS%),EPSDates,EPSGrowth(Avg%),EPSGrowth_2Y(Avg%),EPSGrowth_4Y(Avg%),RevenueDates,RevenueGrowth(Avg%),RevenueGrowth_QTR(Avg%),RevenueGrowth_2Y(Avg%),RevenueGrowth_4Y(Avg%),FreeCashflowGrowth(Avg%),OperatingCashflow(Avg),WorkingCapital(Avg),BVPS,EPS,PE,PEG,ImpliedEarningsGrowth,LowPE,TrailingPE,AverageLowTrailing,CurrentStockEstimatePrice,PriceEstimate10y,TodaysPriceForRequiredReturn,MOS,MOS(80%),IntrinsicValue,RGV(sb>1),LatestPrice,UpsidePcnt,DownsidePcnt,MeanTargetPrice,LowTargetPrice,HighPrice,Bargain(MOS),Bargain(MOS80%),DividendYield"); + return sb.ToString(); + } + } +} diff --git a/MarketData/MarketDataLib/Helper/AnalystPriceTargetMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/AnalystPriceTargetMarketDataHelper.cs new file mode 100755 index 0000000..b9309b2 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/AnalystPriceTargetMarketDataHelper.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class AnalystPriceTargetMarketDataHelper : MarketDataHelperBase + { + private static int MaxThreads = 10; //(int)ThreadHelperEnum.MaxThreads; + private static int SLEEP_TIME_MS = 500; + + public AnalystPriceTargetMarketDataHelper() + { + } + public bool LoadAnalystPriceTarget(String symbol=null) + { + Profiler profiler=new Profiler(); + try + { + if(symbol==null)Queue=PricingDA.GetSymbols(); + else (Queue=new List()).Add(symbol); + ShuffleQueue(); // shuffle up the symbols + Index=-1; + ManualResetEvent[] resetEvents = new ManualResetEvent[MaxThreads]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)resetEvents[eventIndex] = new ManualResetEvent(true); + MDTrace.WriteLine(String.Format("Queuing analyst price target fetches ...")); + DateTime modified=DateTime.Now; + while (true) + { + ManualResetEvent[] availableEvents=GetAvailableEvents(resetEvents); + ManualResetEvent[] busyEvents=GetBusyEvents(resetEvents); + if (null == PeekQueueItem() && 0==busyEvents.Length) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Analyst price target queue contains {0} items, busy events {1}, all done.",0,busyEvents.Length)); + break; + } + for (int index = 0; index < availableEvents.Length; index++) + { + symbol=GetQueueItem(); + if (null != symbol) + { + availableEvents[index].Reset(); + ThreadHelper analystPriceTargetThreadHelper = new ThreadHelper(symbol,modified,availableEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadAnalystPriceTarget, analystPriceTargetThreadHelper); + try { Thread.Sleep(SLEEP_TIME_MS); }catch (Exception) { ;} + } + else + { + busyEvents=GetBusyEvents(resetEvents); + if(busyEvents.Length!=availableEvents.Length) + { + ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length]; + Array.Copy(busyEvents, resizedEvents,busyEvents.Length); + resetEvents = resizedEvents; + } + break; + } + } // for + MDTrace.WriteLine(LogLevel.DEBUG,"Analyst price target waiting for free slots..."); + if(resetEvents.Length>0)WaitHandle.WaitAny(resetEvents); + if(null==PeekQueueItem())resetEvents=ResizeEvents(resetEvents); + } // while + MDTrace.WriteLine(LogLevel.DEBUG,"Analyst price target completed."); + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadAnalystPriceTarget]End, total took {0}(ms)",profiler.End())); + } + } + public void ThreadPoolCallbackLoadAnalystPriceTarget(Object analystPriceTargetThreadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)analystPriceTargetThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load analyst price target, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadAnalystPriceTargetEx(threadHelper.Symbol,threadHelper.Modified); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load analyst price target, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } +// Single threaded method, use for debugging a single symbol fetch without going through the queue + public static void LoadAnalystPriceTargetEx(String symbol,DateTime modified) + { + if (!AnalystPriceTargetDA.CheckAnalystPriceTargetModifiedOn(symbol, modified)) + { + LoadAnalystPriceTargetEx(symbol); + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,"Already have analyst price target for '"+symbol+"' on "+Utility.DateTimeToStringMMHDDHYYYY(modified)); + } + } + public static void LoadAnalystPriceTargetEx(String symbol) + { + try + { + MDTrace.WriteLine(LogLevel.DEBUG,"Loading analyst price target for for '" + symbol + "'"); + AnalystPriceTarget analystPriceTarget = MarketDataHelper.GetAnalystPriceTarget(symbol); + if (null != analystPriceTarget) + { + AnalystPriceTargetDA.InsertAnalystPriceTarget(analystPriceTarget); + MDTrace.WriteLine(LogLevel.DEBUG,""); + MDTrace.WriteLine(LogLevel.DEBUG,AnalystPriceTarget.Header); + MDTrace.WriteLine(LogLevel.DEBUG,analystPriceTarget.ToString()); + MDTrace.WriteLine(LogLevel.DEBUG,""); + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Failed to load analyst price target for '" + symbol + "'"); + MDTrace.WriteLine(LogLevel.DEBUG,"Exception was " + exception.ToString()); + } + } + } +} + + diff --git a/MarketData/MarketDataLib/Helper/BollingerBandHelperSheet.cs b/MarketData/MarketDataLib/Helper/BollingerBandHelperSheet.cs new file mode 100755 index 0000000..f341c81 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/BollingerBandHelperSheet.cs @@ -0,0 +1,144 @@ +// using System; +// using System.IO; +// using Microsoft.Office.Interop.Excel; +// using MarketData.DataAccess; +// using MarketData.MarketDataModel; +// using MarketData.Generator; +// using MarketData.Utils; + +// namespace MarketData.Helper +// { +// public class BollingerBandSheetHelper +// { +// public BollingerBandSheetHelper() +// { +// } +// public static bool GenerateBollingerBandSheet(String strPathTemplateFile,String symbol,int movingAverageDays,int historicalDays) +// { +// Microsoft.Office.Interop.Excel.Application excelApp = null; +// Microsoft.Office.Interop.Excel.Workbook workbook = null; +// Microsoft.Office.Interop.Excel.Worksheet worksheet = null; +// Microsoft.Office.Interop.Excel.Sheets worksheets = null; +// int rowOffset = 1; +// try +// { +// String currentWorkingDirectory = Directory.GetCurrentDirectory(); +// if (!File.Exists(strPathTemplateFile)) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,"Cannot locate "+strPathTemplateFile); +// return false; +// } +// DateGenerator dateGenerator = new DateGenerator(); +// DateTime startDate = dateGenerator.GetPrevBusinessDay(DateTime.Now); +// Prices prices = PricingDA.GetPrices(symbol,startDate,historicalDays); +// if (null == prices || 0 == prices.Count) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,"No prices for "+symbol); +// return false; +// } +// Price price = prices[0]; +// String pathOutputFile = currentWorkingDirectory + "\\" + symbol + "-BB-" + Utility.DateTimeToStringMMHDDHYYYY(price.Date); +// MDTrace.WriteLine(LogLevel.DEBUG,"Generating "+pathOutputFile); +// String companyName = PricingDA.GetNameForSymbol(symbol); +// File.Delete(pathOutputFile+".xlsx"); +// excelApp = new Microsoft.Office.Interop.Excel.Application(); +// excelApp.ScreenUpdating=false; +// workbook = excelApp.Workbooks.Open(strPathTemplateFile, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false); +// worksheets = workbook.Worksheets; +// worksheet = (Microsoft.Office.Interop.Excel.Worksheet)worksheets.get_Item("Sheet1"); +// Microsoft.Office.Interop.Excel.ChartObjects chartObjects = worksheet.ChartObjects(); +// Microsoft.Office.Interop.Excel.ChartObject chartObject = chartObjects.Item(1); +// chartObject.Chart.ChartTitle.Text = companyName + " (" + symbol + ") "+Utility.DateTimeToStringMMHDDHYYYY(prices[prices.Count-1].Date)+" Thru "+Utility.DateTimeToStringMMHDDHYYYY(price.Date); +// BollingerBands bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices, movingAverageDays); +// Axis vertAxis = (Axis)chartObject.Chart.Axes(XlAxisType.xlValue, XlAxisGroup.xlPrimary); +// vertAxis.MaximumScaleIsAuto = false; +// vertAxis.MaximumScale = GetMaxData(bollingerBands); +// vertAxis.MinimumScaleIsAuto = false; +// vertAxis.MinimumScale = GetMinData(bollingerBands); +// vertAxis.HasMajorGridlines = true; +// Axis horzAxis = (Axis)chartObject.Chart.Axes(XlAxisType.xlCategory, XlAxisGroup.xlPrimary); +// horzAxis.HasMajorGridlines = true; +// for (int index = 0; index < bollingerBands.Count; index++) +// { +// BollingerBandElement bollingerBandElement = bollingerBands[index]; +// worksheet.Cells[index + 1 + rowOffset, 1] = bollingerBandElement.Date; +// worksheet.Cells[index + 1 + rowOffset, 2] = bollingerBandElement.Symbol; +// worksheet.Cells[index + 1 + rowOffset, 3] = bollingerBandElement.Open; +// worksheet.Cells[index + 1 + rowOffset, 4] = bollingerBandElement.High; +// worksheet.Cells[index + 1 + rowOffset, 5] = bollingerBandElement.Low; +// worksheet.Cells[index + 1 + rowOffset, 6] = bollingerBandElement.Close; +// worksheet.Cells[index + 1 + rowOffset, 7] = bollingerBandElement.Volume; +// worksheet.Cells[index + 1 + rowOffset, 8] = bollingerBandElement.SMAN; +// worksheet.Cells[index + 1 + rowOffset, 9] = bollingerBandElement.StDevN; +// worksheet.Cells[index + 1 + rowOffset, 10] = bollingerBandElement.K; +// worksheet.Cells[index + 1 + rowOffset, 11] = bollingerBandElement.L; +// worksheet.Cells[index + 1 + rowOffset, 12] = bollingerBandElement.KL1; +// worksheet.Cells[index + 1 + rowOffset, 13] = bollingerBandElement.LP1; +// } +// workbook.SaveAs(pathOutputFile, Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Microsoft.Office.Interop.Excel.XlSaveConflictResolution.xlUserResolution, true, Type.Missing, Type.Missing, Type.Missing); +// return true; +// } +// catch (Exception exception) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); +// return false; +// } +// finally +// { +// if (null != worksheet) ReleaseObject(worksheet); +// if (null != worksheets) ReleaseObject(worksheets); +// if (null != workbook) ReleaseObject(workbook); +// excelApp.Quit(); +// } +// } +// private static double GetMinData(BollingerBands bollingerBands) +// { +// double minData = double.MaxValue; +// for (int index = 0; index < bollingerBands.Count; index++) +// { +// BollingerBandElement bollingerBandElement = bollingerBands[index]; +// if(bollingerBandElement.Open maxData) maxData = bollingerBandElement.Open; +// if (bollingerBandElement.High > maxData) maxData = bollingerBandElement.High; +// if (bollingerBandElement.Low > maxData) maxData = bollingerBandElement.Low; +// if (bollingerBandElement.K > maxData) maxData = bollingerBandElement.K; +// if (bollingerBandElement.L > maxData) maxData = bollingerBandElement.L; +// if (bollingerBandElement.KL1 > maxData) maxData = bollingerBandElement.KL1; +// if (bollingerBandElement.LP1 > maxData) maxData = bollingerBandElement.LP1; +// } +// return maxData+(maxData*.05); +// } +// private static void ReleaseObject(object obj) +// { +// try +// { +// System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj); +// obj = null; +// } +// catch (Exception ex) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,ex.ToString()); +// obj = null; +// } +// finally +// { +// GC.Collect(); +// } +// } +// } +// } \ No newline at end of file diff --git a/MarketData/MarketDataLib/Helper/CIKMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/CIKMarketDataHelper.cs new file mode 100755 index 0000000..ff97ec8 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/CIKMarketDataHelper.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class CIKMarketDataHelper + { + private static int MaxThreads = (int)ThreadHelperEnum.MaxThreads; + private List symbols; + private int currentIndex = 0; + + public CIKMarketDataHelper() + { + } + public bool UpdateAllMissingCIK() + { + Profiler profiler=new Profiler(); + try + { + symbols = PricingDA.GetSymbolsForNullCIK(); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper cikThreadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdateMissingCIK, cikThreadHelper); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load CIK, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateAllMissingCIK]End, total took {0}(ms)",profiler.End())); + } + } + private List GetQueueSymbols() + { + List queueSymbols = new List(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < symbols.Count; index++) + { + queueSymbols.Add(symbols[index]); + } + currentIndex = index; + return queueSymbols; + } + public void ThreadPoolCallbackUpdateMissingCIK(Object threadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)threadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load CIK, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + UpdateMissingCIKEx(threadHelper.Symbol); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load CIK, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } + public static void UpdateMissingCIKEx(String symbol) + { + DateGenerator dateGenerator = new DateGenerator(); + String cik = MarketDataHelper.GetCIK(symbol); + if (null == cik) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No CIK for symbol {0}",symbol)); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("CIK for symbol {0}={1}",symbol,cik)); + PricingDA.UpdateCIKForSymbol(symbol, cik); + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/CompanyProfileMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/CompanyProfileMarketDataHelper.cs new file mode 100755 index 0000000..6e07cb3 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/CompanyProfileMarketDataHelper.cs @@ -0,0 +1,131 @@ +using System; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class CompanyProfileThreadHelper : ThreadHelper + { + public CompanyProfile CompanyProfile{get;set;} + + public CompanyProfileThreadHelper() + { + } + public CompanyProfileThreadHelper(CompanyProfile companyProfile, ManualResetEvent resetEvent) + { + CompanyProfile=companyProfile; + ResetEvent=resetEvent; + } + } + public class CompanyProfileMarketDataHelper + { + private static int MaxThreads = (int)ThreadHelperEnum.MaxThreads; + private CompanyProfiles companyProfiles; + private int currentIndex = 0; + + public CompanyProfileMarketDataHelper() + { + } + public bool UpdateCompanyProfile(String symbol) + { + Profiler profiler=new Profiler(); + try + { + companyProfiles=new CompanyProfiles(); + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + if(null==companyProfile)return false; + companyProfiles.Add(companyProfile); + currentIndex = 0; + while (true) + { + CompanyProfiles queueProfiles = GetQueueProfiles(); + if (null == queueProfiles || 0 == queueProfiles.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueProfiles.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueProfiles.Count; index++) + { + CompanyProfileThreadHelper companyProfileThreadHelper = new CompanyProfileThreadHelper(queueProfiles[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallback, companyProfileThreadHelper); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load company profile, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateCompanyProfiles]End, total took {0}(ms)",profiler.End())); + } + } + public bool UpdateCompanyProfiles() + { + Profiler profiler=new Profiler(); + try + { + companyProfiles=CompanyProfileDA.GetCompanyProfiles(); + currentIndex = 0; + while (true) + { + CompanyProfiles queueProfiles = GetQueueProfiles(); + if (null == queueProfiles || 0 == queueProfiles.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueProfiles.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueProfiles.Count; index++) + { + CompanyProfileThreadHelper companyProfileThreadHelper = new CompanyProfileThreadHelper(queueProfiles[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallback, companyProfileThreadHelper); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load company profile, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateCompanyProfiles]End, total took {0}(ms)",profiler.End())); + } + } + private CompanyProfiles GetQueueProfiles() + { + CompanyProfiles queueProfiles = new CompanyProfiles(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < companyProfiles.Count; index++) + { + queueProfiles.Add(companyProfiles[index]); + } + currentIndex = index; + return queueProfiles; + } + public void ThreadPoolCallback(Object companyProfileThreadHelperContext) + { + CompanyProfileThreadHelper companyProfileThreadHelper = (CompanyProfileThreadHelper)companyProfileThreadHelperContext; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load profile, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, companyProfileThreadHelper.CompanyProfile.Symbol)); + LoadCompanyProfileEx(companyProfileThreadHelper.CompanyProfile); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load profile, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, companyProfileThreadHelper.CompanyProfile.Symbol)); + companyProfileThreadHelper.ResetEvent.Set(); + } + private static void LoadCompanyProfileEx(CompanyProfile companyProfile) + { + CompanyProfile marketCompanyProfile = MarketDataHelper.GetCompanyProfile(companyProfile.Symbol); + if (null == marketCompanyProfile) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No company profile for symbol '" + companyProfile.Symbol + "'"); + return; + } + if(!String.IsNullOrEmpty(marketCompanyProfile.Sector) && !marketCompanyProfile.Sector.Equals("N/A"))companyProfile.Sector=marketCompanyProfile.Sector; + if(!String.IsNullOrEmpty(marketCompanyProfile.Industry) && !marketCompanyProfile.Industry.Equals("N/A"))companyProfile.Industry=marketCompanyProfile.Industry; + if(!String.IsNullOrEmpty(marketCompanyProfile.Description) && !marketCompanyProfile.Description.Equals("N/A"))companyProfile.Description=marketCompanyProfile.Description; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("LoadCompanyProfileEx: Updating company profile.....Symbol:{0} Sector:{1} Industry:{2}",companyProfile.Symbol,companyProfile.Sector, companyProfile.Industry)); + CompanyProfileDA.UpdateCompanyProfile(companyProfile); + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/DividendHistoryMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/DividendHistoryMarketDataHelper.cs new file mode 100755 index 0000000..8a4b9ef --- /dev/null +++ b/MarketData/MarketDataLib/Helper/DividendHistoryMarketDataHelper.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class DividendHistoryThreadHelper : ThreadHelper + { + public DividendHistoryThreadHelper() + { + } + public DividendHistoryThreadHelper(String symbol, ManualResetEvent resetEvent) + { + Symbol=symbol; + ResetEvent=resetEvent; + } + public DividendHistoryThreadHelper(String symbol, DateTime modified,ManualResetEvent resetEvent) + { + Symbol=symbol; + Modified=modified; + ResetEvent=resetEvent; + } + + } + public class DividendHistoryMarketDataHelper + { + private static int MaxThreads =10; //2;//(int)ThreadHelperEnum.MaxThreads; + private static int WAIT_TIME_MS=1000; // wait between request + private static Random generator=new Random(); + private List symbols; + private int currentIndex = 0; + private static int successHits=0; + + public DividendHistoryMarketDataHelper() + { + } + public static int NextRandom(int min,int max) + { + return generator.Next(min,max); + } + public bool UpdateDividendHistory(String symbol) + { + Profiler profiler=new Profiler(); + try + { + symbols = new List(); + symbols.Add(symbol); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new DividendHistoryThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadDividendHistory, threadHelper); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load dividend history, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateDividendHistory]End, total took {0}(ms)",profiler.End())); + } + } + public bool UpdateDividendHistory() + { + Profiler profiler=new Profiler(); + try + { + symbols = PricingDA.GetSymbols(); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new DividendHistoryThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadDividendHistory, threadHelper); + try { Thread.Sleep(WAIT_TIME_MS); }catch(Exception) { ;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load dividend history, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateDividendHistory]End, total took {0}(ms)",profiler.End())); + } + } + private List GetQueueSymbols() + { + List queueSymbols = new List(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < symbols.Count; index++) + { + queueSymbols.Add(symbols[index]); + } + currentIndex = index; + return queueSymbols; + } + public void ThreadPoolCallbackLoadDividendHistory(Object threadHelperContext) + { + DividendHistoryThreadHelper threadHelper = (DividendHistoryThreadHelper)threadHelperContext; + try + { // nasdaq website is very bot sensitive. this is why all the sleeps and delays here in this block + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load dividend history, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + if(UpdateDividendHistoryEx(threadHelper.Symbol))successHits++; + //if(successHits>100) + //{ + // successHits=0; + // MDTrace.WriteLine(LogLevel.DEBUG,"Pausing for 60 seconds."); + // Thread.Sleep(60000); + //} + //else if(1==DividendHistoryMarketDataHelper.NextRandom(1,20)) + //{ + // MDTrace.WriteLine(LogLevel.DEBUG,"Pausing for 10 seconds."); + // Thread.Sleep(10000); + //} + //else if(1==DividendHistoryMarketDataHelper.NextRandom(1,100)) + //{ + // MDTrace.WriteLine(LogLevel.DEBUG,"Pausing for 30 seconds."); + // Thread.Sleep(30000); + //} + //else Thread.Sleep(50); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load dividend history, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } + public static bool UpdateDividendHistoryEx(String symbol) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Retrieving dividend history for " + symbol); + DividendHistory dividendHistory = MarketDataHelper.GetDividendHistory(symbol); + if (null == dividendHistory || 0 == dividendHistory.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Unable to retrieve dividend history for " + symbol); + return false; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Got {0} dividend history records for {1}", dividendHistory.Count, symbol)); + MDTrace.WriteLine(LogLevel.DEBUG,"Adding..."); + if (DividendHistoryDA.InsertOrUpdate(dividendHistory)) MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Added {0} dividend history records for {1}", dividendHistory.Count, symbol)); + else MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Failed to update dividend history for {0}", symbol)); + return true; + } + } +} + + diff --git a/MarketData/MarketDataLib/Helper/ETFHoldingsMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/ETFHoldingsMarketDataHelper.cs new file mode 100755 index 0000000..f6a04b8 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/ETFHoldingsMarketDataHelper.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class ETFHoldingsMarketDataHelper + { + private static int MaxThreads = 10; // 5 (int)ThreadHelperEnum.MaxThreads; + private List symbols; + private int currentIndex = 0; + private int WAIT_BETWEEN_REQUESTS=250; // 500 + + public ETFHoldingsMarketDataHelper() + { + } + public bool LoadETFHoldings(String symbol) + { + Profiler profiler=new Profiler(); + try + { + symbols = new List(); + symbols.Add(symbol); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadETFHoldings, threadHelper); + try{Thread.Sleep(WAIT_BETWEEN_REQUESTS);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load ETF Holdings, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadETFHoldings]End, total took {0}(ms)",profiler.End())); + } + } + public bool LoadETFHoldings() + { + Profiler profiler=new Profiler(); + try + { + symbols = PricingDA.GetSymbolsETF(); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadETFHoldings, threadHelper); + try{Thread.Sleep(WAIT_BETWEEN_REQUESTS);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load ETF Holdings, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadETFHoldings]End, total took {0}(ms)",profiler.End())); + } + } + private List GetQueueSymbols() + { + List queueSymbols = new List(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < symbols.Count; index++) + { + queueSymbols.Add(symbols[index]); + } + currentIndex = index; + return queueSymbols; + } + public void ThreadPoolCallbackLoadETFHoldings(Object threadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)threadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load ETF Holdings, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadETFHoldingsEx(threadHelper.Symbol); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load ETF Holdings, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } + public static void LoadETFHoldingsEx(String symbol) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Retrieving holdings for " + symbol); + ETFHoldings etfHoldings = MarketDataHelper.GetETFHoldings(symbol); + if (null == etfHoldings || 0 == etfHoldings.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Error retreiving ETF holdings for '"+symbol+"'"); + return; + } + if (!ETFHoldingsDA.InsertOrUpdate(etfHoldings)) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Error adding ETF holdings for " + symbol); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,"********* E T F H O L D I N G S ********"); + foreach (ETFHolding etfHolding in etfHoldings) + { + MDTrace.WriteLine(LogLevel.DEBUG,etfHolding.ETFSymbol + ","+etfHolding.HoldingSymbol + "," + etfHolding.HoldingSymbolShareClass + "," + etfHolding.HoldingCompanyName); + } + MDTrace.WriteLine(LogLevel.DEBUG,"************************"); + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/EarningsAnnouncementsMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/EarningsAnnouncementsMarketDataHelper.cs new file mode 100755 index 0000000..9243154 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/EarningsAnnouncementsMarketDataHelper.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class EarningsAnnouncementsMarketDataHelper : MarketDataHelperBase + { + private static int MaxThreads = 7; // (int)ThreadHelperEnum.MaxThreads; + + public EarningsAnnouncementsMarketDataHelper() + { + } + public bool UpdateEarningsAnnouncements(String symbol=null) + { + Profiler profiler=new Profiler(); + try + { + if(symbol==null)Queue=PricingDA.GetSymbols(); + else (Queue=new List()).Add(symbol); + Index=-1; + ManualResetEvent[] resetEvents = new ManualResetEvent[MaxThreads]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)resetEvents[eventIndex] = new ManualResetEvent(true); + MDTrace.WriteLine(String.Format("Queuing earnings announcement fetches ...")); + DateTime modified=DateTime.Now; + while (true) + { + ManualResetEvent[] availableEvents=GetAvailableEvents(resetEvents); + ManualResetEvent[] busyEvents=GetBusyEvents(resetEvents); + if (null == PeekQueueItem() && 0==busyEvents.Length) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Earnings announcement queue contains {0} items, busy events {1}, all done.",0,busyEvents.Length)); + break; + } + for (int index = 0; index < availableEvents.Length; index++) + { + symbol=GetQueueItem(); + if (null != symbol) + { + availableEvents[index].Reset(); + ThreadHelper earningsAnnouncementsThreadHelper = new ThreadHelper(symbol,modified,availableEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackEarningsAnnouncements, earningsAnnouncementsThreadHelper); + } + else + { + busyEvents=GetBusyEvents(resetEvents); + if(busyEvents.Length!=availableEvents.Length) + { + ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length]; + Array.Copy(busyEvents, resizedEvents,busyEvents.Length); + resetEvents = resizedEvents; + } + break; + } + } // for + MDTrace.WriteLine(LogLevel.DEBUG,"Earnings announcements waiting for free slots..."); + if(resetEvents.Length>0)WaitHandle.WaitAny(resetEvents); + if(null==PeekQueueItem())resetEvents=ResizeEvents(resetEvents); + } // while + MDTrace.WriteLine(LogLevel.DEBUG,"Earnings announcements completed."); + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateEarningsAnnouncements]End, total took {0}(ms)",profiler.End())); + } + } + public void ThreadPoolCallbackEarningsAnnouncements(Object earningsAnnouncementsThreadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)earningsAnnouncementsThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load earnings announcements, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadEarningsAnnouncementsEx(threadHelper.Symbol,threadHelper.Modified); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load earnings announcements, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } +// Single threaded method, use for debugging a single symbol fetch without going through the queue + public static void LoadEarningsAnnouncementsEx(String symbol,DateTime modified) + { + EarningsAnnouncements earningsAnnouncements=MarketDataHelper.GetEarningsAnnouncements(symbol); + if(null==earningsAnnouncements||0==earningsAnnouncements.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Error loading earnings announcements for '"+symbol+"'"); + return; + } + MDTrace.WriteLine(String.Format("[UpdateEarningsAnnouncements] Got {0} for {1}",earningsAnnouncements.Count,symbol)); + if(!EarningsAnnouncementsDA.InsertEarningsAnnouncements(earningsAnnouncements))MDTrace.WriteLine(String.Format("[UpdateEarningsAnnouncements] Insert failed for {0}",symbol)); + else MDTrace.WriteLine(String.Format("[UpdateEarningsAnnouncements] Insert succeeded for {0}",symbol)); + } + } +} + + diff --git a/MarketData/MarketDataLib/Helper/FinancialStatementsMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/FinancialStatementsMarketDataHelper.cs new file mode 100755 index 0000000..935c84d --- /dev/null +++ b/MarketData/MarketDataLib/Helper/FinancialStatementsMarketDataHelper.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; +using System.IO; + +namespace MarketData.Helper +{ + public class FinancialStatementsMarketDataHelper : MarketDataHelperBase + { + private static int MaxThreads = 10; // (int)ThreadHelperEnum.MaxThreads; + private static int PAUSE_BETWEEN_STATEMENTS=125; + + public FinancialStatementsMarketDataHelper() + { + } + public bool LoadFinancialStatements(String symbol=null) + { + Profiler profiler=new Profiler(); + try + { + if(symbol==null)Queue=PricingDA.GetSymbols(); + else (Queue=new List()).Add(symbol); + Index=-1; + ManualResetEvent[] resetEvents = new ManualResetEvent[MaxThreads]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)resetEvents[eventIndex] = new ManualResetEvent(true); + MDTrace.WriteLine(String.Format("Queuing FinancialStatements ...")); + DateTime modified=DateTime.Now; + while (true) + { + ManualResetEvent[] availableEvents=GetAvailableEvents(resetEvents); + ManualResetEvent[] busyEvents=GetBusyEvents(resetEvents); + if (null == PeekQueueItem() && 0==busyEvents.Length) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("FinancialStatements queue contains {0} items, busy events {1}, all done.",0,busyEvents.Length)); + break; + } + for (int index = 0; index < availableEvents.Length; index++) + { + symbol=GetQueueItem(); + if (null != symbol) + { + availableEvents[index].Reset(); + ThreadHelper threadHelper = new ThreadHelper(symbol,modified,availableEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadFinancialStatements, threadHelper); + try{Thread.Sleep(250);}catch(Exception){;} // adding a short pause between requests + } + else + { + busyEvents=GetBusyEvents(resetEvents); + if(busyEvents.Length!=availableEvents.Length) + { + ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length]; + Array.Copy(busyEvents, resizedEvents,busyEvents.Length); + resetEvents = resizedEvents; + } + break; + } + } // for + MDTrace.WriteLine(LogLevel.DEBUG,"FinancialStatements waiting for free slots..."); + if(resetEvents.Length>0)WaitHandle.WaitAny(resetEvents); + if(null==PeekQueueItem())resetEvents=ResizeEvents(resetEvents); + } // while + MDTrace.WriteLine(LogLevel.DEBUG,"FinancialStatements completed."); + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadFinancialStatements]End, total took {0}(ms)",profiler.End())); + } + } + public void ThreadPoolCallbackLoadFinancialStatements(Object threadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)threadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Financial Statements, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadFinancialStatementsEx(threadHelper.Symbol,threadHelper.Modified); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Financial Statements, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } +// Single threaded method, use for debugging a single symbol fetch without going through the queue + public static void LoadFinancialStatementsEx(String symbol,DateTime modified) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Retrieving income statements for '" + symbol + "'"); +// download available annual income statement data for whatever years are available + try{Thread.Sleep(PAUSE_BETWEEN_STATEMENTS);}catch(Exception){;} + if (!IncomeStatementDA.CheckIncomeStatementModifiedOn(symbol,modified,IncomeStatement.PeriodType.Annual)) + { + List incomeStatements = MarketDataHelper.GetIncomeStatement(symbol,IncomeStatement.PeriodType.Annual); + if (null == incomeStatements || 0 == incomeStatements.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No Annual income statement for " + symbol); + } + else + { + foreach(IncomeStatement incomeStatement in incomeStatements) + { + IncomeStatement previousIncomeStatement=IncomeStatementDA.GetIncomeStatement(incomeStatement.Symbol,incomeStatement.AsOf,incomeStatement.Period); + incomeStatement.MergeFrom(previousIncomeStatement); + } + IncomeStatementDA.InsertIncomeStatements(incomeStatements); + MDTrace.WriteLine(LogLevel.DEBUG,IncomeStatement.Heading); + for (int pindex = 0; pindex < incomeStatements.Count; pindex++) + { + MDTrace.WriteLine(LogLevel.DEBUG,incomeStatements[pindex].ToString()); + } + } + } + else MDTrace.WriteLine(LogLevel.DEBUG,"Already downloaded annual income statement for '"+symbol+"' on "+Utility.DateTimeToStringMMHDDHYYYY(modified)); +// download quarterly income statement data for whatever quarters are available + try{Thread.Sleep(PAUSE_BETWEEN_STATEMENTS);}catch(Exception){;} + if (!IncomeStatementDA.CheckIncomeStatementModifiedOn(symbol, modified, IncomeStatement.PeriodType.Quarterly)) + { + List incomeStatements = MarketDataHelper.GetIncomeStatement(symbol, IncomeStatement.PeriodType.Quarterly); + if (null == incomeStatements || 0 == incomeStatements.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No Quarterly income statement for " + symbol); + } + else + { + foreach(IncomeStatement incomeStatement in incomeStatements) + { + IncomeStatement previousIncomeStatement=IncomeStatementDA.GetIncomeStatement(incomeStatement.Symbol,incomeStatement.AsOf,incomeStatement.Period); + incomeStatement.MergeFrom(previousIncomeStatement); + } + IncomeStatementDA.InsertIncomeStatements(incomeStatements); + MDTrace.WriteLine(LogLevel.DEBUG,IncomeStatement.Heading); + for (int pindex = 0; pindex < incomeStatements.Count; pindex++) + { + MDTrace.WriteLine(LogLevel.DEBUG,incomeStatements[pindex].ToString()); + } + } + } + else MDTrace.WriteLine(LogLevel.DEBUG,"Already downloaded quarterly income statement for '" + symbol + "' on " + Utility.DateTimeToStringMMHDDHYYYY(modified)); + MDTrace.WriteLine(LogLevel.DEBUG,"Retrieving balancesheet for '" + symbol + "'"); +// download annual balance sheet data for whatever years are available + try{Thread.Sleep(PAUSE_BETWEEN_STATEMENTS);}catch(Exception){;} + if (!BalanceSheetDA.CheckBalanceSheetModifiedOn(symbol, modified,BalanceSheet.PeriodType.Annual)) + { + List balanceSheets = MarketDataHelper.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual); + if (null == balanceSheets || 0 == balanceSheets.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No Annual balance sheet for " + symbol); + } + else + { + foreach(BalanceSheet balanceSheet in balanceSheets) + { + BalanceSheet previousBalanceSheet=BalanceSheetDA.GetBalanceSheet(balanceSheet.Symbol,balanceSheet.AsOf,balanceSheet.Period); + balanceSheet.MergeFrom(previousBalanceSheet); + } + BalanceSheetDA.InsertBalanceSheets(balanceSheets); + MDTrace.WriteLine(LogLevel.DEBUG,BalanceSheet.Heading); + for (int pindex = 0; pindex < balanceSheets.Count; pindex++) + { + MDTrace.WriteLine(LogLevel.DEBUG,balanceSheets[pindex].ToString()); + } + } + } + else MDTrace.WriteLine(LogLevel.DEBUG,"Already downloaded annual balance sheet for '" + symbol + "' on " + Utility.DateTimeToStringMMHDDHYYYY(modified)); +// download quarterly balance sheet data for whatever quarters are available + try{Thread.Sleep(PAUSE_BETWEEN_STATEMENTS);}catch(Exception){;} + if (!BalanceSheetDA.CheckBalanceSheetModifiedOn(symbol, modified, BalanceSheet.PeriodType.Quarterly)) + { + List balanceSheets = MarketDataHelper.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Quarterly); + if (null == balanceSheets || 0 == balanceSheets.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No Quarterly balance sheet for " + symbol); + } + else + { + foreach(BalanceSheet balanceSheet in balanceSheets) + { + BalanceSheet previousBalanceSheet=BalanceSheetDA.GetBalanceSheet(balanceSheet.Symbol,balanceSheet.AsOf,balanceSheet.Period); + balanceSheet.MergeFrom(previousBalanceSheet); + } + BalanceSheetDA.InsertBalanceSheets(balanceSheets); + MDTrace.WriteLine(LogLevel.DEBUG,BalanceSheet.Heading); + for (int pindex = 0; pindex < balanceSheets.Count; pindex++) + { + MDTrace.WriteLine(LogLevel.DEBUG,balanceSheets[pindex].ToString()); + } + } + } + else MDTrace.WriteLine(LogLevel.DEBUG,"Already downloaded quarterly balance sheet for '" + symbol + "' on " + Utility.DateTimeToStringMMHDDHYYYY(modified)); + MDTrace.WriteLine(LogLevel.DEBUG,"Retrieving cashflow statements for '" + symbol + "'"); +// download annual cashflow data for whatever years are available + try{Thread.Sleep(PAUSE_BETWEEN_STATEMENTS);}catch(Exception){;} + if (!CashflowStatementDA.CheckCashflowStatementModifiedOn(symbol, modified,CashflowStatement.PeriodType.Annual)) + { + List cashflowStatements = MarketDataHelper.GetCashflowStatement(symbol,CashflowStatement.PeriodType.Annual); + if (null == cashflowStatements || 0 == cashflowStatements.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No Annual cashflow statement for " + symbol); + } + else + { + foreach(CashflowStatement cashflowStatement in cashflowStatements) + { + CashflowStatement previousCashflowStatement=CashflowStatementDA.GetCashflowStatement(cashflowStatement.Symbol,cashflowStatement.AsOf,cashflowStatement.Period); + cashflowStatement.MergeFrom(previousCashflowStatement); + } + CashflowStatementDA.InsertCashflowStatement(cashflowStatements); + MDTrace.WriteLine(LogLevel.DEBUG,CashflowStatement.Heading); + for (int pindex = 0; pindex < cashflowStatements.Count; pindex++) + { + MDTrace.WriteLine(LogLevel.DEBUG,cashflowStatements[pindex].ToString()); + } + } + } + else MDTrace.WriteLine(LogLevel.DEBUG,"Already downloaded annual cashflow statement for '" + symbol + "' on " + Utility.DateTimeToStringMMHDDHYYYY(modified)); +// download quarterly cashflow statement for whatever quarters are available + try{Thread.Sleep(PAUSE_BETWEEN_STATEMENTS);}catch(Exception){;} + if (!CashflowStatementDA.CheckCashflowStatementModifiedOn(symbol, modified, CashflowStatement.PeriodType.Quarterly)) + { + List cashflowStatements = MarketDataHelper.GetCashflowStatement(symbol,CashflowStatement.PeriodType.Quarterly); + if (null == cashflowStatements || 0 == cashflowStatements.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No Quarterly cashflow statement for " + symbol); + } + else + { + foreach(CashflowStatement cashflowStatement in cashflowStatements) + { + CashflowStatement previousCashflowStatement=CashflowStatementDA.GetCashflowStatement(cashflowStatement.Symbol,cashflowStatement.AsOf,cashflowStatement.Period); + cashflowStatement.MergeFrom(previousCashflowStatement); + } + CashflowStatementDA.InsertCashflowStatement(cashflowStatements); + MDTrace.WriteLine(LogLevel.DEBUG,CashflowStatement.Heading); + for (int pindex = 0; pindex < cashflowStatements.Count; pindex++) + { + MDTrace.WriteLine(LogLevel.DEBUG,cashflowStatements[pindex].ToString()); + } + } + } + else MDTrace.WriteLine(LogLevel.DEBUG,"Already downloaded quarterly cashflow statement for '" + symbol + "' on " + Utility.DateTimeToStringMMHDDHYYYY(modified)); + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/FundamentalMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/FundamentalMarketDataHelper.cs new file mode 100755 index 0000000..340355d --- /dev/null +++ b/MarketData/MarketDataLib/Helper/FundamentalMarketDataHelper.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class FundamentalMarketDataHelper : MarketDataHelperBase + { + private static int MaxThreads = 5; //(int)ThreadHelperEnum.MaxThreads; + private UpdateManager updateManager=new UpdateManager(); + + public FundamentalMarketDataHelper() + { + } + public bool LoadFundamentals(String symbol=null) + { + Profiler profiler=new Profiler(); + try + { + if(symbol==null)Queue=PricingDA.GetSymbols(); + else (Queue=new List()).Add(symbol); + + updateManager.Prepare("fundamentals_session.txt"); + Queue=Queue.Except(new List(updateManager.Entries)).ToList(); + + Index=-1; + ManualResetEvent[] resetEvents = new ManualResetEvent[MaxThreads]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)resetEvents[eventIndex] = new ManualResetEvent(true); + MDTrace.WriteLine(String.Format("Queuing fundamentals ...")); + DateTime modified=DateTime.Now; + while (true) + { + ManualResetEvent[] availableEvents=GetAvailableEvents(resetEvents); + ManualResetEvent[] busyEvents=GetBusyEvents(resetEvents); + if (null == PeekQueueItem() && 0==busyEvents.Length) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Fundamentals queue contains {0} items, busy events {1}, all done.",0,busyEvents.Length)); + break; + } + for (int index = 0; index < availableEvents.Length; index++) + { + symbol=GetQueueItem(); + if (null != symbol) + { + availableEvents[index].Reset(); + ThreadHelper fundamentalThreadHelper = new ThreadHelper(symbol,modified,availableEvents[index]); + fundamentalThreadHelper.UpdateManager=updateManager; + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadFundamental, fundamentalThreadHelper); +// try{Thread.Sleep(2000);}catch(Exception){;} // adding a short pause between requests + try{Thread.Sleep(1000);}catch(Exception){;} // changing this because I am going to run a test against TOR + } + else + { + busyEvents=GetBusyEvents(resetEvents); + if(busyEvents.Length!=availableEvents.Length) + { + ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length]; + Array.Copy(busyEvents, resizedEvents,busyEvents.Length); + resetEvents = resizedEvents; + } + break; + } + } // for + MDTrace.WriteLine(LogLevel.DEBUG,"Fundamentals waiting for free slots..."); + if(resetEvents.Length>0)WaitHandle.WaitAny(resetEvents); + if(null==PeekQueueItem())resetEvents=ResizeEvents(resetEvents); + } // while + MDTrace.WriteLine(LogLevel.DEBUG,"Fundamentals completed."); + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadFundamentals]End, total took {0}(ms)",profiler.End())); + updateManager.Dispose(); + } + } + public bool LoadFundamentalsFinViz(String symbol=null) + { + Profiler profiler=new Profiler(); + try + { + if(symbol==null)Queue=PricingDA.GetSymbols(); + else (Queue=new List()).Add(symbol); + + updateManager.Prepare("fundamentals_session.txt"); + Queue=Queue.Except(new List(updateManager.Entries)).ToList(); + + Index=-1; + ManualResetEvent[] resetEvents = new ManualResetEvent[MaxThreads]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)resetEvents[eventIndex] = new ManualResetEvent(true); + MDTrace.WriteLine(String.Format("Queuing fundamentals ...")); + DateTime modified=DateTime.Now; + while (true) + { + ManualResetEvent[] availableEvents=GetAvailableEvents(resetEvents); + ManualResetEvent[] busyEvents=GetBusyEvents(resetEvents); + if (null == PeekQueueItem() && 0==busyEvents.Length) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Fundamentals queue contains {0} items, busy events {1}, all done.",0,busyEvents.Length)); + break; + } + for (int index = 0; index < availableEvents.Length; index++) + { + symbol=GetQueueItem(); + if (null != symbol) + { + availableEvents[index].Reset(); + ThreadHelper fundamentalThreadHelper = new ThreadHelper(symbol,modified,availableEvents[index]); + fundamentalThreadHelper.UpdateManager=updateManager; + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadFundamentalFinViz, fundamentalThreadHelper); + try{Thread.Sleep(250);}catch(Exception){;} // adding a short pause between requests + } + else + { + busyEvents=GetBusyEvents(resetEvents); + if(busyEvents.Length!=availableEvents.Length) + { + ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length]; + Array.Copy(busyEvents, resizedEvents,busyEvents.Length); + resetEvents = resizedEvents; + } + break; + } + } // for + MDTrace.WriteLine(LogLevel.DEBUG,"Fundamentals waiting for free slots..."); + if(resetEvents.Length>0)WaitHandle.WaitAny(resetEvents); + if(null==PeekQueueItem())resetEvents=ResizeEvents(resetEvents); + } // while + MDTrace.WriteLine(LogLevel.DEBUG,"Fundamentals completed."); + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadFundamentals]End, total took {0}(ms)",profiler.End())); + updateManager.Dispose(); + } + } + +// ****************************************************************************************************************************************************************** +// ********************************************************************** T H R E A D C A L L B A C K ************************************************************** +// ****************************************************************************************************************************************************************** + public void ThreadPoolCallbackLoadFundamental(Object fundamentalThreadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)fundamentalThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load fundamental, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadFundamentalEx(threadHelper.Symbol,threadHelper.Modified,threadHelper.updateManager); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load fundamental, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } + public void ThreadPoolCallbackLoadFundamentalFinViz(Object fundamentalThreadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)fundamentalThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load fundamental, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadFundamentalEx(threadHelper.Symbol,threadHelper.Modified,threadHelper.updateManager,true); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load fundamental, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } +// ********************************************************************************************************************************************************************* +// ********************************************************************************************************************************************************************* +// ********************************************************************************************************************************************************************* +// Single threaded method, use for debugging a single symbol fetch without going through the queue + public static void LoadFundamentalEx(String symbol,DateTime modified,UpdateManager updateManager,bool useFinViz=false) + { + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + if(null!=companyProfile&&!companyProfile.IsEquity) + { + updateManager.Add(symbol); + return; + } + if (!FundamentalDA.CheckFundamentalModifiedOn(symbol, modified)) + { + bool result=false; + result=useFinViz?LoadFundamentalExFinViz(symbol):LoadFundamentalEx(symbol); + if(result)updateManager.Add(symbol); + } + else + { + Fundamental fundamental=FundamentalDA.GetFundamental(symbol,modified); +// Even if we have the record Yahoo may not have given us some values. (i.e) Sometime we get zero back from yahoo in EnterpriseValue. Subsequent runs should re-fetch from Yahoo in this case +// If the existing record contains zero in EnterpriseValue then re-fetch it + if(null==fundamental||0.00==fundamental.EnterpriseValue) + { + bool result=false; + result=useFinViz?LoadFundamentalExFinViz(symbol):LoadFundamentalEx(symbol); + if(result)updateManager.Add(symbol); + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,"Already have fundamental for '"+symbol+"' on "+Utility.DateTimeToStringMMHDDHYYYY(modified)); + updateManager.Add(symbol); + } + } + } + public static bool LoadFundamentalEx(String symbol) + { + try + { + MDTrace.WriteLine(LogLevel.DEBUG,"Loading fundamental data for '"+symbol+"'"); + Fundamental fundamental = MarketDataHelper.GetFundamental(symbol); + if (null == fundamental) {MDTrace.WriteLine(LogLevel.DEBUG,"Error loading fundmental for '"+symbol+"'");return false;} + else + { + Fundamental priorFundamental=FundamentalDA.GetFundamental(symbol); + fundamental.MergeFrom(priorFundamental); // if any fields are missing on this run then carry forward fields from previous run + FundamentalDA.InsertFundamental(fundamental); + MDTrace.WriteLine(LogLevel.DEBUG,Fundamental.Header); + MDTrace.WriteLine(LogLevel.DEBUG,fundamental.ToString()); + return true; + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Failed to load funamental for '"+symbol+"'"); + MDTrace.WriteLine(LogLevel.DEBUG,"Exception was "+exception.ToString()); + return false; + } + } + public static bool LoadFundamentalExFinViz(String symbol) + { + try + { + MDTrace.WriteLine(LogLevel.DEBUG,"Loading fundamental data for '"+symbol+"'"); + Fundamental fundamental = MarketDataHelper.GetFundamentalFinViz(symbol); + if (null == fundamental) {MDTrace.WriteLine(LogLevel.DEBUG,"Error loading fundmental for '"+symbol+"'");return false;} + DateTime? nextEarningsDate=EarningsAnnouncementsDA.GetNextEarningsDate(symbol); + if(null!=nextEarningsDate)fundamental.NextEarningsDate=nextEarningsDate.Value; + Fundamental priorFundamental=FundamentalDA.GetFundamental(symbol); + fundamental.MergeFrom(priorFundamental); // if any fields are missing on this run then carry forward fields from previous run + FundamentalDA.InsertFundamental(fundamental); + MDTrace.WriteLine(LogLevel.DEBUG,Fundamental.Header); + MDTrace.WriteLine(LogLevel.DEBUG,fundamental.ToString()); + return true; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Failed to load funamental for '"+symbol+"'"); + MDTrace.WriteLine(LogLevel.DEBUG,"Exception was "+exception.ToString()); + return false; + } + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/HeadlinesMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/HeadlinesMarketDataHelper.cs new file mode 100755 index 0000000..3373409 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/HeadlinesMarketDataHelper.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class HeadlinesMarketDataHelper + { + private static int MaxThreads = 5; // (int)ThreadHelperEnum.MaxThreads; + private static int WAIT_BETWEEN_REQUESTS_MS = 2000; // wait ms between requests + private List symbols; + private int currentIndex = 0; + + public HeadlinesMarketDataHelper() + { + } + public bool LoadHeadlines() + { + Profiler profiler=new Profiler(); + try + { + symbols=PricingDA.GetSymbols(); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadHeadline, threadHelper); + try{Thread.Sleep(WAIT_BETWEEN_REQUESTS_MS);}catch{;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load Headline, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadHeadlines]End, total took {0}(ms)",profiler.End())); + } + } + public bool LoadHeadlines(List requestSymbols) + { + Profiler profiler=new Profiler(); + try + { + symbols=requestSymbols; + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadHeadline, threadHelper); + try{Thread.Sleep(WAIT_BETWEEN_REQUESTS_MS);}catch{;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load Headline, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadHeadlines]End, total took {0}(ms)",profiler.End())); + } + } + private List GetQueueSymbols() + { + List queueSymbols = new List(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < symbols.Count; index++) + { + queueSymbols.Add(symbols[index]); + } + currentIndex = index; + return queueSymbols; + } + public void ThreadPoolCallbackLoadHeadline(Object threadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)threadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Headline, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadHeadlineEx(threadHelper.Symbol); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Headline, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } +// This method is used by unit test + public static Headlines GetHeadlinesEx(String symbol) + { + Headlines headlinesCollection=new Headlines(); + Headlines headlines=null; +// SEEKING ALPHA + headlines=MarketDataHelper.GetCompanyHeadlinesSeekingAlpha(symbol); + if(null!=headlines)headlinesCollection.AddRange(headlines); +// NASDAQ + headlines=MarketDataHelper.GetCompanyHeadlinesNASDAQ(symbol); + if(null!=headlines)headlinesCollection.AddRange(headlines); +// MARKETWATCH + headlines=MarketDataHelper.GetCompanyHeadlinesMarketWatch(symbol); + if(null!=headlines)headlinesCollection.AddRange(headlines); + return headlinesCollection; + } +// *********************************************************************************************************************************************** +// *********************************************************************************************************************************************** +// *********************************************************************************************************************************************** + + public static void LoadHeadlineEx(String symbol) + { + DateTime marketDate=PremarketDA.GetLatestMarketDate(); + marketDate=new DateTime(marketDate.Year,marketDate.Month,marketDate.Day,23,59,59); + + Headlines headlines=null; +// NASDAQ + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetCompanyHeadlinesNASDAQ {0}",symbol)); + headlines=MarketDataHelper.GetCompanyHeadlinesNASDAQ(symbol); + if(headlines.IsNullOrEmpty()) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No headlines for {0} from NASDAQ",symbol)); + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Got {0} headlines for {1} from NASDAQ",headlines.Count,symbol)); + headlines=new Headlines(headlines.Where(x=>x.Date {2}",headline.Symbol,headline.Date.ToShortDateString(),headline.Entry)); + } + } +// MARKETWATCH + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetCompanyHeadlinesMarketWatch {0}",symbol)); + headlines=MarketDataHelper.GetCompanyHeadlinesMarketWatch(symbol); + if(headlines.IsNullOrEmpty()) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No headlines for {0} from MARKETWATCH",symbol)); + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Got {0} headlines for {1} from MARKETWATCH",headlines.Count,symbol)); + headlines=new Headlines(headlines.Where(x=>x.Date {2}",headline.Symbol,headline.Date.ToShortDateString(),headline.Entry)); + } + } +// SEEKING ALPHA + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetCompanyHeadlinesSeekingAlpha {0}",symbol)); + headlines=MarketDataHelper.GetCompanyHeadlinesSeekingAlpha(symbol); + if(headlines.IsNullOrEmpty()) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No headlines for {0} from Seeking Alpha",symbol)); + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Got {0} headlines for {1} from Seeking Alpha",headlines.Count,symbol)); + headlines=new Headlines(headlines.Where(x=>x.Date {2}",headline.Symbol,headline.Date.ToShortDateString(),headline.Entry)); + } + } + return; + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/HistoricalMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/HistoricalMarketDataHelper.cs new file mode 100755 index 0000000..7135e7b --- /dev/null +++ b/MarketData/MarketDataLib/Helper/HistoricalMarketDataHelper.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class HistoricalMarketDataHelper + { + private static int MaxThreads = (int)ThreadHelperEnum.MaxThreads; + private List symbols; + private int currentIndex = 0; + + public HistoricalMarketDataHelper() + { + } + public bool LoadHistorical(String symbol) + { + Profiler profiler=new Profiler(); + try + { + symbols = new List(); + symbols.Add(symbol); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadHistorical, threadHelper); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load Historical, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadHistorical]End, total took {0}(ms)",profiler.End())); + } + } + public bool LoadHistorical() + { + Profiler profiler=new Profiler(); + try + { + symbols = PricingDA.GetSymbols(); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadHistorical, threadHelper); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load Historical, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadHistorical]End, total took {0}(ms)",profiler.End())); + } + } + private List GetQueueSymbols() + { + List queueSymbols = new List(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < symbols.Count; index++) + { + queueSymbols.Add(symbols[index]); + } + currentIndex = index; + return queueSymbols; + } + public void ThreadPoolCallbackLoadHistorical(Object threadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)threadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Historical, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadHistoricalEx(threadHelper.Symbol); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Historical, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } + public static void LoadHistoricalEx(String symbol) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Loading time series data values for '" + symbol + "'"); + Dictionary timeSeriesCollection = MarketDataHelper.GetHistoricalValues(symbol); + if (null == timeSeriesCollection || 0 == timeSeriesCollection.Count) + { + return; + } + List keys=new List(timeSeriesCollection.Keys); + for (int cIndex = 0; cIndex < keys.Count; cIndex++) + { + TimeSeriesCollection timeSeriesElements = timeSeriesCollection[keys[cIndex]]; + if (null == timeSeriesElements || 0 == timeSeriesElements.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Unable to retrieve time series values for '" + symbol + "'"); + continue; + } + HistoricalDA.InsertTimeSeries(timeSeriesElements); + } + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/InsiderTransactionMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/InsiderTransactionMarketDataHelper.cs new file mode 100755 index 0000000..ab41b4c --- /dev/null +++ b/MarketData/MarketDataLib/Helper/InsiderTransactionMarketDataHelper.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + + public class InsiderTransactionThreadHelper : ThreadHelper + { + public InsiderTransactionThreadHelper(String symbol, ManualResetEvent resetEvent) + : base(symbol, resetEvent) + { + } + public int YearGreaterEqual { get; set; } + } + + public class InsiderTransactionMarketDataHelper + { + private static int MaxThreads = 10; // 10 threads avoids receiving HTTP Response 429 (Too many requests) + private static int WAIT_TIME_MS=500; // wait between request + private List symbols; + private int currentIndex = 0; + private UpdateManager UpdateManager = new UpdateManager(); + + public InsiderTransactionMarketDataHelper() + { + } + public bool LoadInsiderTransactions(String symbol) + { + Profiler profiler=new Profiler(); + try + { + symbols = new List(); + symbols.Add(symbol); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index], resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallback, threadHelper); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Insider Transactions, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadInsiderTransactions]End, total took {0}(ms)",profiler.End())); + } + } + public bool LoadInsiderTransactions(List symbols) + { + Profiler profiler=new Profiler(); + try + { + this.symbols = symbols; + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index], resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallback, threadHelper); + try { Thread.Sleep(WAIT_TIME_MS); } catch(Exception) { ;} // wait + } + MDTrace.WriteLine(LogLevel.DEBUG,"Insider Transactions, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadInsiderTransactions]End, total took {0}(ms)",profiler.End())); + } + } + public bool LoadInsiderTransactionsYearGreaterEqual(List symbols,int yearGreaterEqual) + { + Profiler profiler=new Profiler(); + try + { + this.symbols = symbols; + currentIndex = 0; + + UpdateManager.Prepare("load_insider_transactions_year.txt", 7); // use max age 7 days + this.symbols=this.symbols.Except(new List(UpdateManager.Entries)).ToList(); + + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + InsiderTransactionThreadHelper threadHelper = new InsiderTransactionThreadHelper(queueSymbols[index], resetEvents[index]); + threadHelper.UpdateManager=UpdateManager; + threadHelper.YearGreaterEqual=yearGreaterEqual; + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackYearGreaterEqual, threadHelper); + try { Thread.Sleep(WAIT_TIME_MS); } catch(Exception) { ;} // wait + } + MDTrace.WriteLine(LogLevel.DEBUG,"Insider Transactions, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadInsiderTransactions]End, total took {0}(ms)",profiler.End())); + } + } + + private List GetQueueSymbols() + { + List queueSymbols = new List(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < symbols.Count; index++) + { + queueSymbols.Add(symbols[index]); + } + currentIndex = index; + return queueSymbols; + } + + public void ThreadPoolCallback(Object threadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)threadHelperContext; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Insider Transactions Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadInsiderTransactionsSymbolEx(threadHelper.Symbol); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Insider Transactions Thread {0} ended for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + threadHelper.ResetEvent.Set(); + } + + public static void LoadInsiderTransactionsSymbolEx(String symbol) + { + symbol = symbol.ToUpper(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load insider transactions for {0}", symbol)); + InsiderTransactions insiderTransactions = MarketDataHelper.GetInsiderTransactions(symbol); + if (null == insiderTransactions || 0 == insiderTransactions.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No insider transactions for {0}", symbol)); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Insider Transactions, Saving {0} records for {1}", insiderTransactions.Count, symbol)); + InsiderTransactionDA.InsertInsiderTransactions(insiderTransactions); + MDTrace.WriteLine(LogLevel.DEBUG,"Insider Transactions - Done."); + } + + public void ThreadPoolCallbackYearGreaterEqual(Object threadHelperContext) + { + InsiderTransactionThreadHelper threadHelper = (InsiderTransactionThreadHelper)threadHelperContext; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Insider Transactions Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadInsiderTransactionsYearGreaterEqualEx(threadHelper.Symbol,threadHelper.YearGreaterEqual); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Insider Transactions Thread {0} ended for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + threadHelper.UpdateManager.Add(threadHelper.Symbol); + threadHelper.ResetEvent.Set(); + } + + public static void LoadInsiderTransactionsYearGreaterEqualEx(String symbol, int yearGreaterEqual) + { + symbol = symbol.ToUpper(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load insider transactions for {0} years>={1}", symbol,yearGreaterEqual)); + InsiderTransactions insiderTransactions = MarketDataHelper.GetInsiderTransactionsYear(symbol, yearGreaterEqual); + if (null == insiderTransactions || 0 == insiderTransactions.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No insider transactions for {0} years>={1}", symbol,yearGreaterEqual)); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Insider Transactions, Saving {0} records for {1} years>={2}", insiderTransactions.Count, symbol, yearGreaterEqual)); + InsiderTransactionDA.DeleteInsiderTransactionsYearsGreaterEqual(symbol, yearGreaterEqual); + InsiderTransactionDA.InsertInsiderTransactions(insiderTransactions); + MDTrace.WriteLine(LogLevel.DEBUG,"Insider Transactions - Done."); + } + } +} diff --git a/MarketData/MarketDataLib/Helper/InsiderTransactionsParser.cs b/MarketData/MarketDataLib/Helper/InsiderTransactionsParser.cs new file mode 100755 index 0000000..3d09324 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/InsiderTransactionsParser.cs @@ -0,0 +1,243 @@ +using System; +using System.Text; +using System.Collections.Generic; +using System.IO; +using HtmlAgilityPack; +using MarketData.Utils; +using MarketData.MarketDataModel; +using MarketDataLib.Utility; +using System.Collections.Concurrent; + +namespace MarketData.Helper +{ + public class InsiderTransactionsParser + { + private static ConcurrentDictionary transactionCodes=new ConcurrentDictionary(); + private static InsiderTransactionsParser instance=null; + private InsiderTransactionsParser() + { + BuildTransactionCodes(); + } + + public static InsiderTransactionsParser GetInstance() + { + lock(typeof(InsiderTransactionsParser)) + { + if(null==instance)instance=new InsiderTransactionsParser(); + return instance; + } + } + + /// + /// Parse the SECFilings. Each SECFiling may contain a list of InsiderTransaction + /// + /// The SECFilings. + public InsiderTransactions Parse(SECFilings secFilings) + { + try + { + InsiderTransactions insiderTransactions=new InsiderTransactions(); + + if(null==secFilings || 0==secFilings.Count)return insiderTransactions; + foreach(SECFiling secFiling in secFilings) + { + InsiderTransactions secFilinginsiderTransactions = + Parse(secFiling.FormText, secFiling.Symbol, + secFiling.SECAccessionNumber, + secFiling.Form, secFiling.FilingDate); + if(null!=secFilinginsiderTransactions && secFilinginsiderTransactions.Count>0) + insiderTransactions.AddRange(secFilinginsiderTransactions); + } + return insiderTransactions; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Parse SECFiling got exception {0}",exception.ToString())); + return new InsiderTransactions(); + } + } + + public InsiderTransactions Parse(String strHtml,String symbol, String secAccessionNumber, String form, DateTime filingDate) + { + try + { + InsiderTransactions insiderTransactions = new InsiderTransactions(); + if(null==strHtml)return null; + + List> dictionaryList=new List>(); + String insiderName=null; + + byte[] streamBytes = Encoding.ASCII.GetBytes(strHtml); + MemoryStream memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection tables=htmlDocument.DocumentNode.SelectNodes("//table"); + + if(null==tables || tables.Count<5)return null; + + HtmlNode nameAndAddressTable=FindTable(tables,"1. Name and Address of Reporting Person"); + if(null==nameAndAddressTable)return null; + HtmlNodeCollection nameAndAddressRows = nameAndAddressTable.SelectNodes(".//tr"); + if(nameAndAddressRows.Count<2)return null; + insiderName=ApplyNameCase(nameAndAddressRows[1].InnerText); + + for(int index=0;index dictionary=new Dictionary(); + dictionary.Add("Title of Security",dataCollection[0].InnerHtml); + dictionary.Add("Transaction Date",dataCollection[1].InnerHtml); + dictionary.Add("Transaction Code",dataCollection[3].InnerHtml); + dictionary.Add("Securities Acquired or Disposed",dataCollection[5].InnerHtml); + dictionary.Add("Acquired or Disposed",dataCollection[6].InnerHtml); + dictionary.Add("Price",dataCollection[7].InnerHtml); + dictionary.Add("Ownership Form",dataCollection[9].InnerHtml); + dictionaryList.Add(dictionary); + } + } + } + + int sequenceNumber=0; + foreach(Dictionary dictionary in dictionaryList) + { + String strItem=null; + InsiderTransaction insiderTransaction=new InsiderTransaction(); + insiderTransaction.Symbol=symbol; + insiderTransaction.SECAccessionNumber=secAccessionNumber; + insiderTransaction.Form=form; + insiderTransaction.FilingDate=filingDate; + insiderTransaction.InsiderName=insiderName; + insiderTransaction.Securities=GetFirstSection(Sections.GetSections(dictionary["Title of Security"])); + insiderTransaction.OwnershipType=GetOwnershipForm(Sections.GetSections(dictionary["Ownership Form"])); + if(String.IsNullOrEmpty(insiderTransaction.OwnershipType))continue; + strItem=GetFirstSection(Sections.GetSections(dictionary["Transaction Date"])); + if(String.IsNullOrEmpty(strItem))continue; + insiderTransaction.TransactionDate=Utility.ParseDate(strItem); + insiderTransaction.NatureOfTransaction=transactionCodes.ContainsKey(GetFirstSection(Sections.GetSections(dictionary["Transaction Code"])))?transactionCodes[GetFirstSection(Sections.GetSections(dictionary["Transaction Code"]))]:Constants.CONST_QUESTION; + insiderTransaction.NumberOrValueAcquiredDisposed=FeedParser.ParseValue(GetFirstSection(Sections.GetSections(dictionary["Securities Acquired or Disposed"]))); +// insiderTransaction.FormRowNumber=((decimal)insiderTransaction.NumberOrValueAcquiredDisposed).ToString(); + insiderTransaction.FormRowNumber=(++sequenceNumber).ToString(); + insiderTransaction.Price=FeedParser.ParseValue(CombineSections(Sections.GetSections(dictionary["Price"]))); + String acquiredOrDisposed=GetAcquiredOrDisposed(dictionary); + if(null==acquiredOrDisposed) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Parse - Cannot determine acquied or disposed for accession#{0}",secAccessionNumber)); + continue; + } + if(acquiredOrDisposed.Equals("D")) + { + insiderTransaction.NumberOrValueAcquiredDisposed*=-1; + } + insiderTransactions.Add(insiderTransaction); + } + return insiderTransactions; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Parse - Got exception {0}",exception.ToString())); + return null; + } + } + + private HtmlNode FindTable(HtmlNodeCollection tables,String startsWith) + { + if(null==tables)return null; + for(int index=0;index1)sb.Append(item.Substring(0,1).ToUpper()+item.Substring(1)); + else sb.Append(item.ToUpper()); + if(index sections) + { + String item=GetFirstSection(sections); + if(null==item)item=""; + item=item.ToUpper(); + if(item.Equals("D"))return "Direct Ownership"; + else if(item.Equals("I"))return "Indirect Ownership"; + return ""; + } + + private String GetAcquiredOrDisposed(Dictionary dictionary) + { + if(!dictionary.ContainsKey("Acquired or Disposed"))return null; + List section=Sections.GetSections(dictionary["Acquired or Disposed"]); + if(null==section||0==section.Count)return null; + String acquiredOrDisposed=section[0]; + if(null==acquiredOrDisposed)return null; + return acquiredOrDisposed.Trim().ToUpper(); + } + + private String GetFirstSection(List sections) + { + if(null==sections || 0==sections.Count)return ""; + return sections[0]; + } + + private String CombineSections(List sections) + { + StringBuilder sb=new StringBuilder(); + if(null==sections || 0==sections.Count)return ""; + foreach(String section in sections) + { + sb.Append(section); + } + return sb.ToString(); + } + + private void BuildTransactionCodes() + { + transactionCodes.TryAdd("P","Open market or private purchase of non-derivative or derivative security"); + transactionCodes.TryAdd("S","Open market or private sale of non-derivative or derivative security"); + transactionCodes.TryAdd("V","Transaction voluntarily reported earlier than required"); + transactionCodes.TryAdd("A","Grant, award or other acquisition pursuant to Rule 16b-3(d)"); + transactionCodes.TryAdd("D","Disposition to the issuer of issuer equity securities pursuant to Rule 16b-3(e)"); + transactionCodes.TryAdd("F","Payment of exercise price or tax liability by delivering or withholding securities incident to the receipt, exercise or vesting of a security issued in accordance with Rule 16b-3"); + transactionCodes.TryAdd("I","Discretionary transaction in accordance with Rule 16b-3(f) resulting in acquisition or disposition of issuer securities"); + transactionCodes.TryAdd("M","Exercise or conversion of derivative security exempted pursuant to Rule 16b-3"); + transactionCodes.TryAdd("C","Conversion of derivative security"); + transactionCodes.TryAdd("E","Expiration of short derivative position"); + transactionCodes.TryAdd("H","Expiration (or cancellation) of long derivative position with value received"); + transactionCodes.TryAdd("O","Exercise of out-of-the-money derivative security"); + transactionCodes.TryAdd("X","Exercise of in-the-money or at-the-money derivative security"); + transactionCodes.TryAdd("G","Bona fide gift"); + transactionCodes.TryAdd("L","Small acquisition under Rule 16a-6"); + transactionCodes.TryAdd("W","Acquisition or disposition by will or the laws of descent and distribution"); + transactionCodes.TryAdd("Z","Deposit into or withdrawal from voting trust"); + transactionCodes.TryAdd("J","Other acquisition or disposition (describe transaction)"); + transactionCodes.TryAdd("K","Transaction in equity swap or instrument with similar characteristics"); + transactionCodes.TryAdd("U","Disposition pursuant to a tender of shares in a change of control transaction"); + } + } +} diff --git a/MarketData/MarketDataLib/Helper/MarketDataHelper.cs b/MarketData/MarketDataLib/Helper/MarketDataHelper.cs new file mode 100755 index 0000000..3101fab --- /dev/null +++ b/MarketData/MarketDataLib/Helper/MarketDataHelper.cs @@ -0,0 +1,5527 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using System.Data; +using System.Threading; +using System.Net; +using System.Reflection; +using System.Xml.Linq; +using Newtonsoft.Json.Linq; +using HtmlAgilityPack; +using MarketData.MarketDataModel; +using MarketData.Utils; +using MarketData.CSVHelper; +using MarketData.DataAccess; +using MarketData.Integration; +using System.Globalization; +using MarketDataLib.Utility; + +//Zacks Rank - Zacks +//Splits - EODDATA +//GDP Data - WorldBank +//Dividend History - NASDAQ +//Options - NASDAQ +//Analyst Ratings - Briefing.com +//SEC Filings - SEC.GOV (EDGAR) +//Yield Curve - Treasury.Gov +//ETF Holdings - Yahoo Finance +//Insider Transactions - Insider Tracking.com +//Company Profile - MorningStar + Reuters +//Headlines - Seeking Alpha + NASDAQ +//CIK Codes - SEC.GOV +//Analyst Price Target - Yahoo Finance , Market Beat as backup +//Historical - MorningStar +//Income Statement - NASDAQ +//Balance Sheet - NASDAQ +//Statement of Cashflows - MorningStar +//Fundamentals - 2 Sources....Yahoo Finance & FINVIZ +// a) Key Statistics +// b) Financials +//Intraday Pricing - Yahoo Finance + BigCharts +//Historical Pricing - BigCharts + Yahoo Finance +//CompanyDescription - Reuters +//Premarket - CNN + +namespace MarketData.Helper +{ + public class MarketDataHelper + { + public static int DEFAULT_TIMEOUT_MS=30000; + public static String SEC_BASE_URL="https://www.sec.gov"; + + + public static bool GetWorldTime() + { + Profiler profiler = new Profiler(); + HttpNetResponse httpNetResponse=null; + + try + { + StringBuilder sb = new StringBuilder(); + sb.Append("https://www.timeanddate.com/worldclock/"); + String strRequest = sb.ToString(); + WebProxy webProxy=HttpNetRequest.GetProxy(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetWorldTime:{0}",strRequest)); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV4A(strRequest, null, webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return false; + } + + if(String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No data returned for request {0}",strRequest)); + return false; + } + + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetWorldTime Received {0} bytes of data.",httpNetResponse.ResponseString.Length)); + + + return true; + + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return false; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("MarketData.GetWorldTime: Done, took {0}(ms)", profiler.End())); + } + } + + + +// ****************************************************************************************************************************************************************************** +// ************************************************************************************ P R E M A R K E T D A T A *********************************************************** +// ****************************************************************************************************************************************************************************** + public static PremarketElements GetPremarketData() + { + Profiler profiler = new Profiler(); + HttpNetResponse httpNetResponse=null; + MemoryStream memoryStream=null; + PremarketElements premarketElements=new PremarketElements(); + DateTime timestamp=DateTime.Now; + + try + { + StringBuilder sb=new StringBuilder(); + String strRequest=null; + + sb.Append("https://production.dataviz.cnn.io/markets/futures/summary"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetPremarketData Request {0} ",strRequest)); + httpNetResponse=HttpNetRequest.GetRequestStreamCSV(strRequest); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetPremarketData Request '{0}'. Failed with {1}",strRequest,httpNetResponse.ErrorMessage)); + return null; + } + + List> items=LocateJSONItems(httpNetResponse.ResponseString); + if(null==items || 0==items.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetPremarketData Request '{0}'. No Data",strRequest)); + return premarketElements; + } + for(int index=0;index pair=items[index]; + if(pair[1].Equals("S&P 500")) + { + PremarketElement premarketElement=new PremarketElement(); + premarketElement.Market="S&P"; + premarketElement.ChangeValue=FeedParser.ParseValue((items[index+2])[1]); + premarketElement.ChangePercent=FeedParser.ParseValue((items[index+3])[1])*100.00; + premarketElement.Timestamp=timestamp; + premarketElements.Add(premarketElement); + } + else if(pair[1].Equals("NASDAQ")) + { + PremarketElement premarketElement=new PremarketElement(); + premarketElement.Market="NASDAQ"; + premarketElement.ChangeValue=FeedParser.ParseValue((items[index+2])[1]); + premarketElement.ChangePercent=FeedParser.ParseValue((items[index+3])[1])*100.00; + premarketElement.Timestamp=timestamp; + premarketElements.Add(premarketElement); + } + else if(pair[1].Equals("DOW")) + { + PremarketElement premarketElement=new PremarketElement(); + premarketElement.Market="DOW"; + premarketElement.ChangeValue=FeedParser.ParseValue((items[index+2])[1]); + premarketElement.ChangePercent=FeedParser.ParseValue((items[index+3])[1])*100.00; + premarketElement.Timestamp=timestamp; + premarketElements.Add(premarketElement); + } + } + return premarketElements; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=memoryStream) memoryStream.Close(); + if(null!=httpNetResponse) httpNetResponse.Dispose(); + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("MarketData.GetPremarketData: Done, took {0}(ms)", profiler.End())); + } + } +// ****************************************************************************************************************************************************************************** +// ************************************************************************** Z A C K S E A R N I N G S A N N O U N C E M E N T S ******************************************* +// ****************************************************************************************************************************************************************************** + public static EarningsAnnouncements GetEarningsAnnouncements(String symbol) + { + Profiler profiler = new Profiler(); + HttpNetResponse httpNetResponse=null; + EarningsAnnouncements earningsAnnouncements=new EarningsAnnouncements(); + MemoryStream memoryStream=null; + try + { + StringBuilder sb=new StringBuilder(); + sb.Append("https://www.zacks.com/stock/research/").Append(symbol).Append("/earnings-announcements"); + String strRequest=sb.ToString(); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV4(strRequest); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + String responseString=httpNetResponse.ResponseString; +// get next earnings date + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection table = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"key-expected-earnings-data-module\"]"); + if (null != table && 0 != table.Count) + { + HtmlNodeCollection rows = table[0].SelectNodes(".//tr"); + String[] requiredElements={"Report Date","Period Ending","Zacks Consensus Estimate","Earnings ESP"}; + if(2==rows.Count) + { + HtmlNodeCollection headerColumns = rows[0].SelectNodes(".//th"); + if (null!=headerColumns && 0!=headerColumns.Count && HeaderContains(headerColumns,requiredElements)) + { + HtmlNodeCollection dataColumns = rows[1].ChildNodes; + String[] reportElements=dataColumns[1].InnerText.Split(' '); + String reportDate=reportElements[0]; + if(!"NA".Equals(reportDate)) + { + String[] formats=new[] {"MM/yyyy","M/yyyy"}; + String periodEnding=dataColumns[3].InnerText; + EarningsAnnouncement earningsAnnouncement=new EarningsAnnouncement(); + earningsAnnouncement.Symbol=symbol; + earningsAnnouncement.Date=Utility.ParseDate(reportDate); + earningsAnnouncement.PeriodEnding=DateTime.ParseExact(periodEnding, formats, new System.Globalization.CultureInfo("en-US"),DateTimeStyles.AssumeLocal); + if(reportElements[1].Equals("(AMC)"))earningsAnnouncement.Time="After Close"; + else if(reportElements[1].Equals("(NONE)"))earningsAnnouncement.Time="Before Open"; + else earningsAnnouncement.Time=reportElements[1]; + earningsAnnouncements.Add(earningsAnnouncement); + } + } + } + } + +// get historical + responseString=Utility.KeepAfter(responseString,"earnings_announcements_earnings_table"); + if(null==responseString)return null; + responseString=Utility.KeepBefore(responseString,"] ]"); + if(null==responseString)return null; + responseString=responseString+"]"; + responseString=Utility.KeepAfter(responseString,"[ ["); + if(null==responseString)return null; + responseString="["+responseString; + responseString=Utility.RemoveDivs(responseString); + if(null==responseString)return null; + String[] items=responseString.Split(']'); + for(int index=0;index 0) continue; + HtmlNodeCollection dataColumns = rows[index].SelectNodes(".//td"); + if(dataColumns.Count<4)continue; + if(null!=dataColumns[0])split.Exchange=dataColumns[0].InnerText.Trim().ToUpper(); // exchange + if(null!=dataColumns[1])split.Symbol=dataColumns[1].InnerText.Trim().ToUpper(); + if(null!=dataColumns[2])split.EffectiveDate=Utility.ParseDate(dataColumns[2].InnerText.Trim().ToUpper()); + if(null!=dataColumns[3])split.StrRatio=dataColumns[3].InnerText.Trim().ToUpper(); + splits.Add(split); + } + memoryStream.Close(); + memoryStream.Dispose(); + return splits; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// *************************************************************************************************************************************************************************************** +// ************************************************************************** G D P P E R C A P I T A D A T A W O R L D B A N K ************************************************* +// *************************************************************************************************************************************************************************************** + public static EconomicIndicators GetGDPPerCapita(bool debug=false) + { + HttpNetResponse httpNetResponse=null; + try + { +// Retrieve compressed CSV from World Bank web site and write to disk + StringBuilder sb=new StringBuilder(); + String strRequest; + String currentWorkingDirectory=Directory.GetCurrentDirectory(); + String strExtractFolder=currentWorkingDirectory+"\\"+"extracts"; + String strFileName="API_NY.GDP.MKTP.CD_DS2_V2_USD.zip"; + String strPathFileName=currentWorkingDirectory+"\\"+strFileName; + sb.Append("http://api.worldbank.org/v2/en/indicator/NY.GDP.MKTP.CD?downloadformat=csv"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Downloading {0} from {1}",strFileName,strRequest)); + httpNetResponse=HttpNetRequest.GetRequestStreamZIP(strRequest); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + if(File.Exists(strPathFileName))File.Delete(strPathFileName); + FileStream outStream=new FileStream(strPathFileName,FileMode.Create); + byte[] streamBytes=httpNetResponse.ResponseStream.GetBuffer(); + outStream.Write(streamBytes,0,streamBytes.Length); + outStream.Flush(); + outStream.Close(); + return EconomicIndicators.FromZipFile(strPathFileName,strExtractFolder,debug); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// *************************************************************************************************************************************************************************************** +// ************************************************************************** D I V I D E N D H I S T O R Y N A S D A Q *********************************************************** +// *************************************************************************************************************************************************************************************** + public static DividendHistory GetDividendHistory(String symbol) + { + HttpNetResponse httpNetResponse=null; + DividendHistory dividendHistory = new DividendHistory(); + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + CookieCollection cookieCollection = new CookieCollection(); + WebProxy webProxy=HttpNetRequest.GetProxy("GetDividendHistory"); + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + if(!companyProfile.IsEquity)sb.Append("https://api.nasdaq.com/api/quote/").Append(symbol).Append("/dividends?assetclass=etf"); + else sb.Append("https://api.nasdaq.com/api/quote/").Append(symbol).Append("/dividends?assetclass=stocks"); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Requesting {0}",strRequest)); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV4(strRequest, cookieCollection, webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + if(httpNetResponse.StatusCode.Equals(System.Net.HttpStatusCode.Forbidden)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Retrying request:{0}, after 15000(ms)",httpNetResponse.Request)); + try{Thread.Sleep(15000);}catch(Exception){;} + httpNetResponse=HttpNetRequest.GetRequestStreamCSV(strRequest, cookieCollection, webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + } + else return null; + } + + int groupBy=6; + + List> items=LocateJSONItems(httpNetResponse.ResponseString); + if(null==items || 0==items.Count || items.Count uniqueSymbols = new Dictionary(); + AnalystRatings analystRatings = new AnalystRatings(); + AnalystRatings ratings = null; + + ratings = GetLatestAnalystRatingsBriefing("Upgrades"); + if (null != ratings) + { + foreach (AnalystRating analystRating in ratings) + { + if (!uniqueSymbols.ContainsKey(analystRating.Symbol)) + { + analystRatings.Add(analystRating); + uniqueSymbols.Add(analystRating.Symbol, analystRating.Symbol); + } + } + } + ratings = GetLatestAnalystRatingsBriefing("Downgrades"); + if (null != ratings) + { + foreach (AnalystRating analystRating in ratings) + { + if (!uniqueSymbols.ContainsKey(analystRating.Symbol)) + { + analystRatings.Add(analystRating); + uniqueSymbols.Add(analystRating.Symbol, analystRating.Symbol); + } + } + } + ratings = GetLatestAnalystRatingsBriefing("Reiterated"); + if (null != ratings) + { + foreach (AnalystRating analystRating in ratings) + { + if (!uniqueSymbols.ContainsKey(analystRating.Symbol)) + { + analystRatings.Add(analystRating); + uniqueSymbols.Add(analystRating.Symbol, analystRating.Symbol); + } + } + } + ratings = GetLatestAnalystRatingsBriefing("Initiated"); + if (null != ratings) + { + foreach (AnalystRating analystRating in ratings) + { + if (!uniqueSymbols.ContainsKey(analystRating.Symbol)) + { + analystRatings.Add(analystRating); + uniqueSymbols.Add(analystRating.Symbol, analystRating.Symbol); + } + } + } + return analystRatings; + } + + private static AnalystRatings GetLatestAnalystRatingsBriefing(String type) + { + MemoryStream memoryStream = null; + HttpNetResponse httpNetResponse = null; + AnalystRatings analystRatings = new AnalystRatings(); + try + { + String strRequest = null; + if ("Upgrades".Equals(type)) strRequest = "https://www.briefing.com/Inv/content/Calendar/Updown/upgrade.htm"; + else if ("Downgrades".Equals(type)) strRequest = "https://www.briefing.com/Inv/content/Calendar/Updown/downgrade.htm"; + else if ("Reiterated".Equals(type)) strRequest = "https://www.briefing.com/Inv/content/Calendar/Updown/reiterated.htm"; + else if ("Initiated".Equals(type)) strRequest = "https://www.briefing.com/Inv/content/Calendar/Updown/initiated.htm"; + else return null; + + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV4(strRequest); + if (!httpNetResponse.Success || null == httpNetResponse.ResponseString) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection divSectionDate = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"calDATE\"]"); + HtmlNodeCollection divSectionHeader = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"calHDR2\"]"); + HtmlNodeCollection divSections = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"calEVENT\"]"); + + if (null == divSectionDate || 0 == divSectionDate.Count) return null; + if (null == divSectionHeader || 0 == divSectionHeader.Count) return null; + if (null == divSections || 0 == divSections.Count) return null; + + DateTime ratingsDate = Utility.ParseDate(divSectionDate[0].InnerText); + String ratingsType = divSectionHeader[0].InnerText; + if (!ratingsType.StartsWith(type.ToUpper())) return null; + + // calDATA + for (int index = 0; index < divSections.Count; index++) + { + + List items = Sections.GetSections(divSections[index].InnerHtml); + if (null == items || 0 == items.Count) continue; + + AnalystRating analystRating = new AnalystRating(); + analystRating.CompanyName = items.Count > 0 ? items[0] : null; + analystRating.Date = ratingsDate; + analystRating.Symbol = items.Count > 4 ? items[4] : null; + analystRating.Type = type; + if (items.Count > 10 && items[10].StartsWith("Brokerage Firm")) analystRating.BrokerageFirm = items.Count > 12 ? items[12] : null; + if (items.Count > 22 && items[22].StartsWith("Ratings Change")) analystRating.RatingsChange = items.Count > 24 ? items[24] : null; + if (null != analystRating.RatingsChange & analystRating.RatingsChange.Contains("»")) analystRating.RatingsChange = analystRating.RatingsChange.Replace("»", "->"); + if (items.Count > 28 && items[28].StartsWith("Price Tgt")) + { + String priceTarget = items.Count > 31 ? items[31] : null; + if (null != priceTarget && priceTarget.Contains("»")) priceTarget = priceTarget.Replace("»", "-"); + if (priceTarget.Contains("-")) + { + String[] prices = priceTarget.Split('-'); + priceTarget = prices[1]; + } + analystRating.PriceTarget = FeedParser.ParseValue(priceTarget); + } + analystRatings.Add(analystRating); + } + return analystRatings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return analystRatings; + } + finally + { + if (null != memoryStream) memoryStream.Close(); + if (null != httpNetResponse) httpNetResponse.Dispose(); + } + } +// ****************************************************************************************************************************************************************************************** +// ****************************************************************************** A N A L Y S T R A T I N G S M A R K E T B E A T ******************************************************* +// ****************************************************************************************************************************************************************************************** + public static AnalystRatings GetAnalystRatingsMarketBeat(String symbol) + { + AnalystRatings analystRatings=new AnalystRatings(); + String nasdaq="NASDAQ"; + String nyse="NYSE"; + + try + { + StringBuilder sb=new StringBuilder(); + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + HtmlNodeCollection ratingsTable=null; + ratingsTable=GetRatingsTableOnMarketBeat(symbol,nyse); + if(null==ratingsTable) ratingsTable=GetRatingsTableOnMarketBeat(symbol,nasdaq); + if(null==ratingsTable) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No ratings for {0} on MarketBeat",symbol)); + return null; + } + HtmlNodeCollection header=ratingsTable[0].SelectNodes(".//th"); + string[] requiredElements=new string[]{"Date","Brokerage","Action","Rating","Price Target","Details"}; + if(!HeaderContains(header,requiredElements))return null; + HtmlNodeCollection data=ratingsTable[0].SelectNodes(".//tr//td"); + if(null==data)return analystRatings; + for(int index=0,rowIndex=0;index"); + analystRating.RatingsChange=strRating; + if(null!=strPriceTarget) + { + + if(strPriceTarget.Contains("➝")) strPriceTarget=strPriceTarget.Replace("➝","-"); + if(strPriceTarget.Contains("-")) + { + String[] prices=strPriceTarget.Split('-'); + strPriceTarget=prices[1]; + } + analystRating.PriceTarget=FeedParser.ParseValue(strPriceTarget); + } + if(analystRating.Type.Equals("Boost Price Target")) analystRating.Type="Upgrades"; + if(analystRating.Type.Equals("Upgrade")) analystRating.Type="Upgrades"; + if(analystRating.Type.Equals("Downgrade")) analystRating.Type="Downgrades"; + if(analystRating.Type.StartsWith("Reiterated")) analystRating.Type="Reiterated"; + if(analystRating.Type.StartsWith("Initiated")) analystRating.Type="Initiated"; + if(analystRating.Type.StartsWith("Set Price Target"))analystRating.Type="Initiated"; + if(!analystRating.Type.Equals("Upgrades")&&!analystRating.Type.Equals("Downgrades")&&!analystRating.Type.Equals("Reiterated")&&!analystRating.Type.Equals("Initiated")) continue; + analystRatings.Add(analystRating); + } + return new AnalystRatings(analystRatings.Distinct().ToList()); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return analystRatings; + } + finally + { + } + } + + private static bool HeaderContains(HtmlNodeCollection header,String[] requiredElements) + { + List headerElements=new List(); + if(null==header)return false; + for(int index=0;index exceptions=requiredElements.Except(headerElements).ToList(); + return exceptions.Count()>0?false:true; + } + + private static int HeaderIndexOf(HtmlNodeCollection header,String identifier) + { + if(null==header)return -1; + for(int index=0;index sections=Sections.GetSections(data[indexer].InnerHtml); + if(null==sections || 0==sections.Count)return data[indexer].InnerText; + return sections[0]; + } + + private static HtmlNodeCollection GetRatingsTableOnMarketBeat(String symbol,String exchange) + { + MemoryStream memoryStream=null; + HttpNetResponse httpNetResponse=null; + + try + { + String strRequest=null; + StringBuilder sb=new StringBuilder(); + sb.Append("https://www.marketbeat.com/stocks/").Append(exchange).Append("/").Append(symbol).Append("/price-target"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV3(strRequest, "www.marketbeat.com"); + if(!httpNetResponse.Success||String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes=Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream=new MemoryStream(streamBytes); + HtmlDocument htmlDocument=new HtmlDocument(); + htmlDocument.Load(memoryStream); + + HtmlNodeCollection ratingsTable=htmlDocument.DocumentNode.SelectNodes("//*[@class=\"scroll-table sort-table\"]"); + if(null==ratingsTable||0==ratingsTable.Count) return null; + return ratingsTable; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + if(null!=memoryStream) memoryStream.Close(); + if(null!=httpNetResponse) httpNetResponse.Dispose(); + } + } + +// *************************************************************************************************************************************************************************** +//***************************************************************** C I K C O D E S - S E C . G O V *********************************************************************** +// *************************************************************************************************************************************************************************** + public static String GetCIK(String symbol) + { + MemoryStream memoryStream = null; + HttpNetResponse httpNetResponse=null; + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + symbol = symbol.ToUpper(); + sb.Append(SEC_BASE_URL).Append("/cgi-bin/browse-edgar?CIK=").Append(symbol.ToUpper()).Append("&Find=Search&owner=exclude&action=getcompany"); + strRequest = sb.ToString(); + WebProxy webProxy=HttpNetRequest.GetProxy("GetCIK"); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5(strRequest,DEFAULT_TIMEOUT_MS,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection rows = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"companyInfo\"]"); // yfnc_tablehead1,yfnc_modtitle1,yfnc_tabledata1 + if (null == rows || 1!=rows.Count) + { + if (null == rows) MDTrace.WriteLine(LogLevel.DEBUG,"[GetCIK] Received no rows for '" + symbol + "'"); + else MDTrace.WriteLine(LogLevel.DEBUG,"Expected 1 row, got " + rows.Count + " for '" + symbol + "'"); + return null; + } + HtmlNode htmlNodeTitle = rows[0]; + HtmlNodeCollection nodes = htmlNodeTitle.SelectNodes(".//a"); + if (null == nodes || 0==nodes.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Expected tag for symbol '" + symbol + "'"); + return null; + } + String cik = null; + String[] strings = nodes[0].InnerText.Split(' '); + if (strings.Length >= 1) cik = strings[0]; + return cik; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if (null != memoryStream) memoryStream.Close(); + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// *************************************************************************************************************************************************************************************** +// ************************************ S E C F I L I N G S - F O R M 4 & F O R M 5 - F O R I N S I D E R T R A N S A C T I O N S S E C . G O V ***************************S +// *************************************************************************************************************************************************************************************** + public static InsiderTransactions GetInsiderTransactions(String symbol,int timePeriodDays=5) + { + MemoryStream memoryStream = null; + HttpNetResponse httpNetResponse=null; + String[] descriptionStartsWith=new String[]{"Form 4","Form 5"}; + DateTime minFilingDate=DateTime.Now; + int maxFilings=80; + bool continuationFlag=true; + int TIMEOUT_MS_BETWEEN_REQUESTS=1000; + + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactions: symbol:{0} dayCount:{1}",symbol,timePeriodDays)); + DateGenerator dateGenerator=new DateGenerator(); + String cik=PricingDA.GetCIKForSymbol(symbol); + if(null==cik) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactions: No CIK for symbol {0}",symbol)); + return null; + } + minFilingDate=dateGenerator.DaysAddActual(minFilingDate,Math.Abs(timePeriodDays)*-1); + SECFilings secFilings = new SECFilings(); + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append(SEC_BASE_URL).Append("/cgi-bin/browse-edgar?action=getcompany&CIK=").Append(cik).Append("&type=&dateb=&owner=include&count="+maxFilings.ToString()); + strRequest = sb.ToString(); + WebProxy webProxy=HttpNetRequest.GetProxy("GetInsiderTransactions"); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5(strRequest,DEFAULT_TIMEOUT_MS,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactions: Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection tables = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"tableFile2\"]"); + if (null == tables || tables.Count < 1) return null; + HtmlNodeCollection rows = tables[0].SelectNodes(".//tr"); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactions: symbol:{0} .Fetching {1} SECFilingDocuments ",symbol,rows.Count)); + for (int row = 0; row < rows.Count && continuationFlag; row ++) + { + try{Thread.Sleep(TIMEOUT_MS_BETWEEN_REQUESTS);}catch(Exception){;} + HtmlNodeCollection headerColumns = rows[row].SelectNodes(".//th"); + if (null != headerColumns && headerColumns.Count > 0) continue; + HtmlNodeCollection dataColumns = rows[row].SelectNodes(".//td"); + if (null == dataColumns || 5 != dataColumns.Count) continue; + HtmlNodeCollection nodes = dataColumns[1].SelectNodes(".//a"); + if (null == nodes || 0 == nodes.Count) continue; + String secFilingUrl=SEC_BASE_URL + nodes[0].GetAttributeValue("href", "unknown"); + SECFilings innerCollection = GetSECFilingDocuments(symbol, DateTime.Parse(dataColumns[3].InnerText), secFilingUrl); + for (int index = 0; null!=innerCollection && index < innerCollection.Count; index++) + { + SECFiling innerFiling = innerCollection[index]; + if(innerFiling.FilingDateinnerFiling.Description.StartsWith(x)))continue; + secFilings.Add(innerFiling); + } + } + return InsiderTransactionsParser.GetInstance().Parse(secFilings); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if (null != memoryStream) memoryStream.Close(); + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } + + /// + /// Get InsiderTransactions for years greater than or equal to specified year. + /// For example. If 2023 is specified then get all for years>=2023 + /// + /// The symbol. + /// the new y-coordinate. + public static InsiderTransactions GetInsiderTransactionsYear(String symbol,int yearGreaterThanEqualTo) + { + MemoryStream memoryStream = null; + HttpNetResponse httpNetResponse=null; + String[] descriptionStartsWith=new String[]{"Form 4","Form 5"}; + int maxFilings=120; + bool continuationFlag=true; + int TIMEOUT_MS_BETWEEN_REQUESTS=1000; + + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactionsYear: symbol:{0} year:{1}",symbol,yearGreaterThanEqualTo)); + DateGenerator dateGenerator=new DateGenerator(); + String cik=PricingDA.GetCIKForSymbol(symbol); + if(null==cik) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactionsYear: No CIK for symbol {0}",symbol)); + return null; + } + SECFilings secFilings = new SECFilings(); + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append(SEC_BASE_URL).Append("/cgi-bin/browse-edgar?action=getcompany&CIK=").Append(cik).Append("&type=&dateb=&owner=include&count="+maxFilings.ToString()); + strRequest = sb.ToString(); + WebProxy webProxy=HttpNetRequest.GetProxy("GetInsiderTransactions"); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5(strRequest,DEFAULT_TIMEOUT_MS,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactionsYear: Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection tables = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"tableFile2\"]"); + if (null == tables || tables.Count < 1) return null; + HtmlNodeCollection rows = tables[0].SelectNodes(".//tr"); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetInsiderTransactionsYear: symbol:{0} year:{1}. Fetching {2} SECFilingDocuments ",symbol,yearGreaterThanEqualTo,rows.Count)); + for (int row = 0; row < rows.Count && continuationFlag; row ++) + { + try{Thread.Sleep(TIMEOUT_MS_BETWEEN_REQUESTS);}catch(Exception){;} + HtmlNodeCollection headerColumns = rows[row].SelectNodes(".//th"); + if (null != headerColumns && headerColumns.Count > 0) continue; + HtmlNodeCollection dataColumns = rows[row].SelectNodes(".//td"); + if (null == dataColumns || 5 != dataColumns.Count) continue; + HtmlNodeCollection nodes = dataColumns[1].SelectNodes(".//a"); + if (null == nodes || 0 == nodes.Count) continue; + String secFilingUrl=SEC_BASE_URL + nodes[0].GetAttributeValue("href", "unknown"); + SECFilings innerCollection = GetSECFilingDocuments(symbol, DateTime.Parse(dataColumns[3].InnerText), secFilingUrl); + for (int index = 0; null!=innerCollection && index < innerCollection.Count; index++) + { + SECFiling innerFiling = innerCollection[index]; + if(innerFiling.FilingDate.YearinnerFiling.Description.StartsWith(x)))continue; + secFilings.Add(innerFiling); + } + } + return InsiderTransactionsParser.GetInstance().Parse(secFilings); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if (null != memoryStream) memoryStream.Close(); + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// *************************************************************************************************************************************************************************************** +// ********************************************************************** S E C F I L I N G S - S E C . G O V ******************************************************************** +// *************************************************************************************************************************************************************************************** + public static SECFilings GetSECFilings(String symbol,int maxFilings=80) + { + try + { + String cik=PricingDA.GetCIKForSymbol(symbol); + if(null==cik) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetSECFilings: No CIK for symbol {0}",symbol)); + return null; + } + return GetSECFilings(symbol,cik,maxFilings); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; } + } + + public static SECFilings GetSECFilings(String symbol,String cik,int maxFilings=80) + { + MemoryStream memoryStream = null; + HttpNetResponse httpNetResponse=null; + int TIMEOUT_MS_BETWEEN_DOCUMENTS=1000; + + try + { + SECFilings secFilings = new SECFilings(); + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append(SEC_BASE_URL).Append("/cgi-bin/browse-edgar?action=getcompany&CIK=").Append(cik).Append("&type=&dateb=&owner=include&count="+maxFilings.ToString()); + strRequest = sb.ToString(); + WebProxy webProxy=HttpNetRequest.GetProxy("GetSECFilings"); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5(strRequest,DEFAULT_TIMEOUT_MS,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection tables = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"tableFile2\"]"); + if (null == tables || tables.Count < 1) return null; + HtmlNodeCollection rows = tables[0].SelectNodes(".//tr"); + for (int row = 0; row < rows.Count; row ++) + { + HtmlNodeCollection headerColumns = rows[row].SelectNodes(".//th"); + if (null != headerColumns && headerColumns.Count > 0) continue; + HtmlNodeCollection dataColumns = rows[row].SelectNodes(".//td"); + if (null == dataColumns || 5 != dataColumns.Count) continue; + HtmlNodeCollection nodes = dataColumns[1].SelectNodes(".//a"); + if (null == nodes || 0 == nodes.Count) continue; + String secFilingUrl=SEC_BASE_URL + nodes[0].GetAttributeValue("href", "unknown"); + try { Thread.Sleep(TIMEOUT_MS_BETWEEN_DOCUMENTS); }catch(Exception) { ;} + SECFilings innerCollection = GetSECFilingDocuments(symbol, DateTime.Parse(dataColumns[3].InnerText), secFilingUrl); + for (int index = 0; null!=innerCollection && index < innerCollection.Count; index++) + { + SECFiling innerFiling = innerCollection[index]; + secFilings.Add(innerFiling); + } + } + return secFilings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if (null != memoryStream) memoryStream.Close(); + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// Get the filing document in XML format + private static SECFilings GetSECFilingDocuments(String symbol,DateTime filingDate,String secFilingDocumentUrl) + { + MemoryStream memoryStream = null; + SECFilings secFilings = new SECFilings(); + String secFilingDocument = null; + HttpNetResponse httpNetResponse=null; + int TIMEOUT_MS_BETWEEN_DOCUMENTS=1000; + + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetSECFilingDocuments[Retrieving documents at {0}]",secFilingDocumentUrl)); + WebProxy webProxy=HttpNetRequest.GetProxy("GetSECFilingDocuments"); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5(secFilingDocumentUrl,DEFAULT_TIMEOUT_MS,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetSECFilingDocuments[Request:{0} failed with status {1}]",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection secNodes = htmlDocument.DocumentNode.SelectNodes("//*[@id=\"secNum\"]"); + String secAccessionNumber = secNodes[0].InnerText; + secAccessionNumber = secAccessionNumber.Replace("\n",""); + secAccessionNumber = secAccessionNumber.Trim(); + if (secAccessionNumber.Contains("SEC Accession No.")) secAccessionNumber = secAccessionNumber.Substring(18, secAccessionNumber.Length - 18); + else return null; + secNodes = htmlDocument.DocumentNode.SelectNodes("//*[@id=\"formName\"]"); + String formName = secNodes[0].InnerText; + formName = formName.Replace("\n", ""); + formName = formName.Trim(); + HtmlNodeCollection tables = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"tableFile\"]"); + if (null == tables || tables.Count < 1) return null; + HtmlNodeCollection rows = tables[0].SelectNodes(".//tr"); + httpNetResponse.Dispose(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetSECFilingDocuments. Examining form {0} with {1} entries",formName,rows.Count)); + // go through the rows in the table file, searching for the different submission form content + int sequence = 0; + for (int row = 0; row < rows.Count; row++) + { + HtmlNodeCollection headerColumns = rows[row].SelectNodes(".//th"); + if (null != headerColumns && headerColumns.Count > 0) continue; + HtmlNodeCollection dataColumns = rows[row].SelectNodes(".//td"); + if (null == dataColumns || 5 != dataColumns.Count) continue; + String document = dataColumns[2].InnerText.Trim(); + String type = dataColumns[3].InnerText.Trim(); + if(null!=type && type.Equals("GRAPHIC"))continue; + if (document.Contains(".htm")) + { + + HtmlNodeCollection nodes = dataColumns[2].SelectNodes(".//a"); + if (null == nodes || 0 == nodes.Count) continue; + String secFilingDocumentXmlUrl = SEC_BASE_URL + nodes[0].GetAttributeValue("href", "unknown"); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetSECFilingDocuments. Requesting {0}",secFilingDocumentXmlUrl)); + try{Thread.Sleep(TIMEOUT_MS_BETWEEN_DOCUMENTS);}catch(Exception){;} + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5(secFilingDocumentXmlUrl,DEFAULT_TIMEOUT_MS,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetSECFilingDocuments. Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + continue; + } + secFilingDocument = httpNetResponse.ResponseString; + if (null == secFilingDocument) continue; + SECFiling secFiling = new SECFiling(); + secFiling.SECAccessionNumber = secAccessionNumber; + secFiling.Sequence = sequence++; + secFiling.Symbol = symbol; + secFiling.Form = type; + secFiling.Description = formName; + secFiling.FilingDate = filingDate; + secFiling.FileNumber = dataColumns[4].InnerText.Trim(); + secFiling.SecFilingUrl = secFilingDocumentXmlUrl; + secFiling.FormText = secFilingDocument; + secFiling.FormText = secFiling.FormText.Replace("\n",""); + if (null == secFiling.FormText) continue; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetSECFilingDocuments. Got {0} for {1} filed on {2}",secFiling.Description,symbol,secFiling.FilingDate.ToShortDateString())); + secFilings.Add(secFiling); + httpNetResponse.Dispose(); + } + } + return secFilings; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if (null != memoryStream) + { + memoryStream.Close(); + memoryStream = null; + } + } + } +// *************************************************************************************************************************************************************************************** +// ********************************************************************** Y I E L D C U R V E - T R E A S U R Y . G O V ************************************************************** +// *************************************************************************************************************************************************************************************** + public static YieldCurve GetYieldCurve(int year) + { + YieldCurve yieldCurve = new YieldCurve(); + HttpNetResponse httpNetResponse=null; + + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append("https://home.treasury.gov/resource-center/data-chart-center/interest-rates/pages/xml?data=daily_treasury_yield_curve&field_tdr_date_value=").Append(year); + strRequest = sb.ToString(); + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + XElement po = XElement.Parse(httpNetResponse.ResponseString); + IEnumerable childElements = from el in po.Elements() where el.Name.LocalName.Equals("entry") select el; + foreach (XElement element in childElements) + { + IEnumerable childElementsL1 = from el in element.Elements() select el; + foreach (XElement elementL1 in childElementsL1) + { + if(elementL1.Name.LocalName.Equals("content")) + { + IEnumerable elementsL2=elementL1.Elements(); + if(!elementsL2.FirstOrDefault().Name.LocalName.Equals("properties"))continue; + IEnumerable elementsL3=elementsL2.FirstOrDefault().Elements(); + YieldCurveData yieldCurveData = new YieldCurveData(); + yieldCurveData.Date=Utility.Epoch; + foreach (XElement elementL3 in elementsL3) + { + if(elementL3.Name.LocalName.EndsWith("NEW_DATE")) yieldCurveData.Date=Utility.ParseDate(Utility.RemoveAfter(elementL3.Value,'T')); + else if(elementL3.Name.LocalName.EndsWith("1MONTH"))yieldCurveData.Mo1=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("2MONTH"))yieldCurveData.Mo2=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("3MONTH"))yieldCurveData.Mo3=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("6MONTH"))yieldCurveData.Mo6=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("1YEAR"))yieldCurveData.Yr1=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("2YEAR"))yieldCurveData.Yr2=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("3YEAR"))yieldCurveData.Yr3=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("5YEAR"))yieldCurveData.Yr5=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("7YEAR"))yieldCurveData.Yr7=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("10YEAR"))yieldCurveData.Yr10=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("20YEAR"))yieldCurveData.Yr20=FeedParser.ParseValue(elementL3.Value); + else if(elementL3.Name.LocalName.EndsWith("30YEAR"))yieldCurveData.Yr30=FeedParser.ParseValue(elementL3.Value); + } + if(yieldCurveData.IsValid())yieldCurve.Add(yieldCurveData); + } + } + } + yieldCurve=new YieldCurve(yieldCurve.Distinct().ToList()); + return yieldCurve; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return yieldCurve; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// *************************************************************************************************************************************************************************************** +// ********************************************************************** E T F H O L D I N G S - Y A H O O F I N A N C E ********************************************************* +// *************************************************************************************************************************************************************************************** + public static ETFHoldings GetETFHoldings(String etfSymbol) + { + MemoryStream memoryStream = null; + ETFHoldings etfHoldings = new ETFHoldings(); + HttpNetResponse httpNetResponse=null; + DateTime modified=DateTime.Now; + + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + etfSymbol = etfSymbol.ToUpper(); + sb.Append("https://finance.yahoo.com/quote/").Append(etfSymbol).Append("/holdings"); + strRequest = sb.ToString(); + + WebProxy webProxy=HttpNetRequest.GetProxy("GetETFHoldings"); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetETFHoldings:{0}",strRequest)); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV7(strRequest,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + + List sections = Sections.GetAllItemsInSections(httpNetResponse.ResponseString,"table"); + if(null == sections || 1!=sections.Count) + { + etfHoldings=TryParseYahooFinanceETFHoldings(etfSymbol,httpNetResponse.ResponseString); + if(null==etfHoldings) + { + MDTrace.WriteLine(LogLevel.DEBUG,"GetETFHoldings: Unable to interpret response."); + return null; + } + return etfHoldings; + } + String marker=" sections = Sections.GetAllItemsInSections(responseString,"section"); + if(null==sections || 0==sections.Count)return null; + String sectionItem=sections.Where(x => x.Contains("data-testid=\"top-holdings\"")).FirstOrDefault(); + if(String.IsNullOrEmpty(sectionItem))return null; + List spans =Sections.GetAllItemsInSections(sectionItem,"span"); + if(null==spans || 0==spans.Count || spans.Count","<"); + String companyNameHeading=Utility.BetweenString(spans[index+1],">","<"); + String percentOfAssetsHeading=Utility.BetweenString(spans[index+2],">","<"); + if(!symbolNameHeading.Equals("Symbol") || !companyNameHeading.Equals("Company") || !percentOfAssetsHeading.Equals("% Assets")) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Unexpected heading."); + return null; + } + } + else + { + ETFHolding etfHolding = new ETFHolding(); + etfHolding.ETFSymbol = etfSymbol; + etfHolding.HoldingSymbolShareClass = null; + etfHolding.HoldingCompanyName = Utility.BetweenString(spans[index+1],">","<"); + etfHolding.HoldingSymbol = etfHolding.HoldingSymbolShareClass = Utility.BetweenString(spans[index],">","<"); + if (null == etfHolding.HoldingSymbol || "N/A".Equals(etfHolding.HoldingSymbol) || "".Equals(etfHolding.HoldingSymbol)) continue; + etfHolding.PercentOfAssets = FeedParser.ParseValue(Utility.BetweenString(spans[index+2],">","<")); + etfHolding.Modified = modified; + etfHoldings.Add(etfHolding); + } + } + return 0==etfHoldings.Count?null:etfHoldings; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[TryParseYahooFinanceETFHoldings] Exception: {0}",exception.ToString())); + return null; + } + } +// ****************************************************************************************************************************************************************************** +// **************************************************************************C O M P A N Y P R O F I L E ********************************************************************** +// ***************************************************************** P R O F I L E : M O R N I N G S T A R ******************************************************************* +// ***************************************************************** D E S C R I P T I O N : R E U T E R S ******************************************************************** +// ****************************************************************************************************************************************************************************** + public static CompanyProfile GetCompanyProfile(String symbol) + { + String nasdaq = "xnas"; + String nyse = "xnys"; + CompanyProfile companyProfile = null; + companyProfile = GetCompanyProfileYahoo(symbol); + if (null==companyProfile)companyProfile=GetCompanyProfileMorningStar(symbol,nasdaq); + if (null == companyProfile) companyProfile = GetCompanyProfileMorningStar(symbol, nyse); + return companyProfile; + } + + // GetCompanyProfile - DataSource Yahoo Finance + public static CompanyProfile GetCompanyProfileYahoo(String symbol) + { + HttpNetResponse httpNetResponse = null; + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + symbol = symbol.ToUpper(); + + WebProxy webProxy = HttpNetRequest.GetProxy("GetCompanyProfileYahoo"); + sb.Append("http://finance.yahoo.com/q/pr?s=").Append(symbol).Append("+Profile"); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV1(strRequest); + if (!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + +// Locate Industry + String strIndustry = Sections.LocateItem(httpNetResponse.ResponseString, "Industry", 4); + if(strIndustry == null)strIndustry = Sections.LocateItem(httpNetResponse.ResponseString, "Industry:??", 2); + +// Locate Sector + String strSector = Sections.LocateItem(httpNetResponse.ResponseString, "Sector", 4); + if (null == strSector) strSector = Sections.LocateItem(httpNetResponse.ResponseString, "Sector(s)", 4); + if(null == strSector) strSector = Sections.LocateItem(httpNetResponse.ResponseString, "Sector:??", 3); + + if (null != strIndustry && strIndustry.Contains(Constants.CONST_QUESTION)) strIndustry = strIndustry.Replace(Constants.CONST_QUESTION, " - "); + if (null != strSector && strSector.Contains(Constants.CONST_QUESTION)) strSector = strSector.Replace(Constants.CONST_QUESTION, " - "); + +// Locate Description + String strDescription = Sections.LocateItem(httpNetResponse.ResponseString, "Description", 4); + if(null == strDescription) + { + List indices = Sections.LocateAllOccurrences(httpNetResponse.ResponseString, "Description"); + if(indices.Count>0) + { + List sections = Sections.GetSections(httpNetResponse.ResponseString); + strDescription = Sections.GetFirstNonEmptyItemInSection(sections, indices[0]+1); + } + } + + if(null!=strDescription && strDescription.Equals("Description Information Not Available")) + { + strDescription = null; + } + + if(null == strIndustry || null == strSector || null == strDescription) + { + return null; + } + + CompanyProfile companyProfile = new CompanyProfile(); + companyProfile.Symbol = symbol; + companyProfile.Sector = strSector; + companyProfile.Industry = strIndustry; + companyProfile.Description = strDescription; + if (null != companyProfile.Sector) companyProfile.Sector = companyProfile.Sector.Trim(); + if (null != companyProfile.Industry) companyProfile.Industry = companyProfile.Industry.Trim(); + if (null != companyProfile.Description) companyProfile.Description = Utility.RemoveHtml(companyProfile.Description.Trim()); + return companyProfile; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG, exception); + return null; + } + finally + { + if (null != httpNetResponse) httpNetResponse.Dispose(); + } + } + + public static CompanyProfile GetCompanyProfileMorningStar(String symbol,String exchange) + { + HttpNetResponse httpNetResponse=null; + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + symbol = symbol.ToUpper(); + WebProxy webProxy=HttpNetRequest.GetProxy("GetCompanyProfileMorningStar"); + sb.Append(String.Format("https://www.morningstar.com/stocks/{0}/{1}/quote",exchange,symbol)); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV5A(strRequest, 10000, webProxy); + + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + + String strSector=null; + String strIndustry=null; + String strDescription=null; + int itemIndex=0; + List sections=Sections.GetSections(httpNetResponse.ResponseString); + + bool found=Sections.FindInSections(sections,"Sector",0,ref itemIndex); + if(found)strSector=sections[itemIndex+3]; + + found=Sections.FindInSections(sections,"Industry",itemIndex,ref itemIndex); + if(found)strIndustry=sections[itemIndex+3]; + + found=Sections.FindInSections(sections,"Business Description",itemIndex,ref itemIndex); + if(found)strDescription=sections[itemIndex+2]; + else + { + itemIndex=0; + found=Sections.FindInSections(sections,"Company Profile",itemIndex,ref itemIndex); + if(found)strDescription = Sections.GetFirstNonEmptyItemInSection(sections, itemIndex+1); + } + + if(null==strIndustry && null==strSector)return null; + + strSector=strSector.Trim(); + strIndustry=strIndustry.Trim(); + CompanyProfile companyProfile = new CompanyProfile(); + companyProfile.Symbol = symbol; + companyProfile.Sector = strSector; + companyProfile.Industry = strIndustry; + companyProfile.Description=strDescription; + if(null!=companyProfile.Sector)companyProfile.Sector=companyProfile.Sector.Trim(); + if(null!=companyProfile.Industry)companyProfile.Industry=companyProfile.Industry.Trim(); + if(null!=strDescription)companyProfile.Description=companyProfile.Description.Trim(); + + if(null!=companyProfile.Industry && companyProfile.Industry.Contains(Constants.CONST_QUESTION)) + { + companyProfile.Industry=companyProfile.Industry.Replace(Constants.CONST_QUESTION," - "); + } + if(null!=companyProfile.Sector && companyProfile.Sector.Contains(Constants.CONST_QUESTION)) + { + companyProfile.Sector=companyProfile.Sector.Replace(Constants.CONST_QUESTION," - "); + } + if((null!=companyProfile.Sector && companyProfile.Sector.Equals(Constants.CONST_QUESTION)) + || (null!=companyProfile.Industry && companyProfile.Industry.Equals(Constants.CONST_QUESTION)) + || (null!=companyProfile.Description && companyProfile.Description.Equals(Constants.CONST_QUESTION)))return null; + return companyProfile; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } + +// *************************************************************************************************************************************************************************** +//***************************************************************** H E A D L I N E S - S E E K I N G A L P H A *********************************************************** +// *************************************************************************************************************************************************************************** + public static Headlines GetCompanyHeadlinesSeekingAlpha(String symbol) + { + Headlines headlines = GetCompanyHeadlinesSeekingAlphaV3(symbol); + return headlines; + } + + + /// + /// Retrieves headlines from seeking alpha. If ignoreMarketDate is TRUE then the results will not be + /// filtered by the current market date . + /// + /// + /// + /// + public static Headlines GetCompanyHeadlinesSeekingAlphaV3(String symbol, bool ignoreMarketDate=false) + { + HttpNetResponse httpNetResponse=null; + Headlines headlines=new Headlines(); + + try + { + String domain = "seekingalpha.com"; + StringBuilder sb = new StringBuilder(); + String strRequest; + symbol = symbol.ToUpper(); + +// Visit the home page + WebProxy webProxy=HttpNetRequest.GetProxy("GetCompanyHeadlinesSeekingAlphaV3"); + sb.Append("https://").Append(domain); + + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5D(sb.ToString(),domain,30000,webProxy,false); + if(!httpNetResponse.Success)return null; + CookieCollection cookieCollection = httpNetResponse.CookieCollection; + + sb=new StringBuilder(); + DateTime marketDate=PremarketDA.GetLatestMarketDate(); + if(Utility.IsEpoch(marketDate))marketDate=DateTime.Now; + + #region Create Cookies + + StringBuilder lastVisitedPage = new StringBuilder(); + lastVisitedPage.Append("%7B%22pathname%22%3A%22https%3A%2F%2Fseekingalpha.com%2Fsymbol%2F"); + lastVisitedPage.Append(symbol); + lastVisitedPage.Append("%2Fnews%22%2C%22pageKey%22%3A%22947f55ae-51ad-480f-9f22-54ef1d5904d1%22%7D"); + + cookieCollection.Add(new Cookie("LAST_VISITED_PAGE", lastVisitedPage.ToString()) { Domain = domain }); + cookieCollection.Add(new Cookie("_ga", "GA1.1.1862228764.1739274352") { Domain = domain }); + cookieCollection.Add(new Cookie("_ga_KGRFF2R2C5","GS1.1.1739274352.1.1.1739274637.60.0.0"){ Domain = domain }); + cookieCollection.Add(new Cookie("_gcl_au","1.1.1611738349.1739274352"){ Domain = domain }); + cookieCollection.Add(new Cookie("_pxvid","bfabea2f-e86d-11ef-832d-24c9f227f821"){ Domain = domain }); + cookieCollection.Add(new Cookie("_sasource",""){ Domain = domain }); + cookieCollection.Add(new Cookie("pxcts","bfabfefc-e86d-11ef-832f-7d1e5f897eb5"){ Domain = domain }); + + #endregion + sb.Append("https://").Append(domain).Append("/api/v3/symbols/").Append(symbol).Append("/news?filter[since]="); + sb.Append("0"); + sb.Append("&filter[until]="); + sb.Append("0"); + sb.Append("&id=").Append(symbol); + sb.Append("&include=author,primaryTickers,secondaryTickers,sentiments,otherTags&isMounting=true&page[size]=40&page[number]=1"); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG, strRequest); + + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5D(strRequest,domain,30000,webProxy,false,cookieCollection); + + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + List keyValuePairs = MarketDataHelper.LocateJSONKeyValuePairs(httpNetResponse.ResponseString, "\"publishOn\"", "\"title\""); + if(null==keyValuePairs)return null; + + foreach (KeyValue keyValue in keyValuePairs) + { + Headline headline=null; + if (keyValue.Value.StartsWith("Video")) headline = new Headline(symbol, Utility.ParseDate(keyValue.Key.Substring(0, keyValue.Key.IndexOf('T'))),Uri.UnescapeDataString(keyValue.Value)); + else headline = new Headline(symbol, Utility.ParseDate(keyValue.Key.Substring(0, keyValue.Key.IndexOf('T'))), keyValue.Value); + headline.Entry=headline.Entry.Replace("\\"," "); + headline.Entry=headline.Entry.Trim(); + headline.Entry=Encoding.UTF8.GetString(Encoding.Default.GetBytes(headline.Entry)); + headline.Entry=Uri.UnescapeDataString(headline.Entry); + headline.Source = "Seeking Alpha"; + headlines.Add(headline); + } + + if(!ignoreMarketDate) + { + headlines = new Headlines(headlines.Where(x => x.Date.Date.Equals(marketDate.Date)).ToList()); + } + + return headlines; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } + +// *************************************************************************************************************************************************************************** +//***************************************************************** H E A D L I N E S - M A R K E T W A T C H ************************************************************* +// *************************************************************************************************************************************************************************** + + public static Headlines GetCompanyHeadlinesMarketWatch(String symbol) + { + HttpNetResponse httpNetResponse=null; + Headlines headlines=new Headlines(); + DateTime modified=DateTime.Now; + + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + symbol = symbol.ToUpper(); + MemoryStream memoryStream=null; + CookieCollection cookieCollection=new CookieCollection(); + httpNetResponse= HttpNetRequest.GetRequestNoEncodingV4("https://www.marketwatch.com",cookieCollection); + Thread.Sleep(500); + sb.Append("https://www.marketwatch.com/investing/stock/").Append(symbol).Append("?mod=search_symbol"); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG, strRequest); + WebProxy webProxy=HttpNetRequest.GetProxy("GetCompanyHeadlinesMarketWatch"); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5B(strRequest,DEFAULT_TIMEOUT_MS,webProxy,true,cookieCollection); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + byte[] streamBytes=Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream=new MemoryStream(streamBytes); + HtmlDocument htmlDocument=new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection divSections=htmlDocument.DocumentNode.SelectNodes("//*[@class=\"article__content\"]"); + + if(null == divSections) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No headlines for request {0} ",strRequest)); + return headlines; + } + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + + + for(int nodeIndex=0;nodeIndex sections=Sections.GetSections(htmlNodeHeadline.InnerHtml); + if(null == sections || 0==sections.Count)continue; + String strHeadline = Utility.RemoveHtml(sections[sections.Count-1]); + String strTimestamp = htmlNodeTimestamp.InnerText; + + if(String.IsNullOrEmpty(strHeadline) || String.IsNullOrEmpty(strTimestamp)) + { + continue; + } + + Headline headline= new Headline(); + headline.Symbol=symbol; + headline.Date=FeedParser.ParseValueDateTimeMonthFormatTZ(strTimestamp); + headline.Entry=strHeadline.Trim(); + headline.Source="MarketWatch"; + headline.Modified=modified; + headline.CompanyName=null!=companyProfile?companyProfile.CompanyName:null; + + if(Utility.IsEpoch(headline.Date)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Invalid date for symbol {0}",symbol)); + continue; + } + headlines.Add(headline); + } + headlines=new Headlines(headlines.Distinct().ToList()); + return headlines; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// *************************************************************************************************************************************************************************** +//************************************************************************ H E A D L I N E S - N A S D A Q ****************************************************************** +// *************************************************************************************************************************************************************************** + public static Headlines GetCompanyHeadlinesNASDAQ(String symbol) + { + HttpNetResponse httpNetResponse=null; + MemoryStream memoryStream=null; + Headlines headlines=new Headlines(); + try + { + StringBuilder sb=new StringBuilder(); + String strRequest; + symbol=symbol.ToUpper(); + sb.Append("https://api.nasdaq.com/api/news/topic/articlebysymbol?q=").Append(symbol).Append("|etf&offset=0&limit=8&fallback=false"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5(strRequest,DEFAULT_TIMEOUT_MS); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + + List> items=LocateJSONItemsTags(httpNetResponse.ResponseString); + if(null==items || items.Count<7)return null; + int index=0; + for(;index GetHistoricalValues(String symbol) + { + Dictionary values = new Dictionary(); + HttpNetResponse httpNetResponse=null; + String nasdaq = "xnas"; + String nyse = "xnyse"; + String nys="xnys"; + String salVersion="4.30.0"; + String salVerson45100="4.51.0"; + String strDefinition = default; + String strColumnDefinition = default; + int TIMEOUT_BETWEEN_REQUESTS_MS=500; + + String exchange=nasdaq; + String url="https://www.morningstar.com/api/v2/stocks/"; + + try + { + StringBuilder sb = new StringBuilder(); + StringBuilder strReferer = new StringBuilder(); + String strRequest; + sb=new StringBuilder(); + sb.Append(url).Append(exchange).Append("/").Append(symbol).Append("/performance"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + WebProxy webProxy=HttpNetRequest.GetProxy("GetHistoricalValues"); + + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV3A(strRequest,webProxy); + if(!httpNetResponse.Success||null==httpNetResponse.ResponseString || "".Equals(httpNetResponse.ResponseString)) + { + sb=new StringBuilder(); + exchange=nys; + sb.Append(url).Append(exchange).Append("/").Append(symbol).Append("/performance"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV3A(strRequest,webProxy); + if(!httpNetResponse.Success||null==httpNetResponse.ResponseString || "".Equals(httpNetResponse.ResponseString)) + { + sb=new StringBuilder(); + exchange=nyse; + sb.Append(url).Append(exchange).Append("/").Append(symbol).Append("/performance"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV3A(strRequest,webProxy); + if(!httpNetResponse.Success||null==httpNetResponse.ResponseString || "".Equals(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + } + } +// This next call does not make any outgoing calls, it just attempts to parse out the morningstar security identifier. + String securityId=GetMStarSecurityId(symbol,httpNetResponse.ResponseString); + if(null==securityId) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Cannot determine MorningStar Identifier for {0}",symbol)); + return null; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Morningstar Mapping:'{0}'=>'{1}'",symbol,securityId)); + +// PROFITABILITY AND EFFICIENCY - SOURCES ROA AND ROIC + sb=new StringBuilder(); + sb.Append("https://api-global.morningstar.com/sal-service/v1/stock/keyMetrics/profitabilityAndEfficiency/").Append(securityId).Append("?languageId=en&locale=en&clientId=MDC&component=sal-eqsv-key-metrics-profitability-efficiency&version=").Append(salVerson45100); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + try{Thread.Sleep(TIMEOUT_BETWEEN_REQUESTS_MS);}catch{;} + httpNetResponse = HttpNetRequest.GetRequestNoEncodingMStar(strRequest,webProxy); + if(!httpNetResponse.Success || String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("[GetHistoricalValues::OperatingPerformance] Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + List> profitabilityItems=LocateJSONItems(httpNetResponse.ResponseString); + Dictionary dataSetsProfitabilityAndEfficiency=GetData("fiscalPeriodYear", profitabilityItems, httpNetResponse.ResponseString); + httpNetResponse.Dispose(); + +// KETSTATS - FINANCIALHEALTH + sb=new StringBuilder(); + sb.Append("https://api-global.morningstar.com/sal-service/v1/stock/keyStats/financialHealth/").Append(securityId).Append("?languageId=en&locale=en&clientId=MDC&component=sal-components-key-stats-financial-health&version=").Append(salVersion); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + try{Thread.Sleep(TIMEOUT_BETWEEN_REQUESTS_MS);}catch{;} + httpNetResponse = HttpNetRequest.GetRequestNoEncodingMStar(strRequest,webProxy); + if(!httpNetResponse.Success || String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("[GetHistoricalValues::FinancialHeath] Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + List> items=LocateJSONItems(httpNetResponse.ResponseString); + Dictionary dataSetsFinancialHealth=GetData("fiscalPeriodYearMonth", items, httpNetResponse.ResponseString); + httpNetResponse.Dispose(); + +// NEWFINANCIALS - ANNUAL/SUMMARY + sb=new StringBuilder(); + sb.Append("https://api-global.morningstar.com/sal-service/v1/stock/newfinancials/").Append(securityId).Append("/annual/summary?reportType=A&languageId=en&locale=en&clientId=MDC&component=sal-components-equity-financials-summary&version=").Append(salVersion); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + try{Thread.Sleep(TIMEOUT_BETWEEN_REQUESTS_MS);}catch{;} + httpNetResponse = HttpNetRequest.GetRequestNoEncodingMStar(strRequest,webProxy); + if(!httpNetResponse.Success || String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("[GetHistoricalValues::AnnualSummary] Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + Dictionary dataSetsAnnuals=GetData(httpNetResponse.ResponseString); + httpNetResponse.Dispose(); + +// NEWFINANCIALS - INCOMESTATEMENT + sb=new StringBuilder(); + sb.Append("https://api-global.morningstar.com/sal-service/v1/stock/newfinancials/").Append(securityId).Append("/incomeStatement/detail?dataType=A&reportType=A&locale=en&languageId=en&locale=en&clientId=MDC&component=sal-components-equity-financials-details&version=").Append(salVersion); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + try{Thread.Sleep(TIMEOUT_BETWEEN_REQUESTS_MS);}catch{;} + httpNetResponse = HttpNetRequest.GetRequestNoEncodingMStar(strRequest,webProxy); + if(!httpNetResponse.Success || String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("[GetHistoricalValues::IncomeStatement] Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + Dictionary dataSetsIncomeStatement=GetData(httpNetResponse.ResponseString); + httpNetResponse.Dispose(); + +// NEWFINANCIALS - CASHFLOW + sb=new StringBuilder(); + sb.Append("https://api-global.morningstar.com/sal-service/v1/stock/newfinancials/").Append(securityId).Append("/cashFlow/detail?dataType=A&reportType=A&locale=en&languageId=en&locale=en&clientId=MDC&component=sal-components-equity-financials-details&version=").Append(salVersion); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + try{Thread.Sleep(TIMEOUT_BETWEEN_REQUESTS_MS);}catch{;} + httpNetResponse = HttpNetRequest.GetRequestNoEncodingMStar(strRequest,webProxy); + if(!httpNetResponse.Success || String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("[GetHistoricalValues::Cashflow] Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + Dictionary dataSetsCashflowStatement=GetData(httpNetResponse.ResponseString); + httpNetResponse.Dispose(); + +//NEWFINANCIALS - BALANCESHEET + sb=new StringBuilder(); + sb.Append("https://api-global.morningstar.com/sal-service/v1/stock/newfinancials/").Append(securityId).Append("/balanceSheet/detail?dataType=A&reportType=A&locale=en&languageId=en&locale=en&clientId=MDC&component=sal-components-equity-financials-details&version=").Append(salVersion); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + try{Thread.Sleep(TIMEOUT_BETWEEN_REQUESTS_MS);}catch{;} + httpNetResponse = HttpNetRequest.GetRequestNoEncodingMStar(strRequest,webProxy); + if(!httpNetResponse.Success || String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("[GetHistoricalValues::BalanceSheet] Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + Dictionary dataSetsBalanceSheet=GetData(httpNetResponse.ResponseString); + httpNetResponse.Dispose(); + +// RETURN ON ASSETS + strDefinition="roa"; + strColumnDefinition="columnDefs"; + if(dataSetsProfitabilityAndEfficiency.ContainsKey(strDefinition)) + { + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.ROA; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsProfitabilityAndEfficiency[strColumnDefinition],dataSetsProfitabilityAndEfficiency[strDefinition],elementType); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// RETURN ON INVESTED CAPITAL + strDefinition="roic"; + strColumnDefinition="columnDefs"; + if(dataSetsProfitabilityAndEfficiency.ContainsKey(strDefinition)) + { + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.ROIC; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsProfitabilityAndEfficiency[strColumnDefinition],dataSetsProfitabilityAndEfficiency[strDefinition],elementType); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// BOOK VALUE PER SHARE + strDefinition="bookValuePerShare"; + strColumnDefinition="columnDefs"; + if(dataSetsFinancialHealth.ContainsKey(strDefinition)) + { + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.BVPS; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsFinancialHealth[strColumnDefinition],dataSetsFinancialHealth[strDefinition],elementType); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// INVENTORIES + strDefinition="Inventories"; + strColumnDefinition="columnDefs"; + if(dataSetsBalanceSheet.ContainsKey(strDefinition)) + { + double multiplier=dataSetsBalanceSheet["multiplier"].GetItem(0); + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.Inventory; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsBalanceSheet[strColumnDefinition],dataSetsBalanceSheet[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// ACCOUNTS RECEIVABLES + strDefinition="Trade/Accounts Receivable, Current"; + strColumnDefinition="columnDefs"; + if(dataSetsBalanceSheet.ContainsKey(strDefinition)) + { + double multiplier=dataSetsBalanceSheet["multiplier"].GetItem(0); + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.AccountsReceivable; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsBalanceSheet[strColumnDefinition],dataSetsBalanceSheet[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// COST OF GOOD AND SERVICES + strDefinition="Cost of Goods and Services"; + strColumnDefinition="columnDefs"; + if(dataSetsIncomeStatement.ContainsKey(strDefinition)) + { + double multiplier=dataSetsIncomeStatement["multiplier"].GetItem(0)*-1.00; + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.COGS; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsIncomeStatement[strColumnDefinition],dataSetsIncomeStatement[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// TOTAL OPERATING PROFIT/LOSS + strDefinition="Total Operating Profit/Loss"; + strColumnDefinition="columnDefs"; + if(dataSetsIncomeStatement.ContainsKey(strDefinition)) + { + double multiplier=dataSetsIncomeStatement["multiplier"].GetItem(0); + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.OperatingIncome; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsIncomeStatement[strColumnDefinition],dataSetsIncomeStatement[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// INTEREST EXPENSE + strDefinition="Interest Expense Net of Capitalized Interest"; + strColumnDefinition="columnDefs"; + if(dataSetsIncomeStatement.ContainsKey(strDefinition)) + { + double multiplier=dataSetsIncomeStatement["multiplier"].GetItem(0)*-1.00; + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.InterestExpense; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsIncomeStatement[strColumnDefinition],dataSetsIncomeStatement[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// REPORTED EFFECTIVE TAX RATE + strDefinition="Reported Effective Tax Rate"; + strColumnDefinition="columnDefs"; + if(dataSetsIncomeStatement.ContainsKey(strDefinition)) + { + double multiplier=100.00; + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.TaxRate; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsIncomeStatement[strColumnDefinition],dataSetsIncomeStatement[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// TOTAL REVENUE + strDefinition="Total Revenue"; + strColumnDefinition="columnDefs"; + if(dataSetsAnnuals.ContainsKey(strDefinition)) + { + double multiplier=dataSetsAnnuals["multiplier"].GetItem(0); + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.Revenue; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsAnnuals[strColumnDefinition],dataSetsAnnuals[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// NET INCOME AVAILABLE TO COMMON STOCKHOLDERS + strDefinition="Net Income Available to Common Stockholders"; + strColumnDefinition="columnDefs"; + if(dataSetsAnnuals.ContainsKey(strDefinition)) + { + double multiplier=dataSetsAnnuals["multiplier"].GetItem(0); + multiplier/=1000000; + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.NetIncomeAvailableToCommonShareholders; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsAnnuals[strColumnDefinition],dataSetsAnnuals[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// DILUTED EPS + strDefinition="Diluted EPS"; + strColumnDefinition="columnDefs"; + if(dataSetsAnnuals.ContainsKey(strDefinition)) + { + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.EPS; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsAnnuals[strColumnDefinition],dataSetsAnnuals[strDefinition],elementType); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// WORKING CAPITAL + strDefinition="Working Capital"; + strColumnDefinition="columnDefs"; + if(dataSetsAnnuals.ContainsKey(strDefinition)) + { + double multiplier=dataSetsAnnuals["multiplier"].GetItem(0); + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.WorkingCapital; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsAnnuals[strColumnDefinition],dataSetsAnnuals[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString()); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// FREE CASHFLOW + strDefinition="Free Cash Flow"; + strColumnDefinition="columnDefs"; + if(dataSetsAnnuals.ContainsKey(strDefinition)) + { + double multiplier=dataSetsAnnuals["multiplier"].GetItem(0); + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.FreeCashflow; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsAnnuals[strColumnDefinition],dataSetsAnnuals[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + +// OPERATING CASHFLOW + strDefinition="Cash Generated from Operating Activities"; + strColumnDefinition="columnDefs"; + if(dataSetsCashflowStatement.ContainsKey(strDefinition)) + { + double multiplier=dataSetsCashflowStatement["multiplier"].GetItem(0); + TimeSeriesElement.ElementType elementType=TimeSeriesElement.ElementType.OperatingCashflow; + TimeSeriesCollection timeSeriesCollection=CreateTimeSeriesCollection(symbol, dataSetsCashflowStatement[strColumnDefinition],dataSetsCashflowStatement[strDefinition],elementType,multiplier); + if (null != timeSeriesCollection && 0 != timeSeriesCollection.Count) + { + values.Add(elementType, timeSeriesCollection); + String strMessage=String.Format("got {0} records for '{1}' for {2}. Data:{3}",timeSeriesCollection.Count,symbol,TimeSeriesElement.StringForType(elementType),timeSeriesCollection.ToString() ); + MDTrace.WriteLine(LogLevel.DEBUG,strMessage); + } + } + + return values; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + + internal class MStarDataSet + { + private String name; + private List values; + public MStarDataSet() + { + values=new List(); + } + public MStarDataSet(String name,List values) + { + this.name=name; + this.values=values; + } + public MStarDataSet(String name,String value) + { + values=new List(); + this.name=name; + this.values.Add(value); + } + public String Name + { + get{return name;} + set{name=value;} + } + public List Values + { + get{return values;} + private set{;} + } + public T GetItem(int index=0) + { + T result=default(T); + try {result = (T)Convert.ChangeType(values[index], typeof(T));} + catch {result = default(T);} + return result; + } + } + +// \"indexName\":\"Morningstar US Market TR USD\",\"ebitdaCurrency\":\"USD\"}}" +//\"orderOfMagnitude\":\"Million\", + private static double GetMultiplierForDataSet(String responseString) + { + double multiplier=1.00; + try + { + string token="\"indexName\""; + int index=responseString.IndexOf(token); + if(-1==index) + { + token="\"orderOfMagnitude\""; + index=responseString.IndexOf(token); + if(-1==index)return multiplier; + string strSubString=responseString.Substring(index+token.Length); + strSubString=Utility.BetweenString(strSubString,"\"","\""); + string[] parts=strSubString.Split(' '); + if(1!=parts.Length)return multiplier; + if(parts[0].Equals("Million"))multiplier=1000000; + else if(parts[0].Equals("Billion"))multiplier=1000000000; + else if(parts[0].Equals("Trillion"))multiplier=1000000000000; + else multiplier=1.00; + return multiplier; + } + else + { + string strSubString=responseString.Substring(index+token.Length); + strSubString=Utility.BetweenString(strSubString,"\"","\""); + string[] parts=strSubString.Split(' '); + if(2>parts.Length)return multiplier; + if(parts[parts.Length-2].Equals("TR"))multiplier=1000000000; + else + { + multiplier=1; + } + return multiplier; + } + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetMultiplierForDataSet encountered an exception:{0}",exception.ToString())); + return multiplier; + } + } + +// \"indexName\":\"Morningstar US Market TR USD\",\"ebitdaCurrency\":\"USD\"}}" +//\"orderOfMagnitude\":\"Million\", +// {"currency":"USD","currencySymbol":"$","orderOfMagnitude":"Billion","fiscalYearEndDate":"12-31"},"userType":"Free"} + private static String GetCurrencyForDataSet(String responseString) + { + String currency=null; + try + { + string token="\"indexName\""; + int index=responseString.IndexOf(token); + if(-1==index) + { + token="\"currency\""; + index=responseString.IndexOf(token); + if(-1==index)return currency; + string strSubString=responseString.Substring(index+token.Length); + strSubString=Utility.BetweenString(strSubString,"\"","\""); + string[] parts=strSubString.Split(' '); + if(1!=parts.Length)return currency; + currency=parts[0]; + return currency; + } + else + { + string strSubString=responseString.Substring(index+token.Length); + strSubString=Utility.BetweenString(strSubString,"\"","\""); + string[] parts=strSubString.Split(' '); + if(2>parts.Length)return currency; + currency=parts[parts.Length-1]; + return currency; + } + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetCurrencyForDataSet encountered an exception:{0}",exception.ToString())); + return currency; + } + } + + public static String GetMStarSecurityId(String symbol,String responseString) + { + String securityIdentifier=null; + if(MStarSecurityDA.HasSecurityId(symbol)) + { + securityIdentifier=MStarSecurityDA.GetSecurityId(symbol); + return securityIdentifier; + } + securityIdentifier=GetMStarSecurityId_1(responseString); + if(null==securityIdentifier) + { + securityIdentifier=GetMStarSecurityId_2(symbol,responseString); + if(null==securityIdentifier) + { + securityIdentifier=GetMStarSecurityId_3(responseString); + } + } + if(null==securityIdentifier)return null; + MStarSecurityDA.PutSecurityId(symbol,securityIdentifier); + return securityIdentifier; + } + +//byId:{\"0P000003MU\":$} +// AAPL:0P000000GY + +// 5","0P000003MU","MIDD",60 + private static String GetMStarSecurityId_2(String symbol,String responseString) + { + try + { + String searchString="\""+symbol+"\""; + int index=responseString.LastIndexOf(searchString); + if(-1==index)return null; + int commaCount=0; + while(index>=0 && commaCount!=2) + { + char ch=responseString[index--]; + if(ch.Equals(','))commaCount++; + } + if(index<0)return null; + responseString=responseString.Substring(index+1); + String securityIdentifier=Utility.BetweenString(responseString,"\"","\""); + if(securityIdentifier.Equals("en-us")||securityIdentifier.StartsWith("blt"))return null; + return securityIdentifier; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetMStarSecurityId_2 encountered an exception:{0}",exception.ToString())); + return null; + } + } + +// us","AAON",401,"subscription","blt8b91befd99376df6","bltc8ff21a187c6e079",2,"image\u002Fsvg+xml","blt187f65f0e94c77b5","0P00000012",60,80,"AAON In + private static String GetMStarSecurityId_3(String responseString) + { + try + { + string token="0P"; + int index=responseString.IndexOf(token); + if(-1==index)return null; + string securityIdentifier=responseString.Substring(index-token.Length); + securityIdentifier=Utility.BetweenString(securityIdentifier,"\"","\""); + return securityIdentifier; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetMStarSecurityId_3 encountered an exception:{0}",exception.ToString())); + return null; + } + } + +//","performanceID":"0P000000GY","securityID":"0P000000GY","ticker":"AAPL","exc + private static String GetMStarSecurityId_1(String responseString) + { + try + { + string token="\"securityID\""; + int index=responseString.IndexOf(token); + if(-1==index)return null; + string securityIdentifier=responseString.Substring(index+token.Length); + securityIdentifier=Utility.BetweenString(securityIdentifier,"\"","\""); + return securityIdentifier; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetMStarSecurityId_1 encountered an exception:{0}",exception.ToString())); + return null; + } + } + + private static Dictionary GetData(String responseString) + { + try + { + Dictionary uniqueDataLabels=new Dictionary(); + String label="\"label\""; + String datum="\"datum\""; + String columnDefs="\"columnDefs\""; + String strData=null; + Dictionary data=new Dictionary(); + if(null==responseString)return data; + int index=responseString.IndexOf(columnDefs); + if(-1==index)return null; + strData=responseString.Substring(index+columnDefs.Length); + strData=Utility.BetweenString(strData,"[","]"); + List items = Utility.ToList(strData,','); + for(int itemIndex=0;itemIndex(); + } + } + + private static Dictionary GetData(String mainHeading, List> items,String responseString) + { + try + { + Dictionary data=new Dictionary(); + Dictionary> dataDictionary=new Dictionary>(); + Dictionary uniqueElementNamesDictionary=new Dictionary(); + + if(null==mainHeading || null==items || null==responseString) + { + return data; + } + for(int itemIndex=0;itemIndex subItems=items[itemIndex]; + if(subItems[0].Equals(mainHeading)) + { + String strDate=subItems[1]; + dataDictionary.Add(strDate,new Dictionary()); + for(++itemIndex;itemIndex subsubItems=items[itemIndex]; + if(subsubItems[0].Equals(mainHeading)) + { + itemIndex--; + break; + } + Dictionary datedItems=dataDictionary[strDate]; + String subItemElementName=subsubItems[0]; + if(!datedItems.ContainsKey(subItemElementName)) + { + if(!uniqueElementNamesDictionary.ContainsKey(subItemElementName))uniqueElementNamesDictionary.Add(subItemElementName,subItemElementName); + datedItems.Add(subItemElementName,subsubItems[1]); + } + } + } + } + List strDates=new List(dataDictionary.Keys); + List uniqueElementNames=new List(uniqueElementNamesDictionary.Keys); + data.Add("columnDefs",new MStarDataSet("columnDefs",strDates)); + + foreach(String elementName in uniqueElementNames) + { + List elementValues=new List(); + foreach(String strDate in strDates) + { + Dictionary inner=dataDictionary[strDate]; + if(!inner.ContainsKey(elementName)) + { + continue; + } + elementValues.Add(inner[elementName]); + } + data.Add(elementName,new MStarDataSet(elementName,elementValues)); + } + double multiplier=GetMultiplierForDataSet(responseString); + if(double.IsNaN(multiplier))multiplier=1.00; // This GetData method is only used to retrieve ratios so far so the data sets do not have a multiplier section. + data.Add("multiplier",new MStarDataSet("multiplier",multiplier.ToString())); // If this method is expanded to retrieve data points other than non-ratios then you will have to come up with method for retrieving the multiplier. + return data; // so that we know if the data is in trillions, billions, millions and what not. + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetData(String mainHeading, List> items) encountered an exception {0}",exception.ToString())); + return new Dictionary(); + } + } + + private static TimeSeriesCollection CreateTimeSeriesCollection(String symbol, MStarDataSet colDefData, MStarDataSet dataElements, TimeSeriesElement.ElementType elementType,double multiplier=1.00) + { + TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(); + Dictionary dates = new Dictionary(); + DateTime today=DateTime.Now; + try + { + if(null==colDefData || null==dataElements || null==colDefData.Values || null==dataElements.Values || dataElements.Values.Count()!=colDefData.Values.Count()) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Cannot create time series for symbol {0} for element type {1}",symbol,TimeSeriesElement.StringForType(elementType))); + return timeSeriesCollection; + } + for (int index = 0; index < colDefData.Values.Count;index++) + { + DateTime reportDate=DateTime.Now; + String strDateElement=colDefData.Values[index]; + String strDataElement=dataElements.Values[index]; + + if("_PO_".Equals(strDataElement)) + { + continue; + } + if("null".Equals(strDataElement)) + { + continue; + } + + if(strDateElement.Length.Equals(4)) + { + bool result=DateTime.TryParseExact(strDateElement, new string[]{"yyyy"}, new System.Globalization.CultureInfo("en-US"), DateTimeStyles.AssumeLocal,out reportDate); + if(!result)continue; + if(reportDate.Year.Equals(today.Year)) + { + reportDate=new DateTime(reportDate.Year,today.Month,1); + } + else + { + reportDate=new DateTime(reportDate.Year,12,31); + } + } + else + { + bool result=DateTime.TryParseExact(strDateElement, new string[]{"yyyy-MM"}, new System.Globalization.CultureInfo("en-US"), DateTimeStyles.AssumeLocal,out reportDate); + if(!result)continue; + } + TimeSeriesElement timeSeriesElement = new TimeSeriesElement(); + timeSeriesElement.Type = elementType; + timeSeriesElement.Symbol = symbol; + timeSeriesElement.AsOf =reportDate; + timeSeriesElement.Value = FeedParser.ParseValue(dataElements.Values[index])*multiplier; + if (double.IsNaN(timeSeriesElement.Value)) continue; + if (!dates.ContainsKey(timeSeriesElement.AsOf)) + { + dates.Add(timeSeriesElement.AsOf, timeSeriesElement.AsOf); + timeSeriesCollection.Add(timeSeriesElement); + } + } + return timeSeriesCollection; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("CreateTimeSeriesCollection encountered an exception processing symbol '{0}' {1}",symbol,exception.ToString())); + return new TimeSeriesCollection(); + } + } +// **************************************************************************************************************************************************************************** +// ************************************************************ M O R N I N G S T A R H I S T O R I C A L D A T A V 2 E N D *********************************************** +// **************************************************************************************************************************************************************************** + +// ***************************************************************************************************************************************************************************** +// ************************************************************ C A S H F L O W S T A T E M E N T - M O R N I N G S T A R V 2 ********************************************** +// ***************************************************************************************************************************************************************************** + public static List GetCashflowStatement(String symbol,CashflowStatement.PeriodType periodType) + { + List cashflowStatements=null; + HttpNetResponse httpNetResponse=null; + String nasdaq = "xnas"; + String nyse = "xnyse"; + String nys="xnys"; + + try + { + if(!CashflowStatement.PeriodType.Annual.Equals(periodType)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Unsupported CashflowStatement.PeriodType Quarterly. Only Annual supported from M*")); + return null; + } + StringBuilder sb = new StringBuilder(); + StringBuilder strReferer = new StringBuilder(); + String strRequest; + sb=new StringBuilder(); + sb.Append("https://www.morningstar.com/stocks/").Append(nasdaq).Append("/").Append(symbol).Append("/performance"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + WebProxy webProxy=HttpNetRequest.GetProxy("GetCashflowStatement"); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV3A(strRequest,webProxy); + if(!httpNetResponse.Success||null==httpNetResponse.ResponseString || "".Equals(httpNetResponse.ResponseString)) + { + sb=new StringBuilder(); + sb.Append("https://www.morningstar.com/stocks/").Append(nys).Append("/").Append(symbol).Append("/performance"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV3A(strRequest,webProxy); + if(!httpNetResponse.Success||null==httpNetResponse.ResponseString || "".Equals(httpNetResponse.ResponseString)) + { + sb=new StringBuilder(); + sb.Append("https://www.morningstar.com/stocks/").Append(nyse).Append("/").Append(symbol).Append("/performance"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + httpNetResponse = HttpNetRequest.GetRequestNoEncodingV3A(strRequest,webProxy); + if(!httpNetResponse.Success||null==httpNetResponse.ResponseString || "".Equals(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Request:{0} failed with status {1}", httpNetResponse.Request, httpNetResponse.StatusCode)); + return null; + } + } + } + String securityId=GetMStarSecurityId(symbol,httpNetResponse.ResponseString); + if(null==securityId) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Cannot determine MorningStar Identifier for {0}",symbol)); + return null; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Morningstar Mapping:'{0}'=>'{1}'",symbol,securityId)); + try{Thread.Sleep(250);}finally{;} + +// Fetch the equity financial details. Success often requires several attempts. + httpNetResponse=GetMStarEquityFinancialDetails(securityId); + if(!httpNetResponse.Success || String.IsNullOrEmpty(httpNetResponse.ResponseString)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Failed to retrieve MorningStar EquityFinancialDetails.")); + } + Dictionary dataSetsCashflowStatement=GetData(httpNetResponse.ResponseString); + httpNetResponse.Dispose(); + + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Got {0} cashflow statement items for {1}",dataSetsCashflowStatement.Count,symbol)); + + cashflowStatements=CreateCashflowStatements(symbol, dataSetsCashflowStatement); + return cashflowStatements; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetCashflowStatement encountered an exception {0}",exception.ToString())); + return null; + } + } + + private static HttpNetResponse GetMStarEquityFinancialDetails(String securityId) + { + HttpNetResponse httpNetResponse = new HttpNetResponse(); + int maxRetries=10; + int retry=0; + int waitBetweenAttemptsMS=500; + + StringBuilder sb=new StringBuilder(); + sb.Append("https://api-global.morningstar.com/sal-service/v1/stock/newfinancials/").Append(securityId).Append("/cashFlow/detail?dataType=A&reportType=A&locale=en&languageId=en&locale=en&clientId=MDC&component=sal-components-equity-financials-details&version=3.74.0"); + String strRequest=sb.ToString(); + try + { + MDTrace.WriteLine(LogLevel.DEBUG,strRequest); + WebProxy webProxy=HttpNetRequest.GetProxy("GetCashflowStatement"); + while(retry CreateCashflowStatements(String symbol,Dictionary cashflowDataElements) + { + DateTime today=DateTime.Now; + List cashflowStatements=new List(); + String currencyCashflow=cashflowDataElements["currency"].Values[0]; + double cashflowStatementMultiplier=double.Parse(cashflowDataElements["multiplier"].Values[0]); + Dictionary conversionRates=new Dictionary(); + String baseCurrency="USD"; + + try + { + Dictionary> cashflowDictionaryByDate=CreateDictionaryByDate(cashflowDataElements); + List cashflowDateKeys=new List(cashflowDictionaryByDate.Keys); + if(0==cashflowDateKeys.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("CreateCashflowStatements: No dates in cashflowDataElement.")); + return null; + } + + foreach(DateTime cashflowDate in cashflowDateKeys) + { + Dictionary cashflowDatedElements=cashflowDictionaryByDate[cashflowDate]; + + CashflowStatement cashflowStatement=new CashflowStatement(); + cashflowStatement.Symbol=symbol; + cashflowStatement.AsOf=cashflowDate; + cashflowStatement.Modified=DateTime.Now; + cashflowStatement.Period=CashflowStatement.PeriodType.Annual; + + if(!baseCurrency.Equals(currencyCashflow)) + { + if(null==CurrencyConversionDA.GetMaxDateForCurrency(currencyCashflow,baseCurrency,cashflowStatement.AsOf)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*********** Retrieving currency rates for {0} {1}",currencyCashflow,cashflowStatement.AsOf.ToShortDateString())); + CurrencyConversionCollection currencyConversionCollection=MarketDataHelper.GetCurrencyConversion(currencyCashflow,cashflowStatement.AsOf); + if(!CurrencyConversionDA.InsertCurrencyConversionRates(currencyConversionCollection)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*********** No currency conversion from {0} to {1} for date {2}",currencyCashflow,baseCurrency,cashflowStatement.AsOf.ToShortDateString())); + return null; + } + } + CurrencyConversionElement currencyConversionElement=CurrencyConversionDA.GetCurrencyConversionMaxDate(currencyCashflow,baseCurrency,cashflowStatement.AsOf); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("************ Currency conversion for CashflowStatement : {0} to {1} for date {2} multiplier {3}",currencyCashflow,baseCurrency,cashflowStatement.AsOf.ToShortDateString(),Utility.FormatNumber(currencyConversionElement.UnitsPerSource,6))); + conversionRates.Add(cashflowStatement.AsOf,currencyConversionElement); + } + + double currencyMultiplier=1.00; + currencyMultiplier=conversionRates.ContainsKey(cashflowStatement.AsOf)?conversionRates[cashflowStatement.AsOf].UnitsPerSource:currencyMultiplier; + + if(cashflowDatedElements.ContainsKey("Depreciation and Amortization, Non-Cash Adjustment")) + { + String value = cashflowDatedElements["Depreciation and Amortization, Non-Cash Adjustment"]; + if(!"_PO_".Equals(value)&&!"null".Equals(value)) + { + cashflowStatement.DepreciationAndAmortization=double.Parse(value)*cashflowStatementMultiplier*currencyMultiplier; + } + else cashflowStatement.DepreciationAndAmortization=double.NaN; + } + + if(cashflowDatedElements.ContainsKey("Deferred Taxes, Non-Cash Adjustment")) + { + String value = cashflowDatedElements["Deferred Taxes, Non-Cash Adjustment"]; + if(!"_PO_".Equals(value)&&!"null".Equals(value)) + { + cashflowStatement.DeferredIncomeTaxes=double.Parse(value)*cashflowStatementMultiplier*currencyMultiplier; + } + else cashflowStatement.DeferredIncomeTaxes=double.NaN; + } + + if(cashflowDatedElements.ContainsKey("Stock-Based Compensation, Non-Cash Adjustment")) + { + String value = cashflowDatedElements["Stock-Based Compensation, Non-Cash Adjustment"]; + if(!"_PO_".Equals(value)&&!"null".Equals(value)) + { + cashflowStatement.StockBasedCompensation=double.Parse(value)*cashflowStatementMultiplier*currencyMultiplier; + } + else cashflowStatement.StockBasedCompensation=double.NaN; + } + + if(cashflowDatedElements.ContainsKey("Change in Trade/Accounts Receivable")) + { + String value = cashflowDatedElements["Change in Trade/Accounts Receivable"]; + if(!"_PO_".Equals(value)&&!"null".Equals(value)) + { + cashflowStatement.AccountsReceivable=double.Parse(value)*cashflowStatementMultiplier*currencyMultiplier; + } + else cashflowStatement.AccountsReceivable=double.NaN; + } + + if(cashflowDatedElements.ContainsKey("Change in Accrued Expenses")) + { + String value = cashflowDatedElements["Change in Accrued Expenses"]; + if(!"_PO_".Equals(value)&&!"null".Equals(value)) + { + cashflowStatement.AccruedLiabilities=double.Parse(value)*cashflowStatementMultiplier*currencyMultiplier; + } + else cashflowStatement.AccruedLiabilities=double.NaN; + } + + if(cashflowDatedElements.ContainsKey("Cash Generated from Operating Activities")) + { + String value = cashflowDatedElements["Cash Generated from Operating Activities"]; + if(!"_PO_".Equals(value)&&!"null".Equals(value)) + { + cashflowStatement.OperatingCashflow=double.Parse(value)*cashflowStatementMultiplier*currencyMultiplier; + } + else cashflowStatement.OperatingCashflow=double.NaN; + } + + if(cashflowDatedElements.ContainsKey("Purchase/Sale and Disposal of Property, Plant and Equipment, Net")) + { + String value = cashflowDatedElements["Purchase/Sale and Disposal of Property, Plant and Equipment, Net"]; + if(!"_PO_".Equals(value)&&!"null".Equals(value)&& !double.IsNaN(cashflowStatement.OperatingCashflow)) + { + cashflowStatement.FreeCashflow=(cashflowStatement.OperatingCashflow+(double.Parse(value)*cashflowStatementMultiplier))*currencyMultiplier; + } + else cashflowStatement.FreeCashflow=double.NaN; + } + + if(cashflowStatement.IsValid()) + { + cashflowStatements.Add(cashflowStatement); + } + } + + return cashflowStatements; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("CreateCashflowStatements: Exception encountered {0}",exception.ToString())); + return null; + } + } + + private static Dictionary> CreateDictionaryByDate(Dictionary dataSets) + { + try + { + DateTime today=DateTime.Now; + Dictionary> dictionaryByDate=new Dictionary>(); + MStarDataSet columnDefs=dataSets["columnDefs"]; + List itemKeys=new List(dataSets.Keys); + + itemKeys.RemoveAt(itemKeys.IndexOf("columnDefs")); + itemKeys.RemoveAt(itemKeys.IndexOf("multiplier")); + itemKeys.RemoveAt(itemKeys.IndexOf("currency")); + for(int dateIndex=0;dateIndex()); + } + Dictionary datedCollection=dictionaryByDate[reportDate]; + + if(!datedCollection.ContainsKey(itemKey)) + { + datedCollection.Add(itemKey,value); + } + else datedCollection[itemKey]=value; + } + } + return dictionaryByDate; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("CreateDictionaryByDate: Exception encountered {0}",exception.ToString())); + return null; + } + } + +// ***************************************************************************************************************************************************************************** +// ************************************************************ C A S H F L O W S T A T E M E N T - M O R N I N G S T A R V 2 E N D ************************************ +// ***************************************************************************************************************************************************************************** + +// **************************************************************************************************************************************************************************** +// ************************************************************ I N C O M E S T A T E M E N T - N A S D A Q / F I N V I Z ************************************************** +// **************************************************************************************************************************************************************************** + public static List GetIncomeStatement(String symbol,IncomeStatement.PeriodType periodType) + { + List incomeStatements=GetIncomeStatementNASDAQ(symbol,periodType); + if(null!=incomeStatements && incomeStatements.Count>0)return incomeStatements; + incomeStatements=GetIncomeStatementFinViz(symbol,periodType); + return incomeStatements; + } + + +//{"currency":"USD","data":{ +//"Period End Date":["TTM","1/2/2021","12/28/2019","12/29/2018","12/30/2017","12/31/2016","1/2/2016","1/3/2015"], +//"Total Revenue":["2,930.65","2,513.26","2,959.45","2,722.93","2,335.54","2,267.85","1,826.60","1,636.54"], +//"Cost of Revenue":["1,872.32","1,631.21","1,855.95","1,718.79","1,422.80","1,366.67","1,120.09","995.95"], +//"Selling, General and Administrative":["596.80","531.90","583.81","538.84","468.22","471.64","344.55","320.37"], +//"Gross Profit":["1,058.33","882.05","1,103.50","1,004.14","912.74","901.18","706.50","640.59"], +//"Total Operating Expense":["2,492.86","2,188.83","2,445.40","2,276.97","1,956.93","1,848.83","1,523.99","1,336.11"], + +//"Research and Development":["","35.30","41.20","35.30","29.10","26.30","22.40","22.60"], +//"Net Income":["322.20","207.29","352.24","317.15","298.13","284.22","191.61","193.31"], +//"Income Avail. to Common Incl. Extraord.":["322.20","207.29","352.24","317.15","298.13","284.22","191.61","193.31"], + +//"Interest Income Net":["-71.44","-81.52","-83.51","-56.21","-23.64","-21.98","-10.17","-11.99"], +//"Period Length":["12 Months","53 Weeks","52 Weeks","52 Weeks","52 Weeks","52 Weeks","52 Weeks","53 Weeks"], +//"Unusual Expense/Income":["23.74","25.72","5.64","19.33","65.91","10.52","59.35","19.78"], +//"Operating Income":["437.79","324.43","514.04","445.97","378.61","419.02","302.60","300.43"], +//"Other Income Net":["31.16","25.14","32.09","33.76","28.55","24.27","-11.27","-7.65"], +//"Net Income Before Taxes":["397.51","268.06","462.62","423.51","383.53","421.31","281.17","280.79"], +//"Provision for Income Taxes":["75.31","60.76","110.38","106.36","85.40","137.09","89.56","87.48"], +//"Income Avail. to Common Excl. Extraord.":["322.20","207.29","352.24","317.15","298.13","284.22","191.61","193.31"], +//"Diluted Average Shares":["55.71","55.14","55.66","55.60","56.72","57.09","56.97","56.78"], +//"Diluted EPS Excl. Extraord.":["5.76196","3.75969","6.32888","5.70376","5.25623","4.97882","3.36317","3.40434"], +//"Diluted EPS Incl. Extraord.":["5.76196","3.75969","6.32888","5.70376","5.25623","4.97882","3.36317","3.40434"]}} + public static List GetIncomeStatementFinViz(String symbol,IncomeStatement.PeriodType periodType) + { + HttpNetResponse httpNetResponse=null; + String baseCurrency="USD"; + try + { + List incomeStatements=new List(); + Dictionary conversionRates=new Dictionary(); + + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append("https://finviz.com/api/statement.ashx?t=").Append(symbol.ToLower()); + if(IncomeStatement.PeriodType.Annual.Equals(periodType))sb.Append("&s=IA"); + else sb.Append("&s=IQ"); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetIncomeStatementsFinViz {0}",strRequest)); + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}:{1}",(int)httpNetResponse.StatusCode,httpNetResponse.StatusCode)); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetIncomeStatementsFinViz for {0} failed with {1}",strRequest,httpNetResponse.ErrorMessage)); + return null; + } + String currency="USD"; + JObject json=JObject.Parse(httpNetResponse.ResponseString); + JToken jsonToken=null; + + if(null!=(jsonToken=json.SelectToken("currency"))) + { + currency=jsonToken.ToObject(); + } + + if(null==(jsonToken=json.SelectToken("data"))) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("")); + return null; + } + + List strDateItems=null; + List strTotalRevenueItems=null; + List strCostOfRevenueItems=null; + List strSGAItems=null; + List strGrossProfitItems=null; + List strTotalOperatingExpense=null; + List strResearchAndDevelopmentItems=null; + List strIncomeAvailableToCommonShareHolders=null; + + JToken token=jsonToken["Period End Date"]; + if(null==token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No IncomeStatemnt dates returned for {0}",symbol)); + return null; + } + strDateItems=token.ToObject>(); + + token=jsonToken["Total Revenue"]; + if(null!=token)strTotalRevenueItems=token.ToObject>(); + + token=jsonToken["Cost of Revenue"]; + if(null!=token)strCostOfRevenueItems=token.ToObject>(); + + token=jsonToken["Selling, General and Administrative"]; + if(null!=token)strSGAItems=token.ToObject>(); + + token=jsonToken["Gross Profit"]; + if(null!=token)strGrossProfitItems=token.ToObject>(); + + token=jsonToken["Total Operating Expense"]; + if(null!=token)strTotalOperatingExpense=token.ToObject>(); + + token=jsonToken["Research and Development"]; + if(null!=token)strResearchAndDevelopmentItems=token.ToObject>(); + + token=jsonToken["Income Avail. to Common Incl. Extraord."]; + if(null!=token)strIncomeAvailableToCommonShareHolders=token.ToObject>(); + + for(int index=0;indexindex)incomeStatement.TotalRevenue=FeedParser.ParseValue(strTotalRevenueItems[index])*1000000.00*multiplier; + if(null!=strCostOfRevenueItems && strCostOfRevenueItems.Count>index)incomeStatement.CostOfRevenue=FeedParser.ParseValue(strCostOfRevenueItems[index])*1000000.00*multiplier; + if(null!=strSGAItems && strSGAItems.Count>index)incomeStatement.SGA=FeedParser.ParseValue(strSGAItems[index])*1000000.00*multiplier; + if(null!=strGrossProfitItems && strGrossProfitItems.Count>index)incomeStatement.GrossProfit=FeedParser.ParseValue(strGrossProfitItems[index])*1000000.00*multiplier; + if(null!=strTotalOperatingExpense && strTotalOperatingExpense.Count>index)incomeStatement.OperatingExpenses=FeedParser.ParseValue(strTotalOperatingExpense[index])*1000000.00*multiplier; + if(null!=strResearchAndDevelopmentItems && strResearchAndDevelopmentItems.Count>index)incomeStatement.ResearchAndDevelopment=FeedParser.ParseValue(strResearchAndDevelopmentItems[index])*1000000.00*multiplier; + if(null!=strIncomeAvailableToCommonShareHolders && strIncomeAvailableToCommonShareHolders.Count>index)incomeStatement.NetIncomeApplicableToCommonShares=FeedParser.ParseValue(strIncomeAvailableToCommonShareHolders[index])*1000000.00*multiplier; + incomeStatements.Add(incomeStatement); + } + return incomeStatements; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetIncomeStatementFinViz Symbol:{0} Exception:{1}",symbol,exception.ToString())); + return null; + } + } + public static List GetIncomeStatementNASDAQ(String symbol,IncomeStatement.PeriodType periodType) + { + List incomeStatements=new List(); + HttpNetResponse httpNetResponse=null; + MemoryStream memoryStream=null; + double multiplier=1000.00; + try + { + StringBuilder sb=new StringBuilder(); + String strRequest; + sb.Append("https://api.nasdaq.com/api/company/").Append(symbol).Append("/financials"); + if(periodType.Equals(IncomeStatement.PeriodType.Annual))sb.Append(""); + else sb.Append("?frequency=2"); + + strRequest=sb.ToString(); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV4(strRequest); + if(!httpNetResponse.Success) return incomeStatements; + byte[] streamBytes=Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + JObject json=JObject.Parse(httpNetResponse.ResponseString); + JToken jsonToken=null; + if(null==(jsonToken=json.SelectToken("data.incomeStatementTable.headers"))) + { + String reason="unknown"; + jsonToken=json.SelectToken("message"); + if(null!=jsonToken)reason=jsonToken.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("***** Response contains no headers for symbol:{0} for request:{1}, Reason:{2}",symbol,strRequest,reason)); + return incomeStatements; + } + JObject headerObject=(JObject)jsonToken; + int elements=headerObject.Count-1; + String headerElement=headerObject["value1"].ToString(); + if((periodType.Equals(IncomeStatement.PeriodType.Annual)&&!headerElement.Equals("Period Ending:"))||(periodType.Equals(IncomeStatement.PeriodType.Quarterly)&&!headerElement.Equals("Quarterly Ending:"))) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("***** Response contains unexpected header for symbol:{0} for request:{1}",symbol,strRequest)); + return incomeStatements; + } + + for(int headerIndex=2;headerIndex GetBalanceSheet(String symbol,BalanceSheet.PeriodType periodType) + { + List balanceSheet=null; + balanceSheet=GetBalanceSheetNASDAQ(symbol,periodType); + if(null!=balanceSheet && balanceSheet.Count>0)return balanceSheet; + balanceSheet=GetBalanceSheetFinViz(symbol,periodType); + return balanceSheet; + } +//https://finviz.com/api/statement.ashx?t=aapl&s=BA +//https://finviz.com/api/statement.ashx?t=aapl&s=BQ +//{"currency":"USD", +//"data":{ +//"Period End Date":["9/26/2020","9/28/2019","9/29/2018","9/30/2017","9/24/2016","9/26/2015","9/27/2014","9/28/2013"], +//"Cash and Equivalents":["20,243.00","36,640.00","14,338.00","12,307.00","11,883.00","9,731.00","3,612.00","5,554.00"], +//"Short Term Investments":["52,927.00","51,713.00","40,388.00","53,892.00","46,671.00","20,481.00","11,233.00","26,287.00"], +//"Cash and Short Term Investments":["90,943.00","100,557.00","66,301.00","74,181.00","67,155.00","41,601.00","25,077.00","40,546.00"], +//"Accounts Receivable - Trade, Net":["16,120.00","22,926.00","23,186.00","17,874.00","15,754.00","16,849.00","17,460.00","13,102.00"], +//"Total Receivables, Net":["37,445.00","45,804.00","48,995.00","35,673.00","29,299.00","30,343.00","27,219.00","20,641.00"], +//"Total Inventory":["4,061.00","4,106.00","3,956.00","4,855.00","2,132.00","2,349.00","2,111.00","1,764.00"], +//"Total Current Assets":["143,713.00","162,819.00","131,339.00","128,645.00","106,869.00","89,378.00","68,531.00","73,286.00"], +//"Property, Plant And Equipment - Gross":["112,096.00","95,957.00","90,403.00","75,076.00","61,245.00","49,257.00","39,015.00","28,519.00"], +//"Property, Plant And Equipment - Net":["45,336.00","37,378.00","41,304.00","33,783.00","27,010.00","22,471.00","20,624.00","16,597.00"], +//"Goodwill, Net":["","","","","5,414.00","5,116.00","4,616.00","1,577.00"], +//"Intangibles, Net":["","","","","3,206.00","3,893.00","4,142.00","4,179.00"], +//"Long Term Investments":["100,887.00","105,341.00","170,799.00","194,714.00","170,430.00","164,065.00","130,162.00","106,215.00"], +//"Other Long Term Assets":["33,952.00","32,978.00","22,283.00","18,177.00","8,757.00","5,422.00","3,764.00","5,146.00"], +//"Total Assets":["323,888.00","338,516.00","365,725.00","375,319.00","321,686.00","290,345.00","231,839.00","207,000.00"], +//"Accounts Payable":["42,296.00","46,236.00","55,888.00","44,242.00","37,294.00","35,490.00","30,196.00","22,367.00"], +//"Accrued Expenses":["1,436.00","","","","20,951.00","24,169.00","7,689.00","4,782.00"], +//"Notes Payable/Short Term Debt":["4,996.00","5,980.00","11,964.00","11,977.00","8,105.00","8,499.00","6,308.00","0.00"], +//"Current Port. of LT Debt/Capital Leases":["8,797.00","10,260.00","8,784.00","6,496.00","3,500.00","2,500.00","",""], +//"Other Current liabilities":["47,867.00","43,242.00","39,293.00","38,099.00","9,156.00","9,952.00","19,255.00","16,509.00"], +//"Total Current Liabilities":["105,392.00","105,718.00","115,929.00","100,814.00","79,006.00","80,610.00","63,448.00","43,658.00"], +//"Long Term Debt":["98,667.00","91,807.00","93,735.00","97,207.00","75,427.00","53,329.00","28,987.00","16,960.00"], +//"Capital Lease Obligations":["637.00","","","","","","",""], +//"Total Long Term Debt":["99,304.00","91,807.00","93,735.00","97,207.00","75,427.00","53,329.00","28,987.00","16,960.00"], +//"Total Debt":["113,097.00","108,047.00","114,483.00","115,680.00","87,032.00","64,328.00","35,295.00","16,960.00"], +//"Other Liabilities":["53,853.00","50,503.00","48,914.00","11,747.00","12,985.00","12,989.00","7,598.00","6,344.00"], +//"Total Liabilities":["258,549.00","248,028.00","258,578.00","241,272.00","193,437.00","170,990.00","120,292.00","83,451.00"], +//"Common Stock":["50,779.00","45,174.00","40,201.00","35,867.00","31,251.00","27,416.00","23,313.00","19,764.00"], +//"Additional Paid-In Capital":["","","","","","","",""], +//"Retained Earnings":["14,966.00","45,898.00","70,400.00","98,330.00","96,364.00","92,284.00","87,152.00","104,256.00"], +//"Unrealized Gain (Loss)":["1,846.00","707.00","-3,209.00","328.00","1,174.00","-653.00","-242.00","-105.00"], +//"Other Equity":["-2,252.00","-1,291.00","-245.00","-478.00","-540.00","308.00","1,324.00","-366.00"], +//"Total Equity":["65,339.00","90,488.00","107,147.00","134,047.00","128,249.00","119,355.00","111,547.00","123,549.00"], +//"Total Liabilities and Equity":["323,888.00","338,516.00","365,725.00","375,319.00","321,686.00","290,345.00","231,839.00","207,000.00"], +//"Total Common Shares Outstanding":["16,976.76","17,772.94","19,019.94","20,504.80","21,344.66","22,315.01","23,464.64","25,177.46"], +//"Full-Time Employees":["147,000","137,000","132,000","123,000","116,000","110,000","92,600","80,300"], +//"Number of Common Shareholders":["22,797","23,233","23,712","25,333","25,641","25,924","26,112","24,710"]}} + public static List GetBalanceSheetFinViz(String symbol,BalanceSheet.PeriodType periodType) + { + HttpNetResponse httpNetResponse=null; + String baseCurrency="USD"; + try + { + List balanceSheets=new List(); + Dictionary conversionRates=new Dictionary(); + + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append("https://finviz.com/api/statement.ashx?t=").Append(symbol.ToLower()); + if(BalanceSheet.PeriodType.Annual.Equals(periodType))sb.Append("&s=BA"); + else sb.Append("&s=BQ"); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetBalanceSheetFinViz {0}",strRequest)); + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}:{1}",(int)httpNetResponse.StatusCode,httpNetResponse.StatusCode)); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetBalanceSheetFinViz for {0} failed with {1}",strRequest,httpNetResponse.ErrorMessage)); + return null; + } + String currency="USD"; + JObject json=JObject.Parse(httpNetResponse.ResponseString); + JToken jsonToken=null; + + if(null!=(jsonToken=json.SelectToken("currency"))) + { + currency=jsonToken.ToObject(); + } + + if(null==(jsonToken=json.SelectToken("data"))) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("")); + return null; + } + + List strDateItems=null; + List strLongTermDebtItems=null; + List strTotalCurrentAssetItems=null; + List strTotalLiabilityItems=null; + List strTotalAssetItems=null; + List strGoodwillItems=null; + List strPPEItems=null; + List strCashAndEquivalentsItems=null; + List strTotalInventoryItems=null; + List strIntangiblesItems=null; + List strTotalCurrentLiabilityItems=null; + List strOtherLiabilityItems=null; + List strTotalEquityItems=null; + + JToken token=jsonToken["Period End Date"]; + if(null==token) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No BalanceSheet dates returned for {0}",symbol)); + return null; + } + strDateItems=token.ToObject>(); + + token=jsonToken["Long Term Debt"]; + if(null!=token)strLongTermDebtItems=token.ToObject>(); + + token=jsonToken["Total Current Assets"]; + if(null!=token)strTotalCurrentAssetItems=token.ToObject>(); + + token=jsonToken["Total Liabilities"]; + if(null!=token)strTotalLiabilityItems=token.ToObject>(); + + token=jsonToken["Total Assets"]; + if(null!=token)strTotalAssetItems=token.ToObject>(); + + token=jsonToken["Goodwill, Net"]; + if(null!=token)strGoodwillItems=token.ToObject>(); + + token=jsonToken["Property, Plant And Equipment - Net"]; + if(null!=token)strPPEItems=token.ToObject>(); + + token=jsonToken["Cash and Equivalents"]; + if(null!=token)strCashAndEquivalentsItems=token.ToObject>(); + + token=jsonToken["Total Inventory"]; + if(null!=token)strTotalInventoryItems=token.ToObject>(); + + token=jsonToken["Intangibles, Net"]; + if(null!=token)strIntangiblesItems=token.ToObject>(); + + token=jsonToken["Total Current Liabilities"]; + if(null!=token)strTotalCurrentLiabilityItems=token.ToObject>(); + + token=jsonToken["Other Liabilities"]; + if(null!=token)strOtherLiabilityItems=token.ToObject>(); + + token=jsonToken["Total Equity"]; + if(null!=token)strTotalEquityItems=token.ToObject>(); + + for(int index=0;indexindex)balanceSheet.LongTermDebt=FeedParser.ParseValue(strLongTermDebtItems[index])*1000000.00*multiplier; + if(null!=strTotalCurrentAssetItems && strTotalCurrentAssetItems.Count>index)balanceSheet.TotalCurrentAssets=FeedParser.ParseValue(strTotalCurrentAssetItems[index])*1000000.00*multiplier; + if(null!=strTotalLiabilityItems && strTotalLiabilityItems.Count>index)balanceSheet.TotalLiabilities=FeedParser.ParseValue(strTotalLiabilityItems[index])*1000000.00*multiplier; + if(null!=strTotalAssetItems && strTotalAssetItems.Count>index)balanceSheet.TotalAssets=FeedParser.ParseValue(strTotalAssetItems[index])*1000000.00*multiplier; + if(null!=strGoodwillItems && strGoodwillItems.Count>index)balanceSheet.Goodwill=FeedParser.ParseValue(strGoodwillItems[index])*1000000.00*multiplier; + if(null!=strPPEItems && strPPEItems.Count>index)balanceSheet.PropertyPlantAndEquipment=FeedParser.ParseValue(strPPEItems[index])*1000000.00*multiplier; + if(null!=strCashAndEquivalentsItems && strCashAndEquivalentsItems.Count>index)balanceSheet.CashAndCashEquivalents=FeedParser.ParseValue(strCashAndEquivalentsItems[index])*1000000.00*multiplier; + if(null!=strTotalInventoryItems && strTotalInventoryItems.Count>index)balanceSheet.Inventory=FeedParser.ParseValue(strTotalInventoryItems[index])*1000000.00*multiplier; + if(null!=strIntangiblesItems && strIntangiblesItems.Count>index)balanceSheet.IntangibleAssets=FeedParser.ParseValue(strIntangiblesItems[index])*1000000.00*multiplier; + if(null!=strTotalCurrentLiabilityItems && strTotalCurrentLiabilityItems.Count>index)balanceSheet.TotalCurrentLiabilities=FeedParser.ParseValue(strTotalCurrentLiabilityItems[index])*1000000.00*multiplier; + if(null!=strOtherLiabilityItems && strOtherLiabilityItems.Count>index)balanceSheet.OtherLiabilities=FeedParser.ParseValue(strOtherLiabilityItems[index])*1000000.00*multiplier; + if(null!=strTotalEquityItems && strTotalEquityItems.Count>index)balanceSheet.TotalStockHolderEquity=FeedParser.ParseValue(strTotalEquityItems[index])*1000000.00*multiplier; + balanceSheets.Add(balanceSheet); + } + return balanceSheets; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetBalanceSheetFinViz Symbol:{0} Exception:{1}",symbol,exception.ToString())); + return null; + } + } + + public static List GetBalanceSheetNASDAQ(String symbol,BalanceSheet.PeriodType periodType) + { + List balanceSheets=new List(); + HttpNetResponse httpNetResponse=null; + MemoryStream memoryStream=null; + double multiplier=1000.00; + try + { + StringBuilder sb=new StringBuilder(); + String strRequest; + sb.Append("https://api.nasdaq.com/api/company/").Append(symbol).Append("/financials"); + if(periodType.Equals(BalanceSheet.PeriodType.Annual)) sb.Append("?frequency=1"); + else sb.Append("?frequency=2"); + + strRequest=sb.ToString(); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV4(strRequest); + if(!httpNetResponse.Success) return balanceSheets; + byte[] streamBytes=Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + JObject json=JObject.Parse(httpNetResponse.ResponseString); + JToken jsonToken=null; + if(null==(jsonToken=json.SelectToken("data.balanceSheetTable.headers"))) + { + String reason="unknown"; + jsonToken=json.SelectToken("message"); + if(null!=jsonToken) reason=jsonToken.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("***** Response contains no headers for symbol:{0} for request:{1}, Reason:{2}",symbol,strRequest,reason)); + return balanceSheets; + } + JObject headerObject=(JObject)jsonToken; + int elements=headerObject.Count-1; + String headerElement=headerObject["value1"].ToString(); + if((periodType.Equals(IncomeStatement.PeriodType.Annual)&&!headerElement.Equals("Period Ending:"))||(periodType.Equals(IncomeStatement.PeriodType.Quarterly)&&!headerElement.Equals("Quarterly Ending:"))) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("***** Response contains unexpected header for symbol:{0} for request:{1}",symbol,strRequest)); + return balanceSheets; + } + + for(int headerIndex=2;headerIndex sections=Sections.GetSections(httpNetResponse.ResponseString); + if(!Sections.FindInSections(sections,"Currency Table:",0,ref itemIndex,false))return null; + if(!Sections.FindInSections(sections,"Currency",itemIndex,ref itemIndex))return null; + itemIndex+=20; + + while(true) + { + CurrencyConversionElement currencyConversionElement=new CurrencyConversionElement(); + currencyConversionElement.AsOf=conversionDate; + currencyConversionElement.SourceCurrency=sourceCurrency; + currencyConversionElement.DestinationCurrency=sections[itemIndex]; + itemIndex+=3; + currencyConversionElement.DestinationCurrencyName=sections[itemIndex]; + itemIndex+=2; + currencyConversionElement.UnitsPerSource=FeedParser.ParseValue(sections[itemIndex]); + itemIndex+=2; + currencyConversionElement.SourcePerUnit=FeedParser.ParseValue(sections[itemIndex]); + currencyConversionElements.Add(currencyConversionElement); + itemIndex+=5; + if(itemIndex>=sections.Count || null==sections[itemIndex] || "".Equals(sections[itemIndex]) || sections[itemIndex].Length<3)break; + } + return currencyConversionElements; + } + catch(Exception) + { + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// *************************************************************************************************************************************************************************************** +// ************************************************************************** F U N D A M E N T A L - F I N V I S ********************************************************* +// *************************************************************************************************************************************************************************************** + public static Fundamental GetFundamentalFinViz(String symbol) + { + HttpNetResponse httpNetResponse=null; + MemoryStream memoryStream=null; + try + { + Fundamental fundamental = new Fundamental(); + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append("https://finviz.com/quote.ashx?t=").Append(symbol.ToLower()); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetFundamental {0}",strRequest)); + WebProxy webProxy=HttpNetRequest.GetProxy("GetFundamentalFinViz"); + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest,webProxy); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}:{1}",(int)httpNetResponse.StatusCode,httpNetResponse.StatusCode)); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Get Fundamental for {0} failed with {1}",strRequest,httpNetResponse.ErrorMessage)); + return null; + } + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection nodeCollection = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"js-snapshot-table snapshot-table2 screener_snapshot-table-body\"]"); + if(null==nodeCollection || nodeCollection.Count<1)return null; + fundamental.AsOf=DateTime.Now; + fundamental.Symbol=symbol; + fundamental.Source = "FINVIZ"; + for(int index=0;index incomeStatements=GetIncomeStatement(symbol,IncomeStatement.PeriodType.Annual); + if(null!=incomeStatements&&0!=incomeStatements.Count) incomeStatement=incomeStatements.OrderByDescending(x => x.AsOf).Take(1).FirstOrDefault(); + + CashflowStatement cashflowStatement=null; + List cashflowStatements=GetCashflowStatement(symbol,CashflowStatement.PeriodType.Annual); + if(null != cashflowStatements && 0!=cashflowStatements.Count) + { + cashflowStatement = cashflowStatements.OrderByDescending(x => x.AsOf).Take(1).FirstOrDefault(); + } + + BalanceSheet balanceSheet=null; + List balanceSheets=GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual); + if(null != balanceSheets && 0!=balanceSheets.Count) + { + balanceSheet = balanceSheets.OrderByDescending(x => x.AsOf).Take(1).FirstOrDefault(); + } + + if(null!=cashflowStatement) + { + fundamental.OperatingCashflow=cashflowStatement.OperatingCashflow; + fundamental.LeveragedFreeCashflow=cashflowStatement.FreeCashflow; + fundamental.EBITDA=fundamental.EBIT+cashflowStatement.DepreciationAndAmortization; + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("************* GETFUNDAMENTALFINVIZ FOR {0} NO CASHFLOW STATEMENT *************",symbol)); + fundamental.OperatingCashflow=double.NaN; + fundamental.LeveragedFreeCashflow=double.NaN; + fundamental.EBITDA=double.NaN; + } + + if(null!=incomeStatement) + { + fundamental.GrossProfit=incomeStatement.GrossProfit; + fundamental.Revenue=incomeStatement.TotalRevenue; + fundamental.EBIT=incomeStatement.EBIT; + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("************* GETFUNDAMENTALFINVIZ FOR {0} NO INCOME STATEMENT *************",symbol)); + fundamental.GrossProfit=double.NaN; + fundamental.Revenue=double.NaN; + fundamental.EBIT=double.NaN; + } + + if(null!=balanceSheet) + { + fundamental.TotalCash=balanceSheet.CashAndCashEquivalents; + fundamental.TotalDebt=balanceSheet.TotalLiabilities; + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("************* GETFUNDAMENTALFINVIZ FOR {0} NO BALANCESHEET *************",symbol)); + fundamental.TotalCash=double.NaN; + fundamental.TotalDebt=double.NaN; + } + + if(!double.IsNaN(fundamental.MarketCap)&&!double.IsNaN(fundamental.TotalDebt)&&!double.IsNaN(fundamental.TotalCash)) fundamental.EnterpriseValue=fundamental.MarketCap+fundamental.TotalDebt-fundamental.TotalCash; + else fundamental.EnterpriseValue=double.NaN; + if(!Double.IsNaN(fundamental.SharesOutstanding)&&0!=fundamental.SharesOutstanding)fundamental.RevenuePerShare=fundamental.Revenue/fundamental.SharesOutstanding; + else fundamental.RevenuePerShare=double.NaN; + if(null!=balanceSheet&&!double.IsNaN(balanceSheet.TotalStockHolderEquity)&&!double.IsNaN(fundamental.TotalDebt)&&0!=fundamental.TotalDebt)fundamental.DebtToEquity=fundamental.TotalDebt/balanceSheet.TotalStockHolderEquity; + else fundamental.DebtToEquity=double.NaN; + if(double.IsNaN(fundamental.DebtToEquity)&&!double.IsNaN(fundamental.Equity)&&0.00!=fundamental.Equity)fundamental.DebtToEquity=fundamental.TotalDebt/fundamental.Equity; + return fundamental; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}.",exception.ToString())); + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + if(null!=memoryStream){memoryStream.Close();memoryStream.Dispose();} + } + } + +// *************************************************************************************************************************************************************************************** +// ************************************************************************** F U N D A M E N T A L - Y A H O O F I N A N C E ********************************************************* +// *************************************************************************************************************************************************************************************** + public static Fundamental GetFundamental(String symbol) + { + Fundamental fundamental=GetFundamentalEx(symbol); + if(null==fundamental)return fundamental; + if(fundamental.GetLoad()<80) + { + Fundamental fundamental2 = GetFundamentalEx(symbol); + if(null!=fundamental2)fundamental.MergeFrom(fundamental2); + } + return fundamental; + } + private static Fundamental GetFundamentalEx(String symbol) + { + HttpNetResponse httpNetResponse=null; + int TIMEOUT_MS=1000*30; + try + { + Fundamental fundamental = new Fundamental(); + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append("https://finance.yahoo.com/quote/").Append(symbol).Append("?p=").Append(symbol); + strRequest = sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetFundamental {0}",strRequest)); + WebProxy webProxy=HttpNetRequest.GetProxy("GetFundamentalEx"); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV5(strRequest,TIMEOUT_MS, webProxy); // user agents refreshed in this version + if(!httpNetResponse.Success) + { + sb=new StringBuilder(); + sb.Append("http://finance.yahoo.com/q?s=").Append(symbol).Append("&ql=1"); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} FAILED!, TRYING {1}",strRequest,sb.ToString())); + strRequest = sb.ToString(); + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} FINAL FAILURE.",strRequest)); + return null; + } + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} SUCCESS.",strRequest)); + fundamental.Symbol=symbol; + fundamental.AsOf=DateTime.Now; + fundamental.Source = "YAHOO"; + fundamental.Beta=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Beta<")); + fundamental.NextEarningsDate=FeedParser.ParseValueDateTimeMonthFormat(Sections.LocateItemAcceptAnyText(httpNetResponse.ResponseString,">Earnings Date<")); + String strText=Sections.LocateFirstItem(httpNetResponse.ResponseString,">52 Week Range<"); + if(null!=strText) + { + String[] strArray = strText.Split('-'); + fundamental.Low52 = FeedParser.ParseValue(strArray[0].Trim()); + fundamental.High52 = FeedParser.ParseValue(strArray[1].Trim()); + } + fundamental.Volume=FeedParser.ParseValueLong(Sections.LocateItem(httpNetResponse.ResponseString,">Volume<")); + fundamental.MarketCap=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Market Cap<")); + fundamental.PE=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">PE Ratio (TTM)<")); + fundamental.EPS=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">EPS (TTM)<")); + try { Thread.Sleep(250);PopulateKeyStatistics(fundamental,webProxy); } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,"*********Unable to populate key statistics."); + MDTrace.WriteLine(LogLevel.DEBUG,"Exception was:"+exception.ToString()); + } + try { Thread.Sleep(250);PopulateFinancials(fundamental); } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,"*********Unable to populate financials."); + MDTrace.WriteLine(LogLevel.DEBUG,"Exception was:"+exception.ToString()); + } + if(fundamental.IsZero()) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("***** Fundamental for {0} is Invalid *****",symbol)); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",fundamental.ToString())); + return null; + } + return fundamental; + } + catch (Exception) + { + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// ************************************************************************************************************************************************************************************* +// ***************************************************************** K E Y S T A T I S T I C S - Y A H O O F I N A N C E ********************************************************** +// ************************************************************************************************************************************************************************************* + private static bool PopulateKeyStatistics(Fundamental fundamental,WebProxy webProxy=null) + { + HttpNetResponse httpNetResponse=null; + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append("http://finance.yahoo.com/q/ks?s=").Append(fundamental.Symbol); + strRequest = sb.ToString(); + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest,webProxy); + if(!httpNetResponse.Success) + { + try{Thread.Sleep(250);}catch(Exception){;} + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return false; + } + } + fundamental.TrailingPE=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Trailing P/E<")); + + fundamental.PEG=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">PEG Ratio (5 yr expected)<")); + if(double.IsNaN(fundamental.PEG))fundamental.PEG=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">PEG Ratio (5yr expected)<")); + + fundamental.ReturnOnAssets=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Return on Assets<")); + if(double.IsNaN(fundamental.ReturnOnAssets))fundamental.ReturnOnAssets=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Return on Assets (ttm)<")); + + fundamental.ReturnOnEquity=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Return on Equity<")); + if(double.IsNaN(fundamental.ReturnOnEquity))fundamental.ReturnOnEquity=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Return on Equity (ttm)<")); + + fundamental.RevenuePerShare=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Revenue Per Share<")); + if(double.IsNaN(fundamental.RevenuePerShare))fundamental.RevenuePerShare=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Revenue Per Share (ttm)<")); + + fundamental.TotalCash=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Total Cash<")); + if(double.IsNaN(fundamental.TotalCash))fundamental.TotalCash=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Total Cash (mrq)<")); + + fundamental.TotalDebt=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Total Debt<")); + if(double.IsNaN(fundamental.TotalDebt))fundamental.TotalDebt=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Total Debt (mrq)<")); + + fundamental.SharesOutstanding=FeedParser.ParseValue(Sections.LocateItemMinDepth(httpNetResponse.ResponseString,">Shares Outstanding<",7)); + if(double.IsNaN(fundamental.SharesOutstanding))fundamental.SharesOutstanding=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,"Implied Shares Outstanding 6 ")); + + fundamental.Revenue=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Revenue<")); + if(double.IsNaN(fundamental.Revenue))fundamental.Revenue=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Revenue (ttm)<")); + + fundamental.QtrlyRevenueGrowth=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Quarterly Revenue Growth<")); + if(double.IsNaN(fundamental.QtrlyRevenueGrowth))fundamental.QtrlyRevenueGrowth=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Quarterly Revenue Growth (yoy)<")); + + fundamental.GrossProfit=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Gross Profit<")); + if(double.IsNaN(fundamental.GrossProfit))fundamental.GrossProfit=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Gross Profit (ttm)<")); + + fundamental.EBITDA=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">EBITDA<")); + if(double.IsNaN(fundamental.EBITDA))fundamental.EBITDA=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">EBITDA <")); + + fundamental.NetIncomeAvailableToCommon=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Net Income Avi to Common<")); + if(double.IsNaN(fundamental.NetIncomeAvailableToCommon))fundamental.NetIncomeAvailableToCommon=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Net Income Avi to Common (ttm)<")); + + fundamental.BookValuePerShare=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Book Value Per Share<")); + if(double.IsNaN(fundamental.BookValuePerShare))fundamental.BookValuePerShare=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Book Value Per Share (mrq)<")); + + fundamental.OperatingCashflow=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Operating Cash Flow<")); + if(double.IsNaN(fundamental.OperatingCashflow))fundamental.OperatingCashflow=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Operating Cash Flow (ttm)<")); + + fundamental.LeveragedFreeCashflow=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Levered Free Cash Flow<")); + if(double.IsNaN(fundamental.LeveragedFreeCashflow))fundamental.LeveragedFreeCashflow=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Levered Free Cash Flow (ttm)<")); + + fundamental.EnterpriseValue=FeedParser.ParseValue(Sections.LocateItemMinDepth(httpNetResponse.ResponseString,">Enterprise Value<",7)); + + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return false; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +// ************************************************************************************************************************************************************************************* +// ***************************************************************** F I N A N C I A L S - Y A H O O F I N A N C E ***************************************************************** +// ************************************************************************************************************************************************************************************* + private static bool PopulateFinancials(Fundamental fundamental) + { + HttpNetResponse httpNetResponse=null; + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + sb.Append("https://finance.yahoo.com/quote/").Append(fundamental.Symbol).Append("/financials?p=").Append(fundamental.Symbol); + strRequest = sb.ToString(); + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest); + if(!httpNetResponse.Success) + { + try{Thread.Sleep(250);}catch(Exception){;} + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return false; + } + } + fundamental.EBIT=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">Earnings Before Interest and Taxes<"))*1000.00; + if(double.IsNaN(fundamental.EBIT))fundamental.EBIT=FeedParser.ParseValue(Sections.LocateItem(httpNetResponse.ResponseString,">EBIT<"))*1000.00; + + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return false; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } +//************************************************************************************************************************************************************************************** +//*************************************************************************** I N T R A D A Y P R I C I N G ************************************************************************** +// ************************************************************** M A I N : Y A H O O ************************************************************************************************** +// ************************************************************** B A C K U P : B I G C H A R T S ************************************************************************************** +//************************************************************************************************************************************************************************************** + private delegate Price LatestPriceDelegate(String symbol); + + public static Price GetLatestPrice(String symbol) + { + if(null==symbol)return null; + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + if(null!=companyProfile && companyProfile.FreezePricing) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Pricing for {0} is frozen.",symbol)); + return null; + } + DateTime currentMarketDate=PremarketDA.GetLatestMarketDate(); + LatestPriceDelegate[] latestPriceDelegates=new LatestPriceDelegate[]{GetLatestPriceYahoo,GetLatestPriceBigCharts,GetLatestPriceGoogle}; + Price latestPrice=null; + foreach(LatestPriceDelegate latestPriceDelegate in latestPriceDelegates) + { + latestPrice=latestPriceDelegate.Invoke(symbol); + if(null!=latestPrice && latestPrice.IsValid) + { + if(latestPrice.Date.Date.Equals(currentMarketDate.Date.Date)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Price request from {0} succeeded for {1}",latestPriceDelegate.GetMethodInfo().Name,symbol)); + return latestPrice; + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The date retrieved for {0} via {1} does not match the current market date. Market Date: {2} Price Date: {3}",symbol,latestPriceDelegate.Method.Name,currentMarketDate.ToShortDateString(),latestPrice.Date.ToShortDateString())); + } + } + } + latestPrice=GetPriceAsOf(symbol,currentMarketDate); // try to get the price from MarketWatch historical feed using todays date + if(null!=latestPrice && latestPrice.Date.Date.Equals(currentMarketDate.Date)) return latestPrice; + + if(null!=companyProfile && companyProfile.CanRollPrevious) + { + latestPrice=PricingMarketDataHelper.RollPriceForward(symbol); + if(null!=latestPrice)return latestPrice; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("*** ALL SOURCES FAILED TO RETRIEVE PRICE FOR SYMBOL *** {0}",symbol)); + return null; + } +// *************************************************************************************************************** +// ******************** L A T E S T P R I C E R E T R I E V A L F O R I N T R A - D A Y F E E D ******** +// *************************************************************************************************************** + public static Price GetLatestPriceYahoo(String symbol) + { + HttpNetResponse httpNetResponse=null; + try + { + StringBuilder sb=new StringBuilder(); + String strRequest; + if(null==symbol)return null; + sb.Append("https://finance.yahoo.com/quote/").Append(symbol).Append("/?=").Append(symbol); + strRequest=sb.ToString(); + WebProxy webProxy=HttpNetRequest.GetProxy("GetLatestPriceYahoo"); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV3A(strRequest, webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetLatestPriceYahoo: Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + Price price=new Price(); + price.Symbol=symbol.ToUpper(); + price.Date=DateTime.Now; + price.Close=price.AdjClose=price.Open=price.High=price.Low=double.NaN; + price.Source=Price.PriceSource.Yahoo; + return BuildPriceFromResponse(httpNetResponse.ResponseString,price); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + if(null!=httpNetResponse) httpNetResponse.Dispose(); + } + } + + private static Price BuildPriceFromResponse(String httpNetResponse,Price price) + { + if(httpNetResponse.Contains("HTML_TAG_END")) + { + price = BuildPriceFromSections(httpNetResponse, price); + } + else + { + price = BuildPriceFromTable(httpNetResponse, price); + } + return price; + } + + private static Price BuildPriceFromSections(String httpNetResponse,Price price) + { + try + { + String strResponse=Utility.KeepAfter(httpNetResponse,"HTML_TAG_END"); + List sections = null; + + sections = Sections.GetAllItemsInSections(httpNetResponse, "fin-streamer"); + + String marker ="data-symbol=\""+price.Symbol+"\""; + List dataSections = sections.Where(x => x.Contains(marker)).ToList(); + dataSections = dataSections.Where(x => x.Contains(" data-field=\"regularMarketPrice\"")).ToList(); + if(dataSections.Count>0) + { + dataSections = Sections.GetSections(dataSections[0]); + if(null!=dataSections && dataSections.Count==1) + { + price.Close=price.AdjClose=FeedParser.ParseValue(dataSections[0]); + } + else if(null!=dataSections && dataSections.Count>0) + { + price.Close=price.AdjClose=FeedParser.ParseValue(dataSections[1]); + } + } + + marker = " x.StartsWith(marker)).ToList(); + for(int index=0;index {1}",price.Symbol,exception.ToString())); + return null; + } + } + + private static Price BuildPriceFromTable(String httpNetResponse,Price price) + { + MemoryStream memoryStream = null; + + try + { + List sections = null; + double bid = double.NaN; + double bidContracts = double.NaN; + double ask = double.NaN; + double askContracts = double.NaN; + + String symbol=price.Symbol.ToUpper(); + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + + HtmlNodeCollection table = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"W(100%)\"]"); + if(null == table || 0 == table.Count)return null; + HtmlNodeCollection rows = table[0].SelectNodes(".//tr"); + if (null == rows || 0 == rows.Count) return null; + for(int index=0;index< rows.Count; index++) + { + int itemIndex=0; + String itemValue=null; + String innerHtml = rows[index].InnerHtml; + sections=Sections.GetSections(innerHtml); + + if(Sections.FindInSections(sections, "Previous Close",0, ref itemIndex, true)) + { + itemValue = sections[itemIndex+3]; + } + else if(Sections.FindInSections(sections, "Open",0, ref itemIndex, true)) + { + itemValue = sections[itemIndex+3]; + price.Open=FeedParser.ParseValue(itemValue); + } + else if(Sections.FindInSections(sections, "Bid",0, ref itemIndex, true)) + { + itemValue = sections[itemIndex+3]; + if(String.IsNullOrEmpty(itemValue))continue; + String[] bidContractSplit = itemValue.Split('x'); + bid=FeedParser.ParseValue(bidContractSplit[0]); + bidContracts=FeedParser.ParseValue(bidContractSplit[1]); + } + else if(Sections.FindInSections(sections, "Ask",0, ref itemIndex, true)) + { + itemValue = sections[itemIndex+3]; + if(String.IsNullOrEmpty(itemValue))continue; + String[] askContractSplit = itemValue.Split('x'); + ask = FeedParser.ParseValue(askContractSplit[0]); + askContracts = FeedParser.ParseValue(askContractSplit[1]); + } + else if(Sections.FindInSections(sections, "Day's Range",0, ref itemIndex, true)) + { + itemValue = sections[itemIndex+3]; + String[] subItems=itemValue.Split('-'); + price.Low=FeedParser.ParseValue(subItems[0]); + price.High=FeedParser.ParseValue(subItems[1]); + } + else if(Sections.FindInSections(sections, "52 Week Range",0, ref itemIndex, true)) + { + itemValue = sections[itemIndex+3]; + } + else if(Sections.FindInSections(sections, "Volume",0, ref itemIndex, true)) + { + itemValue = sections[itemIndex+4]; + price.Volume=FeedParser.ParseValueLong(itemValue); + } + else if(Sections.FindInSections(sections, "Avg. Volume",0, ref itemIndex, true)) + { + itemValue = sections[itemIndex+3]; + } + } + + if (double.IsNaN(price.Close)) + { + sections = Sections.GetAllItemsInSections(httpNetResponse, "fin-streamer"); + String marker = "data-symbol=\"" + price.Symbol + "\""; + sections = sections.Where(x => x.Contains(marker)).ToList(); + sections = sections.Where(x => x.Contains(" data-field=\"regularMarketPrice\"")).ToList(); + if (sections.Count > 0) + { + sections = Sections.GetSections(sections[0]); + if (null != sections && sections.Count > 0) + { + price.Close = price.AdjClose = FeedParser.ParseValue(sections[0]); + } + } + } + + if(double.IsNaN(price.Close)) + { + double bidAskPrice=CalculateBidAskPrice(price.Symbol,bid,bidContracts,ask,askContracts); + if(!double.IsNaN(bidAskPrice))price.Close=price.AdjClose=bidAskPrice; + if(double.IsNaN(price.Close) && 0!=price.High && 0!=price.Low)price.Close=price.AdjClose=(price.High+price.Low)/2.00; + } + + CheckPrice(price); + return price; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception: for {0} -> {1}",price.Symbol,exception.ToString())); + return null; + } + finally + { + if(null!=memoryStream) + { + memoryStream.Close(); + memoryStream.Dispose(); + memoryStream=null; + } + } + } + + private static double CalculateBidAskPrice(String symbol,double bid,double bidContracts,double ask, double askContracts) + { + if(double.IsNaN(bid) || double.IsNaN(bidContracts) || double.IsNaN(ask) || double.IsNaN(askContracts) || 0==askContracts || 0==bidContracts)return double.NaN; + double totalContracts = bidContracts + askContracts; + double bidWeight = bidContracts/totalContracts; + double askWeight = askContracts/totalContracts; + double weightedBid = bid*bidWeight; + double weightedAsk = ask*askWeight; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} Bid:{1} x {2} Ask:{3} x {4} Price:{5}",symbol,Utility.FormatCurrency(bid,2),Utility.FormatNumber(bidContracts,0,true),Utility.FormatCurrency(ask,2),Utility.FormatNumber(askContracts,0,true),Utility.FormatCurrency(weightedBid + weightedAsk,2))); + return weightedBid + weightedAsk; + } + + public static void CheckPrice(Price price) + { + if(double.IsNaN(price.Close)&&!double.IsNaN(price.High)&&!double.IsNaN(price.Low)) + { + price.Close=price.AdjClose=(price.High+price.Low)/2.00; + } + if(!double.IsNaN(price.High)&&!double.IsNaN(price.Low)&&0.00!=price.High&&0.00!=price.Low) + { // if the close price is garbage set it to the midpoint of the high and the low + if(price.Closeprice.High||double.IsNaN(price.Close))price.Close=(price.High+price.Low)/2.00; + } + if(double.IsNaN(price.AdjClose))price.AdjClose=price.Close; + if(double.IsNaN(price.Open))price.Open=0.00; + if(double.IsNaN(price.Low))price.Low=0.00; + if(double.IsNaN(price.High))price.High=0.00; + if(0==price.High && !double.IsNaN(price.Close) && 0!=price.Close) + { + price.High=price.Close; + } + if(0==price.Low && !double.IsNaN(price.Close) && 0!=price.Close) + { + price.Low=price.Close; + } + if(0!=price.Close&&0==price.Open&&0==price.High&&0==price.Low) + { + price.Open=price.High=price.Low=price.Close; + } + if(Utility.IsZeroOrNaN(price.Open) && !Utility.IsZeroOrNaN(price.High) && !Utility.IsZeroOrNaN(price.Low)) + { + price.Open=(price.High+price.Low)/2.00; + } + } + +// This is used in the intra-day price feed. + public static Price GetLatestPriceBigCharts(String symbol) + { + HttpNetResponse httpNetResponse=null; + MemoryStream memoryStream=null; + try + { + StringBuilder sb = new StringBuilder(); + String strRequest; + if(null==symbol) return null; + sb.Append("http://bigcharts.marketwatch.com/quickchart/quickchart.asp?symb=").Append(symbol).Append("&insttype=Stock").Append(symbol); + strRequest = sb.ToString(); + + WebProxy webProxy=HttpNetRequest.GetProxy("GetLatestPriceBigCharts"); + httpNetResponse=HttpNetRequest.GetRequestNoEncoding(strRequest,webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + Price price = new Price(); + price.Symbol = symbol.ToUpper(); + price.Date = DateTime.Now; + price.Source=Price.PriceSource.BigCharts; + byte[] streamBytes = Encoding.ASCII.GetBytes(httpNetResponse.ResponseString); + memoryStream = new MemoryStream(streamBytes); + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.Load(memoryStream); + HtmlNodeCollection table = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"quickchart\"]"); + if(null==table||0==table.Count)return null; + HtmlNodeCollection divSection = htmlDocument.DocumentNode.SelectNodes("//*[@class=\"maincontent\"]"); + if(null==divSection)return null; + HtmlNodeCollection rows = divSection[0].SelectNodes(".//tr"); + if(rows.Count<3)return null; + HtmlNode softTimeNode = htmlDocument.DocumentNode.SelectSingleNode("//*[@class=\"soft time\"]"); + if(null!=softTimeNode) + { +// DateTime givenDate=Utility.ParseDate(softTimeNode.InnerHtml); + DateTime givenDate=ConvertBigChartsDate(softTimeNode.InnerHtml); + if(!Utility.IsEpoch(givenDate))price.Date=givenDate; + } + HtmlNodeCollection dataColumns = rows[2].SelectNodes(".//td"); + for(int index=0;index divSections = Sections.GetAllItemsInSections(httpNetResponse.ResponseString,"div"); + if(null==divSections || 0==divSections.Count)return null; + List searchPattern = divSections.Where(x => x.Contains("We couldn't find any match for your search.")).ToList(); + if(null!=searchPattern && searchPattern.Count>0) + { + httpNetResponse.Dispose(); + sb = new StringBuilder(); + sb.Append("https://www.google.com/finance/quote/").Append(symbol).Append(":").Append(exchangeNYSE); + strRequest = sb.ToString(); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV3C(strRequest, webProxy); + if(!httpNetResponse.Success) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Request:{0} failed with status {1}",httpNetResponse.Request,httpNetResponse.StatusCode)); + return null; + } + divSections = Sections.GetAllItemsInSections(httpNetResponse.ResponseString,"div"); + searchPattern = divSections.Where(x => x.Contains("We couldn't find any match for your search.")).ToList(); + if(null!=searchPattern && searchPattern.Count>0) + { + return null; + } + } + + List sections = Sections.GetSections(httpNetResponse.ResponseString); + sections = Sections.FlattenSection(sections); + + int index=0; + + Price price = new Price(); + price.Symbol = symbol.ToUpper(); + price.Source=Price.PriceSource.Google; + price.Close=price.Open=price.High=price.Low=price.AdjClose=double.NaN; + price.Open=0.00; + price.Date = DateTime.Now; + + if(Sections.FindInSections(sections, "After Hours:", 0,ref index, true)) + { + price.Close=price.AdjClose=FeedParser.ParseValue(sections[index-1]); + } + else if(Sections.FindInSections(sections, "Share", 0,ref index, true)) + { + price.Close=price.AdjClose=FeedParser.ParseValue(sections[index+1]); + } + + if(Sections.FindInSections(sections, "Previous close", 0,ref index, true)) + { + price.Open=FeedParser.ParseValue(sections[index+2]); + } + + if(Sections.FindInSections(sections, "Day range", 0,ref index, true)) + { + String itemValue = sections[index+2]; + String[] highLow = itemValue.Split('-'); + price.Low=FeedParser.ParseValue(highLow[0]); + price.High=FeedParser.ParseValue(highLow[1]); + } + if(!price.IsValid)return null; + return price; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } + +// ******************************************************************************************************************************************************************************* +// ************************************************************** H I S T O R I C A L P R I C E S - B I G C H A R T S ******************************************************** +// ******************************************************************************************************************************************************************************* + /// + /// Gets historical pricing from BigCharts + /// + /// + /// Most recent date + /// Most historical date + /// Prices + public static Prices GetPricesAsOf(String symbol, DateTime startDate,DateTime endDate) + { + Prices prices=new Prices(); + + if(null==symbol)return null; + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + if(null!=companyProfile && companyProfile.FreezePricing) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Pricing for {0} is frozen.",symbol)); + return null; + } + DateGenerator dateGenerator=new DateGenerator(); + List dates=dateGenerator.GenerateHistoricalDates(startDate,endDate); + for(int index=0;indexendDate) + { + DateTime tempDate=startDate; + startDate=endDate; + endDate=tempDate; + } + + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[MarketDataHelper:GetDailyPrices]{0} start:{1} end:{2}",symbol,Utility.DateTimeToStringMMHDDHYYYY(startDate),Utility.DateTimeToStringMMHDDHYYYY(endDate))); + StringBuilder sb = new StringBuilder(); + String strRequest; + Prices prices=null; + sb.Append("https://query1.finance.yahoo.com/v7/finance/chart/").Append(symbol).Append("?period1=").Append(Utility.DateToUnixDate(startDate)).Append("&period2=").Append(Utility.DateToUnixDate(endDate)).Append("&interval=1d&events=history"); + strRequest=sb.ToString(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Query:{0}",strRequest)); + WebProxy webProxy=HttpNetRequest.GetProxy("GetDailyPrices"); + CookieCollection cookieCollection=new CookieCollection(); + httpNetResponse=HttpNetRequest.GetRequestNoEncodingV3B(strRequest,cookieCollection,webProxy); + if(!httpNetResponse.Success) return null; + JObject json=JObject.Parse(httpNetResponse.ResponseString); + prices=GetPricesFromJSONString(json,symbol); + return prices; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return null; + } + finally + { + if(null!=httpNetResponse)httpNetResponse.Dispose(); + } + } + private static Prices GetPricesFromJSONString(JObject json,String symbol) + { + Prices prices=new Prices(); + + try + { + JToken token=null; + int items=0; + + try{token=json["chart"]["result"][0]["timestamp"];}catch(Exception){;} + if(null==token) + { + string instrumentType=null; + try{instrumentType=json["chart"]["result"][0]["meta"]["instrumentType"].ToString();}catch(Exception){;} + if(null==instrumentType||!instrumentType.Equals("MUTUALFUND"))return prices; + String strPrice=null; + String strDate=null; + try{strPrice=json["chart"]["result"][0]["meta"]["regularMarketPrice"].ToString();}catch(Exception){;} + try{strDate=json["chart"]["result"][0]["meta"]["currentTradingPeriod"]["regular"]["start"].ToString();}catch(Exception){;} + if(null==strPrice||null==strDate)return prices; + Price price=new Price(); + price.Symbol=symbol; + price.Source=Price.PriceSource.Yahoo; + price.High=price.Low=price.Close=price.Open=price.AdjClose=FeedParser.ParseValue(strPrice); + DateTimeOffset dateTimeOffset=DateTimeOffset.FromUnixTimeSeconds(long.Parse(strDate)); + price.Date=dateTimeOffset.DateTime; + price.Volume=0L; + prices.Add(price); + return prices; + } + try{items=token.Children().Count();}catch(Exception){;} + if(0==items)return prices; + for(int index=0;indexprice.High)price.Close=(price.High+price.Low)/2.00; + + prices.Add(price); + + } + return prices; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString())); + return prices; + } + } + +// ****************************************************************************************************************************************************************************************************************** +// *************************************************************************** E N D Y A H O O H I S T O R I C A L P R I C I N G ******************************************************************************* +// ****************************************************************************************************************************************************************************************************************** + + +// **************************************************************************************************************************************************************************************** +// **************************************************************************** E N D D A T A F E E D S ********************************************************************************* +// **************************************************************************************************************************************************************************************** + + + + +// *************************************************************************************************************************************************************************************** +// *************************************************************************************************************************************************************************************** +// *************************************************************************************************************************************************************************************** + +// 2017 Yahoo Finance Modified Format of all feeds. Most of the HTMLDocument parser code is broken because the response strings are no longer in tabular format. +// It's difficult to make sense of the new response string outside of noting that it remains in aa tag format. The following code is an attempt to make sense of it all. + public static List LocateJSONItems(String strInput,String item,bool isHeading=false) + { + try + { + if(null==item||null==strInput)return null; + int startPos=strInput.IndexOf(item); + if(-1==startPos)return null; + strInput=strInput.Substring(startPos-1); + if(isHeading) + { + strInput=strInput.Substring(item.Length); + startPos=strInput.IndexOf(item); + if(-1==startPos)return null; + strInput=strInput.Substring(startPos-1); + } + strInput=Utility.BetweenString(strInput,"[","]"); + if(null==strInput)return null; + String[] itemsArray=strInput.Split(','); + return itemsArray.ToList(); + } + catch(Exception) + { + return null; + } + } + + public static List LocateJSONKeyValuePairs(String strInput, String item1,String item2) + { + try + { + List items=new List(); + if (null == item1 || null == strInput) return null; + int startPos = strInput.IndexOf(item1); + while(true) + { + KeyValue keyValue=new KeyValue(); + if (-1 == startPos||null==strInput) break; + String strItem = strInput.Substring(startPos); + strItem = Utility.BetweenString(strItem, "\"", "\""); + String strValue = strInput.Substring((startPos+strItem.Length+4)-1); + strValue = Utility.BetweenString(strValue, "\"", "\""); + keyValue.Key=strValue; + try{strInput=strInput.Substring((startPos+strItem.Length+4+strValue.Length+4)-1);} + catch(Exception){break;} + if(null==strInput)break; + startPos = strInput.IndexOf(item2); + if(-1==startPos)break; + strItem = strInput.Substring(startPos); + strItem = Utility.BetweenString(strItem, "\"", "\""); + strValue = strInput.Substring((startPos + strItem.Length + 4) - 1); + strValue = Utility.BetweenString(strValue, "\"", "\""); + keyValue.Value=strValue; + try { strInput = strInput.Substring((startPos + strValue.Length + 4) - 1); } + catch (Exception) { break; } + if(null==strInput)break; + startPos = strInput.IndexOf(item1); + items.Add(keyValue); + } + return items; + } + catch (Exception) + { + return null; + } + } + + public static List> LocateJSONItems(String strInput) + { + List> items=new List>(); + try + { + if(null==strInput)return null; + strInput=Utility.BetweenString(strInput,"[","]"); + if(null==strInput)return null; + String[] itemsArray=strInput.Split(','); + if(null==itemsArray||0==itemsArray.Length)return null; + for(int index=0;index> LocateJSONItemsTags(String strInput) + { + List> items=new List>(); + try + { + if(null==strInput)return null; + String[] itemsArray=strInput.Split(','); + if(null==itemsArray||0==itemsArray.Length)return null; + for(int index=0;indexx.Equals(items[0]))) + { + DateTime now=DateTime.Now; + StringBuilder sb=new StringBuilder(); + sb.Append(items[0]).Append(" ").Append(Utility.Pad(items[1],'0',2)).Append(" ").Append(referenceDate.Year); + referenceDate=Utility.ParseDate(sb.ToString()); + if(referenceDate>now) + { + sb=new StringBuilder(); + sb.Append(items[0]).Append(" ").Append(Utility.Pad(items[1],'0',2)).Append(" ").Append(referenceDate.Year-1); + referenceDate=Utility.ParseDate(sb.ToString()); + } + } + else referenceDate=Utility.Epoch; + if(referenceDate>DateTime.Now)referenceDate=Utility.Epoch; + return referenceDate; + } + +// **************************************************************************************************************************************************************************************** +// **************************************************************************** H E L P E R M E T H O D S ******************************************************************************* +// **************************************************************************************************************************************************************************************** + private static void WriteNodeToDisk(HtmlNodeCollection rows,String strPathFileName) + { + StreamWriter streamWriter = File.CreateText(strPathFileName + ".txt"); + for (int row = 0; row < rows.Count; row++) + { + streamWriter.WriteLine("row="+row.ToString()+", InnerHtml="+rows[row].InnerHtml); + } + streamWriter.Flush(); + streamWriter.Close(); + } + + private static void WriteToDisk(String responseString, String strPathFileName) + { + StreamWriter streamWriter = File.CreateText(strPathFileName); + streamWriter.WriteLine(responseString); + streamWriter.Flush(); + streamWriter.Close(); + } + + private static void WriteToDisk(List sections, String strPathFileName) + { + StreamWriter streamWriter = File.CreateText(strPathFileName); + for(int index=0;index + { + private List queue=null; + private int currentIndex=-1; + public MarketDataHelperBase() + { + } + public List Queue + { + get{return queue;} + set{queue=value;} + } + public void ShuffleQueue() + { + int itemCount = queue.Count; + Random generator = new Random(); + for (int index = 0; index < itemCount; index++) + { + int r1; + int r2; + r1 = generator.Next(0, itemCount - 1); + r2 = generator.Next(0, itemCount - 1); + while (r2.Equals(r1)) r2 = generator.Next(0, itemCount - 1); + T temp = queue[r1]; + queue[r1] = queue[r2]; + queue[r2] = temp; + } + } + + public T PeekQueueItem() + { + if(null==queue)return default(T); + if (currentIndex+1 >= queue.Count) return default(T); + return queue[currentIndex+1]; + } + + public T GetQueueItem() + { + if(null==queue)return default(T); + if (currentIndex+1 >= queue.Count) return default(T); + return queue[++currentIndex]; + } + + public int Index + { + get{return currentIndex;} + set{currentIndex=value;} + } + + public ManualResetEvent[] ResizeEvents(ManualResetEvent[] events) + { + ManualResetEvent[] busyEvents=GetBusyEvents(events); + if(busyEvents.Length!=0) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Resizing event queue to {0}",busyEvents.Length)); + ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length]; + Array.Copy(busyEvents, resizedEvents, busyEvents.Length); + return resizedEvents; + } + return events; + } + + public ManualResetEvent[] GetBusyEvents(ManualResetEvent[] resetEvents) + { + List availableEvents = new List(); + for (int index = 0; index < resetEvents.Length; index++) + { + if (!resetEvents[index].WaitOne(0)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Event {0} is still doing work",resetEvents[index].SafeWaitHandle.DangerousGetHandle().ToString())); + availableEvents.Add(resetEvents[index]); + } + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The event queue has {0} busy slots",availableEvents.Count)); + return availableEvents.ToArray(); + } + + public ManualResetEvent[] GetAvailableEvents(ManualResetEvent[] resetEvents) + { + List availableEvents = new List(); + for (int index = 0; index < resetEvents.Length; index++) + { + if (resetEvents[index].WaitOne(0)) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Event {0} is available for work",resetEvents[index].SafeWaitHandle.DangerousGetHandle().ToString())); + availableEvents.Add(resetEvents[index]); + } + } + return availableEvents.ToArray(); + } + } +} diff --git a/MarketData/MarketDataLib/Helper/MovingAverageHelperSheet.cs b/MarketData/MarketDataLib/Helper/MovingAverageHelperSheet.cs new file mode 100755 index 0000000..fd8f2e9 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/MovingAverageHelperSheet.cs @@ -0,0 +1,133 @@ +// using System; +// using System.IO; +// using System.Collections.Generic; +// using Microsoft.Office.Interop.Excel; +// using MarketData.DataAccess; +// using MarketData.MarketDataModel; +// using MarketData.Generator; +// using MarketData.Utils; +// using MarketData.Generator.MovingAverage; + +// namespace MarketData.Helper +// { +// public class MovingAverageHelperSheet +// { +// public MovingAverageHelperSheet() +// { +// } +// public static bool GenerateMovingAverageSheet(String strPathTemplateFile, String symbol) +// { +// Microsoft.Office.Interop.Excel.Application excelApp = null; +// Microsoft.Office.Interop.Excel.Workbook workbook = null; +// Microsoft.Office.Interop.Excel.Worksheet worksheet = null; +// Microsoft.Office.Interop.Excel.Sheets worksheets = null; +// int rowOffset = 1; +// try +// { +// String companyName = PricingDA.GetNameForSymbol(symbol); +// DateGenerator dateGenerator = new DateGenerator(); +// DateTime startDate = dateGenerator.GetPrevBusinessDay(DateTime.Now); +// String currentWorkingDirectory = Directory.GetCurrentDirectory(); +// if (!File.Exists(strPathTemplateFile)) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,"Cannot locate " + strPathTemplateFile); +// return false; +// } +// MovingAverages movingAverages = MovingAverageGenerator.GenerateMovingAverages(symbol); +// String pathOutputFile = currentWorkingDirectory + "\\" + symbol + "-MA-" + Utility.DateTimeToStringMMHDDHYYYY(movingAverages.ThruDate); +// MDTrace.WriteLine(LogLevel.DEBUG,"Generating " + pathOutputFile); +// File.Delete(pathOutputFile + ".xlsx"); +// excelApp = new Microsoft.Office.Interop.Excel.Application(); +// excelApp.ScreenUpdating = false; +// workbook = excelApp.Workbooks.Open(strPathTemplateFile, 0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false); +// worksheets = workbook.Worksheets; +// worksheet = (Microsoft.Office.Interop.Excel.Worksheet)worksheets.get_Item("Sheet1"); +// Microsoft.Office.Interop.Excel.ChartObjects chartObjects = worksheet.ChartObjects(); +// Microsoft.Office.Interop.Excel.ChartObject movingAverageChartObject = chartObjects.Item(1); // yes, chart 1 is the fast line +// movingAverageChartObject.Chart.ChartTitle.Text = companyName + " (" + symbol + ") " + Utility.DateTimeToStringMMHDDHYYYY(movingAverages.FromDate) + " - " + Utility.DateTimeToStringMMHDDHYYYY(movingAverages.ThruDate) + " MA(55,21,5)"; +// Axis vertAxis = (Axis)movingAverageChartObject.Chart.Axes(XlAxisType.xlValue, XlAxisGroup.xlPrimary); +// vertAxis.MaximumScaleIsAuto = false; +// vertAxis.MaximumScale = GetMaxData(movingAverages); +// vertAxis.MinimumScaleIsAuto = false; +// vertAxis.MinimumScale = GetMinData(movingAverages); +// vertAxis.HasMajorGridlines = true; +// Axis horzAxis = (Axis)movingAverageChartObject.Chart.Axes(XlAxisType.xlCategory, XlAxisGroup.xlPrimary); +// horzAxis.HasMajorGridlines = true; +// for (int index = 0; index < movingAverages.Count; index++) +// { +// MovingAverageElement movingAverageElement = movingAverages[index]; +// worksheet.Cells[index + 1 + rowOffset, 1] = movingAverageElement.Symbol; +// worksheet.Cells[index + 1 + rowOffset, 2] = movingAverageElement.Date; +// worksheet.Cells[index + 1 + rowOffset, 3] = movingAverageElement.Close; +// worksheet.Cells[index + 1 + rowOffset, 4] = movingAverageElement.High; +// worksheet.Cells[index + 1 + rowOffset, 5] = movingAverageElement.Low; +// worksheet.Cells[index + 1 + rowOffset, 6] = movingAverageElement.MA55; +// worksheet.Cells[index + 1 + rowOffset, 7] = movingAverageElement.MA21; +// worksheet.Cells[index + 1 + rowOffset, 8] = movingAverageElement.MA5; +// } +// workbook.SaveAs(pathOutputFile, Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Microsoft.Office.Interop.Excel.XlSaveConflictResolution.xlUserResolution, true, Type.Missing, Type.Missing, Type.Missing); +// return true; +// } +// catch (Exception exception) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); +// return false; +// } +// finally +// { +// if (null != worksheet) ReleaseObject(worksheet); +// if (null != worksheets) ReleaseObject(worksheets); +// if (null != workbook) ReleaseObject(workbook); +// excelApp.Quit(); +// } +// } +// private static double GetMinData(MovingAverages movingAverages) +// { +// double minData = double.MaxValue; +// for (int index = 0; index < movingAverages.Count; index++) +// { +// MovingAverageElement movingAverageElement = movingAverages[index]; +// if (movingAverageElement.Close < minData) minData = movingAverageElement.Close; +// if (movingAverageElement.High < minData) minData = movingAverageElement.High; +// if (movingAverageElement.Low < minData) minData = movingAverageElement.Low; +// if (movingAverageElement.MA55 < minData) minData = movingAverageElement.MA55; +// if (movingAverageElement.MA21 < minData) minData = movingAverageElement.MA21; +// if (movingAverageElement.MA5 < minData) minData = movingAverageElement.MA5; +// } +// return minData - (minData * .05); +// } +// private static double GetMaxData(MovingAverages movingAverages) +// { +// double maxData = 0; +// for (int index = 0; index < movingAverages.Count; index++) +// { +// MovingAverageElement movingAverageElement = movingAverages[index]; +// if (movingAverageElement.Close > maxData) maxData = movingAverageElement.Close; +// if (movingAverageElement.High > maxData) maxData = movingAverageElement.High; +// if (movingAverageElement.Low > maxData) maxData = movingAverageElement.Low; +// if (movingAverageElement.MA55 > maxData) maxData = movingAverageElement.MA55; +// if (movingAverageElement.MA21 > maxData) maxData = movingAverageElement.MA21; +// if (movingAverageElement.MA5 > maxData) maxData = movingAverageElement.MA5; +// } +// return maxData + (maxData * .05); +// } +// private static void ReleaseObject(object obj) +// { +// try +// { +// System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj); +// obj = null; +// } +// catch (Exception ex) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,ex.ToString()); +// obj = null; +// } +// finally +// { +// GC.Collect(); +// } +// } +// } +// } + diff --git a/MarketData/MarketDataLib/Helper/OptionsChainsMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/OptionsChainsMarketDataHelper.cs new file mode 100755 index 0000000..7a0db42 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/OptionsChainsMarketDataHelper.cs @@ -0,0 +1,106 @@ +// using System; +// using System.Collections.Generic; +// using System.Linq; +// using System.Text; +// using System.Threading; +// using MarketData.MarketDataModel; +// using MarketData.DataAccess; +// using MarketData.Utils; + +// namespace MarketData.Helper +// { + + +// public class OptionsChainsMarketDataHelper : MarketDataHelperBase +// { +// private static int MaxThreads = 10; +// public OptionsChainsMarketDataHelper() +// { +// } +// // ****************************************************************************************************************************************************** +// // ********************************************************** O P T I M I Z E D E V E N T H A N D L E R S T A R T *********************************** +// // ****************************************************************************************************************************************************** +// public bool LoadOptionsChains(String symbol) +// { +// List symbols=new List(); +// symbols.Add(symbol); +// return LoadOptionsChains(symbols); +// } +// public bool LoadOptionsChains(List symbols) +// { +// Profiler profiler=new Profiler(); +// try +// { +// Queue=symbols; +// Index=-1; +// ManualResetEvent[] resetEvents = new ManualResetEvent[MaxThreads]; +// for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)resetEvents[eventIndex] = new ManualResetEvent(true); +// MDTrace.WriteLine(String.Format("Queuing options chains ...")); + +// while (true) +// { +// ManualResetEvent[] availableEvents=GetAvailableEvents(resetEvents); +// ManualResetEvent[] busyEvents=GetBusyEvents(resetEvents); +// if (null == PeekQueueItem() && 0==busyEvents.Length) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Queue contains {0} items, busy events {1}, all done.",0,busyEvents.Length)); +// break; +// } +// for (int index = 0; index < availableEvents.Length; index++) +// { +// String symbol=GetQueueItem(); +// if (null != symbol) +// { +// availableEvents[index].Reset(); +// ThreadHelper optionsChainsThreadHelper = new ThreadHelper(symbol, availableEvents[index]); +// ThreadPool.QueueUserWorkItem(ThreadPoolCallback, optionsChainsThreadHelper); +// } +// else +// { +// busyEvents=GetBusyEvents(resetEvents); +// if(busyEvents.Length!=availableEvents.Length) +// { +// ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length]; +// Array.Copy(busyEvents, resizedEvents,busyEvents.Length); +// resetEvents = resizedEvents; +// } +// break; +// } +// } // for +// MDTrace.WriteLine(LogLevel.DEBUG,"Waiting for free slots..."); +// if(resetEvents.Length>0)WaitHandle.WaitAny(resetEvents); +// if(null==PeekQueueItem())resetEvents=ResizeEvents(resetEvents); +// } // while +// MDTrace.WriteLine(LogLevel.DEBUG,"Options chains handler completed."); +// return true; +// } +// finally +// { +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadOptionsChains]End, total took {0}(ms)",profiler.End())); +// } +// } +// public void ThreadPoolCallback(Object optionsChainsThreadHelperContext) +// { +// ThreadHelper optionsChainsThreadHelper = (ThreadHelper)optionsChainsThreadHelperContext; +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Options Chains, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, optionsChainsThreadHelper.Symbol)); +// LoadOptionsChainsSymbolEx(optionsChainsThreadHelper.Symbol); +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Options Chains, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, optionsChainsThreadHelper.Symbol)); +// optionsChainsThreadHelper.ResetEvent.Set(); +// } +// public static void LoadOptionsChainsSymbolEx(String symbol) +// { +// if(null==symbol)return; +// symbol = symbol.ToUpper(); +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Options Chains for {0}", symbol)); +// Options options = MarketDataHelper.GetOptions(symbol); +// if (null == options || 0 == options.Count) +// { +// MDTrace.WriteLine(LogLevel.DEBUG,"Unable to retrieve option chain for " + symbol); +// return; +// } +// MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Options Chains, saving {0} records for {1}", options.Count, symbol)); +// if (OptionsDA.AddOptions(options)) MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Options Chains, Added {0} for {1}", options.Count, symbol)); +// else MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Options Chains, Failed to add options chain for {0}",symbol)); +// } +// } +// } diff --git a/MarketData/MarketDataLib/Helper/PricingMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/PricingMarketDataHelper.cs new file mode 100755 index 0000000..9d46624 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/PricingMarketDataHelper.cs @@ -0,0 +1,831 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; +using System.Net; + +namespace MarketData.Helper +{ + public class PricingThreadHelper : ThreadHelper + { + private DateTime pricingDate=DateTime.Parse("12-31-9999"); + private DateTime? startDate; + private TimeZoneHelper timeZoneInfo; + + public PricingThreadHelper(String symbol,ManualResetEvent resetEvent) + { + Symbol=symbol; + ResetEvent=resetEvent; + } + public PricingThreadHelper(String symbol, DateTime pricingDate,ManualResetEvent resetEvent) + { + Symbol = symbol; + this.pricingDate=pricingDate; + ResetEvent = resetEvent; + timeZoneInfo=new TimeZoneHelper(pricingDate); + } + public PricingThreadHelper(String symbol, ManualResetEvent resetEvent,DateTime? startDate=null) + { + Symbol = symbol; + this.pricingDate=DateTime.Now; + this.startDate=startDate; + ResetEvent = resetEvent; + } + public TimeZoneHelper TimeZoneInfo + { + get{return timeZoneInfo;} + } + public DateTime PricingDate + { + get{return pricingDate;} + } + public DateTime? StartDate + { + get{return startDate;} + } + } + public class PricingMarketDataHelper + { + private static int MaxThreads = (int)ThreadHelperEnum.MaxThreads; + private static int WaitBetweenRequests=125; + private List symbols; + private int currentIndex = 0; + + public PricingMarketDataHelper() + { + } + public static Price RollPriceForward(String symbol) + { + try + { + DateGenerator dateGenerator=new DateGenerator(); + DateTime latestDate=PremarketDA.GetLatestMarketDate(); + if(Utility.IsEpoch(latestDate))return null; + Price latestPrice=PricingDA.GetPrice(symbol); + if(null==latestPrice)return null; + DateTime latestPriceDateSymbol=latestPrice.Date; + latestPrice.Date=latestDate; + PricingDA.InsertPrice(latestPrice); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} price rolled forward from {1} to {2}",symbol,latestPriceDateSymbol.ToShortDateString(),latestDate.ToShortDateString())); + return latestPrice; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception rolling price forward for {0}. Exception was {1}",symbol,exception.ToString())); + return null; + } + } + public bool UpdateLatestPriceAll() + { + Profiler profiler=new Profiler(); + try + { + symbols = PricingDA.GetSymbols(); + currentIndex=0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdateLatestPriceAll, pricingThreadHelper); + try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"UpdateLatestPriceAll, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateLatestPriceAll]End, total took {0}(ms)",profiler.End())); + } + } + public bool UpdatePricesBigCharts(DateTime? startDate=null) // get prices from BigCharts + { + Profiler profiler=new Profiler(); + try + { + symbols = PricingDA.GetSymbols(); + currentIndex=0; + if(null==startDate)startDate=DateTime.Now; + TimeZoneHelper timeZoneHelper=new TimeZoneHelper(startDate.Value); + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index],startDate.Value,resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesBigCharts, pricingThreadHelper); + try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesBigCharts, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesBigCharts]End, total took {0}(ms)",profiler.End())); + } + } + public bool UpdatePricesYahoo(DateTime? startDate=null) // get prices from Yahoo + { + Profiler profiler=new Profiler(); + try + { + symbols=PricingDA.GetSymbols(); + currentIndex=0; + if(null==startDate) startDate=DateTime.Now; + TimeZoneHelper timeZoneHelper=new TimeZoneHelper(startDate.Value); + while(true) + { + List queueSymbols=GetQueueSymbols(); + if(null==queueSymbols||0==queueSymbols.Count) break; + ManualResetEvent[] resetEvents=new ManualResetEvent[queueSymbols.Count]; + for(int eventIndex=0;eventIndex queueSymbols=GetQueueSymbols(); + if(null==queueSymbols||0==queueSymbols.Count) break; + ManualResetEvent[] resetEvents=new ManualResetEvent[queueSymbols.Count]; + for(int eventIndex=0;eventIndex(); + symbols.Add(symbol); + currentIndex=0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], resetEvents[index],asOf); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesAsOf, pricingThreadHelper); + try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesAsOfSymbol, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesAsOfSymbol]End, total took {0}(ms)",profiler.End())); + } + } + public bool UpdatePriceAsOfSymbolYahoo(String symbol,DateTime asOf) // get prices from Yahoo + { + Profiler profiler=new Profiler(); + try + { + symbols=new List(); + symbols.Add(symbol); + currentIndex=0; + while(true) + { + List queueSymbols=GetQueueSymbols(); + if(null==queueSymbols||0==queueSymbols.Count) break; + ManualResetEvent[] resetEvents=new ManualResetEvent[queueSymbols.Count]; + for(int eventIndex=0;eventIndex queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], resetEvents[index],asOf); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesAsOf, pricingThreadHelper); + try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesAsOf, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesAsOf]End, total took {0}(ms)",profiler.End())); + } + } + public bool GetMissingPricesSymbol(String symbol,DateTime? startDate=null) + { + Profiler profiler=new Profiler(); + try + { + List symbols=new List(); + symbols.Add(symbol); + this.symbols=symbols; + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], resetEvents[index],startDate); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackGetMissingPrice, pricingThreadHelper); + try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Get missing prices, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[GetMissingPrices]End, total took {0}(ms)",profiler.End())); + } + } + public bool GetMissingPrices(DateTime? startDate=null) + { + Profiler profiler=new Profiler(); + try + { + this.symbols=PricingDA.GetSymbols(); + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], resetEvents[index],startDate); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackGetMissingPrice, pricingThreadHelper); + try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Get missing prices, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[GetMissingPrices]End, total took {0}(ms)",profiler.End())); + } + } + public bool UpdateLatestPriceSymbol(String symbol) + { + List symbols=new List(); + symbols.Add(symbol); + return UpdateLatestPrices(symbols); + } + public bool UpdateLatestPrices(List symbols) + { + Profiler profiler=new Profiler(); + try + { + DateTime pricingDate=DateTime.Now; + this.symbols = symbols; + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], pricingDate,resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdateLatestPrice, pricingThreadHelper); + try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load prices, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateLatestPrices]End, total took {0}(ms)",profiler.End())); + } + } + public bool LoadPrices(List symbols) + { + Profiler profiler=new Profiler(); + try + { + DateTime pricingDate=DateTime.Now; + this.symbols = symbols; + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], pricingDate,resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadPrices, pricingThreadHelper); + try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;} + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load prices, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadPrices]End, total took {0}(ms)",profiler.End())); + } + } +// ************************************************************************************************************************************ +// *************************************************** T H R E A D P O O L C A L L B A C K ****************************************** +// ************************************************************************************************************************************ + public void ThreadPoolCallbackUpdateLatestPriceAll(Object pricingThreadHelperContext) + { + PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UpdateLatestPriceAll, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol)); + UpdateLatestPriceAllEx(pricingThreadHelper.Symbol); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UpdateLatestPriceAll, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol)); + } + finally + { + pricingThreadHelper.ResetEvent.Set(); + } + } + public void ThreadPoolCallbackUpdatePricesBigCharts(Object pricingThreadHelperContext) + { + PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (BigCharts), Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol)); + UpdatePriceBigChartsEx(pricingThreadHelper.Symbol,pricingThreadHelper.TimeZoneInfo); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (BigCharts), Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol)); + } + finally + { + pricingThreadHelper.ResetEvent.Set(); + } + } + public void ThreadPoolCallbackUpdatePricesYahoo(Object pricingThreadHelperContext) + { + PricingThreadHelper pricingThreadHelper=(PricingThreadHelper)pricingThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (Yahoo), Thread {0} started for {1}...",Thread.CurrentThread.ManagedThreadId,pricingThreadHelper.Symbol)); + UpdatePriceYahoo(pricingThreadHelper.Symbol,pricingThreadHelper.TimeZoneInfo); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (Yahoo), Thread {0} ended for {1}",Thread.CurrentThread.ManagedThreadId,pricingThreadHelper.Symbol)); + } + finally + { + pricingThreadHelper.ResetEvent.Set(); + } + } + public void ThreadPoolCallbackUpdatePricesYahooSweep(Object pricingThreadHelperContext) + { + PricingThreadHelper pricingThreadHelper=(PricingThreadHelper)pricingThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (Yahoo), Thread {0} started for {1}...",Thread.CurrentThread.ManagedThreadId,pricingThreadHelper.Symbol)); + UpdatePriceYahooSweep(pricingThreadHelper.Symbol,pricingThreadHelper.TimeZoneInfo); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (Yahoo), Thread {0} ended for {1}",Thread.CurrentThread.ManagedThreadId,pricingThreadHelper.Symbol)); + } + finally + { + pricingThreadHelper.ResetEvent.Set(); + } + } + public void ThreadPoolCallbackUpdatePricesAsOf(Object pricingThreadHelperContext) + { + PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol)); + UpdatePriceAsOfEx(pricingThreadHelper.Symbol,pricingThreadHelper.StartDate.Value); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol)); + } + finally + { + pricingThreadHelper.ResetEvent.Set(); + } + } + public void ThreadPoolCallbackGetMissingPrice(Object pricingThreadHelperContext) + { + PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext; + try + { + GetMissingPricesEx(pricingThreadHelper.Symbol,pricingThreadHelper.StartDate==null?new DateTime():pricingThreadHelper.StartDate.Value); + } + finally + { + pricingThreadHelper.ResetEvent.Set(); + } + } + public void ThreadPoolCallbackUpdateLatestPrice(Object pricingThreadHelperContext) + { + PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext; + try + { + Price latestPrice = MarketDataHelper.GetLatestPrice(pricingThreadHelper.Symbol); + if (null == latestPrice) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("***** Error retrieving latest price for {0} *****",pricingThreadHelper.Symbol)); + return; + } + + MDTrace.WriteLine(LogLevel.DEBUG,Price.Header); + MDTrace.WriteLine(LogLevel.DEBUG,latestPrice.ToString()); + MDTrace.WriteLine(LogLevel.DEBUG,"Removing price for '"+pricingThreadHelper.Symbol+"' on "+Utility.DateTimeToStringMMSDDSYYYY(latestPrice.Date)); + PricingDA.DeletePrice(pricingThreadHelper.Symbol,latestPrice.Date); + MDTrace.WriteLine(LogLevel.DEBUG,"Adding price for '" + pricingThreadHelper.Symbol + "' on " + Utility.DateTimeToStringMMSDDSYYYY(latestPrice.Date)); + PricingDA.InsertPrice(latestPrice); + } + finally + { + pricingThreadHelper.ResetEvent.Set(); + } + } + public void ThreadPoolCallbackLoadPrices(Object pricingThreadHelperContext) + { + PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol)); + LoadPricesSymbolEx(pricingThreadHelper.Symbol,pricingThreadHelper.PricingDate); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol)); + } + finally + { + pricingThreadHelper.ResetEvent.Set(); + } + } +// **************************************************************************************************************************************** +// **************************************************************************************************************************************** +// **************************************************************************************************************************************** + private List GetQueueSymbols() + { + List queueSymbols = new List(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < symbols.Count; index++) + { + queueSymbols.Add(symbols[index]); + } + currentIndex = index; + return queueSymbols; + } +// ******************************************************************************************************************************************** +// ************************************************************ W O R K E R S ***************************************************************** +// ******************************************************************************************************************************************** + public static void GetMissingPricesEx(String symbol,DateTime startDate) + { + try + { + DateGenerator dateGenerator=new DateGenerator(); + TimeSpan oneDay=new TimeSpan(1,0,0,0); + DateTime? historicalDate = null; + DateTime minDate=Constants.MIN_PRICING_DATE; + + List pricingDatesList = PricingDA.GetPricingDatesForSymbol(symbol); + if (null == pricingDatesList || 0 == pricingDatesList.Count) return; + pricingDatesList=pricingDatesList.Where(x => x.Date>=minDate.Date).ToList(); + if(null==pricingDatesList||0==pricingDatesList.Count) return; + DateTime beginDate = pricingDatesList[0]; + DateTime endDate = pricingDatesList[pricingDatesList.Count - 1]; + Dictionary pricingDates = new Dictionary(); + for (int listIndex = 0; listIndex < pricingDatesList.Count; listIndex++) + { + DateTime pricingDate=pricingDatesList[listIndex]; + pricingDates.Add(pricingDate.Date, pricingDate.Date); + } + Dictionary marketPrices = new Dictionary(); + if (Utility.IsEpoch(startDate)) historicalDate = beginDate; + else historicalDate = startDate; + MDTrace.WriteLine(LogLevel.DEBUG,"Working on '" + symbol + "' from "+Utility.DateTimeToStringMMHDDHYYYY(historicalDate.Value)+" to "+Utility.DateTimeToStringMMHDDHYYYY(endDate)); + Prices prices = MarketDataHelper.GetDailyPrices(symbol, historicalDate.Value, endDate); // yahoo finance + if(null==prices||0==prices.Count)prices=MarketDataHelper.GetPricesAsOf(symbol,historicalDate.Value,endDate); // try big charts + if (null == prices||0==prices.Count)return; + for (int listIndex = 0; listIndex < prices.Count; listIndex++) + { + Price price = prices[listIndex]; + if(!marketPrices.ContainsKey(price.Date.Date))marketPrices.Add(price.Date,price); + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Retrieved {0} prices from feed for {1}",prices.Count,symbol)); + bool added=false; + for (DateTime date = historicalDate.Value.Date; date < endDate.Date; date += oneDay) + { + if (pricingDates.ContainsKey(date.Date)) continue; + if (dateGenerator.IsWeekend(date)) continue; + Price price = null; + if (!marketPrices.ContainsKey(date.Date))continue; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",price.ToString())); + price = marketPrices[date.Date]; + MDTrace.WriteLine(LogLevel.DEBUG,price.ToString()); + PricingDA.InsertPrice(price); + added=true; + } + if(!added) + { + MDTrace.WriteLine(LogLevel.DEBUG,"There were no new prices to add for '" + symbol); + } + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception {0}",exception.ToString())); + } + } + public static void UpdateLatestPriceAllEx(String symbol) + { + try + { + symbol = symbol.ToUpper(); + Price latestPrice = MarketDataHelper.GetLatestPrice(symbol); + if (null == latestPrice) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Error retrieving latest price."); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,Price.Header); + MDTrace.WriteLine(LogLevel.DEBUG,latestPrice.ToString()); + MDTrace.WriteLine(LogLevel.DEBUG,"Removing price for '" + symbol + "' on " + Utility.DateTimeToStringMMSDDSYYYY(latestPrice.Date)); + PricingDA.DeletePrice(symbol, latestPrice.Date); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",latestPrice.ToString())); + PricingDA.InsertPrice(latestPrice); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + } + } + public static void UpdatePriceBigChartsEx(String symbol,TimeZoneHelper timeZoneInfo) + { + try + { + Price price=PricingDA.GetPrice(symbol,timeZoneInfo.StartDate); + if(null!=price) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Already have latest price for '" + symbol + "'"); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Requesting price for {0} for start date:{1} end date:{2}",symbol,timeZoneInfo.StartDate,timeZoneInfo.StartDate)); + Prices prices = MarketDataHelper.GetPricesAsOf(symbol, timeZoneInfo.StartDate,timeZoneInfo.StartDate); + if (null == prices||0==prices.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No prices (GetPricesAsOf) for '" + symbol+ "'"); + return; + } + else + { + for (int secIndex = 0; secIndex < prices.Count; secIndex++) + { + MDTrace.WriteLine(LogLevel.DEBUG,prices[secIndex].ToString()); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Inserting...."); + PricingDA.InsertPrices(prices); + MDTrace.WriteLine(LogLevel.DEBUG,"Done."); + } + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception {0}",exception.ToString())); + } + } + public static void UpdatePriceYahoo(String symbol,TimeZoneHelper timeZoneInfo) + { + try + { + Price price=PricingDA.GetPrice(symbol,timeZoneInfo.StartDate); + if(null!=price) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Already have latest price for '"+symbol+"'"); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Requesting price for {0} for start date:{1} end date:{2}",symbol,timeZoneInfo.StartDate,timeZoneInfo.StartDate)); + price=MarketDataHelper.GetDailyPrice(symbol,timeZoneInfo.StartDate); + if(null==price) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No price (UpdatePriceYahoo) for '"+symbol+"'"); + return; + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",price.ToString())); + PricingDA.InsertPrice(price); + } + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception {0}",exception.ToString())); + } + } + public static void UpdatePriceYahooSweep(String symbol,TimeZoneHelper timeZoneInfo) + { + try + { + CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol); + Price price=PricingDA.GetPrice(symbol,timeZoneInfo.StartDate); + if(null!=price) + { + if(companyProfile==null || !companyProfile.PricingSourceEnum.Equals(CompanyProfile.EnumPricingSource.YAHOO)) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Already have latest price for '"+symbol+"'"); + return; + } + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UpdatePriceYahooSweep: Requesting price for {0} for start date:{1} end date:{2}",symbol,timeZoneInfo.StartDate,timeZoneInfo.StartDate)); + price=MarketDataHelper.GetDailyPrice(symbol,timeZoneInfo.StartDate); + if(null==price) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No price (UpdatePriceYahoo) for '"+symbol+"'"); + return; + } + else if(!price.IsValid) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Invalid price (UpdatePriceYahooSweep) for '"+symbol+"'"); + return; + } + else + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",price.ToString())); + PricingDA.InsertPrice(price); + } + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception {0}",exception.ToString())); + } + } + public static void UpdatePriceAsOfEx(String symbol,DateTime asOf) + { + try + { + DateTime latestDate = PricingDA.GetLatestDate(symbol); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Latest pricing date for {0} is {1}",symbol,latestDate.ToShortDateString())); + if (latestDate.Equals(asOf)) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Already have price for '" + symbol + "' on "+Utility.DateTimeToStringMMHDDHYYYY(asOf)); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Retrieving price for {0} on {1} from BigCharts",symbol,asOf.ToShortDateString())); + Price price = MarketDataHelper.GetPriceAsOf(symbol,asOf); + if (null == price) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Error retrieving price for {0} on {1}",symbol,asOf.ToShortDateString())); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,Price.Header); + MDTrace.WriteLine(LogLevel.DEBUG,price.ToString()); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",price.ToString())); + PricingDA.InsertPrice(price); + MDTrace.WriteLine(LogLevel.DEBUG,""); + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + } + } + + public static void LoadPricesSymbolEx(String symbol,DateTime pricingDate) + { + DateGenerator dateGenerator = new DateGenerator(); + DateTime startDate = pricingDate; // the least recent date + DateTime endDate = pricingDate; // the most recent date + endDate = dateGenerator.GetPrevBusinessDay(endDate); + startDate = PricingDA.GetLatestDate(symbol); + startDate = dateGenerator.FindNextBusinessDay(startDate); + if (startDate.Date > endDate.Date) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Already have latest price for '" + symbol + "'"); + return; + } + Prices prices=MarketDataHelper.GetPricesAsOf(symbol,startDate,endDate); + if (null == prices||0==prices.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No prices (GetDailyPrices) for '" + symbol + "'"); + return; + } + else + { + for (int secIndex = 0; secIndex < prices.Count; secIndex++) + { + MDTrace.WriteLine(LogLevel.DEBUG,prices[secIndex].ToString()); + } + PricingDA.InsertPrices(prices); + MDTrace.WriteLine(LogLevel.DEBUG,"Done."); + } + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/SECFilingMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/SECFilingMarketDataHelper.cs new file mode 100755 index 0000000..2453bb5 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/SECFilingMarketDataHelper.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class SECFilingMarketDataHelper + { + private static int MaxThreads = 5; // 10 requests per second is what is allowable under SEC.GOV. We'll request 5 symbols per batch. Note:each request may contain subrequests + private static int WAIT_TIME_MS=1000; // wait between requests + private List symbols; + private int currentIndex = 0; + + public SECFilingMarketDataHelper() + { + } + public bool UpdateSECFilings(List symbols) + { + Profiler profiler=new Profiler(); + + try + { + this.symbols=symbols; + currentIndex=0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdateSECFiling, threadHelper); + try { Thread.Sleep(WAIT_TIME_MS); } catch(Exception) { ;} // SEC has a traffic limit + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load SEC Filings, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateSECFilings]Exception {0}",exception.ToString())); + return false; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateSECFilings]End, total took {0}(ms)",profiler.End())); + } + } + public bool UpdateSECFilings() + { + Profiler profiler=new Profiler(); + try + { + List watchListSymbols = WatchListDA.GetWatchList("Valuations"); // get the current watchlist symbols + List secFilingSymbols=SECFilingDA.GetDistinctFilingSymbols(); // get the current SEC filing symbols + symbols=watchListSymbols.Union(secFilingSymbols).Distinct().ToList(); // use the union of the two + currentIndex = 0; + while (true) + { + List queueSymbols = GetQueueSymbols(); + if (null == queueSymbols || 0 == queueSymbols.Count) break; + ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++) + { + resetEvents[eventIndex] = new ManualResetEvent(false); + } + for (int index = 0; index < queueSymbols.Count; index++) + { + ThreadHelper threadHelper = new ThreadHelper(queueSymbols[index],resetEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdateSECFiling, threadHelper); + try { Thread.Sleep(WAIT_TIME_MS); }catch(Exception) { ;} // SEC has a traffic limit + } + MDTrace.WriteLine(LogLevel.DEBUG,"Load SEC Filings, waiting for queued items to complete."); + WaitHandle.WaitAll(resetEvents); + } + return true; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateSECFilings]Exception {0}",exception.ToString())); + return false; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateSECFilings]End, total took {0}(ms)",profiler.End())); + } + } + private List GetQueueSymbols() + { + List queueSymbols = new List(); + int index = currentIndex; + for (; index < currentIndex + MaxThreads && index < symbols.Count; index++) + { + queueSymbols.Add(symbols[index]); + } + currentIndex = index; + return queueSymbols; + } + public void ThreadPoolCallbackUpdateSECFiling(Object threadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)threadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load SEC Filing, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + UpdateSECFiling(threadHelper.Symbol); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load SEC Filing, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } + public static void UpdateSECFiling(String symbol) + { + try + { + MDTrace.WriteLine(LogLevel.DEBUG,"UpdateSECFiling '"+symbol+"'"); + String cik = PricingDA.GetCIKForSymbol(symbol); + if (null == cik) + { + MDTrace.WriteLine(LogLevel.DEBUG,"No CIK for symbol '" + symbol + "'"); + return; + } + MDTrace.WriteLine(LogLevel.DEBUG,"UpdateSECFiling for symbol '" + symbol + "'"); + SECFilings secFilings = MarketDataHelper.GetSECFilings(symbol, cik); + if (null != secFilings) + { + for (int index = 0; index < secFilings.Count; index++) + { + StringBuilder sb = new StringBuilder(); + SECFiling secFiling = secFilings[index]; + sb.Append(secFiling.Symbol).Append(","); + sb.Append(Utility.DateTimeToStringYYYYHMMHDD(secFiling.FilingDate)).Append(","); + sb.Append(secFiling.SECAccessionNumber).Append(","); + sb.Append(secFiling.Sequence); + MDTrace.WriteLine(LogLevel.DEBUG,sb.ToString()); + } + MDTrace.WriteLine(LogLevel.DEBUG,"Got "+secFilings.Count+" filings for symbol '"+symbol+"'"); + SECFilingDA.InsertOrUpdateSECFilings(secFilings); + } + return; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return; + } + } + } +} + diff --git a/MarketData/MarketDataLib/Helper/SplitHelper.cs b/MarketData/MarketDataLib/Helper/SplitHelper.cs new file mode 100755 index 0000000..a5c84d3 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/SplitHelper.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ public class SplitHelper + { +// I have found that simply reloading prices with splits from Yahoo solves the issue of corporate actions as they are handled on Yahoo Finanace + public static bool ProcessSplits(Splits splits) + { + foreach(Split split in splits)ProcessSplit(split.Symbol); + return true; + } + public static bool ProcessSplit(String symbol) + { + Splits splits=SplitsDA.GetSplits(symbol); + if(null==splits||0==splits.Count)return false; + DateGenerator dateGenerator=new DateGenerator(); + + for(int index=0;index prices.Count) return null; + DMAPrice maPrice = null; + Price p = prices[startIndex]; + Price p1 = prices[startIndex + 1]; + Price p2 = prices[startIndex + 2]; + Price p3 = prices[startIndex + 3]; + if(!ma21.ContainsKey(p.Date))return null; + maPrice = ma21[p.Date]; + if (p1.Low >= maPrice.AVGPrice) return null; + if (!(p1.Low < p.Low && p2.Low < p1.Low && p3.Low > p2.Low)) return null; + SwingTrade swingTrade = new SwingTrade(); + swingTrade.Symbol = p.Symbol; + DateGenerator dateGenerator = new DateGenerator(); + if (null != bollingerBandElements && bollingerBandElements.ContainsKey(p1.Date) && bollingerBandElements.ContainsKey(p2.Date) && bollingerBandElements.ContainsKey(p3.Date)) + { + BollingerBandElement b1=bollingerBandElements[p1.Date]; + BollingerBandElement b2=bollingerBandElements[p2.Date]; + BollingerBandElement b3 = bollingerBandElements[p3.Date]; + if (p1.Low < b1.L && p2.Low < b2.L && p3.Low > b3.L) + { + swingTrade.SwingType = SwingTrade.TypeOfSwing.LongBand; + swingTrade.CandleDate = p1.Date; + swingTrade.CandleHigh = p1.High; + swingTrade.StopPrice = p1.Low; + swingTrade.CloseDate = p3.Date; + swingTrade.EntryDate = dateGenerator.FindNextBusinessDay(swingTrade.CloseDate); + return swingTrade; + } + } + DateTime? closeDate = FindCloseAboveCandle(prices, p1, startIndex + 4); + swingTrade.SwingType = SwingTrade.TypeOfSwing.Long; + swingTrade.CandleDate = p1.Date; + swingTrade.CandleHigh = p1.High; + swingTrade.StopPrice = p1.Low; + if (null != closeDate) + { + swingTrade.CloseDate = closeDate.Value; + swingTrade.EntryDate = dateGenerator.FindNextBusinessDay(swingTrade.CloseDate); + } + else + { + swingTrade.CloseDate = Utility.Epoch; + swingTrade.EntryDate = Utility.Epoch; + } + if (!swingTrade.EntryDate.Equals(Utility.Epoch) && dateGenerator.DaysBetween(swingTrade.CandleDate, swingTrade.EntryDate) > 15) return null; + return swingTrade; + } + private static DateTime? FindCloseAboveCandle(Prices prices, Price priceCandle, int startIndex) + { + if (startIndex > prices.Count) return null; + for (int index = startIndex; index < prices.Count; index++) + { + Price price = prices[index]; + if (price.Close > priceCandle.High) return price.Date; + } + return null; + } + } +} diff --git a/MarketData/MarketDataLib/Helper/ThreadHelper.cs b/MarketData/MarketDataLib/Helper/ThreadHelper.cs new file mode 100755 index 0000000..b23f062 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/ThreadHelper.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public enum ThreadHelperEnum{MaxThreads=25}; + public class ThreadHelper + { + public String Symbol{get;set;} + public DateTime Modified{get;set;} + public ManualResetEvent ResetEvent{get;set;} + public UpdateManager updateManager; + + public ThreadHelper() + { + Modified=DateTime.Now; + } + public ThreadHelper(String symbol, ManualResetEvent resetEvent) + { + Symbol=symbol; + ResetEvent=resetEvent; + } + public ThreadHelper(String symbol, DateTime modified,ManualResetEvent resetEvent) + { + Symbol=symbol; + Modified=modified; + ResetEvent=resetEvent; + } + public UpdateManager UpdateManager + { + get{return updateManager;} + set{updateManager=value;} + } + } +} diff --git a/MarketData/MarketDataLib/Helper/TimeZoneHelper.cs b/MarketData/MarketDataLib/Helper/TimeZoneHelper.cs new file mode 100755 index 0000000..8ca950c --- /dev/null +++ b/MarketData/MarketDataLib/Helper/TimeZoneHelper.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MarketData.Utils; +using System.Collections.ObjectModel; + +namespace MarketData.Helper +{ + public class TimeZoneHelper + { + private DateGenerator dateGenerator=new DateGenerator(); + private DateTime startDate; + private DateTime endDate; + private DateTime prevBusinessDate; + private DateTime easternTime; + private TimeZoneInfo localZone = TimeZoneInfo.Local; + private TimeZone currentTimeZone=TimeZone.CurrentTimeZone; + private static TimeZoneInfo easternTimeZone = GetEasternTimeZone(); + + public TimeZoneHelper() + { + startDate=DateTime.Now; + endDate = startDate; // the most recent date + prevBusinessDate=startDate; + prevBusinessDate = dateGenerator.GetPrevBusinessDay(endDate); + easternTime=new DateTime(prevBusinessDate.Year,prevBusinessDate.Month,prevBusinessDate.Day,20,30,0); + + if(!currentTimeZone.DaylightName.Equals("Eastern Daylight Time")&&!currentTimeZone.DaylightName.Equals("Eastern Time (US & Canada)")) + { + easternTime=TimeZoneInfo.ConvertTimeToUtc(new DateTime(easternTime.Year,easternTime.Month,easternTime.Day,20,30,0),easternTimeZone); + } + if(prevBusinessDate.Equals(endDate)&&DateTime.Now.TimeOfDay timeZones; + timeZones= TimeZoneInfo.GetSystemTimeZones(); + for (int index = 0; index < timeZones.Count; index++) + { + timeZoneInfo = timeZones[index]; + if (timeZoneInfo.DisplayName.Equals("Eastern Daylight Time")||timeZoneInfo.DisplayName.Equals("Eastern Time (US & Canada)")|| + timeZoneInfo.DaylightName.Equals("Eastern Daylight Time")||timeZoneInfo.StandardName.Equals("Eastern Standard Time")) break; + } + return timeZoneInfo; + } + public DateTime StartDate + { + get{return startDate;} + } + public DateTime EndDate + { + get{return endDate;} + } + public DateTime PrevBusinessDate + { + get{return prevBusinessDate;} + } + public DateTime EasternTime + { + get{return easternTime;} + } + public DateGenerator DateGenerator + { + get{return dateGenerator;} + } + } +} diff --git a/MarketData/MarketDataLib/Helper/ZacksRankMarketDataHelper.cs b/MarketData/MarketDataLib/Helper/ZacksRankMarketDataHelper.cs new file mode 100755 index 0000000..d98a9d7 --- /dev/null +++ b/MarketData/MarketDataLib/Helper/ZacksRankMarketDataHelper.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MarketData.MarketDataModel; +using MarketData.DataAccess; +using MarketData.Utils; + +namespace MarketData.Helper +{ + public class ZacksRankMarketDataHelper : MarketDataHelperBase + { + private static int MaxThreads = (int)ThreadHelperEnum.MaxThreads; + + public ZacksRankMarketDataHelper() + { + } + public bool LoadZacksRank(String symbol=null) + { + Profiler profiler=new Profiler(); + try + { + if(symbol==null)Queue=PricingDA.GetSymbols(); + else (Queue=new List()).Add(symbol); + Index=-1; + ManualResetEvent[] resetEvents = new ManualResetEvent[MaxThreads]; + for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)resetEvents[eventIndex] = new ManualResetEvent(true); + MDTrace.WriteLine(String.Format("Queuing Zacks rank load ...")); + DateTime modified=DateTime.Now; + while (true) + { + ManualResetEvent[] availableEvents=GetAvailableEvents(resetEvents); + ManualResetEvent[] busyEvents=GetBusyEvents(resetEvents); + if (null == PeekQueueItem() && 0==busyEvents.Length) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Zacks Rank queue contains {0} items, busy events {1}, all done.",0,busyEvents.Length)); + break; + } + for (int index = 0; index < availableEvents.Length; index++) + { + symbol=GetQueueItem(); + if (null != symbol) + { + availableEvents[index].Reset(); + ThreadHelper zacksRankThreadHelper = new ThreadHelper(symbol,modified,availableEvents[index]); + ThreadPool.QueueUserWorkItem(ThreadPoolCallback, zacksRankThreadHelper); + } + else + { + busyEvents=GetBusyEvents(resetEvents); + if(busyEvents.Length!=availableEvents.Length) + { + ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length]; + Array.Copy(busyEvents, resizedEvents,busyEvents.Length); + resetEvents = resizedEvents; + } + break; + } + } // for + MDTrace.WriteLine(LogLevel.DEBUG,"Zacks Rank waiting for free slots..."); + if(resetEvents.Length>0)WaitHandle.WaitAny(resetEvents); + if(null==PeekQueueItem())resetEvents=ResizeEvents(resetEvents); + } // while + MDTrace.WriteLine(LogLevel.DEBUG,"Zacks Rank completed."); + return true; + } + finally + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadZacksRanks]End, total took {0}(ms)",profiler.End())); + } + } + public void ThreadPoolCallback(Object threadHelperContext) + { + ThreadHelper threadHelper = (ThreadHelper)threadHelperContext; + try + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Zacks Rank, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + LoadZacksRankEx(threadHelper.Symbol,threadHelper.Modified); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load Zacks Rank, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, threadHelper.Symbol)); + } + finally + { + threadHelper.ResetEvent.Set(); + } + } +// Single threaded method, use for debugging a single symbol fetch without going through the queue + public static void LoadZacksRankEx(String symbol,DateTime modified) + { + LoadZacksRankEx(symbol); + //if (!ZacksRankDA.CheckZacksRankModifiedOn(symbol, modified)) LoadZacksRankEx(symbol); + //else MDTrace.WriteLine(LogLevel.DEBUG,"Already have Zacks Rank for '"+symbol+"' on "+Utility.DateTimeToStringMMHDDHYYYY(modified)); + } + public static void LoadZacksRankEx(String symbol) + { + try + { + MDTrace.WriteLine(LogLevel.DEBUG,"Loading Zacks Rank for '" + symbol + "'"); + ZacksRank zacksRank=MarketDataHelper.GetZacksRank(symbol); + if (null != zacksRank) + { + ZacksRankDA.InsertZacksRank(zacksRank); + MDTrace.WriteLine(LogLevel.DEBUG,AnalystPriceTarget.Header); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Zacks rank:{0} {1}",zacksRank.Symbol,zacksRank.Rank)); + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,"Failed to load Zacks Rank for '" + symbol + "'"); + MDTrace.WriteLine(LogLevel.DEBUG,"Exception was " + exception.ToString()); + } + } + } +} diff --git a/MarketData/MarketDataLib/Integration/HttpNetRequest.cs b/MarketData/MarketDataLib/Integration/HttpNetRequest.cs new file mode 100755 index 0000000..a4082d1 --- /dev/null +++ b/MarketData/MarketDataLib/Integration/HttpNetRequest.cs @@ -0,0 +1,1774 @@ +using System.Net; +using System.Text; +using System.IO.Compression; +using System.Configuration; +using MarketData.Configuration; +// Filename: HttpRequest.cs +// Author:Sean Kessler + +namespace MarketData.Integration +{ + public class HttpNetResponse : IDisposable + { + public enum TypeResponse {Stream,String}; + public String ResponseString{get;set;} + public MemoryStream ResponseStream{get;set;} + public CookieCollection CookieCollection{get;set;} + + public HttpNetResponse() + { + Success=false; + } + public HttpNetResponse(String responseString,String request,HttpWebResponse webResponse,CookieCollection cookieCollection,bool success) + { + ResponseString=responseString; + ResponseType=TypeResponse.String; + Success=success; + Request=request; + CookieCollection=cookieCollection; + if(null!=webResponse)StatusCode=webResponse.StatusCode; + } + public HttpNetResponse(String responseString,String request,HttpWebResponse webResponse,bool success) + { + ResponseString=responseString; + ResponseType=TypeResponse.String; + Success=success; + Request=request; + if(null!=webResponse)StatusCode=webResponse.StatusCode; + } + public HttpNetResponse(MemoryStream responseStream,String request,HttpWebResponse webResponse,bool success) + { + ResponseStream=responseStream; + ResponseType=TypeResponse.String; + Success=success; + Request=request; + if(null!=webResponse)StatusCode=webResponse.StatusCode; + } + public HttpNetResponse(HttpWebResponse webResponse,String request,bool success,String errorMessage) + { + ResponseType=TypeResponse.String; + Success=success; + Request=request; + if(null!=webResponse)StatusCode=webResponse.StatusCode; + ErrorMessage=errorMessage; + } + public Stream ResponseStringToStream() + { + MemoryStream stream = new MemoryStream(); + StreamWriter writer = new StreamWriter(stream); + writer.Write(ResponseString); + writer.Flush(); + stream.Position = 0; + return stream; + } + public String ResponseStreamToString + { + get + { + if(!Success)return null; + return System.Text.Encoding.UTF8.GetString(ResponseStream.ToArray()); + } + } + public TypeResponse ResponseType{get;set;} + public bool Success{get;set;} + public String ErrorMessage{get;set;} + public HttpStatusCode StatusCode{get;set;} + public String Request{get;set;} + public bool IsNetErrorResponse + { + get + { + return (int)StatusCode>=400?true:false; + } + } + public void Dispose() + { + if(null!=ResponseStream) + { + ResponseStream.Close(); + ResponseStream.Dispose(); + ResponseStream=null; + } + } + } +// ********************************************************************************************************************************************************************* + + public class HttpNetRequest + { + public static int REQUEST_TIMEOUT = 300000; + private HttpNetRequest() + { + } + public static HttpNetResponse GetRequestStreamZIP(String strRequest) + { + HttpWebResponse webResponse=null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestStreamZIP[ENTER]{0}",strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + webRequest.Timeout = REQUEST_TIMEOUT; + webRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate"); + webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"; + webRequest.KeepAlive = true; + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + MemoryStream memoryStream=new MemoryStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if(charCount<=0)break; + memoryStream.Write(buffer,0,charCount); + } + memoryStream.Flush(); + return new HttpNetResponse(memoryStream,strRequest,webResponse,true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestStreamZIP[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestStreamZIPV2(String strRequest) + { + HttpWebResponse webResponse=null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestStreamZIPV2[ENTER]{0}",strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + webRequest.Timeout = REQUEST_TIMEOUT; + webRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate"); + webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"; + webRequest.KeepAlive = true; + webRequest.CookieContainer=new CookieContainer(); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + MemoryStream memoryStream=new MemoryStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if(charCount<=0)break; + memoryStream.Write(buffer,0,charCount); + } + memoryStream.Flush(); + return new HttpNetResponse(memoryStream,strRequest,webResponse,true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestStreamZIPV2[LEAVE]"); + } + } + public static HttpNetResponse GetRequestStreamCSV(String strRequest,CookieCollection cookieCollection=null, WebProxy webProxy=null) + { + HttpWebResponse webResponse=null; + try + { + // ServicePointManager.Expect100Continue=true; + // ServicePointManager.SecurityProtocol=SecurityProtocolType.Ssl3|SecurityProtocolType.Tls12|SecurityProtocolType.Tls11|SecurityProtocolType.Tls; + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestStreamCSV[ENTER]{0}",strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy) + { + webRequest.Proxy=webProxy; + } + if(null!=cookieCollection) + { + webRequest.CookieContainer=new CookieContainer(); + webRequest.CookieContainer.Add(cookieCollection); + } + webRequest.Timeout = REQUEST_TIMEOUT; + webRequest.Accept = "text/csv,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate"); // + webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"; + webRequest.KeepAlive = true; + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + + if(webResponse.ContentEncoding.ToLower().Contains("gzip")) + { + responseStream = new GZipStream(responseStream, CompressionMode.Decompress); + StreamReader reader = new StreamReader(responseStream, Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else if(webResponse.ContentEncoding.ToLower().Contains("deflate")) + { + responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); + StreamReader reader = new StreamReader(responseStream, Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else + { + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestStreamCSV[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncoding(String strRequest,WebProxy webProxy=null) + { + HttpWebResponse webResponse=null; + try + { + ServicePointManager.Expect100Continue = true; +// ServicePointManager.SecurityProtocol=SecurityProtocolType.Ssl3|SecurityProtocolType.Tls12|SecurityProtocolType.Tls11|SecurityProtocolType.Tls; + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestNoEncoding[ENTER]{0}",strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.Timeout = REQUEST_TIMEOUT; + webRequest.Accept = "text/html, text/csv"; + webRequest.ContentType="text/csv; charset=utf-8"; + webRequest.Headers.Add("Accept-Encoding: None"); + webRequest.Headers.Add("Accept-Language: en-US"); + webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"; + webRequest.KeepAlive = true; + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 >= charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestNoEncoding[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV1(String strRequest,WebProxy webProxy=null) + { + ServicePointManager.Expect100Continue=true; +// ServicePointManager.SecurityProtocol=SecurityProtocolType.Ssl3|SecurityProtocolType.Tls12|SecurityProtocolType.Tls11|SecurityProtocolType.Tls; + HttpWebResponse webResponse=null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestNoEncoding[ENTER]{0}",strRequest)); + int charCount=0; + byte[] buffer=new byte[8192]; + StringBuilder sb=new StringBuilder(); + HttpWebRequest webRequest=(HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.Timeout=REQUEST_TIMEOUT; + webRequest.Accept="text/html, text/csv"; + webRequest.ContentType="text/csv; charset=utf-8"; + webRequest.Headers.Add("Accept-Encoding: None"); + webRequest.Headers.Add("Accept-Language: en-US"); + webRequest.UserAgent="Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"; + webRequest.KeepAlive=true; + try{webResponse=(HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream=webResponse.GetResponseStream(); + while(true) + { + charCount=responseStream.Read(buffer,0,buffer.Length); + if(0>=charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer,0,charCount)); + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,true); + } + catch(WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch(Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestNoEncoding[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestCSV(String strRequest,String referer) + { + HttpWebResponse webResponse=null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestCSV[ENTER]{0}",strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + webRequest.Timeout = REQUEST_TIMEOUT; + webRequest.Accept="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; + webRequest.ContentType="text/csv; charset=utf-8"; + webRequest.Headers.Add("Accept-Encoding: identity"); // "gzip, deflate" + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Upgrade-Insecure-Requests: 1"); + webRequest.UserAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0"; + webRequest.Referer=referer; + webRequest.KeepAlive = true; + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestCSV[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV2(String strRequest) + { + HttpWebResponse webResponse=null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestNoEncodingV2[ENTER]{0}",strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + webRequest.Timeout = REQUEST_TIMEOUT; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: None"); + webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"; + webRequest.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; + webRequest.KeepAlive = true; + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestNoEncodingV2[LEAVE]"); + } + } +// I am using this code specifically on the seeking alpha web site. it seems as though seeking alpha has implemeted some user agent based bot prevention mechanism on their website +// to prevent scrapers. What I do here is to choose from a set of commonly used user agents and then randomly choose a user agent to code into the request. retry logic up to 3 times +// and handling of 404 (not found) + public static HttpNetResponse GetRequestNoEncodingV3(String strRequest,String referer=null) + { + HttpWebResponse webResponse=null; + WebException lastWebException=null; + + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestNoEncodingV3[ENTER]{0}",strRequest)); + Random random=new Random(); + String[] userAgents= + { + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537." + }; + int MAX_RETRIES=5; + int TIMEOUT_BETWEEN_RETRIES=1000; + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + + for(int count=0;count=userAgents.Length) index=userAgents.Length-1; + String userAgent=userAgents[index]; + webRequest.UserAgent=userAgent; + + try + { + try{webResponse=(HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream=webResponse.GetResponseStream(); + if(webResponse.ContentEncoding.ToLower().Contains("gzip")) + { + responseStream=new GZipStream(responseStream,CompressionMode.Decompress); + StreamReader reader=new StreamReader(responseStream,Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else if(webResponse.ContentEncoding.ToLower().Contains("deflate")) + { + responseStream=new DeflateStream(responseStream,CompressionMode.Decompress); + StreamReader reader=new StreamReader(responseStream,Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else + { + while(true) + { + charCount=responseStream.Read(buffer,0,buffer.Length); + if(0==charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer,0,charCount)); + } + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,true); + } + catch(WebException webException) + { + if(webException.Message.Contains("(404) Not Found")) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + lastWebException=webException; + Thread.Sleep(TIMEOUT_BETWEEN_RETRIES); + } + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("General failure with {0}",lastWebException.Message)); + return new HttpNetResponse(webResponse,strRequest,false,lastWebException.Message); + } + catch(Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestNoEncodingV3A[LEAVE]"); + } + } + +// This one uses the random user agent generator + public static HttpNetResponse GetRequestNoEncodingV3B(String strRequest,CookieCollection cookieCollection=null,WebProxy webProxy=null) + { + HttpWebResponse webResponse=null; + WebException lastWebException=null; + ServicePointManager.Expect100Continue=true; +// ServicePointManager.SecurityProtocol=SecurityProtocolType.Ssl3|SecurityProtocolType.Tls12|SecurityProtocolType.Tls11|SecurityProtocolType.Tls; + + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestNoEncodingV3B[ENTER]{0}",strRequest)); + int MAX_RETRIES=5; + int TIMEOUT_BETWEEN_RETRIES=1000; + int charCount=0; + byte[] buffer=new byte[8192]; + StringBuilder sb=new StringBuilder(); + + for(int count=0;count=userAgents.Length) index=userAgents.Length-1; + String userAgent=userAgents[index]; + webRequest.UserAgent=userAgent; + + try + { + try{webResponse=(HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream=webResponse.GetResponseStream(); + if(webResponse.ContentEncoding.ToLower().Contains("gzip")) + { + responseStream=new GZipStream(responseStream,CompressionMode.Decompress); + StreamReader reader=new StreamReader(responseStream,Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else if(webResponse.ContentEncoding.ToLower().Contains("deflate")) + { + responseStream=new DeflateStream(responseStream,CompressionMode.Decompress); + StreamReader reader=new StreamReader(responseStream,Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else + { + while(true) + { + charCount=responseStream.Read(buffer,0,buffer.Length); + if(0==charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer,0,charCount)); + } + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,true); + } + catch(WebException webException) + { + if(webException.Message.Contains("(404) Not Found")) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + lastWebException=webException; + Thread.Sleep(TIMEOUT_BETWEEN_RETRIES); + } + } + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("General failure with {0}",lastWebException.Message)); + return new HttpNetResponse(webResponse,strRequest,false,lastWebException.Message); + } + catch(Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestNoEncodingV3C[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV4(String strRequest,CookieCollection cookieCollection=null,WebProxy webProxy=null) + { + HttpWebResponse webResponse=null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestNoEncodingV4[ENTER]{0}",strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy) webRequest.Proxy=webProxy; + webRequest.Timeout = REQUEST_TIMEOUT; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: None"); + webRequest.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; + webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MS-RTC LM 8; .NET4.0C; .NET4.0E; InfoPath.3)"; + webRequest.KeepAlive = true; + webRequest.CookieContainer=new CookieContainer(); + if(null!=cookieCollection)webRequest.CookieContainer.Add(cookieCollection); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,webResponse.Cookies,true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestNoEncodingV4[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV4A(String strRequest,CookieCollection cookieCollection=null,WebProxy webProxy=null) + { + HttpWebResponse webResponse=null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE,String.Format("GetRequestNoEncodingV4[ENTER]{0}",strRequest)); + int charCount=0; + byte[] buffer=new byte[8192]; + StringBuilder sb=new StringBuilder(); +// bool expect100Condition=ServicePointManager.Expect100Continue; +// SecurityProtocolType securityProtocolType=ServicePointManager.SecurityProtocol; + ServicePointManager.Expect100Continue=true; +// ServicePointManager.SecurityProtocol=SecurityProtocolType.Tls12; + HttpWebRequest webRequest=(HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.Timeout=REQUEST_TIMEOUT; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate, br"); + webRequest.Accept="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; + webRequest.UserAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0"; + webRequest.KeepAlive=true; + webRequest.CookieContainer=new CookieContainer(); + if(null!=cookieCollection) webRequest.CookieContainer.Add(cookieCollection); + try{webResponse=(HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream=webResponse.GetResponseStream(); + if(webResponse.ContentEncoding.ToLower().Contains("gzip")) + { + responseStream=new GZipStream(responseStream,CompressionMode.Decompress); + StreamReader reader=new StreamReader(responseStream,Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else + { + while(true) + { + charCount=responseStream.Read(buffer,0,buffer.Length); + if(0==charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer,0,charCount)); + } + } +// ServicePointManager.Expect100Continue=expect100Condition; +// ServicePointManager.SecurityProtocol=securityProtocolType; + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,webResponse.Cookies,true); + } + catch(WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response,strRequest,false,webException.Message); + } + catch(Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE,"GetRequestNoEncodingV4[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV5(String strRequest,int webRequestTimeoutMS,WebProxy webProxy=null) + { + HttpWebResponse webResponse = null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE, String.Format("GetRequestNoEncodingV5[ENTER]{0}", strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); +// bool expect100Condition = ServicePointManager.Expect100Continue; +// SecurityProtocolType securityProtocolType = ServicePointManager.SecurityProtocol; +// ServicePointManager.Expect100Continue = true; +// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.Timeout = webRequestTimeoutMS; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: None"); + webRequest.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; + webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MS-RTC LM 8; .NET4.0C; .NET4.0E; InfoPath.3)"; + webRequest.KeepAlive = true; + webRequest.CookieContainer = new CookieContainer(); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } +// ServicePointManager.Expect100Continue = expect100Condition; +// ServicePointManager.SecurityProtocol = securityProtocolType; + return new HttpNetResponse(sb.ToString(), strRequest, webResponse, webResponse.Cookies, true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse, strRequest, false, exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE, "GetRequestNoEncodingV5[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV5A(String strRequest,int webRequestTimeoutMS,WebProxy webProxy=null) + { + HttpWebResponse webResponse = null; + try + { + Random random = new Random(); + String[] userAgents= + { + "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0" + }; + + MDTrace.WriteLine(LogLevel.VERBOSE, String.Format("GetRequestNoEncodingV5A[ENTER]{0}", strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + // bool expect100Condition = ServicePointManager.Expect100Continue; + // SecurityProtocolType securityProtocolType = ServicePointManager.SecurityProtocol; + // ServicePointManager.Expect100Continue = true; + // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.Timeout = webRequestTimeoutMS; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: None"); + webRequest.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; + webRequest.KeepAlive = true; + webRequest.CookieContainer = new CookieContainer(); + double randomNumber=random.NextDouble(); // number between 0 and 1 + int index=(int)(randomNumber*((double)userAgents.Length)); + if(index>=userAgents.Length) index=userAgents.Length-1; + String userAgent=userAgents[index]; + webRequest.UserAgent=userAgent; + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + // ServicePointManager.Expect100Continue = expect100Condition; + // ServicePointManager.SecurityProtocol = securityProtocolType; + return new HttpNetResponse(sb.ToString(), strRequest, webResponse, webResponse.Cookies, true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse, strRequest, false, exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE, "GetRequestNoEncodingV5A[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV5B(String strRequest,int webRequestTimeoutMS,WebProxy webProxy=null,bool useRandomUserAgent=false,CookieCollection cookieCollection=null) + { + HttpWebResponse webResponse = null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE, String.Format("GetRequestNoEncodingV5B[ENTER]{0}", strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + // bool expect100Condition = ServicePointManager.Expect100Continue; + // SecurityProtocolType securityProtocolType = ServicePointManager.SecurityProtocol; + // ServicePointManager.Expect100Continue = true; + // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.Timeout = webRequestTimeoutMS; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: *"); + webRequest.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; + if (useRandomUserAgent) webRequest.UserAgent = UserAgent.GetInstance().GetUserAgent(); + else webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MS-RTC LM 8; .NET4.0C; .NET4.0E; InfoPath.3)"; + webRequest.KeepAlive = true; + webRequest.CookieContainer = new CookieContainer(); + if(null!=cookieCollection)webRequest.CookieContainer.Add(cookieCollection); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + // ServicePointManager.Expect100Continue = expect100Condition; + // ServicePointManager.SecurityProtocol = securityProtocolType; + return new HttpNetResponse(sb.ToString(), strRequest, webResponse, webResponse.Cookies, true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse, strRequest, false, exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE, "GetRequestNoEncodingV5B[LEAVE]"); + } + } + +// This accepts gzip and deflate which seems to work for the seeking alpha news retrieval + public static HttpNetResponse GetRequestNoEncodingV5C(String strRequest,String host,int webRequestTimeoutMS,WebProxy webProxy=null,bool useRandomUserAgent=false,CookieCollection cookieCollection=null) + { + HttpWebResponse webResponse = null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE, String.Format("GetRequestNoEncodingV5C[ENTER]{0}", strRequest)); + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + bool expect100Condition = ServicePointManager.Expect100Continue; + // SecurityProtocolType securityProtocolType = ServicePointManager.SecurityProtocol; + // ServicePointManager.Expect100Continue = true; + // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.Timeout = webRequestTimeoutMS; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate, br"); + webRequest.Host = host; + webRequest.Headers.Add("Sec-GPC: 1"); + webRequest.Headers.Add("Sec-Fetch-Dest: document"); + webRequest.Headers.Add("Sec-Fetch-Mode: navigate"); + webRequest.Headers.Add("Sec-Fetch-Site: none"); + webRequest.Headers.Add("Sec-Fetch-User: ?1"); + webRequest.Headers.Add("DNT: 1"); + webRequest.Headers.Add("Upgrade-Insecure-Requests: 1"); + webRequest.Headers.Add("TE: trailers"); + webRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"; + if (useRandomUserAgent) webRequest.UserAgent = UserAgent.GetInstance().GetUserAgent(); + else webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0"; + webRequest.KeepAlive = true; + webRequest.CookieContainer = new CookieContainer(); + if(null!=cookieCollection)webRequest.CookieContainer.Add(cookieCollection); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + HttpNetResponse httpNetResponse = ProcessWebResponse(strRequest, webResponse); + // ServicePointManager.Expect100Continue = expect100Condition; + // ServicePointManager.SecurityProtocol = securityProtocolType; + return httpNetResponse; + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse, strRequest, false, exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE, "GetRequestNoEncodingV5C[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV5D(String strRequest,String host,int webRequestTimeoutMS,WebProxy webProxy=null,bool useRandomUserAgent=false,CookieCollection cookieCollection=null) + { + HttpWebResponse webResponse = null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE, String.Format("GetRequestNoEncodingV5C[ENTER]{0}", strRequest)); + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + // bool expect100Condition = ServicePointManager.Expect100Continue; + // SecurityProtocolType securityProtocolType = ServicePointManager.SecurityProtocol; + // ServicePointManager.Expect100Continue = true; + // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.Timeout = webRequestTimeoutMS; + webRequest.KeepAlive=true; + webRequest.Headers.Add("Priority: u=0, i"); + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate, br, zstd"); + webRequest.Host = host; + webRequest.Headers.Add("Sec-GPC: 1"); + webRequest.Headers.Add("Sec-Fetch-Dest: document"); + webRequest.Headers.Add("Sec-Fetch-Mode: navigate"); + webRequest.Headers.Add("Sec-Fetch-Site: crosssite"); + webRequest.Headers.Add("Sec-Fetch-User: ?1"); + webRequest.Headers.Add("DNT: 1"); + webRequest.Headers.Add("Upgrade-Insecure-Requests: 1"); + webRequest.Headers.Add("TE: trailers"); + webRequest.Headers.Add("If-None-Match: "+"W/\"e76e3614af0e341af5df8daa8b855a4e\""); + webRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; + if (useRandomUserAgent) webRequest.UserAgent = UserAgent.GetInstance().GetUserAgent(); + else webRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36"; + webRequest.CookieContainer = new CookieContainer(); + if(null!=cookieCollection)webRequest.CookieContainer.Add(cookieCollection); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + HttpNetResponse httpNetResponse = ProcessWebResponse(strRequest, webResponse); + httpNetResponse.CookieCollection = new CookieCollection(); + httpNetResponse.CookieCollection.Add(webResponse.Cookies); + // ServicePointManager.Expect100Continue = expect100Condition; + // ServicePointManager.SecurityProtocol = securityProtocolType; + return httpNetResponse; + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse, strRequest, false, exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE, "GetRequestNoEncodingV5C[LEAVE]"); + } + } + + private static HttpNetResponse ProcessWebResponse(String strRequest,HttpWebResponse webResponse) + { + try + { + Stream responseStream = webResponse.GetResponseStream(); + StringBuilder sb = new StringBuilder(); + int charCount = 0; + byte[] buffer = new byte[8192]; + + if(webResponse.ContentEncoding.ToLower().Contains("gzip")) + { + responseStream = new GZipStream(responseStream, CompressionMode.Decompress); + StreamReader reader = new StreamReader(responseStream, Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else if(webResponse.ContentEncoding.ToLower().Contains("deflate")) + { + responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); + StreamReader reader = new StreamReader(responseStream, Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else + { + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + } + return new HttpNetResponse(sb.ToString(),strRequest,webResponse,true); + } + catch(Exception exception) + { + return new HttpNetResponse(webResponse,strRequest,false,exception.Message); + } + } + + public static HttpNetResponse GetRequestNoEncodingV6(String strRequest, int webRequestTimeoutMS) + { + HttpWebResponse webResponse = null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE, String.Format("GetRequestNoEncodingV6[ENTER]{0}", strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + // bool expect100Condition = ServicePointManager.Expect100Continue; + // SecurityProtocolType securityProtocolType = ServicePointManager.SecurityProtocol; + // ServicePointManager.Expect100Continue = true; + // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + webRequest.Timeout = webRequestTimeoutMS; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate, br"); + webRequest.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; + webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MS-RTC LM 8; .NET4.0C; .NET4.0E; InfoPath.3)"; + webRequest.KeepAlive = true; + webRequest.CookieContainer = new CookieContainer(); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + + Stream responseStream = webResponse.GetResponseStream(); + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + // ServicePointManager.Expect100Continue = expect100Condition; + // ServicePointManager.SecurityProtocol = securityProtocolType; + return new HttpNetResponse(sb.ToString(), strRequest, webResponse, webResponse.Cookies, true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse, strRequest, false, exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE, "GetRequestNoEncodingV6[LEAVE]"); + } + } + + public static HttpNetResponse GetRequestNoEncodingV7(String strRequest,WebProxy webProxy=null,CookieCollection cookieCollection=null) + { + HttpWebResponse webResponse = null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE, String.Format("GetRequestNoEncodingV7[ENTER]{0}", strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + bool expect100Condition = ServicePointManager.Expect100Continue; + // SecurityProtocolType securityProtocolType = ServicePointManager.SecurityProtocol; + // ServicePointManager.Expect100Continue = true; + // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + if(null!=webProxy)webRequest.Proxy=webProxy; + webRequest.KeepAlive=true; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate, br"); + webRequest.Headers.Add("Upgrade-Insecure-Requests: 1"); + webRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; + webRequest.UserAgent = " Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0"; + webRequest.KeepAlive = true; + webRequest.CookieContainer = new CookieContainer(); + if(null!=cookieCollection)webRequest.CookieContainer.Add(cookieCollection); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + Stream responseStream = webResponse.GetResponseStream(); + if (webResponse.ContentEncoding.ToLower().Contains("gzip")) + { + responseStream = new GZipStream(responseStream, CompressionMode.Decompress); + StreamReader reader = new StreamReader(responseStream, Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else if (webResponse.ContentEncoding.ToLower().Contains("deflate")) + { + responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); + StreamReader reader = new StreamReader(responseStream, Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else + { + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + } + // ServicePointManager.Expect100Continue = expect100Condition; + // ServicePointManager.SecurityProtocol = securityProtocolType; + return new HttpNetResponse(sb.ToString(), strRequest, webResponse, webResponse.Cookies, true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse, strRequest, false, exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE, "GetRequestNoEncodingV7[LEAVE]"); + } + } +// This is specifically taylored to Morningstar site for retrieval of historical data + public static HttpNetResponse GetRequestNoEncodingMStar(String strRequest,WebProxy webProxy=null) + { + HttpWebResponse webResponse = null; + try + { + MDTrace.WriteLine(LogLevel.VERBOSE, String.Format("GetRequestNoEncodingMStar[ENTER]{0}", strRequest)); + int charCount = 0; + byte[] buffer = new byte[8192]; + StringBuilder sb = new StringBuilder(); + // bool expect100Condition = ServicePointManager.Expect100Continue; + // SecurityProtocolType securityProtocolType = ServicePointManager.SecurityProtocol; + // ServicePointManager.Expect100Continue = true; + // ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(strRequest)); + webRequest.KeepAlive=true; + webRequest.Headers.Add("Accept-Language: en-US,en;q=0.5"); + webRequest.Headers.Add("Accept-Encoding: gzip, deflate, br"); + webRequest.Headers.Add("DNT: 1"); + webRequest.Headers.Add("Sec-Fetch-Dest:empty"); + webRequest.Headers.Add("Sec-Fetch-Mode:cors"); + webRequest.Headers.Add("Sec-Fetch-Site:same-site"); + webRequest.Headers.Add("X-SAL-ContentType:e7FDDltrTy+tA2HnLovvGL0LFMwT+KkEptGju5wXVTU="); + webRequest.Headers.Add("X-API-RequestId: d2ffea42-4a07-4fa7-fa0d-b307facd81fb"); + webRequest.Headers.Add("ApiKey:lstzFDEOhfFNMLikKa0am9mgEKLBl49T"); + webRequest.Accept = "*/*"; + webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"; + webRequest.Host="api-global.morningstar.com"; + webRequest.Referer="https://www.morningstar.com/stocks/xnas/aapl/performance"; + + if(null!=webProxy)webRequest.Proxy=webProxy; + + webRequest.CookieContainer = new CookieContainer(); + try{webResponse = (HttpWebResponse)webRequest.GetResponse();} + catch(WebException webException) + { + if(IsMovedException(webException)) + { + webRequest=Redirect(webRequest, webException); + webResponse=(HttpWebResponse)webRequest.GetResponse(); + } + else throw; + } + + Stream responseStream = webResponse.GetResponseStream(); + if (webResponse.ContentEncoding.ToLower().Contains("gzip")) + { + responseStream = new GZipStream(responseStream, CompressionMode.Decompress); + StreamReader reader = new StreamReader(responseStream, Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else if (webResponse.ContentEncoding.ToLower().Contains("deflate")) + { + responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); + StreamReader reader = new StreamReader(responseStream, Encoding.Default); + sb.Append(reader.ReadToEnd()); + reader.Close(); + } + else + { + while (true) + { + charCount = responseStream.Read(buffer, 0, buffer.Length); + if (0 == charCount) break; + sb.Append(Encoding.ASCII.GetString(buffer, 0, charCount)); + } + } + // ServicePointManager.Expect100Continue = expect100Condition; + // ServicePointManager.SecurityProtocol = securityProtocolType; + return new HttpNetResponse(sb.ToString(), strRequest, webResponse, webResponse.Cookies, true); + } + catch (WebException webException) + { + return new HttpNetResponse((HttpWebResponse)webException.Response, strRequest, false, webException.Message); + } + catch (Exception exception) + { + return new HttpNetResponse(webResponse, strRequest, false, exception.Message); + } + finally + { + if(null!=webResponse) + { + webResponse.Close(); + webResponse.Dispose(); + } + MDTrace.WriteLine(LogLevel.VERBOSE, "GetRequestNoEncodingMStar[LEAVE]"); + } + } + + private static HttpWebRequest Redirect(HttpWebRequest request, WebException webException) + { + if(!IsMovedException(webException))return null; + HttpWebResponse response = webException.Response as HttpWebResponse; + string locationUri = response.Headers["Location"]; + MDTrace.WriteLine(LogLevel.DEBUG,$"Request is being redirected to {locationUri}"); + Uri redirectUri = new Uri(locationUri); + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(redirectUri); + webRequest.Proxy=request.Proxy; + webRequest.Timeout = request.Timeout; + webRequest.Headers = request.Headers; + webRequest.Accept = request.Accept; + webRequest.UserAgent = request.UserAgent; + webRequest.KeepAlive = request.KeepAlive; + webRequest.CookieContainer = request.CookieContainer; + webRequest.Referer = request.Referer; + webRequest.Host = request.Host; + return webRequest; + } + + private static bool IsMovedException(WebException webException) + { + if(webException.Status.Equals(WebExceptionStatus.ProtocolError)) + { + HttpWebResponse response = webException.Response as HttpWebResponse; + if(response.StatusCode.Equals(HttpStatusCode.MovedPermanently)) + { + return true; + } + } + return false; + } + + /// + /// Get the proxy for the specified service or null if it is not congfigured to use the proxy + /// + ///The service name + public static WebProxy GetProxy(String serviceName) + { + try + { + String proxyAddress=GlobalConfig.Instance.Configuration["proxy_address"]; + if(null==proxyAddress) return null; + String useServiceProxy=ConfigurationManager.AppSettings["proxy_"+serviceName]; + if(null==useServiceProxy||false==bool.Parse(useServiceProxy)) return null; + String[] addressParts=proxyAddress.Split(':'); + SocketControl socketControl=null; + try + { + socketControl=new SocketControl(addressParts[1].Replace("//",null),int.Parse(addressParts[2])); + if(!socketControl.IsConnected())throw new Exception("Unreachable destination "+proxyAddress); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****** ERROR: CANNOT REACH PROXY {0} FOR SERVICE {1}...{2}",proxyAddress,serviceName,exception.ToString())); + return null; + } + socketControl.Close(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("USING PROXY:{0} FOR {1}",proxyAddress,serviceName)); + Uri newUri=new Uri(proxyAddress); + WebProxy proxy=new WebProxy(); + proxy.Address=newUri; + return proxy; + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetProxy: Exception:{0}",exception.ToString())); + return null; + } + } + + /// + /// Get the proxy. This is only to be used as part of unit tests to test out the TOR Proxy. User code should use the GetProxy(serviceName) variation + /// + public static WebProxy GetProxy() + { + String proxyAddress=GlobalConfig.Instance.Configuration["proxy_address"]; + String[] addressParts=proxyAddress.Split(':'); + SocketControl socketControl=null; + try + { + socketControl=new SocketControl(addressParts[1].Replace("//",null),int.Parse(addressParts[2])); + if(!socketControl.IsConnected())throw new Exception("Unreachable destination "+proxyAddress); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("****** ERROR: CANNOT REACH PROXY. {0} {1} ",proxyAddress,exception.ToString())); + return null; + } + socketControl.Close(); + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("USING PROXY:{0} ",proxyAddress)); + Uri newUri=new Uri(proxyAddress); + WebProxy proxy=new WebProxy(); + proxy.Address=newUri; + return proxy; + } + } +} diff --git a/MarketData/MarketDataLib/Integration/Network.cs b/MarketData/MarketDataLib/Integration/Network.cs new file mode 100755 index 0000000..6f21287 --- /dev/null +++ b/MarketData/MarketDataLib/Integration/Network.cs @@ -0,0 +1,92 @@ +using System.Net.NetworkInformation; + +namespace MarketData.Integration +{ + public class NetworkStatus + { + private NetworkStatus() + { + } + /// + /// Indicates whether any network connection is available + /// Filter connections below a specified speed, as well as virtual network cards. + /// + /// + /// true if a network connection is available; otherwise, false. + /// + public static bool IsNetworkAvailable() + { + return IsNetworkAvailable(0); + } + +// On Linux platforms we must be priveleged to send custom payloads so we are using the send option that does not require a payload +// This differs from the windows implementation + public static bool IsInternetConnected() + { + try + { + Ping myPing = new Ping(); + String host = "google.com"; + int timeout = 5000; + PingReply reply = myPing.Send(host, timeout); + + if (reply.Status == IPStatus.Success) + { + return true; + } + else if (reply.Status == IPStatus.TimedOut) + { + return true; + } + else + { + return false; + } + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,$"[Ping] {exception.ToString()}"); + return false; + } + } + /// + /// Indicates whether any network connection is available. + /// Filter connections below a specified speed, as well as virtual network cards. + /// + /// The minimum speed required. Passing 0 will not filter connection using speed. + /// + /// true if a network connection is available; otherwise, false. + /// + public static bool IsNetworkAvailable(long minimumSpeed) + { + if (!NetworkInterface.GetIsNetworkAvailable()) + return false; + + foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) + { + // discard because of standard reasons + if ((ni.OperationalStatus != OperationalStatus.Up) || + (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback) || + (ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel)) + continue; + + // this allow to filter modems, serial, etc. + // I use 10000000 as a minimum speed for most cases + if (ni.Speed < minimumSpeed) + continue; + + // discard virtual cards (virtual box, virtual pc, etc.) + if ((ni.Description.IndexOf("virtual", StringComparison.OrdinalIgnoreCase) >= 0) || + (ni.Name.IndexOf("virtual", StringComparison.OrdinalIgnoreCase) >= 0)) + continue; + + // discard "Microsoft Loopback Adapter", it will not show as NetworkInterfaceType.Loopback but as Ethernet Card. + if (ni.Description.Equals("Microsoft Loopback Adapter", StringComparison.OrdinalIgnoreCase)) + continue; + + return true; + } + return false; + } + } +} diff --git a/MarketData/MarketDataLib/Integration/SMSClient.cs b/MarketData/MarketDataLib/Integration/SMSClient.cs new file mode 100755 index 0000000..94bef57 --- /dev/null +++ b/MarketData/MarketDataLib/Integration/SMSClient.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Mail; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.Integration +{ + public class SMSClient + { + private SMSClient() + { + } + +// +// +// +// + public static void SendSMSEmail(string message, String from, String[] recipients,String smtpAddress,String userName,String password,int port=587) + { + String subject = string.Format("{0} {1}", message, DateTime.Now); + + try + { + if (!NetworkStatus.IsInternetConnected()) + { + MDTrace.WriteLine(LogLevel.DEBUG,"The internet is not connected. Cannot send SMSEmail."); + return; + } + MailMessage mailMessage = new MailMessage(); + mailMessage.From = new MailAddress(from); + mailMessage.Body = message; + mailMessage.Subject = subject; + mailMessage.IsBodyHtml = false; + foreach (String recipient in recipients) + { + mailMessage.To.Add(new MailAddress(recipient)); + } + SmtpClient smtpClient = new SmtpClient(smtpAddress,port); // smtp.gmail.com + smtpClient.UseDefaultCredentials = false; + smtpClient.Credentials = new System.Net.NetworkCredential(userName,password); // skessler1964@gmail.com MN5191306B + smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; + smtpClient.EnableSsl = true; + + smtpClient.Send(mailMessage); + smtpClient.Dispose(); + } + catch (System.Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + } + } + + public static void SendEmail(string message, String from, String[] recipients,String smtpAddress,String userName,String password,int port=587) + { + String subject = string.Format("{0} {1}", message, DateTime.Now); + + try + { + if (!NetworkStatus.IsInternetConnected()) + { + MDTrace.WriteLine(LogLevel.DEBUG,"The internet is not connected. Cannot send Email."); + return; + } + MailMessage mailMessage = new MailMessage(); + mailMessage.From = new MailAddress(from); + mailMessage.Body = message; + mailMessage.Subject = subject; + mailMessage.IsBodyHtml = false; + foreach (String recipient in recipients) + { + mailMessage.To.Add(new MailAddress(recipient)); + } + SmtpClient smtpClient = new SmtpClient(smtpAddress,port); // smtp.gmail.com + smtpClient.UseDefaultCredentials = false; + smtpClient.Credentials = new System.Net.NetworkCredential(userName,password); // skessler1964@gmail.com MN5191306B + smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; + smtpClient.EnableSsl = true; + + smtpClient.Send(mailMessage); + smtpClient.Dispose(); + } + catch (System.Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString()); + } + } + + + + } +} diff --git a/MarketData/MarketDataLib/Integration/Socket.cs b/MarketData/MarketDataLib/Integration/Socket.cs new file mode 100755 index 0000000..c4d588b --- /dev/null +++ b/MarketData/MarketDataLib/Integration/Socket.cs @@ -0,0 +1,548 @@ +using System; +using System.Collections; +using System.Net.Sockets; +using System.Diagnostics; +using System.Net; +using System.IO; +using System.Text; + +// Filename: Socket.cs +// Author:Sean Kessler + +namespace MarketData.Integration +{ + internal class ContentHeader + { + private String server; + private String date; + private String pragma; + private String connection; + private String contentLength; + private String contentType; + private String cookie; + private String cache; + + public ContentHeader() + { + } + public String Server + { + get { return server; } + set { server = value; } + } + public String Date + { + get { return date; } + set { date = value; } + } + public String Pragma + { + get { return pragma; } + set { pragma = value; } + } + public String Connection + { + get { return connection; } + set { connection = value; } + } + public String ContentLength + { + get { return contentLength; } + set { contentLength = value; } + } + public String ContentType + { + get { return contentType; } + set { contentType = value; } + } + public String Cookie + { + get { return cookie; } + set { cookie = value; } + } + public String Cache + { + get { return cache; } + set { cache = value; } + } + } + public class SocketConnector : TcpClient + { + public SocketConnector(Socket serverSocket) + { + Client = serverSocket; + } + } + public class ServerSocketControl + { + private Socket acceptSocket; + private IPEndPoint ipLocalEndPoint; + + public ServerSocketControl(int port) + { + int index; + acceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + acceptSocket.ReceiveTimeout = -1; + IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName()); + IPAddress ipAddress = null; + for (index = 0; index < hostEntry.AddressList.Length; index++) + { + if (IPAddress.TryParse(hostEntry.AddressList[index].ToString(), out ipAddress)) + { + switch (ipAddress.AddressFamily) + { + case System.Net.Sockets.AddressFamily.InterNetwork: + break; + case System.Net.Sockets.AddressFamily.InterNetworkV6: + ipAddress = null; + break; + default: + ipAddress = null; + break; + } + if (null != ipAddress) break; + } + } + if (null == ipAddress) throw new Exception("Could not determine IPV4 address."); + ipLocalEndPoint = new IPEndPoint(ipAddress, port); + SocketControl.TraceOut("[ServerSocketControl] Binding to endpoint " + ipLocalEndPoint); + acceptSocket.Bind(ipLocalEndPoint); + SocketControl.TraceOut("[ServerSocketControl] socket bound"); + acceptSocket.Listen(-1); + } + public ServerSocketControl() + { + int index; + acceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + acceptSocket.ReceiveTimeout = -1; + IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName()); + IPAddress ipAddress = null; + for (index = 0; index < hostEntry.AddressList.Length; index++) + { + if (IPAddress.TryParse(hostEntry.AddressList[index].ToString(), out ipAddress)) + { + switch (ipAddress.AddressFamily) + { + case System.Net.Sockets.AddressFamily.InterNetwork: + break; + case System.Net.Sockets.AddressFamily.InterNetworkV6: + ipAddress = null; + break; + default: + ipAddress = null; + break; + } + if (null != ipAddress) break; + } + } + if (null == ipAddress) throw new Exception("Could not determine IPV4 address."); + ipLocalEndPoint = new IPEndPoint(ipAddress, 0); + SocketControl.TraceOut("[ServerSocketControl] Binding to endpoint " + ipLocalEndPoint); + acceptSocket.Bind(ipLocalEndPoint); + SocketControl.TraceOut("[ServerSocketControl] socket bound"); + acceptSocket.Listen(-1); + ipLocalEndPoint = (IPEndPoint)acceptSocket.LocalEndPoint; + } + public IPEndPoint LocalEndPoint() + { + return ipLocalEndPoint; + } + public IPAddress Address() + { + return ipLocalEndPoint.Address; + } + public int Port() + { + return ipLocalEndPoint.Port; + } + public void Close() + { + if (null == acceptSocket) return; + acceptSocket.Shutdown(SocketShutdown.Both); + acceptSocket.Close(); + acceptSocket = null; + } + public SocketControl Accept() + { + Socket socket = acceptSocket.Accept(); + ipLocalEndPoint = (IPEndPoint)socket.LocalEndPoint; + SocketControl.TraceOut("[ServerSocketControl::Accept] connect accepted on " + ipLocalEndPoint); + SocketConnector socketConnector = new SocketConnector(socket); + return new SocketControl(socketConnector); + } + } + public class SocketControl + { + public const int OkResult = 220; + public const int ErrorResult = 500; + private TcpClient tcpClient; + private NetworkStream networkStream; + private BinaryWriter binaryWriter; + private BinaryReader binaryReader; + + private bool isConnected = false; + + public SocketControl(SocketConnector socketConnector) + { + tcpClient = socketConnector; + tcpClient.LingerState = new LingerOption(false, 0); + tcpClient.ReceiveTimeout = -1; + networkStream = tcpClient.GetStream(); + binaryWriter = new BinaryWriter(networkStream); + binaryReader = new BinaryReader(networkStream); + isConnected = true; + } + public SocketControl(String strHost, int port) + { + tcpClient = new TcpClient(); + tcpClient.Connect(strHost, port); + tcpClient.LingerState = new LingerOption(false, 0); + tcpClient.ReceiveTimeout = -1; + networkStream = tcpClient.GetStream(); + binaryWriter = new BinaryWriter(networkStream); + binaryReader = new BinaryReader(networkStream); + isConnected = true; + } + public void Close() + { + if (!isConnected) return; + isConnected = false; + binaryWriter.Close(); + binaryWriter = null; + binaryReader.Close(); + binaryReader = null; + tcpClient.Close(); + tcpClient = null; + } + public string ReadLine() + { + StringBuilder strLine = new StringBuilder(); + if (!isConnected) return null; + byte[] streamByte = new byte[1]; + while (true) + { + binaryReader.Read(streamByte, 0, 1); + if (13 == streamByte[0]) continue; + else if (10 == streamByte[0]) break; + else if ('\0' == (char)streamByte[0]) break; + strLine.Append((char)streamByte[0]); + streamByte[0] = 0; + } + return strLine.ToString(); + } + public bool WriteLine(string strLine) + { + if (!isConnected || 0 == strLine.Length) return false; + strLine += "\r\n"; + char[] streamData = strLine.ToCharArray(); + binaryWriter.Write(streamData); + binaryWriter.Flush(); + return true; + } + public int GetResultCode(string strLine) + { + if (0 == strLine.Length) return 0; + string strResult = ""; + int strIndex = 0; + while (true) + { + if (strIndex >= 3) break; + if (' ' == strLine[strIndex]) break; + strResult += strLine[strIndex]; + strIndex++; + } + if (0 == strResult.Length) return 0; + return int.Parse(strResult); + } + public string GetResult(string strLine) + { + string strResult = ""; + int strIndex = 0; + int strLength = strLine.Length; + if (0 == strLength) return strResult; + while (' ' != strLine[strIndex] && strIndex < strLength) strIndex++; + strIndex++; + if (strIndex >= strLength) return strResult; + while (strIndex < strLength) + { + strResult += strLine[strIndex]; + strIndex++; + } + return strResult; + } + public char[] GetRequest(string strRequest, int max) + { + if (!isConnected || null == strRequest || 0 == max) return null; + WriteLine("GET " + strRequest); + return Receive(max); + } + public MemoryStream GetRequest(string strRequest) + { + if (!isConnected || null == strRequest) return null; + WriteLine("GET " + strRequest); + return Receive(); + } + public String GetRequestToString(String strRequest) + { + if (!isConnected || null == strRequest) return null; + WriteLine("GET " + strRequest); + MemoryStream memoryStream = Receive(); + memoryStream.Seek(0, SeekOrigin.Begin); + StreamReader streamReader = new StreamReader(memoryStream); + String strResponse = streamReader.ReadToEnd(); + streamReader.Close(); + memoryStream.Close(); + return strResponse; + } + public bool Write(char[] chars) + { + if (!isConnected || null == chars || 0 == chars.Length) return false; + binaryWriter.Write(chars); + binaryWriter.Flush(); + return true; + } + public bool Write(byte[] bytes) + { + if (!isConnected || null == bytes || 0 == bytes.Length) return false; + binaryWriter.Write(bytes); + binaryWriter.Flush(); + return true; + } + public bool Write(byte[] bytes, int length) + { + if (!isConnected || null == bytes || 0 == bytes.Length) return false; + binaryWriter.Write(bytes, 0, length); + binaryWriter.Flush(); + return true; + } + public int ReadInt() + { + char[] chars = new char[4]; + Receive(chars); + return (((byte)chars[3]) << 24) | (((byte)chars[2]) << 16) + (((byte)chars[1]) << 8) + ((byte)chars[0]); + } + public bool IsConnected() + { + return isConnected; + } + public bool Receive(char[] streamChars) + { + byte[] cb; + int count = 0; + int max; + int readCount; + + max = streamChars.Length; + if (!isConnected || 0 == max) return false; + cb = new byte[1]; + while (true) + { + readCount = binaryReader.Read(cb, 0, 1); + if (0 == readCount) break; + streamChars[count++] = (char)cb[0]; + if (count >= max) break; + } + return count == max; + } + public int Receive(ref byte[] streamBytes) + { + int count = 0; + int max; + int readLength = 0; + + max = streamBytes.Length; + if (!isConnected || 0 == max) return count; + while (true) + { + readLength = binaryReader.Read(streamBytes, count, max - count); + if (0 == readLength) break; + count += readLength; + if (count >= max) break; + } + if (0 == count) return count; + byte[] stream = new byte[count]; + Array.Copy(streamBytes, stream, count); + streamBytes = stream; + return count; + } + public char[] Receive(int maxChars) + { + char[] streamChar; + char[] stream; + byte[] cb; + int count = 0; + int readCount = 0; + + if (!isConnected || 0 == maxChars) return null; + streamChar = new char[maxChars]; + while (true) + { + cb = new byte[1]; + readCount = binaryReader.Read(cb, 0, 1); + if (0 == readCount) break; + streamChar[count++] = (char)cb[0]; + if (count >= maxChars) break; + } + stream = new char[count]; + Array.Copy(streamChar, stream, count); + return stream; + } + public MemoryStream Receive() + { + MemoryStream memoryStream = new MemoryStream(); + byte[] cb; + int readCount = 0; + + if (!isConnected) return null; + while (true) + { + cb = new byte[1]; + readCount = binaryReader.Read(cb, 0, 1); + if (0 == readCount) break; + memoryStream.WriteByte(cb[0]); + } + memoryStream.Seek(0, SeekOrigin.Begin); + return memoryStream; + } + public bool Receive(ArrayList receiveStrings, ArrayList responseStrings) + { + bool isInMultiLine = false; + bool returnCode = true; + string seriesItem = ""; + string stringData = ""; + + receiveStrings.Clear(); + if (!isConnected) return false; + while (true) + { + stringData = ReadLine(); + if (null == stringData || 0 == stringData.Length) break; + if (0 == receiveStrings.Count) + { + seriesItem = stringData.Substring(0, 3); + if (!IsInResponse(seriesItem, responseStrings)) + { + returnCode = false; + receiveStrings.Add(stringData); + break; + } + if ('-' == stringData[3]) isInMultiLine = true; + } + if (0 != receiveStrings.Count && isInMultiLine && '-' != stringData[3] && + stringData.Substring(0, 3).Equals(seriesItem)) + { + receiveStrings.Add(stringData); + break; + } + receiveStrings.Add(stringData); + if (!isInMultiLine) break; + } + return returnCode; + } + public bool Receive(ArrayList receiveStrings) + { + bool isInMultiLine = false; + string seriesItem = ""; + string stringData = ""; + + receiveStrings.Clear(); + if (!isConnected) return false; + while (true) + { + stringData = ReadLine(); + if (null == stringData || 0 == stringData.Length) break; + if (0 == receiveStrings.Count) + { + seriesItem = stringData.Substring(0, 3); + try { if ('-' == stringData[3])isInMultiLine = true; } + catch (Exception) { ;} + } + if (0 != receiveStrings.Count && isInMultiLine && '-' != stringData[3] && + stringData.Substring(0, 3).Equals(seriesItem)) + { + receiveStrings.Add(stringData); + break; + } + receiveStrings.Add(stringData); + if (!isInMultiLine) break; + } + if (0 != receiveStrings.Count) return true; + return false; + } + public bool ReceivePage(ArrayList stringArray) + { + string stringData = ""; + int reps = 0; + + stringArray.Clear(); + if (!isConnected) return false; + while (true) + { + stringData = ReadLine(); + if (null == stringData || 0 == stringData.Length) reps++; + else + { + stringArray.Add(stringData); + reps = 0; + } + if (2 == reps) break; + } + return 0 != stringArray.Count ? true : false; + } + public MemoryStream ReceivePage() + { + MemoryStream memoryStream; + ContentHeader contentHeader; + + contentHeader = ReadContentHeader(); + byte[] bytes = new byte[int.Parse(contentHeader.ContentLength)]; + Receive(ref bytes); + memoryStream = new MemoryStream(bytes); + return memoryStream; + } + public bool IsInResponse(string responseString, ArrayList responseStrings) + { + if (0 == responseStrings.Count) return false; + for (int index = 0; index < responseStrings.Count; index++) + { + if (responseString.Equals((string)responseStrings[index])) return true; + } + return false; + } + private ContentHeader ReadContentHeader() + { + ContentHeader contentHeader; + String stringLine; + String token; + String value; + + contentHeader = new ContentHeader(); + while (true) + { + stringLine = ReadLine(); + if (null == stringLine || 0 == stringLine.Length) break; + String[] elements = stringLine.Split(':'); + if (2 != elements.Length) continue; + token = elements[0].Trim().ToUpper(); + value = elements[1].Trim().ToUpper(); + if ("SERVER".Equals(token)) contentHeader.Server = value; + else if ("DATE".Equals(token)) contentHeader.Date = value; + else if ("PRAGMA".Equals(token)) contentHeader.Pragma = value; + else if ("CACHE-CONTROL".Equals(token)) contentHeader.Cache = value; + else if ("CONNECTION".Equals(token)) contentHeader.Connection = value; + else if ("CONTENT-LENGTH".Equals(token)) contentHeader.ContentLength = value; + else if ("CONTENT-TYPE".Equals(token)) contentHeader.ContentType = value; + else if ("SET-COOKIE".Equals(token)) contentHeader.Cookie = value; + } + return contentHeader; + } + [Conditional("TRACENET")] + public static void TraceOut(String strLine) + { + String strThread = "[Thread=" + System.Threading.Thread.CurrentThread.GetHashCode() + "]"; + String strDate = "[" + DateTime.Now.ToString() + "]"; + Trace.WriteLine(strThread + "[]" + strDate + strLine); + } + } +} + diff --git a/MarketData/MarketDataLib/Integration/UserAgent.cs b/MarketData/MarketDataLib/Integration/UserAgent.cs new file mode 100755 index 0000000..4a30e1a --- /dev/null +++ b/MarketData/MarketDataLib/Integration/UserAgent.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.Integration +{ + public class UserAgent + { + private static UserAgent instance=null; + private String[] userAgents= + { + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.3 24.31", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3.1 Safari/605.1.1 23.33", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Safari/605.1.1 14.12", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.3 13.92", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0. 3.92", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Agency/93.8.2357.5 3.92", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 OPR/107.0.0. 3.92", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.3 3.92", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123. 3.14", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103. 1.57", + "Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.3 0.78", + "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115. 0.78", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Viewer/99.9.8853.8 0.78", + "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115. 0.78", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.3 0.78" + }; + + private Random random=new Random(); + private UserAgent() + { + } + public static UserAgent GetInstance() + { + lock(typeof(UserAgent)) + { + if(null==instance) instance=new UserAgent(); + return instance; + } + } + public String GetUserAgent() + { + lock(this) + { + double randomNumber=random.NextDouble(); // number between 0 and 1 + int index=(int)(randomNumber*((double)userAgents.Length)); + return userAgents[index]; + } + } + } + +} diff --git a/MarketData/MarketDataLib/MDTrace.cs b/MarketData/MarketDataLib/MDTrace.cs new file mode 100755 index 0000000..1f8bfc3 --- /dev/null +++ b/MarketData/MarketDataLib/MDTrace.cs @@ -0,0 +1,159 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Text; +using System.Reflection; +//using System.Runtime.Remoting.Messaging; + +// Filename: MarketDataTrace.cs +// Author:Sean Kessler +// Date:11/2005 + +namespace MarketData +{ + public enum LogLevel : uint + { + NONE=0x0000, + INFO=0x0002, + DEBUG=0x0004, + VERBOSE=0x0008 + }; +/// MarketDataTrace - Utility for . + public class MDTrace + { + private static LogLevel logLevel=LogLevel.DEBUG; + +/// MarketDataTrace - Private constructor prevents instantiation. +/// none + private MDTrace() + { + } + +/// LogLevel - Get/Set Log level. +/// The log level. +/// LogLevel + public static LogLevel LogLevel + { + get{return logLevel;} + set{logLevel=value;} + } +/// WriteLine - Writes a line of text to trace log. +/// string content of message to write. +/// void +// [Conditional("TRACE")] + public static void Write(LogLevel logLevel,string message) + { + if(MDTrace.logLevelWriteLine - Writes a line of text to trace log. +/// string content of message to write. +/// void +// [Conditional("TRACE")] + public static void WriteLine(string message) + { + WriteLine(LogLevel.DEBUG,GetCallerIP()+GetThreadRep()+GetLogLevelRep()+"["+DateTime.Now.ToString()+"]"+" "+GetMethodInfo()+message); + Console.WriteLine(message); + } +/// WriteLine - Writes a line of text to trace log. +/// string content of message to write. +/// void +// [Conditional("TRACE")] + public static void WriteLine(LogLevel logLevel,Exception exception) + { + if(MDTrace.logLevelWriteLine - Writes a line of text to trace log. +/// string content of message to write. +/// void +// [Conditional("TRACE")] + public static void WriteLine(LogLevel logLevel,string message) + { + if(MDTrace.logLevelIndent - set trace log indentation. +/// void +// [Conditional("TRACE")] + public static void Indent() + { + Trace.Indent(); + } +/// Unindent - set trace log indentation back. +/// void +// [Conditional("TRACE")] + public static void Unindent() + { + Trace.Unindent(); + } +/// Flush - Flush trace log buffers to disk. +/// void +// [Conditional("TRACE")] + public static void Flush() + { + Trace.Flush(); + } +/// GetLogLevel - Return current log level. +/// LogLevel + public static LogLevel GetLogLevel(String strLogLevel) + { + if(strLogLevel.Equals("debug"))return LogLevel.DEBUG; + else if(strLogLevel.Equals("verbose"))return LogLevel.VERBOSE; + else if(strLogLevel.Equals("info"))return LogLevel.INFO; + else return LogLevel.NONE; + } + +/// GetLogLevel - Return current log level. +/// LogLevel + private static string GetLogLevelRep() + { + if (MDTrace.logLevel == LogLevel.DEBUG) return "[TRACE.DEBUG]"; + else if (MDTrace.logLevel == LogLevel.VERBOSE) return "[TRACE.VERBOSE]"; + else if (MDTrace.logLevel == LogLevel.INFO) return "[TRACE.INFO]"; + else return "[TRACE.NONE]"; + } +/// GetThreadRep - Return threading information. +/// LogLevel + private static string GetThreadRep() + { + return "[Thread="+Thread.CurrentThread.GetHashCode()+"]"; + } +/// GetMethodInfo - Returns information about the calling method 2 frames up. +/// String + private static String GetMethodInfo() + { + StringBuilder sb=new StringBuilder(); + StackFrame frame=new StackFrame(2,true); + MethodBase methodBase=frame.GetMethod(); + ParameterInfo[] parameters=methodBase.GetParameters(); + sb.Append("[").Append(methodBase.DeclaringType.FullName).Append("::").Append(methodBase.Name).Append("("); + for(int index=0;indexGetCallerIP - Returns the calling methods IP address. +/// String + private static String GetCallerIP() + { + return "[LOCAL]"; + // String hostName=(String)CallContext.GetData("HostName"); + // String hostAddress=(String)CallContext.GetData("HostAddress"); + // if(null!=hostName)hostName=hostName.Split('.')[0]; + // if(null==hostName && null==hostAddress)return "[LOCAL]"; + // return "["+hostAddress+"->"+hostName+"]"; + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataLib.csproj b/MarketData/MarketDataLib/MarketDataLib.csproj new file mode 100755 index 0000000..e4ff123 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataLib.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + disable + CA1416;CS8769;CS0108;CS8602;CS8601;CS8620;CS8618;CS8603;CS8767;CS8625;CS8604;CS8600;CS8604 + + + + ..\assemblies\HtmlAgilityPack.dll + + + + + + + + + + + diff --git a/MarketData/MarketDataLib/MarketDataModel/AnalystPriceTarget.cs b/MarketData/MarketDataLib/MarketDataModel/AnalystPriceTarget.cs new file mode 100755 index 0000000..9b2fefa --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/AnalystPriceTarget.cs @@ -0,0 +1,76 @@ +using System; +using System.Text; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class AnalystPriceTarget + { + private DateTime date; + private String symbol; + private double meanTargetPrice; + private double medianTargetPrice; + private double highTargetPrice; + private double lowTargetPrice; + + public AnalystPriceTarget() + { + } + public DateTime Date + { + get { return date; } + set { date = value; } + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public double MeanTargetPrice + { + get { return meanTargetPrice; } + set { meanTargetPrice = value; } + } + public double MedianTargetPrice + { + get { return medianTargetPrice; } + set { medianTargetPrice = value; } + } + public double HighTargetPrice + { + get { return highTargetPrice; } + set { highTargetPrice = value; } + } + public double LowTargetPrice + { + get { return lowTargetPrice; } + set { lowTargetPrice = value; } + } + public static String Header + { + get + { + StringBuilder sb = new StringBuilder(); + sb.Append("Date").Append(","); + sb.Append("Symbol").Append(","); + sb.Append("MeanTargetPrice").Append(","); + sb.Append("MedianTargetPrice").Append(","); + sb.Append("HighTargetPrice").Append(","); + sb.Append("LowTargetPrice"); + return sb.ToString(); + } + } + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(Symbol).Append(","); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(Date)).Append(","); + sb.Append(symbol).Append(","); + sb.Append(String.Format("{0:0.00}", MeanTargetPrice)).Append(","); + sb.Append(String.Format("{0:0.00}", MedianTargetPrice)).Append(","); + sb.Append(String.Format("{0:0.00}", HighTargetPrice)).Append(","); + sb.Append(String.Format("{0:0.00}", LowTargetPrice)); + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/MarketDataModel/AnalystRatings.cs b/MarketData/MarketDataLib/MarketDataModel/AnalystRatings.cs new file mode 100755 index 0000000..bfbf05e --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/AnalystRatings.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class AnalystRatings : List + { + public AnalystRatings() + { + } + public AnalystRatings(List analystRatings) + { + foreach(AnalystRating analystRating in analystRatings)Add(analystRating); + } + public List Symbols + { + get { return (from analystRating in this select analystRating.Symbol).ToList(); } + } + public void Remove(List symbols) + { + for (int index = 0; index < symbols.Count; index++) + { + this.RemoveAll(x => x.Symbol.Equals(symbols[index])); + } + } + public void CalculateUpdatePercentiles() + { + double totalCount=1; + double upgradeCount=0; + for(int index=this.Count-1;index>=0;index--,totalCount++) + { + AnalystRating analystRating=this[index]; + if(analystRating.Type.Equals("Upgrades")&&!analystRating.RatingsChange.Contains("Sell"))upgradeCount++; + analystRating.UpgradePercentile=(upgradeCount/totalCount)*100.00; + } + } + } + public class AnalystRating + { + private DateTime date; + private String symbol; + private String brokerageFirm; + private String type; + private String ratingsChange; + private double priceTarget; + private String companyName; + private double upgradePercentile; + + public AnalystRating() + { + } + public DateTime Date + { + get { return date; } + set { date = value; } + } + public String Symbol + { + get { return symbol; } + set { symbol = value.Trim(); } + } + public String CompanyName + { + get { return companyName; } + set { companyName = value; } + } + public String BrokerageFirm + { + get { return brokerageFirm; } + set { brokerageFirm=value; } + } + public String Type + { + get { return type; } + set { type = value; } + } + public String RatingsChange + { + get { return ratingsChange; } + set { ratingsChange = value; } + } + public double PriceTarget + { + get { return priceTarget; } + set { priceTarget = value; } + } + public double UpgradePercentile + { + get{return upgradePercentile;} + set{upgradePercentile=value;} + + } + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(Symbol).Append(","); + sb.Append(CompanyName).Append(","); + sb.Append(BrokerageFirm).Append(","); + sb.Append(Type).Append(","); + sb.Append(RatingsChange).Append(","); + sb.Append(Utility.FormatCurrency(PriceTarget)); + return sb.ToString(); + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/BalanceSheet.cs b/MarketData/MarketDataLib/MarketDataModel/BalanceSheet.cs new file mode 100755 index 0000000..d76243d --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/BalanceSheet.cs @@ -0,0 +1,209 @@ +using System; +using System.Text; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class BalanceSheet + { + public enum PeriodType { Annual = 0, Quarterly = 1 } + private String symbol; + private DateTime asof; + private double longTermDebt; + private double otherLiabilities; + private double deferredLongTermLiabilities; + private double minorityInterest; + private double negativeGoodwill; + private double goodwill; + private double totalStockHolderEquity; + private double inventory; + private double propertyPlantAndEquipment; + private double intangibleAssets; + private double accumulatedAmortization; + private double totalAssets; + private double totalCurrentAssets; + private double totalLiabilities; + private double totalCurrentLiabilities; + private double cashAndCashEquivalents; + private PeriodType period; + private DateTime modified; + + public BalanceSheet() + { + } +// It is appropriate to use the AsOf date in the comparison of the financial statements because the AsOf date is the statement date. + public void MergeFrom(BalanceSheet previousBalanceSheet) + { + if(null==previousBalanceSheet)return; + if(!Symbol.Equals(previousBalanceSheet.Symbol))return; + if(!AsOf.Date.Equals(previousBalanceSheet.AsOf.Date))return; + if(!Period.Equals(previousBalanceSheet.Period))return; + if(Utility.IsZeroOrNaN(LongTermDebt))LongTermDebt=previousBalanceSheet.LongTermDebt; + if(Utility.IsZeroOrNaN(OtherLiabilities))OtherLiabilities=previousBalanceSheet.OtherLiabilities; + if(Utility.IsZeroOrNaN(DeferredLongTermLiabilities))DeferredLongTermLiabilities=previousBalanceSheet.DeferredLongTermLiabilities; + if(Utility.IsZeroOrNaN(MinorityInterest))MinorityInterest=previousBalanceSheet.MinorityInterest; + if(Utility.IsZeroOrNaN(NegativeGoodwill))NegativeGoodwill=previousBalanceSheet.NegativeGoodwill; + if(Utility.IsZeroOrNaN(Goodwill))Goodwill=previousBalanceSheet.Goodwill; + if(Utility.IsZeroOrNaN(TotalStockHolderEquity))TotalStockHolderEquity=previousBalanceSheet.TotalStockHolderEquity; + if(Utility.IsZeroOrNaN(Inventory))Inventory=previousBalanceSheet.Inventory; + if(Utility.IsZeroOrNaN(PropertyPlantAndEquipment))PropertyPlantAndEquipment=previousBalanceSheet.PropertyPlantAndEquipment; + if(Utility.IsZeroOrNaN(IntangibleAssets))IntangibleAssets=previousBalanceSheet.IntangibleAssets; + if(Utility.IsZeroOrNaN(AccumulatedAmortization))AccumulatedAmortization=previousBalanceSheet.AccumulatedAmortization; + if(Utility.IsZeroOrNaN(TotalAssets))TotalAssets=previousBalanceSheet.TotalAssets; + if(Utility.IsZeroOrNaN(TotalCurrentAssets))TotalCurrentAssets=previousBalanceSheet.TotalCurrentAssets; + if(Utility.IsZeroOrNaN(TotalLiabilities))TotalLiabilities=previousBalanceSheet.TotalLiabilities; + if(Utility.IsZeroOrNaN(TotalCurrentLiabilities))TotalCurrentLiabilities=previousBalanceSheet.TotalCurrentLiabilities; + if(Utility.IsZeroOrNaN(CashAndCashEquivalents))CashAndCashEquivalents=previousBalanceSheet.CashAndCashEquivalents; + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public DateTime AsOf + { + get { return asof; } + set { asof = value; } + } + public double CashAndCashEquivalents + { + get { return cashAndCashEquivalents; } + set { cashAndCashEquivalents = value; } + } + public double LongTermDebt + { + get { return longTermDebt; } + set { longTermDebt = value; } + } + public double OtherLiabilities + { + get { return otherLiabilities; } + set { otherLiabilities = value; } + } + public double DeferredLongTermLiabilities + { + get { return deferredLongTermLiabilities; } + set { deferredLongTermLiabilities = value; } + } + public double MinorityInterest + { + get { return minorityInterest; } + set { minorityInterest = value; } + } + public double Goodwill + { + get { return goodwill; } + set { goodwill = value; } + } + public double NegativeGoodwill + { + get { return negativeGoodwill; } + set { negativeGoodwill = value; } + } + public double TotalStockHolderEquity + { + get { return totalStockHolderEquity; } + set { totalStockHolderEquity=value; } + } + public PeriodType Period + { + get { return period; } + set { period = value; } + } + public double Inventory + { + get { return inventory; } + set { inventory = value; } + } + public double PropertyPlantAndEquipment + { + get { return propertyPlantAndEquipment; } + set { propertyPlantAndEquipment = value; } + } + public double IntangibleAssets + { + get { return intangibleAssets; } + set { intangibleAssets = value; } + } + public double AccumulatedAmortization + { + get { return accumulatedAmortization; } + set { accumulatedAmortization=value; } + } + public String PeriodAsString + { + get { return PeriodType.Quarterly.Equals(period) ? "Quarterly" : "Annual"; } + } + public double TotalAssets + { + get{return totalAssets;} + set{totalAssets=value;} + } + public double TotalCurrentAssets + { + get{return totalCurrentAssets;} + set{totalCurrentAssets=value;} + } + public double TotalLiabilities + { + get{return totalLiabilities;} + set{totalLiabilities=value;} + } + public double TotalCurrentLiabilities + { + get{return totalCurrentLiabilities;} + set{totalCurrentLiabilities=value;} + } + public double NetCurrentAssetValue + { + get{return TotalCurrentAssets-TotalLiabilities;} + } + public double NetFixedAssets + { + get + { + if(double.IsNaN(TotalAssets)||double.IsNaN(TotalCurrentAssets)||double.IsNaN(Goodwill))return double.NaN; + return TotalAssets-TotalCurrentAssets-Goodwill; + } + } + public DateTime Modified + { + get { return modified; } + set { modified = value; } + } + + public static String Heading + { + get + { + StringBuilder sb = new StringBuilder(); + sb.Append("Symbol,AsOf,LongTermDebt,OtherLiabilities,DeferredLongTermLiabilities,MinorityInterest,NegativeGoodwill,TotalStockHolderEquity,Inventory,PP&E,IntangibleAssets,AccumulatedAmortization,Period,TotalAssets,TotalCurrentAssets,TotalLiabilities,TotalCurrentLiabilities,CashAndCashEquivalents,NetCurrentAssetValue"); + return sb.ToString(); + } + } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(symbol).Append(","); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(asof)).Append(","); + sb.Append(String.Format("{0:C}", LongTermDebt)).Append(","); + sb.Append(String.Format("{0:C}", OtherLiabilities)).Append(","); + sb.Append(String.Format("{0:C}", DeferredLongTermLiabilities)).Append(","); + sb.Append(String.Format("{0:C}", MinorityInterest)).Append(","); + sb.Append(String.Format("{0:C}", NegativeGoodwill)).Append(","); + sb.Append(String.Format("{0:C}", TotalStockHolderEquity)).Append(","); + sb.Append(String.Format("{0:C}", Inventory)).Append(","); + sb.Append(String.Format("{0:C}", PropertyPlantAndEquipment)).Append(","); + sb.Append(String.Format("{0:C}", IntangibleAssets)).Append(","); + sb.Append(String.Format("{0:C}", AccumulatedAmortization)).Append(","); + sb.Append(PeriodAsString).Append(","); + sb.Append(String.Format("{0:C}", TotalAssets)).Append(","); + sb.Append(String.Format("{0:C}", TotalCurrentAssets)).Append(","); + sb.Append(String.Format("{0:C}", TotalLiabilities)).Append(","); + sb.Append(String.Format("{0:C}", TotalCurrentLiabilities)).Append(","); + sb.Append(String.Format("{0:C}", CashAndCashEquivalents)).Append(","); + sb.Append(String.Format("{0:C}", NetCurrentAssetValue)); + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/MarketDataModel/BetaModel.cs b/MarketData/MarketDataLib/MarketDataModel/BetaModel.cs new file mode 100755 index 0000000..1430e4c --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/BetaModel.cs @@ -0,0 +1,88 @@ +using System; +using System.Text; +using System.Linq; +using MarketData.Utils; +using System.Collections.Generic; +using MarketData.ValueAtRisk; +using MarketData.Numerical; + +namespace MarketData.MarketDataModel +{ + public class PortfolioHoldingsWithBeta : List + { + private PortfolioHoldingsWithBeta() + { + } +// Copy Constructor + public PortfolioHoldingsWithBeta(List portfolioHoldingsWithBeta) + { + PortfolioBeta = 0.00; + if (null == portfolioHoldingsWithBeta) return; + foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in portfolioHoldingsWithBeta) Add(portfolioHoldingWithBeta); + foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in this) PortfolioBeta += portfolioHoldingWithBeta.WeightedBeta; + } + public PortfolioHoldingsWithBeta(PortfolioHoldings portfolioHoldings,DateTime analysisDate) + { + PortfolioBeta = 0.00; + if (null == portfolioHoldings) return; + foreach (PortfolioHolding portfolioHolding in portfolioHoldings) Add(new PortfolioHoldingWithBeta(portfolioHolding, analysisDate)); + foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in this) PortfolioBeta += portfolioHoldingWithBeta.WeightedBeta; + foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in this) portfolioHoldingWithBeta.BetaContribution = portfolioHoldingWithBeta.WeightedBeta / PortfolioBeta; + } + public PortfolioHoldingsWithBeta(PortfolioTrades portfolioTrades, DateTime analysisDate) + { + PortfolioBeta = 0.00; + double totalExposure = 0.00; + if (null == portfolioTrades) return; + List positions = portfolioTrades.GetPositions(analysisDate); + foreach (MarketDataModel.Position position in positions) Add(new PortfolioHoldingWithBeta(position, analysisDate)); + foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in this) totalExposure += portfolioHoldingWithBeta.Exposure; + foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in this) + { + portfolioHoldingWithBeta.WeightExp = portfolioHoldingWithBeta.Exposure / totalExposure; + portfolioHoldingWithBeta.WeightedBeta = portfolioHoldingWithBeta.WeightExp * portfolioHoldingWithBeta.Beta; + } + foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in this) PortfolioBeta += portfolioHoldingWithBeta.WeightedBeta; + foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in this) portfolioHoldingWithBeta.BetaContribution = portfolioHoldingWithBeta.WeightedBeta / PortfolioBeta; + } + public double PortfolioBeta { get; private set; } + public double Exposure + { + get + { + return (from PortfolioHoldingWithBeta portfolioHoldingWithBeta in this select portfolioHoldingWithBeta.Exposure).Sum(); + } + } + } + public class PortfolioHoldingWithBeta + { + private PortfolioHoldingWithBeta() + { + } + // Assumes that the portfolioTrade is an open trade +// public PortfolioHoldingWithBeta(MarketDataModel.Position position, DateTime? analysisDate = null) + public PortfolioHoldingWithBeta(MarketDataModel.Position position, DateTime analysisDate) + { + Symbol = position.Symbol; + Exposure = position.Exposure; + //if (null == analysisDate) analysisDate = DateTime.Now; + Beta = BetaGenerator.Beta(position.Symbol, analysisDate); + } +// public PortfolioHoldingWithBeta(PortfolioHolding portfolioHolding, DateTime? analysisDate = null) + public PortfolioHoldingWithBeta(PortfolioHolding portfolioHolding, DateTime analysisDate) + { + //if (null == analysisDate) analysisDate = DateTime.Now; + Symbol = portfolioHolding.Symbol; + Exposure = portfolioHolding.Exposure; + WeightExp = portfolioHolding.WeightExp; + Beta = BetaGenerator.Beta(portfolioHolding.Symbol, analysisDate); + WeightedBeta = portfolioHolding.WeightExp * Beta; + } + public String Symbol { get; set; } + public double Exposure { get; set; } + public double Beta { get; private set; } + public double WeightExp { get; set; } + public double WeightedBeta { get; set; } + public double BetaContribution { get; set; } + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/MarketDataModel/BollingerBand.cs b/MarketData/MarketDataLib/MarketDataModel/BollingerBand.cs new file mode 100755 index 0000000..59ae23e --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/BollingerBand.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using MarketData.Utils; +using MarketData.Numerical; + +namespace MarketData.MarketDataModel +{ + public class BollingerBandElementsByDate : Dictionary + { + public BollingerBandElementsByDate() + { + } + } + public class BollingerBands : BollingerBandElements + { + public BollingerBands() + { + } + public BollingerBands(List bollingerBandElements) + { + foreach(BollingerBandElement bollingerBandElement in bollingerBandElements)Add(bollingerBandElement); + } + public static String GetHeader(int movingAverageDays=20) + { + StringBuilder sb = new StringBuilder(); + sb.Append("Date,Symbol,Open,High,Low,Close,Volume,SMA(").Append(movingAverageDays).Append("),StDev(").Append(movingAverageDays).Append("),K,L,K-1,L+1"); + return sb.ToString(); + } + public BollingerBandElementsByDate GetBollingerBandElementsByDate() + { + BollingerBandElementsByDate bollingerBandElementsByDate = new BollingerBandElementsByDate(); + for (int index = 0; index < Count; index++) + { + BollingerBandElement bollingerBandElement = this[index]; + if (!bollingerBandElementsByDate.ContainsKey(bollingerBandElement.Date)) bollingerBandElementsByDate.Add(bollingerBandElement.Date, bollingerBandElement); + } + return bollingerBandElementsByDate; + } + } +// ********************************************************************************** + public class BollingerBandElements : List + { + public BollingerBandElements() + { + } + public BollingerBandElements(List bollingerBandElements) + { + foreach(BollingerBandElement bollingerBandElement in bollingerBandElements)Add(bollingerBandElement); + } + public LeastSquaresResult LeastSquaresFitClose() + { + double[] closingPrices=(from BollingerBandElement bollingerBandElement in this select bollingerBandElement.Close).ToList().ToArray(); + LeastSquaresResult leastSquaresResult=Numerics.LeastSquares(closingPrices); + return leastSquaresResult; + } + } + public class BollingerBandElement + { + private DateTime date; + private String symbol; + private double open; + private double high; + private double low; + private double close; + private long volume; + private double smaN; + private double stdevN; + private double k; + private double l; + private double kl1; + private double lp1; + + public BollingerBandElement() + { + } + public DateTime Date + { + get { return date; } + set { date = value; } + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public double Open + { + get { return open; } + set { open = value; } + } + public double High + { + get { return high; } + set { high = value; } + } + public double Low + { + get { return low; } + set { low = value; } + } + public double Close + { + get { return close; } + set { close = value; } + } + public double SMAN + { + get { return smaN; } + set { smaN = value; } + } + public double StDevN + { + get { return stdevN; } + set { stdevN = value; } + } + public long Volume + { + get { return volume; } + set { volume = value; } + } + public double K + { + get { return k; } + set { k = value; } + } + public double L + { + get { return l; } + set { l = value; } + } + public double KL1 + { + get { return kl1; } + set { kl1 = value; } + } + public double LP1 + { + get { return lp1; } + set { lp1 = value; } + } + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(Date)).Append(","); + sb.Append(Symbol).Append(","); + sb.Append(Open).Append(","); + sb.Append(High).Append(","); + sb.Append(Low).Append(","); + sb.Append(Close).Append(","); + sb.Append(Volume).Append(","); + sb.Append(SMAN).Append(","); + sb.Append(StDevN).Append(","); + sb.Append(K).Append(","); + sb.Append(L).Append(","); + sb.Append(KL1).Append(","); + sb.Append(LP1); + return sb.ToString(); + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/CashTransactions.cs b/MarketData/MarketDataLib/MarketDataModel/CashTransactions.cs new file mode 100755 index 0000000..bb4681b --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/CashTransactions.cs @@ -0,0 +1,23 @@ +using System; +using System.Text; +using System.Collections.Generic; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class CashTransactions : List + { + } + public class CashTransaction + { + public CashTransaction() + { + } + public String Account { get; set; } + public DateTime TransactionDate { get; set; } + public String Description { get; set; } + public double Credit { get; set; } + public double Debit { get; set; } + public double Balance { get; set; } + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/MarketDataModel/CashflowStatement.cs b/MarketData/MarketDataLib/MarketDataModel/CashflowStatement.cs new file mode 100755 index 0000000..c6524e3 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/CashflowStatement.cs @@ -0,0 +1,160 @@ +using System; +using System.Text; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + + public class CashflowStatement + { + public enum PeriodType { Annual=0,Quarterly=1} + private String symbol; + private DateTime asof; + private double depreciationAndAmortization; + private double deferredIncomeTaxes; + private double stockBasedCompensation; + private double accountsReceivable; + private double inventory; + private double accountsPayable; + private double accruedLiabilities; + private double operatingCashflow; + private double freeCashflow; + private PeriodType period; + private DateTime modified; + + public CashflowStatement() + { + } +// It is appropriate to use the AsOf date in the comparison of the financial statements because the AsOf date is the statement date. + public void MergeFrom(CashflowStatement previousCashflowStatement) + { + if(null==previousCashflowStatement)return; + if(!symbol.Equals(previousCashflowStatement.Symbol))return; + if(!AsOf.Date.Equals(previousCashflowStatement.AsOf.Date))return; + if(!Period.Equals(previousCashflowStatement.Period))return; + if(Utility.IsZeroOrNaN(DepreciationAndAmortization))DepreciationAndAmortization=previousCashflowStatement.DepreciationAndAmortization; + if(Utility.IsZeroOrNaN(DeferredIncomeTaxes))DeferredIncomeTaxes=previousCashflowStatement.DeferredIncomeTaxes; + if(Utility.IsZeroOrNaN(StockBasedCompensation))StockBasedCompensation=previousCashflowStatement.StockBasedCompensation; + if(Utility.IsZeroOrNaN(AccountsReceivable))AccountsReceivable=previousCashflowStatement.AccountsReceivable; + if(Utility.IsZeroOrNaN(Inventory))Inventory=previousCashflowStatement.Inventory; + if(Utility.IsZeroOrNaN(AccountsPayable))AccountsPayable=previousCashflowStatement.AccountsPayable; + if(Utility.IsZeroOrNaN(AccruedLiabilities))AccruedLiabilities=previousCashflowStatement.AccruedLiabilities; + if(Utility.IsZeroOrNaN(OperatingCashflow))OperatingCashflow=previousCashflowStatement.OperatingCashflow; + if(Utility.IsZeroOrNaN(FreeCashflow))FreeCashflow=previousCashflowStatement.FreeCashflow; + } + + public bool IsValid() + { + if(String.IsNullOrEmpty(symbol))return false; + if(AsOf.Date.Equals(Utility.Epoch))return false; + if(Utility.IsZeroOrNaN(DepreciationAndAmortization)&& + Utility.IsZeroOrNaN(DeferredIncomeTaxes)&& + Utility.IsZeroOrNaN(StockBasedCompensation)&& + Utility.IsZeroOrNaN(AccountsReceivable)&& + Utility.IsZeroOrNaN(Inventory)&& + Utility.IsZeroOrNaN(AccountsPayable)&& + Utility.IsZeroOrNaN(AccruedLiabilities)&& + Utility.IsZeroOrNaN(OperatingCashflow)&& + Utility.IsZeroOrNaN(FreeCashflow) + )return false; + return true; + } + + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public DateTime AsOf + { + get { return asof; } + set { asof = value; } + } + public double DepreciationAndAmortization + { + get{return depreciationAndAmortization;} + set{depreciationAndAmortization=value;} + } + public double DeferredIncomeTaxes + { + get{return deferredIncomeTaxes;} + set{deferredIncomeTaxes=value;} + } + public double StockBasedCompensation + { + get{return stockBasedCompensation;} + set{stockBasedCompensation=value;} + } + public double AccountsReceivable + { + get{return accountsReceivable;} + set{accountsReceivable=value;} + } + public double Inventory + { + get{return inventory;} + set{inventory=value;} + } + public double AccountsPayable + { + get{return accountsPayable;} + set{accountsPayable=value;} + } + public double AccruedLiabilities + { + get{return accruedLiabilities;} + set{accruedLiabilities=value;} + } + public double OperatingCashflow + { + get{return operatingCashflow;} + set{operatingCashflow=value;} + } + public double FreeCashflow + { + get{return freeCashflow;} + set{freeCashflow=value;} + } + public PeriodType Period + { + get { return period; } + set { period = value; } + } + public String PeriodAsString + { + get { return PeriodType.Quarterly.Equals(period) ? "Quarterly" : "Annual"; } + } + public DateTime Modified + { + get { return modified; } + set { modified = value; } + } + public static String Heading + { + get + { + StringBuilder sb = new StringBuilder(); + sb.Append("Symbol,AsOf,DepreciationAndAmortization,DeferredIncomeTaxes,StockBasedCompensation,AccountsReceivable,Inventory,AccountsPayable,AccruedLiabilities,OperatingCashflow,FreeCashflow,Period"); + return sb.ToString(); + } + } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(symbol).Append(","); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(asof)).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", DepreciationAndAmortization))).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", DeferredIncomeTaxes))).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", StockBasedCompensation))).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", AccountsReceivable))).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", Inventory))).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", AccountsPayable))).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", AccruedLiabilities))).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", OperatingCashflow))).Append(","); + sb.Append(Utility.AddQuotes(String.Format("{0:C}", FreeCashflow))).Append(","); + sb.Append(PeriodAsString); + return sb.ToString(); + } + } +} + diff --git a/MarketData/MarketDataLib/MarketDataModel/Cashflows.cs b/MarketData/MarketDataLib/MarketDataModel/Cashflows.cs new file mode 100755 index 0000000..2b57ef4 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/Cashflows.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; + +namespace MarketData.MarketDataModel +{ + public class Cashflows : List + { + } + public class CashflowElement + { + public CashflowElement(DateTime asof, double cashflow) + { + AsOf = asof; + Cashflow = cashflow; + } + public DateTime AsOf { get; set; } + public double Cashflow { get; set; } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/CompanyProfile.cs b/MarketData/MarketDataLib/MarketDataModel/CompanyProfile.cs new file mode 100755 index 0000000..7fcb5a8 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/CompanyProfile.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MarketData.MarketDataModel +{ + public class CompanyProfiles : List + { + public CompanyProfiles() + { + } + } + public class CompanyProfile + { + public enum EnumPricingSource{YAHOO,BIGCHARTS,UNKNOWN}; + public static String PRICING_SOURCE_YAHOO="YAHOO"; + public static String PRICING_SOURCE_BIGCHARTS="BIGCHARTS"; + private String symbol; + private String industry; + private String sector; + private String securityType; + private String companyName; + private String description; + private String pricingSource; + private bool canRollPrevious; + private bool freezePricing; + + public CompanyProfile() + { + } + public String Industry + { + get { return industry; } + set { industry = value; } + } + public String Sector + { + get { return sector; } + set { sector = value; } + } + public String SecurityType + { + get { return securityType;; } + set { securityType = value; } + } + public bool IsEquity + { + get + { + return null!=SecurityType && SecurityType.Equals("EQUITY"); + } + } + public String CompanyName + { + get{return companyName;} + set{companyName=value;} + } + public String Description + { + get{return description;} + set{description=value;} + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public String PricingSource + { + set{pricingSource=value;} + } + public bool CanRollPrevious + { + get{return canRollPrevious;} + set{canRollPrevious=value;} + } + public bool FreezePricing + { + get{return freezePricing;} + set{freezePricing=value;} + } + + public EnumPricingSource PricingSourceEnum + { + get + { + if(null==pricingSource)return EnumPricingSource.UNKNOWN; + else if(pricingSource.Equals(PRICING_SOURCE_YAHOO))return EnumPricingSource.YAHOO; + else if(pricingSource.Equals(PRICING_SOURCE_BIGCHARTS))return EnumPricingSource.BIGCHARTS; + return EnumPricingSource.UNKNOWN; + } + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/Constants.cs b/MarketData/MarketDataLib/MarketDataModel/Constants.cs new file mode 100755 index 0000000..69067e9 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/Constants.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.MarketDataModel +{ + public class Constants + { + public static readonly String CONST_ALL ="{All}"; + public static readonly String CONST_DASHES = "---"; + public static readonly String CONST_QUESTION = "???"; + public static readonly String NA = "N.A."; + public static readonly DateTime MIN_PRICING_DATE=DateTime.Parse("01-01-2009"); + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/CurrencyConversionElement.cs b/MarketData/MarketDataLib/MarketDataModel/CurrencyConversionElement.cs new file mode 100755 index 0000000..e3c088f --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/CurrencyConversionElement.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.MarketDataModel +{ + public class CurrencyConversionCollection : List + { + public CurrencyConversionCollection() + { + } + public CurrencyConversionCollection(List currencyConversionCollection) + { + foreach(CurrencyConversionElement currencyConversionElement in currencyConversionCollection)Add(currencyConversionElement); + } + } + public class CurrencyConversionElement + { + public String SourceCurrency{get;set;} + public DateTime AsOf{get;set;} + public String DestinationCurrency{get;set;} + public String DestinationCurrencyName{get;set;} + public double UnitsPerSource{get;set;} + public double SourcePerUnit{get;set;} + }} diff --git a/MarketData/MarketDataLib/MarketDataModel/DCFValuation.cs b/MarketData/MarketDataLib/MarketDataModel/DCFValuation.cs new file mode 100755 index 0000000..3b8bbd1 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/DCFValuation.cs @@ -0,0 +1,317 @@ +using System; +using System.Text; +using System.Collections.Generic; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class Enhancements + { + public bool DebtLoad { get; set; } + public double ROIC { get; set; } + public double ROICGrowth { get; set; } + public double EPSGrowth { get; set; } + public double RevenueGrowth { get; set; } + public double BVPS { get; set; } + public double PBVPS { get; set; } + public double EPS { get; set; } + public double PE { get; set; } + public double PEG { get; set; } + public double MOS { get; set; } + public double MOS80 { get; set; } + public double IntrinsicValue { get; set; } // Benjamin Graham original intrinsic value + public double IntrinsicValueRevised { get; set; } // Benjamin Graham revised instrinsic value (uses the yield on 20 year corporate bonds + public double RGVIntrinsic { get; set; } + public double RGVIntrinsicRevised { get; set; } + public Enhancements() + { + DebtLoad = false; + ROIC = double.NaN; + ROICGrowth = double.NaN; + EPSGrowth = double.NaN; + RevenueGrowth = double.NaN; + BVPS = double.NaN; + PBVPS = double.NaN; + EPS = double.NaN; + PE = double.NaN; + PEG = double.NaN; + MOS = double.NaN; + MOS80 = double.NaN; + IntrinsicValue = double.NaN; + RGVIntrinsic = double.NaN; + IntrinsicValueRevised = double.NaN; + RGVIntrinsicRevised = double.NaN; + } + } + public class DCFValuation + { + public const double MARKET_RETURN=.11; + private String symbol; + private double wacc=double.NaN; + private double costOfEquity=double.NaN; + private double costOfDebt=double.NaN; + private double marketValueOfEquity=double.NaN; + private double marketValueOfDebt = double.NaN; + private double totalCapitalInvested = double.NaN; + private double corporateTaxRate = double.NaN; + private double beta = double.NaN; + private double riskFreeRate = double.NaN; + private double interestExpense = double.NaN; + private double interestRate = double.NaN; + private double totalDebt = double.NaN; + private double outstandingShares = double.NaN; + private double freeCashflowGrowth = double.NaN; + private double presentValue = double.NaN; + private double stockPriceValuation = double.NaN; + private double marketReturn=MARKET_RETURN; + private Price currentPrice; + private Cashflows cashflows = new Cashflows(); + private ReturnItems returnItems = new ReturnItems(); + private Enhancements enhancements = new Enhancements(); + private String message; + private bool useMarketReturn = false; + public bool success = false; + + public bool UseMarketReturn + { + get { return useMarketReturn; } + set { useMarketReturn = value; if (useMarketReturn)marketReturn = 0.00; else marketReturn = MARKET_RETURN; } + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public Price CurrentPrice + { + get { return currentPrice; } + set { currentPrice = value; } + } + public double WACC + { + get { return wacc; } + set { wacc = value; } + } + public double CostOfEquity + { + get { return costOfEquity; } + set { costOfEquity = value; } + } + public double CostOfDebt + { + get { return costOfDebt; } + set { costOfDebt = value; } + } + public double MarketValueOfEquity + { + get { return marketValueOfEquity; } + set { marketValueOfEquity = value; } + } + public double MarketValueOfDebt + { + get { return marketValueOfDebt; } + set { marketValueOfDebt = value; } + } + public double TotalCapitalInvested + { + get { return totalCapitalInvested; } + set { totalCapitalInvested = value; } + } + public double CorporateTaxRate + { + get { return corporateTaxRate; } + set { corporateTaxRate = value; } + } + public double Beta + { + get { return beta; } + set { beta = value; } + } + public double RiskFreeRate + { + get { return riskFreeRate; } + set { riskFreeRate = value; } + } + public double InterestExpense + { + get { return interestExpense; } + set { interestExpense = value; } + } + public double InterestRate + { + get { return interestRate; } + set { interestRate = value; } + } + public double TotalDebt + { + get { return totalDebt; } + set { totalDebt = value; } + } + public double FreeCashflowGrowth + { + get { return freeCashflowGrowth; } + set { freeCashflowGrowth = value; } + } + public double OutstandingShares + { + get { return outstandingShares; } + set { outstandingShares = value; } + } + public ReturnItems ReturnItems + { + get { return returnItems; } + } + public Cashflows Cashflows + { + get { return cashflows; } + } + public double StockPriceValuation + { + get { return stockPriceValuation; } + set { stockPriceValuation = value; } + } + public double PresentValue + { + get { return presentValue; } + set { presentValue = value; } + } + public double MarketReturn + { + get { return marketReturn; } + set { marketReturn = value; } + } + public String Message + { + get { return message; } + set { message = value; } + } + public bool Success + { + get { return success; } + set { success = value; } + } + public Enhancements Enhancements + { + get { return enhancements; } + set { enhancements = value; } + } + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(Symbol).Append(","); + sb.Append(Success).Append(","); + if (!Success) + { + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + sb.Append(","); + + sb.Append(Message); + } + else + { + sb.Append(WACC).Append(","); + sb.Append(MarketReturn).Append(","); + sb.Append(CostOfEquity).Append(","); + sb.Append(CostOfDebt).Append(","); + sb.Append(MarketValueOfEquity).Append(","); + sb.Append(MarketValueOfDebt).Append(","); + sb.Append(TotalCapitalInvested).Append(","); + sb.Append(CorporateTaxRate).Append(","); + sb.Append(Beta).Append(","); + sb.Append(RiskFreeRate).Append(","); + sb.Append(InterestExpense).Append(","); + sb.Append(InterestRate).Append(","); + sb.Append(TotalDebt).Append(","); + sb.Append(OutstandingShares).Append(","); + sb.Append(FreeCashflowGrowth).Append(","); + sb.Append(PresentValue).Append(","); + sb.Append(StockPriceValuation).Append(","); + if (null == currentPrice) + { + sb.Append(","); + sb.Append(","); + } + else + { + sb.Append(CurrentPrice.Close).Append(","); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(CurrentPrice.Date)).Append(","); + } + + sb.Append(Enhancements.DebtLoad?"PASS":"FAIL").Append(","); + sb.Append(Enhancements.ROIC).Append(","); + sb.Append(Enhancements.ROICGrowth).Append(","); + sb.Append(Enhancements.EPSGrowth).Append(","); + sb.Append(Enhancements.RevenueGrowth).Append(","); + sb.Append(Enhancements.BVPS).Append(","); + sb.Append(Enhancements.PBVPS).Append(","); + sb.Append(Enhancements.EPS).Append(","); + sb.Append(Enhancements.PEG).Append(","); + sb.Append(Enhancements.MOS).Append(","); + sb.Append(Enhancements.MOS80).Append(","); + sb.Append(Enhancements.IntrinsicValue).Append(","); + sb.Append(Enhancements.IntrinsicValueRevised).Append(","); + sb.Append(Enhancements.RGVIntrinsic).Append(","); + sb.Append(Enhancements.RGVIntrinsicRevised).Append(","); + + sb.Append(Message); + } + return sb.ToString(); + } + public static String Header + { + get + { + StringBuilder sb = new StringBuilder(); + sb.Append("SYMBOL,STATUS,WACC,MARKET_RETURN,COST_OF_EQUITY,COST_OF_DEBT,MARKET_VALUE_OF_EQUITY,MARKET_VALUE_OF_DEBT,TOTAL_CAPITAL_INVESTED,CORPORATE_TAX_RATE,BETA,RISK_FREE_RATE,INTEREST_EXPENSE,INTEREST_RATE,TOTAL_DEBT,OUTSTANDING_SHARES,FREE_CASHFLOW_GROWTH,PRESENT_VALUE,STOCK_PRICE_VALUATION,CURRENT_STOCK_PRICE,PRICING_DATE,"); + sb.Append("DEBT_LOAD,"); + sb.Append("ROIC_GROWTH,"); + sb.Append("EPS_GROWTH,"); + sb.Append("REVENUE_GROWTH,"); + sb.Append("BVPS,"); + sb.Append("PBVPS,"); + sb.Append("EPS,"); + sb.Append("PEG,"); + sb.Append("MOS,"); + sb.Append("MOS80,"); + sb.Append("INTRINSIC_VALUE,"); + sb.Append("INSTRINSIC_VALUE_REVISED,"); + sb.Append("RGV_INSTRINSIC_VALUE,"); + sb.Append("RGV_INSTRINSIC_VALUE_REVISED,"); + sb.Append("MESSAGE"); + return sb.ToString(); + } + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/DMADeviation.cs b/MarketData/MarketDataLib/MarketDataModel/DMADeviation.cs new file mode 100755 index 0000000..2b8bde8 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/DMADeviation.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; + +namespace MarketData.MarketDataModel +{ + public class DMADeviations : List + { + public DMADeviations() + { + } + } + public class DMADeviation + { + private String symbol; + private DateTime date; + private double stdevPrice; + private double currentPrice; + public DMADeviation() + { + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public DateTime Date + { + get { return date; } + set { date = value; } + } + public double StDevPrice + { + get { return stdevPrice; } + set { stdevPrice = value; } + } + public double CurrentPrice + { + get { return currentPrice; } + set { currentPrice = value; } + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/DMAPrice.cs b/MarketData/MarketDataLib/MarketDataModel/DMAPrice.cs new file mode 100755 index 0000000..46e7fe3 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/DMAPrice.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; + +namespace MarketData.MarketDataModel +{ + public class DMAPricesByDate : Dictionary + { + public DMAPricesByDate() + { + } + } + public class DMAValues : List + { + public DMAValues() + { + } + public float[] GetValues(int startIndex, int count) + { + if (startIndex + count > Count) return null; + float[] valuesArray = new float[count]; + for (int index = startIndex, arrayIndex = 0; index < startIndex + count; index++, arrayIndex++) + { + valuesArray[arrayIndex] = (float)this[index].Value; + } + return valuesArray; + } + } + public class DMAPrices : List + { + public DMAPrices() + { + } + public DMAPrices(List dmaPrices) + { + foreach(DMAPrice dmaPrice in dmaPrices)Add(dmaPrice); + } + public DMAPrices Top(int count) + { + DMAPrices dmaPrices=new DMAPrices(); + for(int index=0;indexDecay - decay utility class + public class Decay + { + private int days; + private int applyDays; + private float[] decays; + private float seed; + private const float SEED=.0116F; + + public Decay(int days, float factor, int applyDays) + { + CreateDecay(factor, days, applyDays); + } + public Decay(int days,float factor) + { + CreateDecay(factor,days, days); + } + public Decay(int days) + { + CreateDecay(SEED,days, days); + } + public float this[int day] + { + get{return decays[day];} + set{decays[day]=value;} + } + public int Count + { + get{return decays.Length;} + } + public void Reverse() + { + float[] inverted=new float[this.decays.Length]; + for(int index=0;index 0) + { + decays[0] = 1F; + if (applyDays > 0) decays[0] -= seed; + + for(int index=1;index + { + public DividendHistory() + { + } + public DividendHistory(List items) + { + foreach(DividendHistoryItem item in items)Add(item); + } + public bool HasConsecutivePayments(int requiredConsecutiveMonths) + { + if(0==Count||Count + { + public DividendLoadCollection() + { + } + public DividendLoadCollection(List elements) + { + foreach(DividendLoadElement dividendLoadElement in elements)Add(dividendLoadElement); + } + //public DividendLoadCollection RemoveOutliers(int standardDeviations=4) + //{ + // double[] values = (from DividendLoadElement element in this select element.DividendLoadPcnt).ToArray(); + // double valuesStd=Numerics.Volatility(ref values)*standardDeviations; + // DividendLoadCollection dividendLoadCollection=new DividendLoadCollection((from DividendLoadElement element in this where element.DividendLoadPcnt <=valuesStd select element).ToList()); + // if(0==dividendLoadCollection.Count)return this; + // else return dividendLoadCollection; + //} + } + public class DividendLoadElement + { + public String Symbol{get;set;} + public int Year{get;set;} + public double EPS{get;set;} + public double CashAmount{get;set;} + public int Payments{get;set;} + public double DividendLoadPcnt{get;set;} + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/DividendPayment.cs b/MarketData/MarketDataLib/MarketDataModel/DividendPayment.cs new file mode 100755 index 0000000..f644c1b --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/DividendPayment.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class DividendPayments : List + { + public DividendPayments() + { + } + public DividendPayments(List dividendPayments) + { + foreach(DividendPayment dividendPayment in dividendPayments)Add(dividendPayment); + } + public double GetDividendPaymentsToDate(DateTime date) + { + return (from DividendPayment dividendPayment in this where dividendPayment.PaymentDate<=date select dividendPayment.Amount).Sum(); + } + public DividendPayments FilterAccounts(String filterAccounts) + { + if(null==filterAccounts)return this; + List accountsToInclude=Utility.ToList(filterAccounts); + DividendPayments dividendPayments=new DividendPayments((from DividendPayment dividendPayment in this where accountsToInclude.Any(x=>x.Equals(dividendPayment.Account)) select dividendPayment).ToList()); + return dividendPayments; + } + public DividendPayments FilterSymbols(String filterSymbols) + { + if(null==filterSymbols) return this; + List symbolsToInclude=Utility.ToList(filterSymbols); + DividendPayments dividendPayments=new DividendPayments((from DividendPayment dividendPayment in this where symbolsToInclude.Any(x => x.Equals(dividendPayment.Symbol)) select dividendPayment).ToList()); + return dividendPayments; + } + } + public class DividendPayment + { + public String Account{get;set;} + public String Symbol{get;set;} + public DateTime PaymentDate{get;set;} + public double Amount{get;set;} + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/ETFHoldings.cs b/MarketData/MarketDataLib/MarketDataModel/ETFHoldings.cs new file mode 100755 index 0000000..3211c5d --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/ETFHoldings.cs @@ -0,0 +1,64 @@ +using System; +using System.Text; +using System.Collections.Generic; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class ETFHoldings : List + { + public List GetETFSymbols() + { + Dictionary distinctETFSymbols = new Dictionary(); + for (int index = 0; index < Count; index++) + { + ETFHolding etfHolding = this[index]; + if (!distinctETFSymbols.ContainsKey(etfHolding.ETFSymbol)) distinctETFSymbols.Add(etfHolding.ETFSymbol, etfHolding.ETFSymbol); + } + return new List(distinctETFSymbols.Values); + } + } + public class ETFHolding + { + private String etfSymbol; + private String holdingSymbol; + private String holdingSymbolShareClass; + private String holdingCompanyName; + private double percentOfAssets; + private DateTime modified; + + public ETFHolding() + { + } + public String ETFSymbol + { + get { return etfSymbol; } + set { etfSymbol = value; } + } + public String HoldingSymbol + { + get { return holdingSymbol; } + set { holdingSymbol = value; } + } + public String HoldingSymbolShareClass + { + get { return holdingSymbolShareClass; } + set { holdingSymbolShareClass = value; } + } + public String HoldingCompanyName + { + get { return holdingCompanyName; } + set { holdingCompanyName = value; } + } + public double PercentOfAssets + { + get { return percentOfAssets; } + set { percentOfAssets = value; } + } + public DateTime Modified + { + get { return modified; } + set { modified = value; } + } + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/MarketDataModel/EarningsAnnouncement.cs b/MarketData/MarketDataLib/MarketDataModel/EarningsAnnouncement.cs new file mode 100755 index 0000000..106b067 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/EarningsAnnouncement.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.MarketDataModel +{ + public class EarningsAnnouncements : List + { + public EarningsAnnouncements() + { + } + public EarningsAnnouncements(List earningsAnnouncements) + { + foreach(EarningsAnnouncement earningsAnnouncement in earningsAnnouncements)Add(earningsAnnouncement); + } + } + public class EarningsAnnouncement + { + public EarningsAnnouncement() + { + } + public String Symbol{get;set;} + public DateTime Date{get;set;} + public DateTime PeriodEnding{get;set;} + public double Estimate{get;set;} + public double Reported{get;set;} + public double Surprise{get;set;} + public double SurprisePct{get;set;} + public String Time{get;set;} + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/MarketDataModel/EarningsAnnouncementModel.cs b/MarketData/MarketDataLib/MarketDataModel/EarningsAnnouncementModel.cs new file mode 100755 index 0000000..04339dc --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/EarningsAnnouncementModel.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MarketData.MarketDataModel; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class EarningsAnnouncementModel : IComparable + { + public EarningsAnnouncementModel() + { + } + public EarningsAnnouncementModel(String symbol,DateTime nextEarningsDate) + { + Symbol = symbol; + NextEarningsDate = nextEarningsDate; + } + public int CompareTo(object other) + { + if (other.GetType() != typeof(EarningsAnnouncementModel)) throw new Exception("Expected typeof " + this.GetType().Name); + EarningsAnnouncementModel otherModel = (EarningsAnnouncementModel)other; + return NextEarningsDate.CompareTo(otherModel.NextEarningsDate); + } + public String Symbol { get; set; } + public String CompanyName { get; set; } + public DateTime NextEarningsDate { get; set; } + public int DaysFromToday { get; set; } + public double LastPrice { get; set; } + public double Upside { get; set; } + public double Downside { get; set; } + public double UpsidePcnt { get; set; } + public double DownsidePcnt { get; set; } + public DateTime PricingDate { get; set; } + public double PE { get; set; } + public double PEG { get; set; } + public double AnticipatedEarningsGrowth { get; set; } + public String AnticipatedEarningsGrowthStr + { + get + { + if (double.IsInfinity(AnticipatedEarningsGrowth) || double.NaN.Equals(AnticipatedEarningsGrowth)) return Constants.CONST_DASHES;; + return Utility.FormatPercent(AnticipatedEarningsGrowth); + } + } + public String PEGValuation { get; set; } + public DateTime FundamentalDate { get; set; } // fundamental date + public DateTime PriceTargetDate{get;set;} + } +} \ No newline at end of file diff --git a/MarketData/MarketDataLib/MarketDataModel/EconomicIndicators.cs b/MarketData/MarketDataLib/MarketDataModel/EconomicIndicators.cs new file mode 100755 index 0000000..0e0ccb1 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/EconomicIndicators.cs @@ -0,0 +1,156 @@ +using System.Data; +using MarketData.CSVHelper; + +namespace MarketData.MarketDataModel +{ + public class EconomicIndicators : List + { + public EconomicIndicators() + { + } + public List GetYears() + { + if(0==Count)return null; + List years=(from EconomicIndicator economicIndicator in this select economicIndicator.Year).Distinct().ToList(); + years.Sort(); + return years; + } + public Dictionary GetDictionary() + { + Dictionary dictionary=new Dictionary(); + if(0==Count)return null; + for(int index=0;index list=new List(); + dictionary.Add(economicIndicator.CountryCode,new EconomicIndicators()); + } + EconomicIndicators economicIndicators=dictionary[economicIndicator.CountryCode]; + economicIndicators.Add(economicIndicator); + } + List keys=new List(dictionary.Keys); + foreach(String key in keys) + { + dictionary[key].Sort(new EconomicIndicatorByYear()); + } + return dictionary; + } + public static EconomicIndicators FromZipFile(String strPathZipFile,String strPathExtractFolder,bool debug=false) + { + try + { + if(Directory.Exists(strPathExtractFolder)) + { + try{Directory.Delete(strPathExtractFolder,true);} + catch(Exception exception){MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Unable to delete folder {0}, exception was {1}",strPathExtractFolder,exception.ToString()));} + } + Directory.CreateDirectory(strPathExtractFolder); + List extractFiles=ExtractFileHelper.ExtractToFolder(strPathZipFile,strPathExtractFolder); + if(null==extractFiles||0==extractFiles.Count) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Could not locate data in zip file {0}",strPathZipFile)); + return null; + } + String strPathExtractFile=(from String strPathExtractFileName in extractFiles where !strPathExtractFileName.Contains("Metadata") select strPathExtractFileName).FirstOrDefault(); + if(null==strPathExtractFile) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Could not locate data in zip file {0}",strPathZipFile)); + return null; + } + CSVFileExt2 csvFile=new CSVFileExt2(); + int dataRow=csvFile.FindLineWith(strPathExtractFile,"Country Name"); + if(-1==dataRow) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Could not locate start of data in zip file {0}",strPathZipFile)); + return null; + } + csvFile.LoadCSVFile(strPathExtractFile,dataRow); + if(0==csvFile.RowCount) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Could not locate data in zip file {0}",strPathZipFile)); + return null; + } + if(!debug) + { + try{File.Delete(strPathZipFile);} + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Could not remove zip file {0}, exception was {1}",strPathZipFile,exception.ToString())); + } + } + try{Directory.Delete(strPathExtractFolder,true);} + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Error removing folder {0}, exception was {1}",strPathExtractFolder,exception.ToString())); + } + return EconomicIndicators.FromDataTable(csvFile.ToDataTable()); + } + catch(Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Error extracting economic indicators from zip file {0}, error was {1}",strPathZipFile,exception.ToString())); + return null; + } + } + public static EconomicIndicators FromDataTable(DataTable dataTable) + { + String strValue=null; + String strYear=null; + try + { + EconomicIndicators economicIndicators=new EconomicIndicators(); + DataColumnCollection columns=dataTable.Columns; + DataRowCollection rows=dataTable.Rows; + + for(int rowIndex=0;rowIndex + { + public int Compare(EconomicIndicator p1,EconomicIndicator p2) + { + return p1.Year.CompareTo(p2.Year); + } + } + public class EconomicIndicator + { + public String Source{get;set;} + public String CountryName{get;set;} + public String CountryCode{get;set;} + public String IndicatorName{get;set;} + public String IndicatorCode{get;set;} + public double IndicatorValue{get;set;} + public int Year{get;set;} + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/ExponentialDecay.cs b/MarketData/MarketDataLib/MarketDataModel/ExponentialDecay.cs new file mode 100755 index 0000000..abe5a5a --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/ExponentialDecay.cs @@ -0,0 +1,35 @@ +using System; +using System.Text; +using System.Linq; +using MarketData.Numerical; + +namespace MarketData.MarketDataModel +{ + public class ExponentialDecay + { + private double[] decays=null; + public ExponentialDecay() + { + } + public double this[int sample] + { + get{return decays[sample];} + } + public void Prime(float[] samples,double deviations=2.00) + { + double[]factors=new double[samples.Length]; + decays=new double[samples.Length]; + double stddev=Numerics.StdDev(ref samples); + for(int index=0,ordinal=samples.Length;index + { + public FeedStatistics() + { + } + public FeedStatistics(List feedStatistics) + { + foreach (FeedStatistic feedStatistic in feedStatistics) Add(feedStatistic); + } + } + public class FeedStatistic + { + public enum FeedStatisticType + { + ZACKS_RANK, VALUATIONS, YIELD_CURVE, SPLITS, SECURITY_MASTER, SEC_FILINGS, PRICES, OPTIONS, INSIDER_TRANSACTIONS, FUNDAMENTALS, INCOME_STATEMENT, CASHFLOW_STATEMENT, + BALANCE_SHEET, HISTORICAL, HEADLINES, ETF_HOLDINGS, ECONOMIC_INDICATORS, EARNINGS_ANNOUNCEMENTS, DIVIDEND_HISTORY, CURRENCY_CONVERSION, ANALYST_RATINGS, ANALYST_PRICE_TARGET, + INVALID + }; + public FeedStatistic() + { + } + public String Feed { get; set; } + public int Records { get; set; } + public DateTime Date { get; set; } + + public static List GetFeedStatisticTypes() + { + List types = new List(); + types.Add("Zacks Rank"); + types.Add("Valuations"); + types.Add("Yield Curve"); + types.Add("Splits"); + types.Add("Security Master"); + types.Add("SEC Filings"); + types.Add("Prices"); + types.Add("Options"); + types.Add("Insider Transactions"); + types.Add("Fundamentals"); + types.Add("Income Statement"); + types.Add("Cashflow Statement"); + types.Add("Balance Sheet"); + types.Add("Historical"); + types.Add("Headlines"); + types.Add("ETF Holdings"); + types.Add("Economic Indicators"); + types.Add("Earnings Announcements"); + types.Add("Dividend History"); + types.Add("Currency Conversion"); + types.Add("Analyst Ratings"); + types.Add("Analyst Price Target"); + return types; + } + public static String TypeToString(FeedStatisticType feedStatisticType) + { + if (feedStatisticType.Equals(FeedStatisticType.ZACKS_RANK)) return "Zacks Rank"; + if (feedStatisticType.Equals(FeedStatisticType.VALUATIONS)) return "Valuations"; + if (feedStatisticType.Equals(FeedStatisticType.YIELD_CURVE)) return "Yield Curve"; + if (feedStatisticType.Equals(FeedStatisticType.SPLITS)) return "Splits"; + if (feedStatisticType.Equals(FeedStatisticType.SECURITY_MASTER)) return "Security Master"; + if (feedStatisticType.Equals(FeedStatisticType.SEC_FILINGS)) return "SEC Filings"; + if (feedStatisticType.Equals(FeedStatisticType.PRICES)) return "Prices"; + if (feedStatisticType.Equals(FeedStatisticType.OPTIONS)) return "Options"; + if (feedStatisticType.Equals(FeedStatisticType.INSIDER_TRANSACTIONS)) return "Insider Transactions"; + if (feedStatisticType.Equals(FeedStatisticType.FUNDAMENTALS)) return "Fundamentals"; + if (feedStatisticType.Equals(FeedStatisticType.INCOME_STATEMENT)) return "Income Statement"; + if (feedStatisticType.Equals(FeedStatisticType.CASHFLOW_STATEMENT)) return "Cashflow Statement"; + if (feedStatisticType.Equals(FeedStatisticType.BALANCE_SHEET)) return "Balance Sheet"; + if (feedStatisticType.Equals(FeedStatisticType.HISTORICAL)) return "Historical"; + if (feedStatisticType.Equals(FeedStatisticType.HEADLINES)) return "Headlines"; + if (feedStatisticType.Equals(FeedStatisticType.ETF_HOLDINGS)) return "ETF Holdings"; + if (feedStatisticType.Equals(FeedStatisticType.ECONOMIC_INDICATORS)) return "Economic Indicators"; + if (feedStatisticType.Equals(FeedStatisticType.EARNINGS_ANNOUNCEMENTS)) return "Earnings Announcements"; + if (feedStatisticType.Equals(FeedStatisticType.DIVIDEND_HISTORY)) return "Dividend History"; + if (feedStatisticType.Equals(FeedStatisticType.CURRENCY_CONVERSION)) return "Currency Conversion"; + if (feedStatisticType.Equals(FeedStatisticType.ANALYST_RATINGS)) return "Analyst Ratings"; + if (feedStatisticType.Equals(FeedStatisticType.ANALYST_PRICE_TARGET)) return "Analyst Price Target"; + return "Invalid"; + } + public static FeedStatisticType FromString(String strFeedStatisticType) + { + if (strFeedStatisticType.Equals("Zacks Rank")) return FeedStatisticType.ZACKS_RANK; + if (strFeedStatisticType.Equals("Valuations")) return FeedStatisticType.VALUATIONS; + if (strFeedStatisticType.Equals("Yield Curve")) return FeedStatisticType.YIELD_CURVE; + if (strFeedStatisticType.Equals("Splits")) return FeedStatisticType.SPLITS; + if (strFeedStatisticType.Equals("Security Master")) return FeedStatisticType.SECURITY_MASTER; + if (strFeedStatisticType.Equals("SEC Filings")) return FeedStatisticType.SEC_FILINGS; + if (strFeedStatisticType.Equals("Prices")) return FeedStatisticType.PRICES; + if (strFeedStatisticType.Equals("Options")) return FeedStatisticType.OPTIONS; + if (strFeedStatisticType.Equals("Insider Transactions")) return FeedStatisticType.INSIDER_TRANSACTIONS; + if (strFeedStatisticType.Equals("Fundamentals")) return FeedStatisticType.FUNDAMENTALS; + if (strFeedStatisticType.Equals("Income Statement")) return FeedStatisticType.INCOME_STATEMENT; + if (strFeedStatisticType.Equals("Cashflow Statement")) return FeedStatisticType.CASHFLOW_STATEMENT; + if (strFeedStatisticType.Equals("Balance Sheet")) return FeedStatisticType.BALANCE_SHEET; + if (strFeedStatisticType.Equals("Historical")) return FeedStatisticType.HISTORICAL; + if (strFeedStatisticType.Equals("Headlines")) return FeedStatisticType.HEADLINES; + if (strFeedStatisticType.Equals("ETF Holdings")) return FeedStatisticType.ETF_HOLDINGS; + if (strFeedStatisticType.Equals("Economic Indicators")) return FeedStatisticType.ECONOMIC_INDICATORS; + if (strFeedStatisticType.Equals("Earnings Announcements")) return FeedStatisticType.EARNINGS_ANNOUNCEMENTS; + if (strFeedStatisticType.Equals("Dividend History")) return FeedStatisticType.DIVIDEND_HISTORY; + if (strFeedStatisticType.Equals("Currency Conversion")) return FeedStatisticType.CURRENCY_CONVERSION; + if (strFeedStatisticType.Equals("Analyst Ratings")) return FeedStatisticType.ANALYST_RATINGS; + if (strFeedStatisticType.Equals("Analyst Price Target")) return FeedStatisticType.ANALYST_PRICE_TARGET; + return FeedStatisticType.INVALID; + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/Fundamentals.cs b/MarketData/MarketDataLib/MarketDataModel/Fundamentals.cs new file mode 100755 index 0000000..c9a5c67 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/Fundamentals.cs @@ -0,0 +1,398 @@ +using System; +using System.Collections.Generic; +using System.Net.Http.Headers; +using System.Text; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class Fundamentals : List + { + public Fundamentals() + { + } + } + public class Fundamental + { + private String symbol; + private DateTime asOf; + private DateTime nextEarningsDate; + private double beta; + private double low52; + private double high52; + private Int64 volume; + private double marketCap; + private double pe; + private double eps; + private double peg; + private double returnOnAssets; + private double returnOnEquity; + private double totalCash; + private double totalDebt; + private double sharesOutstanding; + private double revenue; + private double revenuePerShare; + private double qtrlyRevenueGrowth; + private double grossProfit; + private double ebitda; + private double netIncomeAvailableToCommon; + private double bookValuePerShare; + private double operatingCashflow; + private double leveragedFreeCashflow; + private double equity; + private double trailingPE; + private double enterpriseValue; + private double ebit; + private double debtToEquity; + private String source; + + public Fundamental() + { + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public DateTime AsOf + { + get { return asOf; } + set { asOf = value; } + } + public String Source + { + get { return source; } + set { source = value; } + } + public DateTime NextEarningsDate + { + get { return nextEarningsDate; } + set { nextEarningsDate = value; } + } + public double Beta + { + get { return beta; } + set { beta = value; } + } + public double Low52 + { + get { return low52; } + set { low52 = value; } + } + public double High52 + { + get { return high52; } + set { high52 = value; } + } + public Int64 Volume + { + get { return volume; } + set { volume = value; } + } + public double MarketCap + { + get { return marketCap; } + set { marketCap = value; } + } + public double PE + { + get { return pe; } + set { pe = value; } + } + public double EPS + { + get { return eps; } + set { eps = value; } + } + public double PEG + { + get { return peg; } + set { peg = value; } + } + public double ReturnOnAssets + { + get { return returnOnAssets; } + set { returnOnAssets = value; } + } + public double ReturnOnEquity + { + get { return returnOnEquity; } + set { returnOnEquity = value; } + } + public double TotalCash + { + get { return totalCash; } + set { totalCash = value; } + } + public double TotalDebt + { + get { return totalDebt; } + set { totalDebt = value; } + } + public double SharesOutstanding + { + get { return sharesOutstanding; } + set { sharesOutstanding = value; } + } + public double Revenue + { + get { return revenue; } + set { revenue = value; } + } + public double RevenuePerShare + { + get { return revenuePerShare; } + set { revenuePerShare = value; } + } + public double QtrlyRevenueGrowth + { + get { return qtrlyRevenueGrowth; } + set { qtrlyRevenueGrowth = value; } + } + public double GrossProfit + { + get { return grossProfit; } + set { grossProfit=value; } + } + public double EBITDA + { + get { return ebitda; } + set { ebitda = value; } + } + public double EBIT + { + get{return ebit;} + set{ebit=value;} + } + public double EnterpriseValue + { + get{return enterpriseValue;} + set{enterpriseValue=value;} + } + public double NetIncomeAvailableToCommon + { + get { return netIncomeAvailableToCommon; } + set { netIncomeAvailableToCommon = value; } + } + public double BookValuePerShare + { + get { return bookValuePerShare; } + set { bookValuePerShare = value; } + } + public double OperatingCashflow + { + get {return operatingCashflow; } + set { operatingCashflow = value; } + } + public double LeveragedFreeCashflow + { + get { return leveragedFreeCashflow; } + set { leveragedFreeCashflow = value; } + } + public double Equity // on the fly as record is pulled from database + { + get { return equity; } + set { equity = value; } + } + public double TrailingPE + { + get { return trailingPE; } + set { trailingPE = value; } + } + public double DebtToEquity + { + get{return debtToEquity;} + set{debtToEquity=value;} + } +// If columns are added to this object must ensure that the columns are also added to the MergeFrom, IsZero, and GetLoad() methods so that the consistency checks can still function properly +// Do not include a comparison of the AsOf date. The prior fundamental will always have an AsOf date that precedes the one that we fetch. +// In contrast, the AsOf date in the financial statements is the statement date and we use the AsOf date as a comparison there. +// The idea here is to ensure that we do not lose any fidelity of the fundamental data if elements are missing in the current fetch but were present in a previous fetch. + public void MergeFrom(Fundamental previousFundamental) + { + if(null==previousFundamental)return; + if(!Symbol.Equals(previousFundamental.Symbol))return; + if(Utility.IsEpoch(NextEarningsDate))NextEarningsDate=previousFundamental.NextEarningsDate; + if(Utility.IsZeroOrNaN(Beta))Beta=previousFundamental.Beta; + if(Utility.IsZeroOrNaN(Low52))Low52=previousFundamental.Low52; + if(Utility.IsZeroOrNaN(High52))High52=previousFundamental.High52; + if(Int64.MinValue.Equals(Volume)||Int64.MaxValue.Equals(Volume))Volume=previousFundamental.Volume; + if(Utility.IsZeroOrNaN(MarketCap))MarketCap=previousFundamental.MarketCap; + if(Utility.IsZeroOrNaN(PE))PE=previousFundamental.PE; + if(Utility.IsZeroOrNaN(EPS))EPS=previousFundamental.EPS; + if(Utility.IsZeroOrNaN(PEG))PEG=previousFundamental.PEG; + if(Utility.IsZeroOrNaN(ReturnOnAssets))ReturnOnAssets=previousFundamental.ReturnOnAssets; + if(Utility.IsZeroOrNaN(ReturnOnEquity))ReturnOnEquity=previousFundamental.ReturnOnEquity; + if(Utility.IsZeroOrNaN(TotalCash))TotalCash=previousFundamental.TotalCash; + if(Utility.IsZeroOrNaN(TotalDebt))TotalDebt=previousFundamental.TotalDebt; + if(Utility.IsZeroOrNaN(SharesOutstanding))SharesOutstanding=previousFundamental.SharesOutstanding; + if(Utility.IsZeroOrNaN(Revenue))Revenue=previousFundamental.Revenue; + if(Utility.IsZeroOrNaN(RevenuePerShare))RevenuePerShare=previousFundamental.RevenuePerShare; + if(Utility.IsZeroOrNaN(QtrlyRevenueGrowth))QtrlyRevenueGrowth=previousFundamental.QtrlyRevenueGrowth; + if(Utility.IsZeroOrNaN(GrossProfit))GrossProfit=previousFundamental.GrossProfit; + if(Utility.IsZeroOrNaN(EBITDA))EBITDA=previousFundamental.EBITDA; + if(Utility.IsZeroOrNaN(EBIT))EBIT=previousFundamental.EBIT; + if(Utility.IsZeroOrNaN(EnterpriseValue))EnterpriseValue=previousFundamental.EnterpriseValue; + if(Utility.IsZeroOrNaN(NetIncomeAvailableToCommon))NetIncomeAvailableToCommon=previousFundamental.NetIncomeAvailableToCommon; + if(Utility.IsZeroOrNaN(BookValuePerShare))BookValuePerShare=previousFundamental.BookValuePerShare; + if(Utility.IsZeroOrNaN(OperatingCashflow))OperatingCashflow=previousFundamental.OperatingCashflow; + if(Utility.IsZeroOrNaN(LeveragedFreeCashflow))LeveragedFreeCashflow=previousFundamental.LeveragedFreeCashflow; + if(Utility.IsZeroOrNaN(Equity))Equity=previousFundamental.Equity; + if(Utility.IsZeroOrNaN(TrailingPE))TrailingPE=previousFundamental.TrailingPE; + if(Utility.IsZeroOrNaN(DebtToEquity))DebtToEquity=previousFundamental.DebtToEquity; + } + public bool IsZero() + { + double missingItemCount=0.00; + double totalItems=29.00; + double percentMissing=0.00; + if(Utility.IsZeroOrNaN(Beta))missingItemCount++; + if(Utility.IsZeroOrNaN(Low52))missingItemCount++; + if(Utility.IsZeroOrNaN(High52))missingItemCount++; + if(Utility.IsZeroOrNaN((double)Volume))missingItemCount++; + if(Utility.IsZeroOrNaN(MarketCap))missingItemCount++; + if(Utility.IsZeroOrNaN(PE))missingItemCount++; + if(Utility.IsZeroOrNaN(EPS))missingItemCount++; + if(Utility.IsZeroOrNaN(PEG))missingItemCount++; + if(Utility.IsZeroOrNaN(ReturnOnAssets))missingItemCount++; + if(Utility.IsZeroOrNaN(ReturnOnEquity))missingItemCount++; + if(Utility.IsZeroOrNaN(TotalCash))missingItemCount++; + if(Utility.IsZeroOrNaN(TotalDebt))missingItemCount++; + if(Utility.IsZeroOrNaN(SharesOutstanding))missingItemCount++; + if(Utility.IsZeroOrNaN(Revenue))missingItemCount++; + if(Utility.IsZeroOrNaN(SharesOutstanding))missingItemCount++; + if(Utility.IsZeroOrNaN(Revenue))missingItemCount++; + if(Utility.IsZeroOrNaN(RevenuePerShare))missingItemCount++; + if(Utility.IsZeroOrNaN(QtrlyRevenueGrowth))missingItemCount++; + if(Utility.IsZeroOrNaN(GrossProfit))missingItemCount++; + if(Utility.IsZeroOrNaN(EBITDA))missingItemCount++; + if(Utility.IsZeroOrNaN(NetIncomeAvailableToCommon))missingItemCount++; + if(Utility.IsZeroOrNaN(BookValuePerShare))missingItemCount++; + if(Utility.IsZeroOrNaN(OperatingCashflow))missingItemCount++; + if(Utility.IsZeroOrNaN(LeveragedFreeCashflow))missingItemCount++; + if(Utility.IsZeroOrNaN(Equity))missingItemCount++; + if(Utility.IsZeroOrNaN(TrailingPE))missingItemCount++; + if(Utility.IsZeroOrNaN(EnterpriseValue))missingItemCount++; + if(Utility.IsZeroOrNaN(EBIT))missingItemCount++; + if(Utility.IsZeroOrNaN(DebtToEquity))missingItemCount++; + percentMissing=(missingItemCount/totalItems)*100.00; + MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Fundamental load for {0} is {1}%",symbol,100.00-percentMissing)); + if(percentMissing>85.00)return true; + return false; + } + + public double GetLoad() + { + double missingItemCount=0.00; + double totalItems=29.00; + double percentMissing=0.00; + if(Utility.IsZeroOrNaN(Beta))missingItemCount++; + if(Utility.IsZeroOrNaN(Low52))missingItemCount++; + if(Utility.IsZeroOrNaN(High52))missingItemCount++; + if(Utility.IsZeroOrNaN((double)Volume))missingItemCount++; + if(Utility.IsZeroOrNaN(MarketCap))missingItemCount++; + if(Utility.IsZeroOrNaN(PE))missingItemCount++; + if(Utility.IsZeroOrNaN(EPS))missingItemCount++; + if(Utility.IsZeroOrNaN(PEG))missingItemCount++; + if(Utility.IsZeroOrNaN(ReturnOnAssets))missingItemCount++; + if(Utility.IsZeroOrNaN(ReturnOnEquity))missingItemCount++; + if(Utility.IsZeroOrNaN(TotalCash))missingItemCount++; + if(Utility.IsZeroOrNaN(TotalDebt))missingItemCount++; + if(Utility.IsZeroOrNaN(SharesOutstanding))missingItemCount++; + if(Utility.IsZeroOrNaN(Revenue))missingItemCount++; + if(Utility.IsZeroOrNaN(SharesOutstanding))missingItemCount++; + if(Utility.IsZeroOrNaN(Revenue))missingItemCount++; + if(Utility.IsZeroOrNaN(RevenuePerShare))missingItemCount++; + if(Utility.IsZeroOrNaN(QtrlyRevenueGrowth))missingItemCount++; + if(Utility.IsZeroOrNaN(GrossProfit))missingItemCount++; + if(Utility.IsZeroOrNaN(EBITDA))missingItemCount++; + if(Utility.IsZeroOrNaN(NetIncomeAvailableToCommon))missingItemCount++; + if(Utility.IsZeroOrNaN(BookValuePerShare))missingItemCount++; + if(Utility.IsZeroOrNaN(OperatingCashflow))missingItemCount++; + if(Utility.IsZeroOrNaN(LeveragedFreeCashflow))missingItemCount++; + if(Utility.IsZeroOrNaN(Equity))missingItemCount++; + if(Utility.IsZeroOrNaN(TrailingPE))missingItemCount++; + if(Utility.IsZeroOrNaN(EnterpriseValue))missingItemCount++; + if(Utility.IsZeroOrNaN(EBIT))missingItemCount++; + if(Utility.IsZeroOrNaN(DebtToEquity))missingItemCount++; + percentMissing=(missingItemCount/totalItems)*100.00; + return 100.00-percentMissing; + } + + public static String Header + { + get + { + StringBuilder sb=new StringBuilder(); + sb.Append("Symbol").Append(","); + sb.Append("AsOf").Append(","); + sb.Append("Source,"); + sb.Append("NextEarningsDate").Append(","); + sb.Append("Beta").Append(","); + sb.Append("Low52").Append(","); + sb.Append("High52").Append(","); + sb.Append("Volume").Append(","); + sb.Append("MarketCap").Append(","); + sb.Append("PE").Append(","); + sb.Append("EPS").Append(","); + sb.Append("PEG").Append(","); + sb.Append("Return On Assets").Append(","); + sb.Append("Return On Equity").Append(","); + sb.Append("Total Cash").Append(","); + sb.Append("Total Debt").Append(","); + sb.Append("Shares Outstanding").Append(","); + sb.Append("Revenue").Append(","); + sb.Append("RevenuePerShare").Append(","); + sb.Append("QtrlyRevenueGrowth").Append(","); + sb.Append("GrossProfit").Append(","); + sb.Append("EBITDA").Append(","); + sb.Append("NetIncomeAvailableToCommon").Append(","); + sb.Append("BookValuePerShare").Append(","); + sb.Append("OperatingCashflow").Append(","); + sb.Append("LeveragedFreeCashflow").Append(","); + sb.Append("Equity").Append(","); + sb.Append("Trailing PE,"); + sb.Append("EBIT,"); + sb.Append("EnterpriseValue,"); + sb.Append("DebtToEquity"); + return sb.ToString(); + } + } + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(Symbol).Append(","); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(AsOf)).Append(","); + sb.Append(null == Source ? "" : Source).Append(","); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(NextEarningsDate)).Append(","); + sb.Append(String.Format("{0:0.00}",Beta )).Append(","); + sb.Append(String.Format("{0:0.00}",Low52)).Append(","); + sb.Append(String.Format("{0:0.00}",High52)).Append(","); + sb.Append(String.Format("{0:0.00}", Volume)).Append(","); + sb.Append(String.Format("{0:0.00}", MarketCap)).Append(","); + sb.Append(String.Format("{0:0.00}", PE)).Append(","); + sb.Append(String.Format("{0:0.00}", EPS)).Append(","); + sb.Append(String.Format("{0:0.00}", PEG)).Append(","); + sb.Append(String.Format("{0:0.00}", ReturnOnAssets)).Append(","); + sb.Append(String.Format("{0:0.00}", ReturnOnEquity)).Append(","); + sb.Append(String.Format("{0:0.00}", TotalCash)).Append(","); + sb.Append(String.Format("{0:0.00}", TotalDebt)).Append(","); + sb.Append(String.Format("{0:0.00}", SharesOutstanding)).Append(","); + sb.Append(String.Format("{0:0.00}", Revenue)).Append(","); + sb.Append(String.Format("{0:0.00}", RevenuePerShare)).Append(","); + sb.Append(String.Format("{0:0.00}", QtrlyRevenueGrowth)).Append(","); + sb.Append(String.Format("{0:0.00}", GrossProfit)).Append(","); + sb.Append(String.Format("{0:0.00}", EBITDA)).Append(","); + sb.Append(String.Format("{0:0.00}", NetIncomeAvailableToCommon)).Append(","); + sb.Append(String.Format("{0:0.00}", BookValuePerShare)).Append(","); + sb.Append(String.Format("{0:0.00}", OperatingCashflow)).Append(","); + sb.Append(String.Format("{0:0.00}", LeveragedFreeCashflow)).Append(","); + sb.Append(String.Format("{0:0.00}", Equity)).Append(","); + sb.Append(String.Format("{0:0.00}", TrailingPE)).Append(","); + sb.Append(String.Format("{0:0.00}", EBIT)).Append(","); + sb.Append(String.Format("{0}", EnterpriseValue)).Append(","); + sb.Append(String.Format("{0:0.00}", DebtToEquity)); + return sb.ToString(); + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossCompoundModel.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossCompoundModel.cs new file mode 100755 index 0000000..534496d --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossCompoundModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ +// ************************************************************************************************************************************************************** +// *********************************************** G A I N / L O S S C O M P O U N D M O D E L **************************************** +// ************************************************************************************************************************************************************** +// This GainLossModel will be used to model the GainLossView in terms of surfacing the Active Gain/Loss, Active Exposure, Active Gain/Loss%, Total Gain/Loss, Total Gain/Loss % data + public class GainLossCompoundModel + { + public DateTime Date{get;set;} + public double ActiveExposure{get;set;} + public double ActiveGainLoss{get;set;} + public double ActiveGainLossPercent{get;set;} + public double TotalGainLoss{get;set;} + public double TotalGainLossPercent{get;set;} + public double TotalDividendsPaid{get;set;} + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossCompoundModelCollection.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossCompoundModelCollection.cs new file mode 100755 index 0000000..3612eaa --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossCompoundModelCollection.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ +// The GainLossCompoundModelCollection contains both the active gain loss and the total gain loss time series data + public class GainLossCompoundModelCollection : List + { + public GainLossCompoundModelCollection() + { + } + public GainLossCompoundModelCollection(List items) + { + foreach(GainLossCompoundModel item in items)Add(item); + } + public GainLossCompoundModelCollection(GainLossCollection activeGainLossCollection,TotalGainLossCollection totalGainLossCollection) + { + if(null==activeGainLossCollection||null==totalGainLossCollection)return; + Dictionary activeGainLossCollectionByDate=new Dictionary(); + Dictionary totalGainLossCollectionByDate=new Dictionary(); + foreach(GainLossItem gainLossItem in activeGainLossCollection)if(!activeGainLossCollectionByDate.ContainsKey(gainLossItem.Date))activeGainLossCollectionByDate.Add(gainLossItem.Date,gainLossItem); + foreach(TotalGainLossItem gainLossItem in totalGainLossCollection)if(!totalGainLossCollectionByDate.ContainsKey(gainLossItem.Date))totalGainLossCollectionByDate.Add(gainLossItem.Date,gainLossItem); + List dates=new List(activeGainLossCollectionByDate.Keys); + dates.Sort(); + foreach(DateTime date in dates) + { + GainLossItem activeGainLossItem=activeGainLossCollectionByDate[date]; + if(!totalGainLossCollectionByDate.ContainsKey(date))continue; + TotalGainLossItem totalGainLossItem=totalGainLossCollectionByDate[date]; + GainLossCompoundModel gainLossModel=new GainLossCompoundModel(); + gainLossModel.Date=activeGainLossItem.Date; + gainLossModel.ActiveExposure=activeGainLossItem.Exposure; + gainLossModel.ActiveGainLoss=activeGainLossItem.GainLoss; + gainLossModel.ActiveGainLossPercent=activeGainLossItem.GainLossPercent; + gainLossModel.TotalGainLoss=totalGainLossItem.TotalGainLoss; + gainLossModel.TotalGainLossPercent=totalGainLossItem.TotalGainLossPercent; + gainLossModel.TotalDividendsPaid=totalGainLossItem.TotalDividendsPaid; + Add(gainLossModel); + } + } + public DMAValues DMAValuesActiveGainLoss + { + get + { + DMAValues dmaValues = new DMAValues(); + foreach (GainLossCompoundModel gainLoss in this) + { + dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.ActiveGainLoss)); + } + return dmaValues; + } + } + public DMAValues DMAValuesTotalGainLoss + { + get + { + DMAValues dmaValues = new DMAValues(); + foreach (GainLossCompoundModel gainLoss in this) + { + dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.TotalGainLoss)); + } + return dmaValues; + } + } + public DMAValues DMAValuesActiveGainLossPercent + { + get + { + DMAValues dmaValues = new DMAValues(); + foreach (GainLossCompoundModel gainLoss in this) + { + dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.ActiveGainLossPercent)); + } + return dmaValues; + } + } + public DMAValues DMAValuesTotalGainLossPercent + { + get + { + DMAValues dmaValues = new DMAValues(); + foreach (GainLossCompoundModel gainLoss in this) + { + dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.TotalGainLossPercent)); + } + return dmaValues; + } + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossItem.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossItem.cs new file mode 100755 index 0000000..ba57de3 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossItem.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ +// ********************************************************************************************************************************************************************* +// ************************************************************************ G A I N L O S S ************************************************************************** +// ********************************************************************************************************************************************************************* +// This gain loss provides a picture of the Active Gain/Loss. The gain loss on open positions + public class GainLossItem : IComparable + { + private DateTime date; + private double gainLoss; + private double gainLossPercent; + private double exposure; + private double dividends; + private bool valueIsPercent; + public GainLossItem() + { + } + public GainLossItem(DateTime date, double gainLoss,double exposure,bool valueIsPercent) + { + this.date = date; + this.gainLoss = gainLoss; + this.exposure = exposure; + this.valueIsPercent = valueIsPercent; + } + public GainLossItem(DateTime date, double gainLoss,double gainLossPercent,double exposure,bool valueIsPercent) + { + this.date = date; + this.gainLoss = gainLoss; + this.gainLossPercent=gainLossPercent; + this.exposure = exposure; + this.valueIsPercent = valueIsPercent; + } + public GainLossItem(DateTime date, double gainLoss,double gainLossPercent,double exposure,double dividends,bool valueIsPercent) + { + this.date = date; + this.gainLoss = gainLoss; + this.gainLossPercent=gainLossPercent; + this.exposure = exposure; + this.dividends=dividends; + this.valueIsPercent = valueIsPercent; + } + public DateTime Date + { + get { return date; } + } + public double Exposure + { + get + { + return exposure; + } + } + public double GainLoss + { + get { return gainLoss; } + } + public double Dividends + { + get{return dividends;} + } + public double GainLossPercent + { + get { return gainLossPercent; } + } + public bool ValueIsPercent + { + get + { + return valueIsPercent; + } + set + { + valueIsPercent = value; + } + } + public String FormattedGainLoss + { + get + { + if (valueIsPercent) return Utility.FormatNumber(gainLoss); + return Utility.FormatCurrency(gainLoss); + } + } + public int CompareTo(Object obj) + { + if (!obj.GetType().IsInstanceOfType(this)) throw new Exception("Expected GainLoss"); + GainLossItem that = (GainLossItem)obj; + return date.CompareTo(that.Date); + } + } + public class GainLossCollection : List + { + public GainLossCollection(ICollection gainLoss) + : base(gainLoss) + { + } + public DMAValues DMAValues + { + get + { + DMAValues dmaValues = new DMAValues(); + foreach (GainLossItem gainLoss in this) + { + dmaValues.Add(new DMAValue(gainLoss.Date,gainLoss.GainLoss)); + } + return dmaValues; + } + } + public void WriteToDisk(String strPathFileName) + { + FileStream outStream=new FileStream(strPathFileName,FileMode.Create); + StreamWriter streamWriter=new StreamWriter(outStream); + streamWriter.WriteLine("Date,GainLoss,GainLossPercent,Exposure,Dividends,ValueIsPercent"); + foreach(GainLossItem item in this) + { + StringBuilder sb=new StringBuilder(); + sb.Append(item.Date.ToShortDateString()).Append(","); + sb.Append(item.GainLoss).Append(","); + sb.Append(item.GainLossPercent).Append(","); + sb.Append(item.Exposure).Append(","); + sb.Append(item.Dividends).Append(","); + sb.Append(item.ValueIsPercent); + streamWriter.WriteLine(sb.ToString()); + } + streamWriter.Flush(); + streamWriter.Close(); + streamWriter.Dispose(); + outStream.Close(); + outStream.Dispose(); + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossSummaryItem.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossSummaryItem.cs new file mode 100755 index 0000000..82ffdd5 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossSummaryItem.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ + public class GainLossSummaryItem + { + public GainLossSummaryItem() + { + } + public DateTime Date { get; set; } + public String Symbol { get; set; } + public String CompanyName { get; set; } + public double CurrentGainLoss { get; set; } + public double PreviousGainLoss { get; set; } + public double Change { get; set; } + public double ChangePercent { get; set; } + public bool HasStopLimit{get;set;} + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossSummaryItemCollection.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossSummaryItemCollection.cs new file mode 100755 index 0000000..6cff020 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/GainLossSummaryItemCollection.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +// The summary item collection is the data behind the views right-hand grid. This view shows the gain/loss for the date that is selected in the compound model + +namespace MarketData.MarketDataModel.GainLoss +{ + public class GainLossSummaryItemCollection:List + { + public GainLossSummaryItemCollection() + { + } + public GainLossSummaryItemCollection(PortfolioTrades portfolioTrades,ITotalGainLossGenerator gainLossGenerator,IActiveGainLossGenerator activeGainLossGenerator,DateTime? maxDateRef=null) + { + List symbols=portfolioTrades.Symbols; + + if(null==gainLossGenerator || null==activeGainLossGenerator)return; + + foreach(String symbol in symbols) + { + PortfolioTrades portfolioTradesSymbol=portfolioTrades.FilterSymbol(symbol); + GainLossCollection gainLossCollection=activeGainLossGenerator.GenerateGainLoss(portfolioTradesSymbol,maxDateRef); + + TotalGainLossCollection totalGainLossCollection=gainLossGenerator.GenerateTotalGainLoss(portfolioTradesSymbol,maxDateRef); + GainLossCompoundModelCollection gainLossCompoundModelCollection=new GainLossCompoundModelCollection(gainLossCollection,totalGainLossCollection); + + if(1>gainLossCompoundModelCollection.Count) continue; + GainLossSummaryItem gainLossSummaryItem=new GainLossSummaryItem(); + gainLossSummaryItem.Date=gainLossCompoundModelCollection[gainLossCompoundModelCollection.Count-1].Date; + gainLossSummaryItem.Symbol=symbol; + gainLossSummaryItem.CompanyName=PricingDA.GetNameForSymbol(symbol); + gainLossSummaryItem.CurrentGainLoss=gainLossCompoundModelCollection[gainLossCompoundModelCollection.Count-1].ActiveGainLoss; + double previousGainLoss=1==gainLossCompoundModelCollection.Count?0.00:gainLossCompoundModelCollection[gainLossCompoundModelCollection.Count-2].ActiveGainLoss; + gainLossSummaryItem.PreviousGainLoss=previousGainLoss; + gainLossSummaryItem.Change=gainLossSummaryItem.CurrentGainLoss-gainLossSummaryItem.PreviousGainLoss; + if(1==gainLossCollection.Count) gainLossSummaryItem.ChangePercent=0.00; + else + { + double currentMarketValue=gainLossCollection[gainLossCollection.Count-1].Exposure+gainLossCollection[gainLossCollection.Count-1].GainLoss; + double previousMarketValue=gainLossCollection[gainLossCollection.Count-2].Exposure+gainLossCollection[gainLossCollection.Count-2].GainLoss; + if(0.00==previousMarketValue) gainLossSummaryItem.ChangePercent=0.00; + else gainLossSummaryItem.ChangePercent=((currentMarketValue-previousMarketValue)/previousMarketValue)*100; + if(gainLossSummaryItem.CurrentGainLoss<0&&gainLossSummaryItem.PreviousGainLoss<0) + { // if current gainloss is negative and previous gainloss is negative then show change percent as a further dip into negative (i.e.) make sure sign is negative + if(Math.Abs(gainLossSummaryItem.CurrentGainLoss)>Math.Abs(gainLossSummaryItem.PreviousGainLoss)) gainLossSummaryItem.ChangePercent=Math.Abs(gainLossSummaryItem.ChangePercent)*-1.00; + } + else if(gainLossSummaryItem.CurrentGainLoss<0&&gainLossSummaryItem.PreviousGainLoss>0) + { + gainLossSummaryItem.ChangePercent=Math.Abs(gainLossSummaryItem.ChangePercent)*-1.00; + } + else if(gainLossSummaryItem.CurrentGainLoss>0&&gainLossSummaryItem.PreviousGainLoss>0) + { + if(gainLossSummaryItem.CurrentGainLoss symbols=portfolioTrades.Symbols; + foreach(String symbol in symbols) + { + PortfolioTrades portfolioTradesSymbol=portfolioTrades.FilterSymbol(symbol); + ITotalGainLossGenerator gainLossGenerator=new GainLossGenerator(); + IActiveGainLossGenerator activeGainLossGenerator=new ActiveGainLossGenerator(); + GainLossCollection gainLossCollection=activeGainLossGenerator.GenerateGainLoss(portfolioTradesSymbol,maxDateRef); + TotalGainLossCollection totalGainLossCollection=gainLossGenerator.GenerateTotalGainLoss(portfolioTradesSymbol,maxDateRef); + GainLossCompoundModelCollection gainLossCompoundModelCollection=new GainLossCompoundModelCollection(gainLossCollection,totalGainLossCollection); + if(1>gainLossCompoundModelCollection.Count) continue; + GainLossSummaryItem gainLossSummaryItem=new GainLossSummaryItem(); + gainLossSummaryItem.Date=gainLossCompoundModelCollection[gainLossCompoundModelCollection.Count-1].Date; + gainLossSummaryItem.Symbol=symbol; + gainLossSummaryItem.CompanyName=PricingDA.GetNameForSymbol(symbol); + gainLossSummaryItem.CurrentGainLoss=gainLossCompoundModelCollection[gainLossCompoundModelCollection.Count-1].ActiveGainLoss; + double previousGainLoss=1==gainLossCompoundModelCollection.Count?0.00:gainLossCompoundModelCollection[gainLossCompoundModelCollection.Count-2].ActiveGainLoss; + gainLossSummaryItem.PreviousGainLoss=previousGainLoss; + gainLossSummaryItem.Change=gainLossSummaryItem.CurrentGainLoss-gainLossSummaryItem.PreviousGainLoss; + if(1==gainLossCollection.Count) gainLossSummaryItem.ChangePercent=0.00; + else + { + double currentMarketValue=gainLossCollection[gainLossCollection.Count-1].Exposure+gainLossCollection[gainLossCollection.Count-1].GainLoss; + double previousMarketValue=gainLossCollection[gainLossCollection.Count-2].Exposure+gainLossCollection[gainLossCollection.Count-2].GainLoss; + if(0.00==previousMarketValue) gainLossSummaryItem.ChangePercent=0.00; + else gainLossSummaryItem.ChangePercent=((currentMarketValue-previousMarketValue)/previousMarketValue)*100; + if(gainLossSummaryItem.CurrentGainLoss<0&&gainLossSummaryItem.PreviousGainLoss<0) + { // if current gainloss is negative and previous gainloss is negative then show change percent as a further dip into negative (i.e.) make sure sign is negative + if(Math.Abs(gainLossSummaryItem.CurrentGainLoss)>Math.Abs(gainLossSummaryItem.PreviousGainLoss)) gainLossSummaryItem.ChangePercent=Math.Abs(gainLossSummaryItem.ChangePercent)*-1.00; + } + else if(gainLossSummaryItem.CurrentGainLoss<0&&gainLossSummaryItem.PreviousGainLoss>0) + { + gainLossSummaryItem.ChangePercent=Math.Abs(gainLossSummaryItem.ChangePercent)*-1.00; + } + else if(gainLossSummaryItem.CurrentGainLoss>0&&gainLossSummaryItem.PreviousGainLoss>0) + { + if(gainLossSummaryItem.CurrentGainLoss gainLossSummaryItemCollection) + { + foreach(GainLossSummaryItem gainLossSummaryItem in gainLossSummaryItemCollection) Add(gainLossSummaryItem); + } + public GainLossSummaryItemCollection SortByChange() + { + GainLossSummaryItemCollection gainLossSummaryCollection=new GainLossSummaryItemCollection((from GainLossSummaryItem gainLossSummaryItem in this orderby gainLossSummaryItem.Date descending,gainLossSummaryItem.Change descending,gainLossSummaryItem.Symbol descending select gainLossSummaryItem).ToList()); + return gainLossSummaryCollection; + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortGainLossCompoundModelYearDescendingOrder.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortGainLossCompoundModelYearDescendingOrder.cs new file mode 100755 index 0000000..7586b32 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortGainLossCompoundModelYearDescendingOrder.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ + public class SortGainLossCompoundModelYearDescendingOrder : IComparer + { + int IComparer.Compare(GainLossCompoundModel gainLossA, GainLossCompoundModel gainLossB) + { + if (gainLossA.Date < gainLossB.Date) return 1; + if (gainLossA.Date > gainLossB.Date) return -1; + return 0; + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortTotalGainLossYearDescendingOrder.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortTotalGainLossYearDescendingOrder.cs new file mode 100755 index 0000000..efaf53f --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortTotalGainLossYearDescendingOrder.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ + public class SortTotalGainLossYearDescendingOrder:IComparer + { + int IComparer.Compare(TotalGainLossItem gainLossA,TotalGainLossItem gainLossB) + { + if(gainLossA.DategainLossB.Date) return -1; + return 0; + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortYearDescendingOrder.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortYearDescendingOrder.cs new file mode 100755 index 0000000..c0211a7 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/SortYearDescendingOrder.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ + public class SortYearDescendingOrder:IComparer + { + int IComparer.Compare(GainLossItem gainLossA,GainLossItem gainLossB) + { + if(gainLossA.DategainLossB.Date) return -1; + return 0; + } + } +} + diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/TotalGainLossCollection.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/TotalGainLossCollection.cs new file mode 100755 index 0000000..fcc1ba4 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/TotalGainLossCollection.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ +// **************************************************************************************************************************************************** +// ********************************************************************** T O T A L G A I N L O S S ************************************************* +// **************************************************************************************************************************************************** +// This Gain/Loss provides a picture of the total Gain/Loss. This is Gain/Loss generated by all trades + public class TotalGainLossCollection : List + { + public TotalGainLossCollection(ICollection gainLoss) + : base(gainLoss) + { + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/GainLoss/TotalGainLossItem.cs b/MarketData/MarketDataLib/MarketDataModel/GainLoss/TotalGainLossItem.cs new file mode 100755 index 0000000..fc49588 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/GainLoss/TotalGainLossItem.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using MarketData.Utils; +using System.Collections.ObjectModel; +using MarketData.Generator.GainLoss; +using MarketData.DataAccess; + +namespace MarketData.MarketDataModel.GainLoss +{ +// **************************************************************************************************************************************************** +// ********************************************************************** T O T A L G A I N L O S S ************************************************* +// **************************************************************************************************************************************************** +// This Gain/Loss provides a picture of the total Gain/Loss. This is Gain/Loss generated by all trades + public class TotalGainLossItem : IComparable + { + //public TotalGainLossItem() + //{ + //} + public TotalGainLossItem(DateTime date,double totalGainLoss,double totalGainLossPercent,double totalExposure,double totalMarketValue) + { + Date=date; + TotalGainLoss=totalGainLoss; + TotalExposure=totalExposure; + TotalMarketValue=totalMarketValue; + TotalGainLossPercent=totalGainLossPercent; + } + public TotalGainLossItem(DateTime date,double totalGainLoss,double totalGainLossPercent,double totalExposure,double totalMarketValue,double totalDividendsPaid) + { + Date=date; + TotalGainLoss=totalGainLoss; + TotalExposure=totalExposure; + TotalMarketValue=totalMarketValue; + TotalGainLossPercent=totalGainLossPercent; + TotalDividendsPaid=totalDividendsPaid; + } + public DateTime Date{get;private set;} + public double TotalGainLoss{get;private set;} + public double TotalGainLossPercent{get;private set;} + public double TotalExposure{get;private set;} + public double TotalMarketValue{get;private set;} + public double TotalDividendsPaid{get;private set;} + public int CompareTo(Object obj) + { + if (!obj.GetType().IsInstanceOfType(this)) throw new Exception("Expected GainLoss"); + TotalGainLossItem that = (TotalGainLossItem)obj; + return Date.CompareTo(that.Date); + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/Headlines.cs b/MarketData/MarketDataLib/MarketDataModel/Headlines.cs new file mode 100755 index 0000000..fd68345 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/Headlines.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.MarketDataModel +{ + public class HeadlinesEqualityComparer : IEqualityComparer + { + public bool Equals(Headline x,Headline y) + { + if(null==x || null ==y || null==x.Entry || null==y.Entry)return false; + if(x.Date.Equals(y.Date) && x.Entry.Equals(y.Entry))return false; + return true; + } + public int GetHashCode(Headline headline) + { + return (headline.Date.ToShortDateString()+headline.Entry).GetHashCode(); + } + } + public class Headlines : List + { + public Headlines() + { + } + public Headlines(List headlines) + { + foreach(Headline headline in headlines)Add(headline); + } + } + public class Headline + { + public Headline() + { + } + public Headline(Headline headline) + { + Date=headline.Date; + Symbol=headline.Symbol; + CompanyName=headline.CompanyName; + Entry=headline.Entry; + Modified=headline.Modified; + Source=headline.Source; + } + public Headline(String symbol,DateTime date,String entry) + { + Symbol=symbol; + Date=date; + Entry=entry; + Modified=DateTime.Now; + } + public DateTime Date{get;set;} + public String Symbol{get;set;} + public String CompanyName{get;set;} + public String Entry{get;set;} + public DateTime Modified{get;set;} + public String Source{get;set;} + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/IncomeStatement.cs b/MarketData/MarketDataLib/MarketDataModel/IncomeStatement.cs new file mode 100755 index 0000000..b09f709 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/IncomeStatement.cs @@ -0,0 +1,165 @@ +using System; +using System.Text; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class IncomeStatement + { + public enum PeriodType { Annual=0,Quarterly=1} + private String symbol; + private DateTime asof; + private double totalRevenue=double.NaN; + private double costOfRevenue=double.NaN; + private double incomeTaxExpense=double.NaN; + private double grossProfit = double.NaN; + private double netIncome = double.NaN; + private double sga = double.NaN; + private double netIncomeApplicableToCommonShares = double.NaN; + private double ebit = double.NaN; + private double operatingExpenses = double.NaN; + private double researchAndDevelopment = double.NaN; + private double interestExpense = double.NaN; + private PeriodType period; + private DateTime modified; + + public IncomeStatement() + { + } +// It is appropriate to use the AsOf date in the comparison of the financial statements because the AsOf date is the statement date. + public void MergeFrom(IncomeStatement previousIncomeStatement) + { + if(null==previousIncomeStatement)return; + if(!Symbol.Equals(previousIncomeStatement.Symbol))return; + if(!AsOf.Date.Equals(previousIncomeStatement.AsOf.Date))return; + if(!Period.Equals(previousIncomeStatement.Period))return; + if(Utility.IsZeroOrNaN(TotalRevenue))TotalRevenue=previousIncomeStatement.TotalRevenue; + if(Utility.IsZeroOrNaN(CostOfRevenue))CostOfRevenue=previousIncomeStatement.CostOfRevenue; + if(Utility.IsZeroOrNaN(IncomeTaxExpense))IncomeTaxExpense=previousIncomeStatement.IncomeTaxExpense; + if(Utility.IsZeroOrNaN(GrossProfit))GrossProfit=previousIncomeStatement.GrossProfit; + if(Utility.IsZeroOrNaN(NetIncome))NetIncome=previousIncomeStatement.NetIncome; + if(Utility.IsZeroOrNaN(SGA))SGA=previousIncomeStatement.SGA; + if(Utility.IsZeroOrNaN(NetIncomeApplicableToCommonShares))NetIncomeApplicableToCommonShares=previousIncomeStatement.NetIncomeApplicableToCommonShares; + if(Utility.IsZeroOrNaN(EBIT))EBIT=previousIncomeStatement.EBIT; + if(Utility.IsZeroOrNaN(OperatingExpenses))OperatingExpenses=previousIncomeStatement.OperatingExpenses; + if(Utility.IsZeroOrNaN(ResearchAndDevelopment))ResearchAndDevelopment=previousIncomeStatement.ResearchAndDevelopment; + if(Utility.IsZeroOrNaN(InterestExpense))InterestExpense=previousIncomeStatement.InterestExpense; + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public DateTime AsOf + { + get { return asof; } + set { asof = value; } + } + public double TotalRevenue + { + get { return totalRevenue; } + set { totalRevenue = value; } + } + public double CostOfRevenue + { + get { return costOfRevenue; } + set { costOfRevenue = value; } + } + public double GrossProfit + { + get { return grossProfit; } + set { grossProfit = value; } + } + public double NetIncome + { + get { return netIncome; } + set { netIncome = value; } + } +// this number is expressed as a percentage so multiply result by 100 to get the percent. +// this number tells you how much of every sales dollar you get to use in the business. + public double GrossMargin + { + get + { + if (double.IsNaN(GrossProfit) || double.IsNaN(TotalRevenue)) return double.NaN; + return (GrossProfit / TotalRevenue); + } + } + public double IncomeTaxExpense + { + get { return incomeTaxExpense; } + set { incomeTaxExpense = value; } + } + public double SGA + { + get { return sga; } + set { sga = value; } + } + public double NetIncomeApplicableToCommonShares + { + get { return netIncomeApplicableToCommonShares; } + set { netIncomeApplicableToCommonShares = value; } + } + public double EBIT + { + get { return ebit; } + set { ebit = value; } + } + public double OperatingExpenses + { + get { return operatingExpenses; } + set { operatingExpenses = value; } + } + public double ResearchAndDevelopment + { + get { return researchAndDevelopment; } + set { researchAndDevelopment = value; } + } + public double InterestExpense + { + get { return interestExpense; } + set { interestExpense = value; } + } + public PeriodType Period + { + get { return period; } + set { period = value; } + } + public String PeriodAsString + { + get { return PeriodType.Quarterly.Equals(period) ? "Quarterly" : "Annual"; } + } + public DateTime Modified + { + get { return modified; } + set { modified = value; } + } + public static String Heading + { + get + { + StringBuilder sb = new StringBuilder(); + sb.Append("Symbol,AsOf,TotalRevenue,CostOfRevenue,IncomeTaxExpense,GrossProfit,NetIncome,SG&A,NetIncomeApplicableToCommonShares,EBIT,Period"); + return sb.ToString(); + } + } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(symbol).Append(","); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(asof)).Append(","); + sb.Append(String.Format("{0:C}", totalRevenue)).Append(","); + sb.Append(String.Format("{0:C}", costOfRevenue)).Append(","); + sb.Append(String.Format("{0:C}", incomeTaxExpense)).Append(","); + sb.Append(String.Format("{0:C}", grossProfit)).Append(","); + sb.Append(String.Format("{0:C}", netIncome)).Append(","); + sb.Append(String.Format("{0:C}", sga)).Append(","); + sb.Append(String.Format("{0:C}", netIncomeApplicableToCommonShares)).Append(","); + sb.Append(String.Format("{0:C}", ebit)).Append(","); + sb.Append(String.Format("{0:C}", interestExpense)).Append(","); + sb.Append(PeriodAsString); + return sb.ToString(); + } + } +} + diff --git a/MarketData/MarketDataLib/MarketDataModel/InsiderTransaction.cs b/MarketData/MarketDataLib/MarketDataModel/InsiderTransaction.cs new file mode 100755 index 0000000..ed2807c --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/InsiderTransaction.cs @@ -0,0 +1,80 @@ +using System; +using System.Text; +using System.Collections.Generic; +using MarketData.Utils; +using MarketData.Numerical; + +namespace MarketData.MarketDataModel +{ + public class InsiderTransactionSummaries : List + { + public InsiderTransactionSummaries(List insiderTransactionSummaries) + { + foreach(InsiderTransactionSummary insiderTransactionSummary in insiderTransactionSummaries)Add(insiderTransactionSummary); + } + public InsiderTransactionSummaries() + { + } + } + public class InsiderTransactionSummary : IComparable, IBinValueExtractor + { + public String Symbol{get;set;} + public DateTime TransactionDate{get;set;} + public double NumberOfSharesAcquiredDisposed{get;set;} + public double BinValue() + { + return NumberOfSharesAcquiredDisposed; + } + public int CompareTo(Object item) + { + InsiderTransactionSummary other=(InsiderTransactionSummary)item; + return NumberOfSharesAcquiredDisposed.CompareTo(other.NumberOfSharesAcquiredDisposed); + } + } + public class InsiderTransactions : List + { + } + public class InsiderTransaction + { + public String Symbol { get; set; } + public DateTime FilingDate { get; set; } + public DateTime TransactionDate { get; set; } + public String InsiderName { get; set; } + public String OwnershipType { get; set; } + public String Securities { get; set; } + public String NatureOfTransaction { get; set; } + public double NumberOrValueAcquiredDisposed { get; set; } + public double Price { get; set; } + public String Form { get; set; } + public String SECAccessionNumber { get; set; } + public String FormRowNumber { get; set; } + public DateTime Modified { get;set; } + public static String Header + { + get + { + StringBuilder sb=new StringBuilder(); + sb.Append("Symbol,FilingDSate,TransactionDate,InsiderName,OwnershipType,Securities,NatureOfTransaction,NumberOrValueAcquiredDisposed,Price,Form,SECAccessionNumber,FormRowNumber,Modified"); + return sb.ToString(); + } + } + public override string ToString() + { + StringBuilder sb=new StringBuilder(); + sb.Append(Utility.AddQuotes(Symbol)).Append(","); + sb.Append(Utility.AddQuotes(FilingDate.ToShortDateString())).Append(","); + sb.Append(Utility.AddQuotes(TransactionDate.ToShortDateString())).Append(","); + sb.Append(Utility.AddQuotes(InsiderName)).Append(","); + sb.Append(Utility.AddQuotes(OwnershipType)).Append(","); + sb.Append(Utility.AddQuotes(Securities)).Append(","); + sb.Append(Utility.AddQuotes(NatureOfTransaction)).Append(","); + sb.Append(Utility.AddQuotes(Utility.FormatNumber(NumberOrValueAcquiredDisposed,2,true))).Append(","); + sb.Append(Utility.AddQuotes(Utility.FormatNumber(Price,2,true))).Append(","); + sb.Append(Utility.AddQuotes(Form)).Append(","); + sb.Append(Utility.AddQuotes(SECAccessionNumber)).Append(","); + sb.Append(Utility.AddQuotes(FormRowNumber)).Append(","); + sb.Append(Utility.AddQuotes(Modified.ToShortDateString())); + return sb.ToString(); + } + } + } diff --git a/MarketData/MarketDataLib/MarketDataModel/KeyValue.cs b/MarketData/MarketDataLib/MarketDataModel/KeyValue.cs new file mode 100755 index 0000000..2515d2c --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/KeyValue.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.MarketDataModel +{ + public class KeyValue + { + public KeyValue() + { + } + public KeyValue(String key,String value) + { + Key=key; + Value=value; + } + public String Key{get;set;} + public String Value{get;set;} + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/Lexical.cs b/MarketData/MarketDataLib/MarketDataModel/Lexical.cs new file mode 100755 index 0000000..331dc5d --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/Lexical.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MarketData.MarketDataModel +{ + public class LexicalDictionary : Dictionary + { + public LexicalDictionary() + { + } + public LexicalCollection ToList() + { + List lexicalElements=new List(this.Values); + return new LexicalCollection(lexicalElements); + } + } + public class LexicalElement + { + public const String POSITIVE_SENTIMENT="Positive"; + public const String NEGATIVE_SENTIMENT="Negative"; + public const String NEUTRAL_SENTIMENT="Neutral"; + public const String VERB="verb"; + public const String ADJECTIVE="adjective"; + public const String ADVERB="adverb"; + public const String NOUN="noun"; + public const String CONJUNCTION="conjunction"; + + public LexicalElement() + { + } + public LexicalElement(String word,String sentiment) + { + Word=word; + Sentiment=sentiment; + } + public String Word{get;set;} + public String PartOfSpeech{get;set;} + public String Sentiment{get;set;} + } + public class LexicalCollection : List + { + public LexicalCollection() + { + } + public LexicalCollection(List lexicalCollection) + { + foreach(LexicalElement lexicalElement in lexicalCollection)Add(lexicalElement); + } + public LexicalDictionary ToDictionary(String sentiment) + { + LexicalDictionary lexicalCollectionDictionary=new LexicalDictionary(); + List lexicalCollection=(from LexicalElement lexicalElement in this where lexicalElement.Sentiment.Equals(sentiment) select lexicalElement).ToList(); + foreach(LexicalElement lexicalElement in lexicalCollection)lexicalCollectionDictionary.Add(lexicalElement.Word,lexicalElement); + return lexicalCollectionDictionary; + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/MACD.cs b/MarketData/MarketDataLib/MarketDataModel/MACD.cs new file mode 100755 index 0000000..f059d95 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/MACD.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class MACDFastSlowSignalsComparerDesc : IComparer + { + public int Compare(MACDFastSlowSignal macd1, MACDFastSlowSignal macd2) + { + if (macd1.Date < macd2.Date) return -1; + else if (macd1.Date > macd2.Date) return 1; + return 0; + } + } + public class MACDFastSlowSignalsComparerAsc : IComparer + { + public int Compare(MACDFastSlowSignal macd1, MACDFastSlowSignal macd2) + { + if (macd1.Date > macd2.Date) return -1; + else if (macd1.Date < macd2.Date) return 1; + return 0; + } + } + public class MACDFastSlowSignals : List + { + private String symbol; + private DateTime fromDate; + private DateTime thruDate; + private DateTime date; + public MACDFastSlowSignals() + { + } + public MACDFastSlowSignals(ICollection collection) + { + IEnumerator enumerator=collection.GetEnumerator(); + while (enumerator.MoveNext()) Add(enumerator.Current); + } + public Signals FastCondensedSignals{get;set;} + public Signals SlowCondensedSignals{get;set;} + public double MinFastMACD + { + get{return (from MACDFastSlowSignal signal in this select signal.MACDFast).Min()-.25;} + } + public double MinSlowMACD + { + get{return (from MACDFastSlowSignal signal in this select signal.MACDSlow).Min()-.25;} + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public DateTime Date + { + get { return date; } + set { date = value; } + } + public DateTime FromDate + { + get { return fromDate; } + set { fromDate = value; } + } + public DateTime ThruDate + { + get { return thruDate; } + set { thruDate = value; } + } + } + public class MACDFastSlowSignal + { + private DateTime date; + private double signalFast; + private double macdFast; + private double signalSlow; + private double macdSlow; + + public MACDFastSlowSignal() + { + } + public DateTime Date + { + get { return date; } + set { date = value; } + } + public double SignalFast + { + get { return signalFast; } + set { signalFast = value; } + } + public double MACDFast + { + get { return macdFast; } + set { macdFast = value; } + } + public double SignalSlow + { + get { return signalSlow; } + set { signalSlow = value; } + } + public double MACDSlow + { + get { return macdSlow; } + set { macdSlow = value; } + } + } + public class MACDSignals : List + { + public MACDSignals() + { + } + public float[] GetMACD(int startIndex, int count) + { + if (startIndex + count > Count) return null; + float[] macdArray = new float[count]; + for (int index = startIndex, arrayIndex = 0; index < startIndex + count; index++, arrayIndex++) + { + macdArray[arrayIndex] = (float)this[index].MACD; + } + return macdArray; + } + } + public class MACDSignal + { + private String symbol; + private DateTime date; + private double fast; // fast 12 + private double slow; // slow 26 + private double signal; // signal 9 + private double macd; + private double histogram; + + public MACDSignal() + { + } + public String Symbol + { + get {return symbol; } + set { symbol = value; } + } + public DateTime Date + { + get { return date; } + set { date = value; } + } + public double Fast + { + get { return fast; } + set { fast = value; } + } + public double Slow + { + get { return slow; } + set { slow = value; } + } + public double Signal + { + get { return signal; } + set { signal = value; } + } + public double MACD + { + get { return macd; } + set { macd = value; } + } + public double Histogram + { + get { return histogram; } + set { histogram = value; } + } + public static String Header + { + get + { + return "Symbol,Date,Fast,Slow,Signal,MACD,Histogram"; + } + } + public override String ToString() + { + StringBuilder sb=new StringBuilder(); + sb.Append(symbol).Append(","); + sb.Append(Utility.DateTimeToStringMMSDDSYYYY(Date)).Append(","); + sb.Append(String.Format("{0:0.00000}",Fast)).Append(","); + sb.Append(String.Format("{0:0.00000}",Slow)).Append(","); + sb.Append(String.Format("{0:0.00000}",Signal)).Append(","); + sb.Append(String.Format("{0:0.00000}",MACD)).Append(","); + sb.Append(String.Format("{0:0.00000}",Histogram)); + return sb.ToString(); + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/MACDSetup.cs b/MarketData/MarketDataLib/MarketDataModel/MACDSetup.cs new file mode 100755 index 0000000..cd5c29f --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/MACDSetup.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MarketData.MarketDataModel +{ + // MACD(12,26,9) is common + // MACD(12,25,9) is another + // MACD(5,35,5) is another alternative + // MACD(8,17,9) is faster, more sensitive + public class MACDSetup + { + public int fast; + public int slow; + public int signal; + + public MACDSetup(String macdSetup) // (12,26,9) , MACD(8,17,9) macd(12,26,9) + { + macdSetup = macdSetup.ToUpper(); + macdSetup = macdSetup.Replace("MACD", ""); + macdSetup = macdSetup.Replace("(", ""); + macdSetup = macdSetup.Replace(")", ""); + String[] macd = macdSetup.Split(','); + fast = int.Parse(macd[0]); + Slow = int.Parse(macd[1]); + signal = int.Parse(macd[2]); + } + public MACDSetup() + { + fast = 12; + slow = 26; + signal = 9; + } + public MACDSetup(int fast, int slow, int signal) + { + this.fast = fast; + this.slow = slow; + this.signal = signal; + } + public int Fast + { + get { return fast; } + set { fast = value; } + } + public int Slow + { + get { return slow; } + set { slow = value; } + } + public int Signal + { + get { return signal; } + set { signal = value; } + } + public override string ToString() + { + return "MACD(" + fast + "," + slow + "," + signal + ")"; + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/MobileDataModels.cs b/MarketData/MarketDataLib/MarketDataModel/MobileDataModels.cs new file mode 100755 index 0000000..e245e61 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/MobileDataModels.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MarketData.Generator; +using MarketData.MarketDataModel.GainLoss; + +namespace MarketData.MarketDataModel +{ +// These are models that were designed to be consumed by the mobile platform + public class PortfolioTradesWithParityPrice + { + public PortfolioTradesWithParityPrice(PortfolioTrades portfolioTrades, Price parityPrice) + { + Trades = portfolioTrades; + ParityPrice = parityPrice; + } + public Price ParityPrice { get; set; } + public PortfolioTrades Trades { get; set; } + } +// ************************************************************************************ + public class GainLossSummaryItemDetail: GainLossSummaryItem + { + public GainLossSummaryItemDetail() + { + } + public GainLossSummaryItemDetail(GainLossSummaryItem gainLossSummaryItem) + { + this.Date=gainLossSummaryItem.Date; + this.Symbol=gainLossSummaryItem.Symbol; + this.CompanyName=gainLossSummaryItem.CompanyName; + this.CurrentGainLoss=gainLossSummaryItem.CurrentGainLoss; + this.PreviousGainLoss=gainLossSummaryItem.PreviousGainLoss; + this.Change=gainLossSummaryItem.Change; + this.ChangePercent=gainLossSummaryItem.ChangePercent; + this.HasStopLimit=gainLossSummaryItem.HasStopLimit; + } + public int Lots{get;set;} + public double Shares{get;set;} + public double Exposure{get;set;} + public double DividendYield{get;set;} // decimal + public double AnnualDividend{get;set;} // amount + public ParityElement ParityElement{get;set;} + public double AllTimeGainLossPercent{get;set;} + public double PercentDistanceFromAllTimeGainLossPercent{get;set;} + public Price LatestPrice{get;set;} + public double PriceChange{get;set;} + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/ModelPerformance.cs b/MarketData/MarketDataLib/MarketDataModel/ModelPerformance.cs new file mode 100755 index 0000000..a4c73a6 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/ModelPerformance.cs @@ -0,0 +1,83 @@ +using System; +using System.Text; +using MarketData.Utils; +using System.Collections.Generic; + +namespace MarketData.MarketDataModel +{ + public class ModelPerformanceSeries : List + { + public ModelPerformanceSeries() + { + } + public ModelPerformanceSeries(List modelPerformanceItemList) + { + foreach(ModelPerformanceItem modelPerformanceItem in modelPerformanceItemList) Add(modelPerformanceItem); + } + public void CalculatePerformance() + { + for(int index=0;index + { + private DateTime fromDate; + private DateTime thruDate; + + public MovingAverages() + { + } + public MovingAverages(List list) + { + foreach(MovingAverageElement element in list)Add(element); + } + public DateTime FromDate + { + get { return fromDate; } + set { fromDate = value; } + } + public DateTime ThruDate + { + get { return thruDate; } + set { thruDate = value; } + } + } + public class MovingAverageElement + { + private String symbol; + private DateTime date; + private double close; + private double high; + private double low; + private double ma200; + private double ma100; + private double ma55; + private double ma21; + private double ma5; + + public MovingAverageElement() + { + } + public String Symbol + { + get { return symbol; } + set { symbol = value; } + } + public DateTime Date + { + get { return date; } + set { date = value; } + } + public double Close + { + get { return close; } + set { close = value; } + } + public double High + { + get { return high; } + set { high = value; } + } + public double Low + { + get { return low; } + set { low = value; } + } + public double MA200 + { + get{return ma200;} + set{ma200=value;} + } + public double MA100 + { + get { return ma100; } + set { ma100 = value; } + } + public double MA55 + { + get { return ma55; } + set { ma55 = value; } + } + public double MA21 + { + get { return ma21; } + set { ma21 = value; } + } + public double MA5 + { + get { return ma5; } + set { ma5 = value; } + } + } +} diff --git a/MarketData/MarketDataLib/MarketDataModel/MovingDeviation.cs b/MarketData/MarketDataLib/MarketDataModel/MovingDeviation.cs new file mode 100755 index 0000000..8570efa --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/MovingDeviation.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using MarketData.Numerical; + +namespace MarketData.MarketDataModel +{ + public class MovingDeviation + { + private MovingDeviation() + { + } + public static DMADeviations GenerateMovingDeviation(Prices prices, int dayCount) + { + try + { + DMADeviations dmaDeviations = new DMADeviations(); + + for (int index = 0; index < prices.Count; index++) + { + Price price = prices[index]; + DMADeviation dmaDeviation = new DMADeviation(); + dmaDeviation.Symbol = price.Symbol; + dmaDeviation.Date = price.Date; + float[] pricesArray = prices.GetPrices(index, dayCount); + dmaDeviation.StDevPrice = Numerics.Volatility(ref pricesArray); + if (double.IsNaN(dmaDeviation.StDevPrice)) continue; + dmaDeviation.CurrentPrice = price.Close; + dmaDeviations.Add(dmaDeviation); + } + return dmaDeviations; + } + catch (Exception exception) + { + MDTrace.WriteLine(LogLevel.DEBUG,exception); + return null; + } + } + } + +} diff --git a/MarketData/MarketDataLib/MarketDataModel/OptionsModel.cs b/MarketData/MarketDataLib/MarketDataModel/OptionsModel.cs new file mode 100755 index 0000000..1fcab76 --- /dev/null +++ b/MarketData/MarketDataLib/MarketDataModel/OptionsModel.cs @@ -0,0 +1,335 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; +using System.Threading.Tasks; +using MarketData.Utils; + +namespace MarketData.MarketDataModel +{ + public class EquityPriceShocks : List + { + public static EquityPriceShocks CreateEquityPriceShocks(Price latestPrice, OptionsParams optionsParams) + { + EquityPriceShocks equityPriceShocks = new EquityPriceShocks(); + int[] shocks = { 50, 25, 15, 10, 0, -5, -10, -15, -25, -50 }; + for (int index = 0; index < shocks.Length; index++) + { + EquityPriceShock equityPriceShock = new EquityPriceShock(); + equityPriceShock.Rank = shocks[index]; + if (equityPriceShock.Rank > 0) equityPriceShock.PriceShock = "+" + Utility.FormatNumber(equityPriceShock.Rank, 0, false).ToString() + "%"; + else if (equityPriceShock.Rank < 0) equityPriceShock.PriceShock = Utility.FormatNumber(equityPriceShock.Rank, 0, false) + "%"; + else equityPriceShock.PriceShock = "+-" + Utility.FormatNumber(equityPriceShock.Rank, 0, false) + "%"; + equityPriceShock.Premium = optionsParams.Premium; + equityPriceShock.Rank /= 100.00; + equityPriceShock.MarketPrice = latestPrice.Close + (latestPrice.Close * equityPriceShock.Rank); + equityPriceShock.StrikePrice = optionsParams.Strike; + + // We expect the option to be excercises because the strike price is more favorable than market price + // price our gain loss as if we had purchased at prevailing market price and then sold at the strike price + if (optionsParams.Strike < equityPriceShock.MarketPrice) + { + equityPriceShock.PositionGL = (equityPriceShock.StrikePrice * optionsParams.Shares) - (latestPrice.Close * optionsParams.Shares); + equityPriceShock.TransactionGL = equityPriceShock.Premium + equityPriceShock.PositionGL; + equityPriceShock.ExpectedOutcome = "Option will be assigned."; + } + else + // We expect the option to go un-excercised because the stock can be purchased in the open market more cheaply than at our strike price + // price our gain/loss as if we had purchased at prevailing market prie and then sold at the shock price + { + equityPriceShock.PositionGL = (equityPriceShock.MarketPrice * optionsParams.Shares) - (latestPrice.Close * optionsParams.Shares); + equityPriceShock.TransactionGL = equityPriceShock.Premium + equityPriceShock.PositionGL; + equityPriceShock.ExpectedOutcome = "Option will not be assigned."; + } + equityPriceShocks.Add(equityPriceShock); + } + return equityPriceShocks; + } + } + public class EquityPriceShock + { + public String PriceShock { get; set; } + public double Rank { get; set; } + public double MarketPrice { get; set; } + public double StrikePrice { get; set; } + public double Premium { get; set; } + public double PositionGL { get; set; } + public double TransactionGL { get; set; } + public String ExpectedOutcome { get; set; } + } + [Serializable] + public class OptionsParams + { + private int contracts; + private double shares; + public static int CONTRACT_SIZE = 100; + public String Symbol { get; set; } + public String CompanyName { get; set; } + public double Cashdown { get; set; } + public DateTime ExpirationDate { get; set; } + public double Bid { get; set; } + public double Strike { get; set; } + public double OpenInterest { get; set; } + public double Volume { get; set; } + public double Shares + { + get + { + return shares; + } + } + public int Contracts + { + get + { + return contracts; + } + set + { + contracts = value; + shares = contracts * 100.00; + } + } + public double MarketPrice { get; set; } + public double Premium { get; set; } + public double Volatility { get; set; } + public int VolatilityDays { get; set; } + public static String Header + { + get + { + StringBuilder sb = new StringBuilder(); + sb.Append("Symbol").Append(","); + sb.Append("CompanyName").Append(","); + sb.Append("Cashdown").Append(","); + sb.Append("ExpirationDate").Append(","); + sb.Append("Bid").Append(","); + sb.Append("Strike").Append(","); + sb.Append("OpenInterest").Append(","); + sb.Append("Shares").Append(","); + sb.Append("Contracts").Append(","); + sb.Append("MarketPrice").Append(","); + sb.Append("Premium").Append(","); + sb.Append("Volatility").Append(","); + sb.Append("VolatilityDays"); + return sb.ToString(); + } + } + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("\"").Append(Symbol).Append("\"").Append(","); + sb.Append("\"").Append(CompanyName).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatCurrency(Cashdown)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.DateTimeToStringMMHDDHYYYY(ExpirationDate)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatCurrency(Bid)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatCurrency(Strike)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatNumber(OpenInterest,0,true)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatNumber(Shares)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatNumber(Contracts,0,true)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatCurrency(MarketPrice)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatCurrency(Premium)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatCurrency(Volatility)).Append("\"").Append(","); + sb.Append("\"").Append(Utility.FormatNumber(VolatilityDays,0,false)).Append("\""); + return sb.ToString(); + } + } + public class MoneyType + { + public enum MoneyTypeEnum { AtTheMoney, InTheMoney, OutOfTheMoney, Unset }; + public MoneyTypeEnum moneyType = MoneyTypeEnum.Unset; + public MoneyType() + { + moneyType = MoneyTypeEnum.Unset; + } + public MoneyType(double currentPrice, double strikePrice) + { + SetMoney(currentPrice, strikePrice); + } + public MoneyType.MoneyTypeEnum Money + { + get { return moneyType; } + set { moneyType = value; } + } + public void SetMoney(double currentPrice, double strikePrice) + { + double upperPrice = strikePrice + .15; + double lowerPrice = strikePrice - .15; + if (currentPrice <= upperPrice && currentPrice >= lowerPrice) + { + Money = MoneyTypeEnum.AtTheMoney; + } + else if (strikePrice < currentPrice) Money = MoneyTypeEnum.InTheMoney; + else Money = MoneyTypeEnum.OutOfTheMoney; + } + public override string ToString() + { + switch (Money) + { + case MoneyTypeEnum.AtTheMoney: + return "At The Money"; + case MoneyTypeEnum.InTheMoney: + return "In The Money"; + case MoneyTypeEnum.OutOfTheMoney: + return "Out Of The Money"; + default: + return "Unset"; + } + } + } + + +// ******************************************************************************************************************************************************************* +// ************************************************************** P U T C A L L R A T I O C A L C U L A T O R *********************************************** +// ******************************************************************************************************************************************************************* + public class PutCallRatioHelper + { + protected class StrikeExpiryKey + { + public StrikeExpiryKey(double strike,DateTime expiration) + { + Expiration=expiration; + Strike=strike; + } + public DateTime Expiration{get;set;} + public double Strike{get;set;} + public override int GetHashCode() + { + StringBuilder sb=new StringBuilder(); + sb.Append(Expiration.ToShortDateString()).Append(Utility.FormatCurrency(Strike)); + return sb.ToString().GetHashCode(); + } + public override bool Equals(object obj) + { + return Equals(obj as StrikeExpiryKey); + } + public bool Equals(StrikeExpiryKey obj) + { + return obj.ToString().Equals(ToString()); + } + public override String ToString() + { + StringBuilder sb=new StringBuilder(); + sb.Append(Expiration.ToShortDateString()).Append(Utility.FormatCurrency(Strike)); + return sb.ToString(); + } + } + private PutCallRatioHelper() + { + } + public static void CalculatePutCallRatios(Options options) + { + Dictionary putOptions=new Dictionary(); + Dictionary callOptions=new Dictionary(); + foreach(Option option in options) + { + StrikeExpiryKey strikeExpiryKey=new StrikeExpiryKey(option.Strike,option.Expiration); + if(option.Type.Equals(OptionTypeEnum.CallOption)&&!callOptions.ContainsKey(strikeExpiryKey))callOptions.Add(strikeExpiryKey,option); + else if(!putOptions.ContainsKey(strikeExpiryKey))putOptions.Add(strikeExpiryKey,option); + } + foreach(Option option in options) + { + if(option.Volume==0) + { + option.PutCallRatio=double.NaN; + option.CallPutRatio=double.NaN; + continue; + } + StrikeExpiryKey strikeExpiryKey=new StrikeExpiryKey(option.Strike,option.Expiration); + if(option.Type.Equals(OptionTypeEnum.PutOption)) // put options + { + Option callOption=null; + option.CallPutRatio=double.NaN; + if(!callOptions.ContainsKey(strikeExpiryKey)) + { + option.PutCallRatio=double.NaN; + continue; + } + callOption=callOptions[strikeExpiryKey]; + if(0==callOption.Volume) + { + option.PutCallRatio=double.NaN; + continue; + } + option.PutCallRatio=(double)option.Volume/(double)callOption.Volume; + } + else // call options + { + Option putOption=null; + option.PutCallRatio=double.NaN; + if(!putOptions.ContainsKey(strikeExpiryKey)) + { + option.CallPutRatio=double.NaN; + continue; + } + putOption=putOptions[strikeExpiryKey]; + if(0==putOption.Volume) + { + option.CallPutRatio=double.NaN; + continue; + } + option.CallPutRatio=(double)option.Volume/(double)putOption.Volume; + } + } + } + } +// ******************************************************************************************************************************************************************* + + public enum OptionTypeEnum { CallOption, PutOption }; + public class Options : List