using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Configuration;
using MarketData.DataAccess;
using MarketData.MarketDataModel;             
using MarketData.Generator;
using MarketData.Generator.GainLoss;
using MarketData.Helper;
using MarketData.Utils;
using MarketData.Numerical;
using MarketData.ValueAtRisk;
using MarketData.Integration;
using MarketData.Generator.Momentum;
using MarketData.Generator.CMMomentum;
using MarketData.MarketDataModel.GainLoss;
using MarketData.Cache;
using MarketData.Generator.CMTrend;
using Axiom.Interpreter;                                 
using System.Data;
using MarketData.Generator.MovingAverage;
using MarketData.Generator.MGSHMomentum;
using MarketData.Security;
using MarketData.MarketDataModel.User;
using MarketData.Extensions;

namespace MarketData
{
  class Program
  {
    public static void DisplayUsage()
    {
      MDTrace.WriteLine(LogLevel.DEBUG,String.Format("64BIT={0}",Utility.Is64Bit()));
      MDTrace.WriteLine(LogLevel.DEBUG,"usage {service}");
      MDTrace.WriteLine(LogLevel.DEBUG,"****************** T E S T  D A T A  S O U R C E S  E T C .,***************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    RUNPRICECHECKOPENPOSITIONS                - lists the latest available price for the open positions");
      MDTrace.WriteLine(LogLevel.DEBUG,"    SENDSMSEMAIL {message}                    - sends an SMS email to system recipient");
      MDTrace.WriteLine(LogLevel.DEBUG,"****************** D A I L Y   U P D A T E ***************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEDAILY                                  - updates prices, yields, and ratings");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEDAILY2 /DATE:                          - updates prices, yields, and ratings");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEPRICESBIGCHARTS /DATE:                 - updates prices");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEDAILYPRICES /DATE:                          - updates prices BIGCHARTS/YAHOO");
      MDTrace.WriteLine(LogLevel.DEBUG,"****************** M A S T E R   U P D A T E ***************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEALL                                  - updates prices, loads balance sheet and income, loads fundamentals, loads historical");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEALLNOPRICES                          - loads balance sheet and income, loads fundamentals, loads historical");
      MDTrace.WriteLine(LogLevel.DEBUG,"*************** U P D A T E   O P T I O N S   C H A I N S   **************************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEOPTIONSCHAINS                                  - updates all options chains");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEOPTIONSCHAINSSYMBOL /SYMBOL:                            - updates all options chains for symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEOPTIONSCHAINSSYMBOLS /SYMBOLS:                           - updates all options chains for symbols (i.e.) AAPL,MSFT");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEOPTIONSCHAINSWATCHLIST /WATCHLIST:                         - updates all options chains for symbols in watchlist");
      MDTrace.WriteLine(LogLevel.DEBUG,"    DISPLAYAVAILABLEOPTIONS /DAYSOUT: /VERBOSE:[TRUE|FALSE] - displays options matching optimal criteria for covered calls");
      MDTrace.WriteLine(LogLevel.DEBUG,"*************** U P D A T E   C O M P A N Y   P R O F I L E  **************************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATECOMPANYPROFILES                                  - updates all profiles for all symbols");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATECOMPANYPROFILE /SYMBOL:                          - updates all profiles for symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    DISPLAYCOMPANYPROFILES                                 - display market data profiles for all symbols");
      MDTrace.WriteLine(LogLevel.DEBUG,"***************C E N T R A L  I N D E X  K E Y  (Y A H O O  F I N A N C E) **************************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEALLCIK                                  - updates all CIK for all symbols");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEALLMISSINGCIK                           - updates all missing CIK for all symbols");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATECIKSYMBOL /SYMBOL:                               - updates CIK for symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"***************S E C   F I L I N G S **************************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GETSECFILINGSWATCHLIST /WATCHLIST:                    - get SEC filings for valuation");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GETSECFILINGSSYMBOL /SYMBOL:                        - get SEC filings for symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GETSECFILINGSOPENPOSITIONS                     - get SEC filings for for open positions");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATESECFILINGS                           - updates SEC Filings for symbols already covered");
      MDTrace.WriteLine(LogLevel.DEBUG,"***************P R I C E S (Y A H O O  F I N A N C E) **************************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CHECKPRICES :  - looks for price gaps > 5 days, checks continuity of prices");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEMISSINGPRICES /DATE:  - looks through database for missing prices for all securities and attempts to retrieve price.  If date provided will use that date as starting point");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEMISSINGPRICESSYMBOL /SYMBOL:  - update missing prices for symbol.");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEPRICEASOFSYMBOL /SYMBOL: /DATE:    - updates price for given symbol for given date from BIGCHARTS");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEPRICEASOFSYMBOLYAHOO /SYMBOL: /DATE:    - updates price for given symbol for given date from YAHOO");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEPRICESASOF /DATE:                 - updates prices for all symbols for given date");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATELATESTPRICEALL                   - brings prices current for all symbols in database");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATELATESTPRICESYMBOL /SYMBOL:           - brings prices current for all symbols in database");
      MDTrace.WriteLine(LogLevel.DEBUG,"    DELETELATESTPRICESYMBOL /SYMBOL:               - removes latest price for the given symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    DELETEPRICE /SYMBOL: /DATE:               - delete price for symbol on specified date");
      MDTrace.WriteLine(LogLevel.DEBUG,"    DELETEPRICESASOF /DATE:                   - delete all price on specified date");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEPRICES                              - brings prices current for all symbols in database");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEPRICESDATE /DATE:                          - fetched prices for this date");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEPRICESSYMBOL /SYMBOL:                    - brings prices current for specified symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADALLPRICESSYMBOL /SYMBOL:                      - reloads all prices for specified symbol from 01-01-2009");
      MDTrace.WriteLine(LogLevel.DEBUG,"    SHOWALLPRICESSYMBOL /SYMBOL:                      - shows all prices for specified symbol from 01-01-2009");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADALLPRICESSYMBOLDATE /SYMBOL: /DATE:{optional}  - reloads all prices for specified symbol from DATE");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADALLPRICESWATCHLIST /WATCHLIST:                  - reloads all prices for watchlist from 01-01-2009");
      MDTrace.WriteLine(LogLevel.DEBUG,"    ADDPRICE /SYMBOL: /DATE: /TYPE:[OPEN][HIGH][LOW][CLOSE][VOLUME]  - updates symbol with price for specified date");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATELATESTPRICEWATCHLIST /WATCHLIST- updates database with latest price for the symbols in the watchlist");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATELATESTPRICEOPENPOSITIONS - updates database with latest price for the symbols in open positions");
      MDTrace.WriteLine(LogLevel.DEBUG,"    DELETEPRICEWATCHLIST /WATCHLIST: /DATE: - deletes prices for symbols in the watchlist for the specified date");

      MDTrace.WriteLine(LogLevel.DEBUG,"    FINDALLSYMBOLSMISSINGPRICEON /DATE: /ROLLFORWARD:{true}{false} /FILTER:{symbol} - find all symbols that are missing a price on this date. If ROLLFORWARD then roll forward missing price from prior business day (if one found). if FILTER then apply filter to rollforward ");
      MDTrace.WriteLine(LogLevel.DEBUG,"    ROLLPRICEFORWARD /SYMBOL: /FROMDATE: /TODATE:  Roll price forward from the given date to the specified date.");

      MDTrace.WriteLine(LogLevel.DEBUG,"*************************************I N S I D E R  T R A N S A C T I O N S**********************************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADINSIDERTRANSACTIONSSYMBOL /SYMBOL:");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADINSIDERTRANSACTIONS");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADINSIDERTRANSACTIONSYEARGREATEREQUAL /YEAR:");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADINSIDERTRANSACTIONSWATCHLISTS");
      MDTrace.WriteLine(LogLevel.DEBUG,"*******B A L A N C E   S H E E T  A N D  I N C O M E (Y A H O O  F I N A N C E)*****");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADFINANCIALSTATEMENTSSYMBOL /SYMBOL:      - load balance sheet, income statement, and cashflow statement for symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADFINANCIALSTATEMENTS                     - load balance sheet, income statement, and cashflow statement for all");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********F U N D A M E N T A L   D A T A (Y A H O O  F I N A N C E - S U M M A R Y)***************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADFUNDAMENTAL /SYMBOL:");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADFUNDAMENTALS");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADFUNDAMENTALSFINVIZ");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADFUNDAMENTALFINVIZ /SYMBOL");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********H I S T O R I C A    D A T A (M O R N I N G  S T A R )***************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADHISTORICAL");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADHISTORICALSYMBOL /SYMBOL:");
      MDTrace.WriteLine(LogLevel.DEBUG,"*******E C O N O M I C  I N D I C A T O R S  (W O R L D  B A N K ),  H E A D L I N E S, M A R K E T  I N D I C A T O R S  *****");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADGDP - loads annual gdp per capita data from world bank");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADHEADLINESWATCHLIST /WATCHLIST: - loads headlines for the specified watchlist");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADHEADLINESSYMBOL /SYMBOL: - loads headlines for the specified symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    LOADPREMARKETDATA loads pre-market data from CNN (i.e.) S&P Futures, DOW, NASDAQ");
      MDTrace.WriteLine(LogLevel.DEBUG,"********A N A L Y S I S *********************************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCDCF                                   - calculate discounted cashflows");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCSTICKERSYMBOL                         - calculate sticker price for symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCSTICKER                               - calculate main valuation (sticker price) and store to database");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCACQUIRERSMULTIPLE                     - calculate and display acquirers multiple");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCACQUIRERSMULTIPLESYMBOL /SYMBOL:      - calculate and display acquirers multiple for symbol");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCTLBRANKS                              - calculate TLBRanks (ROIC & ROC) and display");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCSTICKERETF /SYMBOL:                   - calculate sticker price for all holdings in ETF");
      MDTrace.WriteLine(LogLevel.DEBUG,"    FINDETFMOS                                - look for ETFs with all holdings within Sticker MOS");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCBETA /SYMBOL: /DAYCOUNT:              - calculate beta for symbol over daycount");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCBETAALL /DAYCOUNT:                    - calculate beta for all symbols over daycount");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CALCPORTFOLIOBETA /ACCOUNT:               - calculate beta for the portfolio or given account");
      MDTrace.WriteLine(LogLevel.DEBUG,"    MAXDIVMINVAR /ANALYSISDATE: /DAYCOUNT: /PERCENTOFEXPOSURE: /EXPOSURE: - picks holdings to add to portfolio which maximize dividends while minimizing VaR");
      MDTrace.WriteLine(LogLevel.DEBUG,"**************************** S T O C H A S T I C S**************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    RUNSTOCHASTICSSYMBOL /SYMBOL:        runs stochastics signal generator");
      MDTrace.WriteLine(LogLevel.DEBUG,"    RUNSTOCHASTICSSIGNALSYMBOL /SYMBOL:        runs stochastics signal generator");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** S W I N G   T R A D E   A N A L Y S I S **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    FINDSWINGTRADESSYMBOL /SYMBOL: /DAYCOUNT:");
      MDTrace.WriteLine(LogLevel.DEBUG,"    FINDCURRENTSWINGTRADES");
      MDTrace.WriteLine(LogLevel.DEBUG,"    FINDCURRENTSWINGTRADESBARGAIN");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** M A C D  A N D  T R A D E  A N A L Y S I S **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    RUNPIVOTS /SYMBOL: /DAYCOUNT:");
      MDTrace.WriteLine(LogLevel.DEBUG,"    RUNMACDSIGNALSYMBOL /SYMBOL: /MACD:[X,Y,Z]    (i.e.)(8,17,9)     - runs the specified symbol and MACD through the signal generator");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GENERATEMOVINGAVERAGESHEET /STRPATHTEMPLATE: /SYMBOL:            - generates 55 day, 21 day, 5 day MA against price.");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GENERATESTOCHASTICS /SYMBOL: /DAYCOUNT: /PERIOD-N:[9] /PERIOD-K:[3]");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GENERATESTOCHASTICSSHEET /STRPATHTEMPLATE: /SYMBOL: /DAYCOUNT:[180] /PERIOD-N:[9] /PERIOD-K:[3]");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GENERATEBOLLINGERBANDS /SYMBOL: /MOVINGAVERAGEDAYS:[20] /HISTORICALDAYS:[180]");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GENERATEBOLLINGERBANDSHEET /STRPATHTEMPLATE: /SYMBOL: /MOVINGAVERAGEDAYS:[20] /HISTORICALDAYS:[180]");
      MDTrace.WriteLine(LogLevel.DEBUG,"    TRADESYMBOL /SYMBOL: /SHARES: /STARTDATE: /HOLDINGDAYS - simulate a historical trade.");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** G A I N  L O S S  **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    SHOWACTIVEGAINLOSS");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** Y I E L D  C U R V E  **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEYIELDCURVE");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEYIELDCURVEHIST /YEARS:");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** E A R N I N G S   A N N O U N C E M E N T  **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEEARNINGSANNOUNCEMENTS");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEEARNINGSANNOUNCEMENTSSYMBOL /SYMBOL:");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** D I V I D E N D  H I S T O R Y  **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEDIVIDENDHISTORY ");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEDIVIDENDHISTORYSYMBOL /SYMBOL:");
      MDTrace.WriteLine(LogLevel.DEBUG, "*********** A N A L Y S T   R A T I N G S   **************");
      MDTrace.WriteLine(LogLevel.DEBUG, "    UPDATELATESTANALYSTRATINGS /CREATESECURITYMASTER:{TRUE|FALSE}");
      MDTrace.WriteLine(LogLevel.DEBUG, "    UPDATEMISSINGANALYSTRATINGS");
      MDTrace.WriteLine(LogLevel.DEBUG, "    UPDATEANALYSTRATINGS /SYMBOL: /MINDATE:");
      MDTrace.WriteLine(LogLevel.DEBUG, "    UPDATEANALYSTPRICETARGET");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** M I S C E L L A N E O U S  **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GETETFHOLDINGS");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GETETFHOLDINGSSYMBOL /SYMBOL:");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEZACKSRANK");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATEZACKSRANKSYMBOL /SYMBOL:");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** S P L I T S   **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    UPDATESPLITS           gets splits from market feed");
      MDTrace.WriteLine(LogLevel.DEBUG,"    PROCESSSPLIT /SYMBOL:  updates the pricing data for the secified split in the splits table");
      MDTrace.WriteLine(LogLevel.DEBUG,"    PROCESSALLSPLITS       updates the pricing data for all of the splits in the splits table");
      MDTrace.WriteLine(LogLevel.DEBUG, "*********** V A L U E  A T  R I S K   **************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GETVAR /DAYCOUNT: /CONFIDENCE: /RETURNDAYS:  (i.e.) GETVAR 30 95 1   ");
      MDTrace.WriteLine(LogLevel.DEBUG,"    GETOPTIMALPOSITIONFROMWATCHLIST /WATCHLIST: /MARKETVALUE: /DAYCOUNT: /CONFIDENCE: /RETURNDAYS:  (i.e.) GETOPTIMALPOSITIONFROMWATCHLIST Valuations 10000 90 95 1");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** C O E F F I C I E N T S ************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    FINDCOEFFICIENTS /SYMBOL: /DAYCOUNT: /STARTDATE:");
      MDTrace.WriteLine(LogLevel.DEBUG, "    DISPLAYVOLATILITY /SYMBOLS: /DAYCOUNT: {/STARTDATE:}");
      MDTrace.WriteLine(LogLevel.DEBUG, "    DISPLAYSHARPERATIO /SYMBOLS: {/MONTHS:} {/STARTDATE:}");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** (C M T R E N D )  M O M E N T U M   G E N E R A T I O N  (M A R C  M I N E R V I N I   &  V A N  T H A R P E - C A N D I D A T E  S E L E C T I O N  B Y  A N D R E A S  C L E N O W ) ************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    RUNCMTREND  /MODE:DAILY|BACKTEST|RUNTRENDTEMPLATE|ENTRYTEST /SYMBOL:{for mode ANALYZE,ENTRYTEST} /TRADEDATE:{for mode DAILY,RUNTRENDTEMPLATE) /STARTDATE:(for mode BACKTEST,ENTRYTEST) /ENDDATE:(for mode BACKTEST) /INITIALCASH: /SESSIONFILE: /MAXOPENPOSITIONS: /MAXDAILYPOSITIONS: Runs Mark Minervini trend");
      MDTrace.WriteLine(LogLevel.DEBUG,"      VALID ARGUMENTS FOR /MODE:BACKTEST ARE /SELLATENDOFSIMULATION: /STARTDATE: /ENDDATE: /SESSIONFILE: /MAXDAILYPOSITIONS: /MAXOPENPOSITIONS: /BENCHMARKMOVINGAVERAGEDAYS: /BENCHMARKMOVINGAVERAGEHORIZON");
      MDTrace.WriteLine(LogLevel.DEBUG,"      VALID ARGUMENTS FOR /MODE:BACKTEST CONTD., /POSITIONRISKPERCENTDECIMAL: /ENTRYTYPE:OverExtended,MVP,PriceTrend,VolumeTrend,RVOL /USEPROFITMAXIMIZATION:{TRUE|FALSE} /USEPROFITMAXIMIZATIONEXPRESSION:{string}");
      MDTrace.WriteLine(LogLevel.DEBUG,"      VALID ARGUMENTS FOR /MODE:BACKTEST CONTD., /POSITIONRISKPERCENTDECIMAL: /ENTRYTYPE:OverExtended,MVP,PriceTrend,VolumeTrend,RVOL /USEPROFITMAXIMIZATION:TRUE /USEPROFITMAXIMIZATIONEXPRESSION:\"R_THRESSHOLD=4;MAX_ATR=3;MAX_R=10;FACTOR=MAX_ATR/MAX_R;MULTIPLIER=MAX_ATR;IF(RMultiple>R_THRESSHOLD){MULTIPLIER=FACTOR*RMultiple;}\"");
      MDTrace.WriteLine(LogLevel.DEBUG,"      VALID ARGUMENTS FOR /MODE:BACKTEST CONTD., /USEPOSITIONSIZINGSTRATEGY:{TRUE|FALSE} /USEPOSITIONSIZINGSTRATEGYSTRATEGY:{TotalRisk:EqualWeight,Formula} /USEPOSITIONSIZINGSTRATEGYFORMULA:{Formula}");
      MDTrace.WriteLine(LogLevel.DEBUG,"      VALID ARGUMENTS FOR /MODE:BACKTEST CONTD., /USETRADEONLYSECTORS:{TRUE|FALSE} /USETRADEONLYSECTORSSECTORS:Healthcare,Technology,Basic Materials,Consumer Defensive,Industrials");
      MDTrace.WriteLine(LogLevel.DEBUG,"      /BENCHMARKMOVINGAVERAGEDAYS: (i.e.) 200, 100, 55");
      MDTrace.WriteLine(LogLevel.DEBUG,"      /BENCHMARKMOVINGAVERAGEHORIZON: (i.e.) 5");
      MDTrace.WriteLine(LogLevel.DEBUG,"    CMTSESSION /SESSIONFILE:{pathfilename}  ");
      MDTrace.WriteLine(LogLevel.DEBUG,"*********** M G  M O M E N T U M  (Q U A N T U M   M O M E N T U M )************");
      MDTrace.WriteLine(LogLevel.DEBUG,"    MGSESSION /SESSIONFILE:");
      MDTrace.WriteLine(LogLevel.DEBUG,@"    MGGAINLOSS /SESSIONFILE:{PATHSESSIONFILE}   (i.e.) MGGAINLOSS /SESSIONFILE:C:\boneyard\marketdata\bin\Debug\saferun\MG20180131.txt");
      MDTrace.WriteLine(LogLevel.DEBUG,"    RUNBACKTEST /STARTDATE: /MAXPOSITIONS: /INITIALCASH: /HOLDINGPERIOD: /{ENDDATE}: /SESSIONFILE:");
      MDTrace.WriteLine(LogLevel.DEBUG,"********** M G S H M O M E N T U M  *********");
      MDTrace.WriteLine(LogLevel.DEBUG,"    MGSHSESSION /SESSIONFILE:");
      MDTrace.WriteLine(LogLevel.DEBUG,"    MGSHRUNBACKTEST /USEHEDGING: /HEDGEINITIALCASH: /USESTOPLIMITS: /KEEPSLOTPOSITIONS: /STARTDATE: /MAXPOSITIONS: /INITIALCASH: /HOLDINGPERIOD: /{ENDDATE}: /SESSIONFILE: ");
      MDTrace.WriteLine(LogLevel.DEBUG,"    MGSHRUNDAILY /SESSIONFILE: /TRADEDATE:");
      MDTrace.WriteLine(LogLevel.DEBUG, "*********** C L E N O W   M O M E N T U M  (C M M O M E N T U M )************");
      MDTrace.WriteLine(LogLevel.DEBUG, "   RUNCMBACKTEST /STARTDATE: /MAXPOSITIONS: /INITIALCASH: /HOLDINGPERIOD: /{USEBINBASEDPOSITIONSIZING}: /{USEBINBASEDPOSITIONSIZINGNUMBINS}: /{TARGETBETA}: /{ENDDATE}: /SESSIONFILE: /{USECNN}: /{USECNNHOST}: /{USECNNDAYCOUNT}:");
      MDTrace.WriteLine(LogLevel.DEBUG, "   CMSESSION /SESSIONFILE:");
      MDTrace.WriteLine(LogLevel.DEBUG, "   CMCANDIDATELASTRESORT /TRADEDATE:");
      MDTrace.WriteLine(LogLevel.DEBUG, @"   CMGAINLOSS /SESSIONFILE:{PATHSESSIONFILE}  (i.e.) CMGAINLOSS /SESSIONFILE:C:\boneyard\marketdata\bin\Debug\saferun\CM20191031.txt");
    }                                                                                                         
// ***************************************************************************************************************************************************************************
    public class Candidate
    {
      public Candidate(String symbol,String companyName,double dividendYieldPcnt,double portfolioVaRPcnt,double dividendLoadPcnt,String sector,String industry)
      {                                                                                                 
        Symbol=symbol;
        CompanyName=companyName;
        DividendYieldPcnt=dividendYieldPcnt;
        PortfolioVaRPcnt=portfolioVaRPcnt;
        DividendLoadPcnt=dividendLoadPcnt;
        Sector=sector;
        Industry=industry;
      }
      public String Symbol{get;set;}
      public String CompanyName{get;set;}
      public double DividendYieldPcnt{get;set;}
      public double PortfolioVaRPcnt{get;set;}
      public double DividendLoadPcnt{get;set;}
      public String Sector{get;set;}
      public String Industry{get;set;}
    }
    private static void MaximizeDividendMinimizeVaR(int dayCount=180,double exposure=double.NaN,double percentOfExposure=5.00/100.00,double varConfidence=95.00)
    {
      String pathOutput="maxdivminvar.csv";
      List<Candidate> candidates=new List<Candidate>();
      DateGenerator dateGenerator=new DateGenerator();
      double investment=double.NaN;
      
      if(double.IsNaN(percentOfExposure))percentOfExposure=5.00/100.00;
      else percentOfExposure/=100.00;
      if(double.IsNaN(varConfidence))varConfidence=95.00;

      FileStream outStream=new FileStream(pathOutput,FileMode.Create);
      StreamWriter streamWriter=new StreamWriter(outStream);
      streamWriter.WriteLine("Symbol,Company,DividendYieldPcnt,PortfolioVaRPcnt,DividendLoadPcnt,Sector,Industry");

      PortfolioTrades portfolioTrades=PortfolioDA.GetOpenTrades();
      if(!double.IsNaN(exposure))investment=exposure;
      else investment=portfolioTrades.Exposure()*percentOfExposure;

      DateTime lastBusinessDate=dateGenerator.FindPrevBusinessDay(DateTime.Now);
      DateTime historicalDate=dateGenerator.GenerateHistoricalDate(lastBusinessDate,dayCount);

      Console.WriteLine(String.Format("MAXDIVMINVAR"));
      Console.WriteLine(String.Format("LASTBUSINESSDATE:{0}",lastBusinessDate.ToShortDateString()));
      Console.WriteLine(String.Format("HISTROICALDATE:{0}",historicalDate.ToShortDateString()));
      Console.WriteLine(String.Format("DAYCOUNT:{0}",dayCount));
      Console.WriteLine(String.Format("INVESTMENT:{0}",investment));
      Console.WriteLine(String.Format("CONFIDENCE:{0}",varConfidence));
      Console.WriteLine(String.Format("OUTPUT:{0}",pathOutput));

      List<String> symbols=PricingDA.GetSymbols();
      foreach(String symbol in symbols)
      {
        double dividendLoadPcnt=double.NaN;
        String sector="";
        String industry="";
        String companyName="";
        portfolioTrades=PortfolioDA.GetOpenTrades();
        List<String> portfolioSymbols=portfolioTrades.Symbols;
//        if(portfolioSymbols.Any(x=>x.Equals(symbol)))continue;
// Historical price check
        Price historicalPrice=PricingDA.GetPrice(symbol,historicalDate);
        if(null==historicalPrice)continue;
        Price currentPrice=PricingDA.GetPrice(symbol);
        if(null==currentPrice)continue;
        if(currentPrice.Close<5.00)continue;

// Volume check
        Prices shortTermPrices=PricingDA.GetPrices(symbol,14);
        if(null==shortTermPrices||shortTermPrices.Count<14)continue;
        float[] volume=shortTermPrices.GetVolume();
        double averageVolume=Numerics.Mean(ref volume);
        if(averageVolume<500000)continue;

// Fundamental check
        Fundamental fundamental=FundamentalDA.GetFundamental(symbol);
        if(null==fundamental)continue;
        if(fundamental.EPS<0)continue;
        if(fundamental.MarketCap<500000000)continue;

// Dividend Yield check
        double dividendYield=DividendHistoryGenerator.GetDividendYield(symbol,currentPrice);
        if(double.IsNaN(dividendYield))continue;
        DividendHistory dividendHistory=DividendHistoryDA.GetDividendHistory(symbol);
        if(dividendHistory.Count<8)continue;

// Company Profile info
        CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol);
        if(null!=companyProfile)
        {
          if(null!=companyProfile.Sector)sector=companyProfile.Sector;
          if(null!=companyProfile.Industry)industry=companyProfile.Industry;
          if(null!=companyProfile.CompanyName)companyName=companyProfile.CompanyName;
        }
        if(sector.Equals("Financial Services")||sector.Equals("Capital Markets")||sector.Equals("Savings & Cooperative Banks")||sector.Equals("Banks - Regional - US"))continue;

// Analyst Ratings check
        AnalystRatings analystRatings=AnalystRatingsDA.GetAnalystRatings(symbol);
        if(null==analystRatings||0==analystRatings.Count)continue;
        analystRatings=new AnalystRatings(analystRatings.Take(5).ToList());
        if(analystRatings.Any(x=>x.RatingsChange.ToUpper().Contains("SELL")))continue;
        //if(analystRatings.Any(x=>x.Type.ToUpper().Contains("DOWNGRADE")))continue;

// Dividend Load check
        DividendLoadCollection dividendLoadCollection=CompositeDA.GetDividendLoad(symbol);
        if(null!=dividendLoadCollection&&0!=dividendLoadCollection.Count)
        {
          DividendLoadCollection element=new DividendLoadCollection(dividendLoadCollection.Take(1).ToList());
          if(element[0].DividendLoadPcnt>65 || element[0].DividendLoadPcnt<0)continue;
          dividendLoadPcnt=element[0].DividendLoadPcnt;
        }

        Console.WriteLine(String.Format("Working on {0}",symbol));
        PortfolioTrade portfolioTrade=new PortfolioTrade();
        portfolioTrade.Symbol=symbol;
        portfolioTrade.TradeDate=historicalDate;
        portfolioTrade.Shares=investment/historicalPrice.Close;
        portfolioTrade.Price=historicalPrice.Close;
        portfolioTrade.BuySell="BUY";
        portfolioTrade.Status="OPEN";
        portfolioTrades.Add(portfolioTrade);
        PortfolioHoldings portfolioHoldings = PortfolioHoldings.GetPortfolioHoldings(portfolioTrades, dayCount,lastBusinessDate);
        VaRResult varResult = HistoricalVaR.GetVaR(portfolioHoldings, varConfidence);
        if(!varResult.Success)continue;
        candidates.Add(new Candidate(symbol,companyName,dividendYield*100.00,Math.Abs(varResult.VaRPercent)*100.00,dividendLoadPcnt,sector,industry));
      }
      candidates=(from Candidate candidate in candidates orderby candidate.DividendYieldPcnt descending, candidate.PortfolioVaRPcnt ascending select candidate).ToList();
      foreach(Candidate candidate in candidates)
      {
        streamWriter.WriteLine(String.Format("{0},{1},{2},{3},{4},{5},{6}",candidate.Symbol,candidate.CompanyName,candidate.DividendYieldPcnt,candidate.PortfolioVaRPcnt,candidate.DividendLoadPcnt,candidate.Sector,candidate.Industry));
      }
      streamWriter.Flush();
      streamWriter.Close();
      streamWriter.Dispose();
      Console.WriteLine(String.Format("output written to :{0}",pathOutput));
    }

    public static void ShowActiveGainLoss()
    {
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"SHOWACTIVEGAINLOSS");
        Dictionary<DateTime,double[]> gainLossElements=new Dictionary<DateTime,double[]>();
        GainLossCollection gainLossCollection=null;
        PortfolioTrades portfolioTrades=PortfolioDA.GetTrades();
        IActiveGainLossGenerator activeReturnGenerator=new ActiveGainLossGenerator();
        gainLossCollection=activeReturnGenerator.GenerateGainLoss(portfolioTrades);
        MDTrace.WriteLine("Date,Exposure,GainLoss,GainLossPercent,Dividends");
        for(int index=0;index<gainLossCollection.Count;index++)
        {
          StringBuilder sb=new StringBuilder();
          GainLossItem gainLossItem=gainLossCollection[index];
          sb.Append(Utility.AddQuotes(Utility.DateTimeToStringMMHDDHYYYY(gainLossItem.Date))).Append(",");
          sb.Append(Utility.AddQuotes(Utility.FormatCurrency(gainLossItem.Exposure))).Append(",");
          sb.Append(Utility.AddQuotes(Utility.FormatCurrency(gainLossItem.GainLoss))).Append(",");
          sb.Append(Utility.AddQuotes(Utility.FormatPercent(gainLossItem.GainLossPercent/100.00,3))).Append(",");
          sb.Append(Utility.AddQuotes(Utility.FormatCurrency(gainLossItem.Dividends)));
          MDTrace.WriteLine(LogLevel.DEBUG,sb.ToString());
        }
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
      }
    }

    public class ProfitExpression
    {
      public String Expression{get;set;}
      public bool UseProfitExpression{get;set;}
    }

    public static void AxiomTest()
    {
       MarketData.Generator.CMTrend.Position position=new  MarketData.Generator.CMTrend.Position();
       CMTParams cmtParams=new CMTParams();
       ProfitExpression profitExpression=new ProfitExpression();

       profitExpression.Expression="";
       profitExpression.UseProfitExpression=true;

      position.Shares=25;
      position.CurrentPrice=220;
      position.PurchasePrice=195.90;
      position.R=5.00;
      cmtParams.UseProfitMaximization=true;


//      StringBuilder sb=new StringBuilder();
//      sb.Append("user_a=66;user_b=66;user_c=66;IF(R>=5){user_a=1;user_b=1;user_c=1;}");
//      sb.Append("MAX_ATR=3;MAX_R=10;FACTOR=0;MULTIPLIER=0;FACTOR=MAX_ATR/MAX_R;MULTIPLIER=MAX_ATR;IF(RMultiple>4){MULTIPLIER=FACTOR*RMultiple;}");
//      sb.Append("R_THRESSHOLD=4;MAX_ATR=3;MAX_R=10;FACTOR=MAX_ATR/MAX_R;MULTIPLIER=MAX_ATR;IF(RMultiple>R_THRESSHOLD){MULTIPLIER=FACTOR*RMultiple;}");

      String expression=@"
      R_THRESHHOLD=4;
      MAX_ATR=3;
      MAX_R=10;
      FACTOR=MAX_ATR/MAX_R;
      MULTIPLIER=MAX_ATR;
      IF(RMultiple>R_THRESHHOLD)
      {
      MULTIPLIER=FACTOR*RMultiple;
      }";

      CodeRunner codeRunner=new CodeRunner();
      SymbolTable symbolTable=codeRunner.SymbolTable;
      symbolTable.AddObjects(new Object[]{position,cmtParams,profitExpression}.ToList());      // inject objects into symbol table.  SymbolTable gets populated using "get_"ers
      codeRunner.Execute(expression);                                                          // run the expression
     double multiplier=codeRunner.GetValue<double>("MULTIPLIER");                              // get the result
     Console.WriteLine(codeRunner.LastMessage);
    }

    public static void SimulateTrade(DateTime startDate, DateTime endDate)
    {
      Dictionary<DateTime,DateTime> tradeableDates=new Dictionary<DateTime,DateTime>();
      Dictionary<DateTime,DateTime> nonTradeableDates=new Dictionary<DateTime,DateTime>();

      DateGenerator dateGenerator=new DateGenerator();
      DateTime currentDate=startDate;
      int tradeableDays=0;
      int nonTradeableDays=0;
      int dayCount=90;

      while(currentDate<endDate)
      {
        bool isTradeableMarket=IsIncreasingRate(currentDate, dayCount, YieldCurve.CurveType.Yr1)?false:true;
        currentDate=dateGenerator.FindNextBusinessDay(currentDate);
        if(isTradeableMarket)
        {
          tradeableDays++;
          tradeableDates.Add(currentDate,currentDate);
        }
        else
        {
           nonTradeableDays++;
           nonTradeableDates.Add(currentDate,currentDate);
        }
      }
      List<DateTime> nonTradeableDatesList=new List<DateTime>(nonTradeableDates.Keys);



      nonTradeableDatesList.Sort((a,b) => a.CompareTo(b));
      foreach(DateTime date in nonTradeableDatesList)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",date.ToShortDateString()));
      }


      Console.WriteLine(String.Format("TradeableDays:{0} Non-TradeableDays:{1}",tradeableDays,nonTradeableDays));
    }
    public static bool IsIncreasingRate(DateTime effectiveDate,int dayCount,YieldCurve.CurveType curveType=YieldCurve.CurveType.Yr1)
    {
      DateGenerator dateGenerator=new DateGenerator();
      DateTime quarterStartDate=dateGenerator.GetPrevQuarterStartDate(effectiveDate);
      YieldCurve yieldCurve = YieldCurveDA.GetYieldCurve(quarterStartDate, dayCount);
      double[] yieldCurveData = yieldCurve.GetYieldCurveDataOrderByDateDescending(YieldCurve.CurveType.Yr1);
      for(int index=0;index<yieldCurveData.Length;index++)yieldCurveData[index]=yieldCurveData[index]*100.00;
      LeastSquaresResult leastSquaresResult = LeastSquaresHelper.CalculateLeastSquares(yieldCurveData);
//		  MDTrace.WriteLine(LogLevel.DEBUG,String.Format("LeastSquaresResult:{0}",Utility.FormatNumber(leastSquaresResult.Slope)));
			if(leastSquaresResult.Slope>1.00)return true;
			return false;
    }

// Last added was 2023 - beware the SPAC "Industry=Shell Companies"
    public static void InsertIPOS()
    {
// paste the symbol and company name's here
        string[,] ipos={
           //{"KVAC","Keen Vision Acquisition Corporation"}
        };

        int items=ipos.Length/2;
        for(int index=0;index<items;index++)
        {
          String symbol=ipos[index,0];
          String company=ipos[index,1];

          if(PricingDA.SecurityExists(symbol))
          {
            Console.WriteLine(String.Format("Already have {0}",symbol));
            continue;
          }
          CompanyProfile companyProfile=MarketDataHelper.GetCompanyProfile(symbol);
          if(null==companyProfile)
          {
            Console.WriteLine(String.Format("No company profile for {0}",symbol));
            continue;
          }
          if(null==companyProfile.CompanyName)
          {
            companyProfile.CompanyName=company;
          }
          if(null==companyProfile.SecurityType)
          {
            companyProfile.SecurityType="EQUITY";
          }
          if(null!=companyProfile && companyProfile.Industry.Equals("Shell Companies"))
          {
            Console.WriteLine(String.Format("{0} is a {1}",symbol,companyProfile.Industry));
            continue;
          }

          PricingDA.AddSecurity(symbol,company);
          CompanyProfileDA.UpdateCompanyProfile(companyProfile);
          LoadAllPricesSymbol(symbol);
          Console.WriteLine();
        }
    }
    // Hang on to this for a while.
    //private static void AdjustCMTCandidates()
    //{
    //    CMTSessionParams sessionParams = CMTSessionManager.RestoreSession(@"C:\boneyard\marketdata\bin\Debug\saferun\CMT20200817.txt");
    //    List<String> validSectors=Utility.ToList(sessionParams.CMTParams.UseTradeOnlySectorsSectors);

    //    List<CMTCandidate> candidatesToRemove=new List<CMTCandidate>();
    //    foreach(CMTCandidate candidate in sessionParams.Candidates)
    //    {
    //      CompanyProfile companyProfile = CompanyProfileDA.GetCompanyProfile(candidate.Symbol);
    //      if(null==companyProfile)
    //      {
    //        Console.WriteLine(String.Format("No company profile for {0}",candidate.Symbol));
    //        candidatesToRemove.Add(candidate);
    //      }
    //      if(!validSectors.Any(x => x.Equals(companyProfile.Sector)))
    //      {
    //        Console.WriteLine(String.Format("Candidate{0}  is in an invalid sector.  Found {1} expected one of {2}",candidate.Symbol,companyProfile.Sector,Utility.ListToString(validSectors.ToList<String>())));
    //        candidatesToRemove.Add(candidate);
    //      }
    //    }
    //    sessionParams.Candidates = new CMTCandidates(sessionParams.Candidates.Except(candidatesToRemove).ToList());
    //    CMTSessionManager.SaveSession(sessionParams,@"C:\boneyard\marketdata\bin\Debug\CMT20200817.txt");
    //}



// ******************************************************************************************************************************************************************************
// ****************************************************************** C U M U L A T I V E  G A I N   L O S S *************************************************************
// ******************************************************************************************************************************************************************************
// This is a test of a new model to calculate the cumulate gain loss for the GainLoss Window
    private static void RunModelPerformance(String symbol=null, bool useDividends=false)
    {
      GainLossGeneratorCum gainLossGeneratorCum=new GainLossGeneratorCum();
      GainLossGenerator gainLossGenerator=new GainLossGenerator();
      PortfolioTrades portfolioTrades=PortfolioDA.GetTrades();
      DividendPayments dividendPayments=null;

      String strPathFileNameCumulative=String.Format("model_performance_dividends_cumulative_{0}.csv",null==symbol?"ALL":symbol);
      String strPathFileNameNonCumulative=String.Format("model_performance_dividends_non_cumulative_{0}.csv",null==symbol?"ALL":symbol);
      
      if(null==symbol)portfolioTrades = PortfolioDA.GetTrades();
      else portfolioTrades = PortfolioDA.GetTrades(symbol);

      if(useDividends)
      {
        if(null!=symbol)dividendPayments=DividendPaymentDA.GetDividendPaymentsForSymbol(symbol);
        else dividendPayments=DividendPaymentDA.GetDividendPayments();
      }

// Run the cumulative version
      TotalGainLossCollection totalGainLossCollectionCum=null;
      if(null!=dividendPayments)totalGainLossCollectionCum=gainLossGeneratorCum.GenerateTotalGainLossWithDividends(portfolioTrades,dividendPayments);
      else totalGainLossCollectionCum=gainLossGeneratorCum.GenerateTotalGainLoss(portfolioTrades);
      Console.WriteLine(String.Format("Writing Cumulative Model to {0}",strPathFileNameCumulative));
      SaveCollection(strPathFileNameCumulative, "CUMULATIVE", totalGainLossCollectionCum);

// Run the regular version
      TotalGainLossCollection totalGainLossCollection=null;
      if(null!=dividendPayments)totalGainLossCollection=gainLossGenerator.GenerateTotalGainLossWithDividends(portfolioTrades,dividendPayments);
      else totalGainLossCollection=gainLossGenerator.GenerateTotalGainLoss(portfolioTrades);
      Console.WriteLine(String.Format("Writing Non-Cumulative Model to {0}",strPathFileNameNonCumulative));
      SaveCollection(strPathFileNameNonCumulative, "NON-CUMULATIVE",totalGainLossCollection);
    }

    public static void SaveCollection(String strPathFileName,String title,TotalGainLossCollection totalGainLossCollection)
    {
      if(File.Exists(strPathFileName))File.Delete(strPathFileName);
      StreamWriter streamWriter = new StreamWriter(new FileStream(strPathFileName,FileMode.CreateNew,FileAccess.Write));
      streamWriter.WriteLine(title);
      streamWriter.WriteLine(TotalGainLossCollection_Header());
      foreach(TotalGainLossItem item in totalGainLossCollection)
      {
        streamWriter.WriteLine(TotalGainLossCollection_Item(item));
      }
      streamWriter.Flush();
      streamWriter.Close();
      streamWriter.Dispose();
    }

    public static void DisplayCollection(String title,TotalGainLossCollection totalGainLossCollection)
    {
      Console.WriteLine(title);
      Console.WriteLine(TotalGainLossCollection_Header());
      foreach(TotalGainLossItem item in totalGainLossCollection)
      {
        Console.WriteLine(TotalGainLossCollection_Item(item));
      }
    }
    public static String TotalGainLossCollection_Header()
    {
      StringBuilder sb=new StringBuilder();
      sb.Append("Date,TotalGainLoss,TotalGainLossPercent,TotalExposure,TotalMarketValue");
      return sb.ToString();
    }
    public static String TotalGainLossCollection_Item(TotalGainLossItem totalGainLossItem)
    {
      StringBuilder sb=new StringBuilder();
      sb.Append(Utility.AddQuotes(Utility.DateTimeToStringMMSDDSYYYY(totalGainLossItem.Date))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatCurrency(totalGainLossItem.TotalGainLoss))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatPercent(totalGainLossItem.TotalGainLossPercent/100.00,2))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatCurrency(totalGainLossItem.TotalExposure))).Append(",");
      sb.Append(Utility.AddQuotes(Utility.FormatCurrency(totalGainLossItem.TotalMarketValue))).Append(",");
      return sb.ToString();
    }

    // All of the CNN image processing related example code that used to be here has been relocated to the CNNImageProcessing project which is a console
    // application that does all of that stuff
    // **********************************************************************************************************

// This nest section is a study for accumulating stocks where there was a price increase >= 15% <= 25% within some period (aw) 
//   [p1,p2,p3,p4,p5......pn-2,pn-1,pn]
//   ------- ow -----     ---- aw ----]    ow+aw = total span
//                                         ow = observation window.  X.  The timeseries leading up to the event
//                                         aw = action window.  The timeseries containing the event
    public static void GetObservations(int observationWindow=90, int actionWindow=30)
    {
      try
      {
        DateTime minDate = DateTime.Parse("01/01/2017");
        DateGenerator dateGenerator = new DateGenerator();
        String pathFileName = "observations.txt";
        int eventWindow = observationWindow + actionWindow;

        if(File.Exists(pathFileName))File.Delete(pathFileName);
        FileStream outStream = new FileStream(pathFileName, FileMode.Create);
        StreamWriter streamWriter = new StreamWriter(outStream);
        streamWriter.WriteLine($"OW={observationWindow},AW={actionWindow}");

        List<String> symbols = PricingDA.GetSymbols();
        for(int index=0;index<symbols.Count();index++)
        {
          String currentSymbol = symbols[index];

          CompanyProfile companyProfile = CompanyProfileDA.GetCompanyProfile(currentSymbol);
          if(null == companyProfile || !companyProfile.IsEquity)continue;

          Console.WriteLine($"Working on {currentSymbol}");
          DateTime latestDate = PricingDA.GetLatestDate(currentSymbol);
          if(Utility.IsEpoch(latestDate) || latestDate<minDate)continue;
          while(true)
          {
            if(latestDate<minDate)break;
            Prices prices = GBPriceCache.GetInstance().GetPrices(currentSymbol,latestDate,eventWindow);
            if(null == prices || prices.Count < eventWindow || prices.Min()<=0.00)break;
            latestDate = dateGenerator.FindPrevBusinessDay(latestDate);
            Prices orderedPrices = new Prices(prices.OrderBy(x => x.Date).ToList());                      // sort the prices so the oldest is in the lowest index
            Prices actionPrices = new Prices(orderedPrices.Skip(observationWindow).ToList());             // get the aw window
            Price p1 = actionPrices[0];                                                                   // get the earlier price from the lowest index
            Price p2 = actionPrices[actionPrices.Count()-1];                                              // get the recent price from the highest index
            double periodReturnPercentDecimal = (p2.Close-p1.Close)/p1.Close;                             // calculate the return over this period
            if(periodReturnPercentDecimal<.15 || periodReturnPercentDecimal>.25)continue;
            float[] priceArray = orderedPrices.GetPrices();                                               // priceArray is ordered earliest date in lowest index, most recent date in highest index
            streamWriter.WriteLine($"SYMBOL={currentSymbol},DATE={orderedPrices[0].Date.ToShortDateString()},PRICES={String.Join(",",priceArray)}");
          }
        }
        streamWriter.Flush();
        streamWriter.Close();
        streamWriter.Dispose();

        CompressObservations(pathFileName);
      }
      catch(Exception exception)
      {
        Console.WriteLine(exception.ToString());
      }
    }

    public static void CompressObservations(String pathFileName)
    {
      DateGenerator dateGenerator = new DateGenerator();
      List<String> itemsToRemove=new List<String>();
      List<String> observations = LoadObservations(pathFileName);
      String prevSymbol = null;
      DateTime prevEventDate = Utility.Epoch;

      if(0==observations.Count)return;
      Console.WriteLine($"Compressing {pathFileName}");
      for(int index=observations.Count-1;index>=0;index--)
      {
        String strLine = observations[index]; 

        if(strLine.StartsWith("OW"))break;
        String symbol=Utility.BetweenString(strLine,"SYMBOL=",",");
        DateTime eventDate = DateTime.Parse(Utility.BetweenString(strLine,"DATE=",","));

        if(null==prevSymbol)
        {
          prevSymbol=symbol;
          prevEventDate = eventDate;
        }
        else if(prevSymbol.Equals(symbol))
        {
          DateTime nextBusinessDay = dateGenerator.FindNextBusinessDay(prevEventDate);
          if(nextBusinessDay.Date.Equals(eventDate.Date))
          {
            observations[index]=null;
          }
          prevEventDate = eventDate;
        }
        else
        {
          prevSymbol=symbol;
          prevEventDate = eventDate;
        }
      }
      observations = observations.Where(x => !String.IsNullOrEmpty(x)).ToList();
      String extension = Path.GetExtension(pathFileName);
      pathFileName = pathFileName.Replace(extension, null);
      Console.WriteLine($"Writing {pathFileName}");
      WriteObservations(pathFileName+".compressed.txt",observations);
      Console.WriteLine("Done.");
    }

    public static List<String> LoadObservations(String pathFileName)
    {
      List<String> lines = new List<string>();
      if(!File.Exists(pathFileName))return lines;
      String strLine;

      FileStream inStream = new FileStream(pathFileName, FileMode.Open);
      StreamReader streamReader = new StreamReader(inStream);
      while(null!=(strLine=streamReader.ReadLine()))
      {
        lines.Add(strLine);
      }
      streamReader.Close();
      streamReader.Dispose();
      inStream.Close();
      inStream.Dispose();
      return lines;
    }

    public static void WriteObservations(String pathFileName,List<String> observations)
    {
      if(File.Exists(pathFileName))
      {
        File.Delete(pathFileName);
      }

      FileStream outStream = new FileStream(pathFileName, FileMode.Create);
      StreamWriter streamWriter = new StreamWriter(outStream);
      foreach(String strLine in observations)
      {
        streamWriter.WriteLine(strLine);
      }
      streamWriter.Flush();
      streamWriter.Close();
      streamWriter.Dispose();
      outStream.Close();
      outStream.Dispose();
    }
// *****************************************************************************************************************************************************

    public static void HedgeTest()
    {
        String hedgeShortSymbol="SH";
        double initialRiskPercentDecimal=.12;
        double cash=10000;
        double cashToInvest=3000;
        double totalGainLoss=0.00;
        bool hedgeOn=false;
        int totalWinners=0;
        int totalLosers=0;
        int hedgeStopLimitScalingVolatilityDays=14;
        int hedgeMinDaysBetweenStopAdjustments=1;

        MGSHPosition position = default;


        MDTrace.WriteLine(LogLevel.DEBUG,"START");
        DateTime analysisStartDate=DateTime.Parse("01/31/2018");
//        DateTime analysisStartDate=DateTime.Parse("01/01/2011");
//        DateTime analysisStartDate=DateTime.Parse("06/06/2018");
        DateTime analysisEndDate=DateTime.Parse("12/31/2024");
        Prices prices = PricingDA.GetPrices(hedgeShortSymbol);

        prices=new Prices(prices.Where(x => x.Date > analysisStartDate).ToList());

        BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices);
        BollingerBandElementsByDate bollingerBandElementsByDate = bollingerBands.GetBollingerBandElementsByDate();

        PricesByDate pricesByDate = prices.GetPricesByDate();
        List<DateTime> dates = new List<DateTime>(pricesByDate.Keys);

        MGSHPositions AllPositions = new MGSHPositions();
        MarketData.Generator.Model.StopLimits StopLimits = new MarketData.Generator.Model.StopLimits();

        HedgeManager hedgeManager = new HedgeManager(){Verbose=true};

        for(int dateIndex=dates.Count-1;dateIndex>=0;dateIndex--)
        {
          DateTime analysisDate = dates[dateIndex];
          if(analysisDate > analysisEndDate)break;
          if(!bollingerBandElementsByDate.ContainsKey(analysisDate))continue;
          BollingerBandElement bollingerBandElement = bollingerBandElementsByDate[analysisDate];

          if(!hedgeOn && hedgeManager.IsOpenHedgeIndicator(analysisDate))
          {
            hedgeOn=true;
            position = new MGSHPosition();
            position.Symbol=hedgeShortSymbol;
            position.PurchasePrice = bollingerBandElement.Close;
            position.PurchaseDate = analysisDate;
            position.SellDate=Utility.Epoch;
            position.InitialStopLimit=position.PurchasePrice/(1.00+initialRiskPercentDecimal);
            position.TrailingStopLimit=position.InitialStopLimit;
            position.LastStopAdjustment=Utility.Epoch;
            position.R=initialRiskPercentDecimal;
            double cashAllocation = Math.Min(cash, cashToInvest);
            position.Shares=(int)(cashAllocation/bollingerBandElement.Close);
            cash-=position.Shares*bollingerBandElement.Close;

// This is for the simulation so that I can see the initial position as a stop limit in the UI
            MarketData.Generator.Model.StopLimit stopLimit = new  MarketData.Generator.Model.StopLimit()
            {
              Symbol=hedgeShortSymbol,
              AnalysisDate=analysisDate,
              PreviousStop=position.PurchasePrice,
              NewStop=position.TrailingStopLimit,
              CurrentPriceLow=0.00,
              CurrentPriceClose=0.00,
              PriceTrendIndicatorSlope=0.00
            };
            StopLimits.Add(stopLimit);

            MDTrace.WriteLine(LogLevel.DEBUG,$"Hedge BUY {analysisDate.ToShortDateString()} {Utility.FormatNumber(position.Shares,2)} shares @ {Utility.FormatCurrency(bollingerBandElement.Close)} Exposure:{Utility.FormatCurrency(position.Shares*bollingerBandElement.Close)}");
          }
          else if(hedgeOn)      // This will check for stop loss violation and close the position
          {
            Price price = GBPriceCache.GetInstance().GetPrice(hedgeShortSymbol, analysisDate);
            if(null == price)
            {
              MDTrace.WriteLine(LogLevel.DEBUG,$"No price for {hedgeShortSymbol} on {analysisDate.ToShortDateString()}");
              continue;
            }
            if(price.Close<position.TrailingStopLimit)
            {
              hedgeOn=false;
              position.SellDate= analysisDate;
              position.CurrentPrice=position.TrailingStopLimit; //bollingerBandElement.Close;
              position.Comment=$"Closed to to stop loss {position.Shares} shares @ {Utility.FormatCurrency(position.CurrentPrice)}";
              if(position.GainLoss>0)totalWinners++;
              else totalLosers++;
              totalGainLoss+=position.GainLoss;
              cash+=position.MarketValue;
              MDTrace.WriteLine(LogLevel.DEBUG,$"Hedge SELL {analysisDate.ToShortDateString()}  {Utility.FormatNumber(position.Shares,2)} shares @ {Utility.FormatCurrency(position.CurrentPrice)} Gain/Loss:{Utility.FormatCurrency(position.GainLoss)}  Gain/Loss(%):{Utility.FormatPercent(position.GainLossPcnt,2)}");
              MDTrace.WriteLine(LogLevel.DEBUG,"**************************************************");
              AllPositions.Add(position);

              MarketData.Generator.Model.StopLimit stopLimit = new  MarketData.Generator.Model.StopLimit()
              {
                Symbol=hedgeShortSymbol,
                AnalysisDate=analysisDate,
                PreviousStop=position.PurchasePrice,
                NewStop=position.CurrentPrice,
                CurrentPriceLow=0.00,
                CurrentPriceClose=0.00,
                PriceTrendIndicatorSlope=0.00
              };
              StopLimits.Add(stopLimit);
            }
            else if(hedgeManager.IsLowerBandBreakIndicator(analysisDate, position))
            {
              MGSHConfiguration msghConfiguration = new MGSHConfiguration();
              msghConfiguration.HedgeMinDaysBetweenStopAdjustments=hedgeMinDaysBetweenStopAdjustments;
              msghConfiguration.StopLimitScalingVolatilityDays=hedgeStopLimitScalingVolatilityDays;
              msghConfiguration.HedgeATRMultiplier=1.00;  //   Check this value against what is being used in the actual config.  It controls how closely the stop limit trails
              MarketData.Generator.Model.StopLimit stopLimit = hedgeManager.EvaluateStopPriceHedge(analysisDate, position, msghConfiguration);
              if(null != stopLimit)StopLimits.Add(stopLimit);
            }
          }
        }
        MGSHSessionParams sessionParams = new MGSHSessionParams();
        sessionParams.LastUpdated=DateTime.Now;
        sessionParams.TradeDate=DateTime.Now;
        sessionParams.StartDate=DateTime.Now;
        sessionParams.AnalysisDate=DateTime.Now;
        sessionParams.Configuration=new MGSHConfiguration();
        sessionParams.ActivePositions=new MGSHActivePositions();
        sessionParams.AllPositions=AllPositions;
        sessionParams.CashBalance=cash;
        sessionParams.NonTradeableCash=0.00;
        sessionParams.StopLimits=StopLimits;
        sessionParams.HedgePositions= new MGSHPositions();
        sessionParams.Cycle = 0;

        MGSHSessionManager mgSession = new MGSHSessionManager();
        mgSession.SaveSession(sessionParams,"MGSH_PROTO_20250128_2.TXT");
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Total Gain/Loss:{Utility.FormatCurrency(totalGainLoss)}"));
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Cash:{Utility.FormatCurrency(cash)}"));
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format($"Open:{hedgeOn}"));

        return;
    }
// ****************************************************************************************************************************************************************
    public static void CrossoverExample()
    {
        // Crossover examples.
        // Example 1
        //List<String> symbols = PricingDA.GetSymbols();
        //List<MovingAverageCrossover> crossovers = new MovingAverageCrossovers();
        //DateTime analysisDate = DateTime.Parse("12/31/2024");
        //for (int index = 0; index < symbols.Count; index++)
        //{
        //  if (0 == (index % 500)) Console.WriteLine($"Working on {index}");
        //  String symbol = symbols[index];
        //  Prices prices = GBPriceCache.GetInstance().GetPrices(symbol, analysisDate, 252);
        //  MovingAverageCrossovers movingAverageCrossovers = ExponentialMovingAverageCrossover.GetMovingAverageCrossovers(prices, .05);  // 5%
        //  movingAverageCrossovers = new MovingAverageCrossovers(movingAverageCrossovers.Where(x => x.EventDate.Equals(analysisDate)).ToList());
        //  crossovers.AddRange(movingAverageCrossovers);
        //}
        //foreach (MovingAverageCrossover movingAverageCrossover in crossovers)
        //{
        //  Console.WriteLine(movingAverageCrossover.ToString());
        //}

        // Example 2
        //String symbol = "SH";
        //DateTime analysisDate = DateTime.Parse("12/31/2024");
        //Prices prices = GBPriceCache.GetInstance().GetPrices(symbol, analysisDate, 252);
        //MovingAverageCrossovers movingAverageCrossovers = ExponentialMovingAverageCrossover.GetMovingAverageCrossovers(prices, .025);
        //foreach (MovingAverageCrossover movingAverageCrossover in movingAverageCrossovers)
        //{
        //  Console.WriteLine(movingAverageCrossover.ToString());
        //}

        //DMAPrices fastDMAPrices = MovingAverageGenerator.GenerateExponentialMovingAverage(prices, 9);
        //DMAPrices slowDMAPrices=MovingAverageGenerator.GenerateExponentialMovingAverage(prices, 41);
        //DMAPricesByDate fastDMAPricesByDate=fastDMAPrices.GetDMAPricesByDate();
        //DMAPricesByDate slowDMAPricesByDate=slowDMAPrices.GetDMAPricesByDate();
        //List<DateTime> availableDates = new List<DateTime>(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
        //StreamWriter streamWriter = new StreamWriter(new FileStream("MovingAverage.csv",FileMode.Create));
        //streamWriter.WriteLine("Date,Fast,Slow");
        //foreach(DateTime date in availableDates)
        //{
        //  DMAPrice fastDMAPrice = fastDMAPricesByDate[date];
        //  DMAPrice slowDMAPrice = slowDMAPricesByDate[date];
        //  streamWriter.WriteLine($"{date.ToShortDateString()},{fastDMAPrice.AVGPrice},{slowDMAPrice.AVGPrice}");
        //}
        //streamWriter.Flush();
        //streamWriter.Close();
        //streamWriter.Dispose();

        // Example 3
        //DateTime beginDate = DateTime.Parse("12/31/2018");
        //DateTime stopDate = DateTime.Parse("12/31/2024");
        //String symbol="^VIX";
        //DateGenerator dateGenerator = new DateGenerator();
        //while(beginDate<=stopDate)
        //{
        //  Prices prices = GBPriceCache.GetInstance().GetPrices(symbol, beginDate, 252);
        //  MovingAverageCrossovers movingAverageCrossovers = ExponentialMovingAverageCrossover.GetMovingAverageCrossovers(prices, .025, 20, 50);  // 1.75%
        //  if(null != movingAverageCrossovers && movingAverageCrossovers.Count>0 && movingAverageCrossovers[0].EventDate.Equals(beginDate))
        //  {
        //    MDTrace.WriteLine(LogLevel.DEBUG,$"Found a crossover  {movingAverageCrossovers[0].ToString()}");
        //  }
        //  beginDate = dateGenerator.FindNextBusinessDay(beginDate);
        //}
    }

    //Security
    //public static bool VerifyPassword(string inputPassword, string storedSalt, string storedHash)
    //public static (string Salt, string Hash) HashPasswordWithSalt(string password)
    //public static string HashPassword(string password)


        //User user = UserDA.GetUser("sean");

        //if(!user.Verify("MN5191306"))
        //{
        //  MDTrace.WriteLine(LogLevel.DEBUG,$"User {user.Username} was not verified");
        //}
        //else
        //{
        //  MDTrace.WriteLine(LogLevel.DEBUG,$"User {user.Username} was verified");
        //}

//        (String salt, String hash) = Encryption.HashPasswordWithSalt("MN5191306");
        //bool result = Encryption.VerifyPassword("MN5191306", salt, hash);

        //User user = new User();
        //user.Username = "Sean";
        //user.Salt = salt;
        //user.Hash = hash;

        //UserDA.AddUser(user);


    static int Main(string[] args)
    {
			try
			{
        MDTrace.LogLevel = LogLevel.DEBUG;
        String strLogFile = "marketdata.log";
        Utility.DeleteFile(strLogFile);
        Trace.Listeners.Add(new TextWriterTraceListener(strLogFile));
        DateTime currentDate=DateTime.Now;

        DateTime maxHolidayDate =HolidayDA.GetMaxHolidayDate();
        if(currentDate>maxHolidayDate)
        {
          Console.WriteLine(String.Format("There are no holidays defined in the system.  Add holidays for year {0} into marketholidays table",currentDate.Year));
          return 0;
        }
        if (args.Length < 1)
        {
          DisplayUsage();                                                                                      
          return 1;
        }
        string arg = args[0].ToUpper();
        if(arg.Equals("RUNMODELPERFORMANCE"))
        {
          Program.RunModelPerformance();
        }
        else if(arg.Equals("RUNPRICECHECKOPENPOSITIONS"))
        {
          Program.RunPriceCheckOpenPositions();
        }
        else if(arg.Equals("SENDSMSEMAIL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("MESSAGE")){Console.WriteLine("MESSAGE is required");return 0;}
          Program.SendSMSEmail(commandArgs.Coalesce<String>("MESSAGE"));
        }
        else if(arg.Equals("SHOWACTIVEGAINLOSS"))
        {
          Program.ShowActiveGainLoss();
        }
        else if (arg.Equals("CHECKPRICES"))
        {
          Program.CheckPrices();
        }
        else if(arg.Equals("MAXDIVMINVAR"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(commandArgs.Has("PERCENTOFEXPOSURE")&&commandArgs.Has("EXPOSURE")){Console.WriteLine("Choose either PERCENTOFEXPOSURE or EXPOSURE.");return 0;}
          if(!commandArgs.Has("PERCENTOFEXPOSURE")&&!commandArgs.Has("EXPOSURE")){Console.WriteLine("Choose either PERCENTOFEXPOSURE or EXPOSURE.");return 0;}
          if(!commandArgs.Has("DAYCOUNT")){Console.WriteLine("DAYCOUNT is required");return 0;}
          Program.MaximizeDividendMinimizeVaR(commandArgs.Coalesce<Int32>("DAYCOUNT"),commandArgs.Coalesce<double>("EXPOSURE",double.NaN),commandArgs.Coalesce<double>("PERCENTOFEXPOSURE",double.NaN),commandArgs.Coalesce<double>("VARCONFIDENCE",double.NaN));
        }
        else if (arg.Equals("UPDATEEARNINGSANNOUNCEMENTS")) 
        {
          Program.UpdateEarningsAnnouncements();
        }
        else if (arg.Equals("UPDATEEARNINGSANNOUNCEMENTSSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATEEARNINGSANNOUNCEMENTSSYMBOL MISSING SYMBOL");return 0;}
          Program.UpdateEarningsAnnouncements(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("UPDATEALL")) 
        {
          Program.UpdateAll();
        }
        else if (arg.Equals("UPDATEALLNOPRICES"))
        {
          Program.UpdateAllNoPrices();
        }
        else if (arg.Equals("UPDATEPRICES"))
        {
          Program.UpdatePrices();
        }
        else if (arg.Equals("UPDATEDAILY"))
        {
          Program.UpdateDaily();         
        }
        else if (arg.Equals("UPDATEDAILY2")) 
        { 
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("DATE")){Console.WriteLine("UPDATEDAILY2 MISSING DATE");return 0;}
          Program.UpdateDaily2(commandArgs.Coalesce<DateTime>("DATE"));
        }
        else if (arg.Equals("UPDATEDAILYPRICES")) 
        { 
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("DATE")){Console.WriteLine("UPDATEPRICES MISSING DATE");return 0;}
          Program.UpdateDailyPrices(commandArgs.Coalesce<DateTime>("DATE"));
        }
        else if(arg.Equals("UPDATEPRICESBIGCHARTS"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("DATE")){Console.WriteLine("UPDATEPRICESBIGCHARTS MISSING DATE");return 0;}
          Program.UpdatePricesBigCharts(commandArgs.Coalesce<DateTime>("DATE"));
        }
        else if(arg.Equals("UPDATESPLITS"))
        {
          Program.UpdateSplits();
        }
        else if(arg.Equals("PROCESSSPLIT"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("PROCESSSPLIT MISSING SYMBOL");return 0;}
          Program.ProcessSplit(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if(arg.Equals("PROCESSALLSPLITS"))
        {
          Program.ProcessAllSplits();
        }
        else if (arg.Equals("UPDATELATESTANALYSTRATINGS"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          if (commandArgs.Has("UPDATESECURITYMASTER")) Program.UpdateLatestAnalystRatings(commandArgs.Coalesce<Boolean>("UPDATESECURITYMASTER"));
          else Program.UpdateLatestAnalystRatings();
        }
        else if (arg.Equals("UPDATEANALYSTRATINGS"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          if (commandArgs.Has("SYMBOL") && commandArgs.Has("MINDATE")) Program.UpdateAnalystRatings(commandArgs.Coalesce<String>("SYMBOL"), commandArgs.Coalesce<DateTime>("MINDATE"));
          else if (commandArgs.Has("SYMBOL") ) Program.UpdateAnalystRatings(commandArgs.Coalesce<String>("SYMBOL"));
          else if (commandArgs.Has("MINDATE")) Program.UpdateAnalystRatings(null,commandArgs.Coalesce<DateTime>("MINDATE"));
          else Program.UpdateAnalystRatings();
        }
        else if (arg.Equals("UPDATEMISSINGANALYSTRATINGS"))
        {
          Program.UpdateMissingAnalystRatings();
        }
        else if (arg.Equals("UPDATEZACKSRANK"))
        {
          Program.LoadZacksRank();
        }
        else if (arg.Equals("UPDATEZACKSRANKSYMBOL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATEZACKSRANKSYMBOL MISSING SYMBOL");return 0;}
          else Program.LoadZacksRank(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("UPDATEANALYSTPRICETARGET"))
        {
          Program.UpdateAnalystPriceTarget();
        }
        else if (arg.Equals("UPDATEPRICESANDYIELD")) 
        {
          Program.UpdatePricesAndYield();
        }
        else if (arg.Equals("UPDATECOMPANYPROFILES")) 
        {
          Program.UpdateCompanyProfiles();
        }
        else if (arg.Equals("UPDATECOMPANYPROFILE")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATECOMPANYPROFILE MISSING SYMBOL");return 0;}
          Program.UpdateCompanyProfile(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("DISPLAYCOMPANYPROFILES")) 
        {
          Program.DisplayCompanyProfiles();
        }
        else if (arg.Equals("GETSECFILINGSSYMBOL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("GETSECFILINGSSYMBOL MISSING SYMBOL");return 0;}
          Program.GetSECFilingsSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("GETSECFILINGSWATCHLIST")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("WATCHLIST")){Console.WriteLine("GETSECFILINGSWATCHLIST MISSING WATCHLIST");return 0;}
          Program.GetSECFilingsWatchList(commandArgs.Coalesce<String>("WATCHLIST"));
        }
        else if (arg.Equals("GETSECFILINGSOPENPOSITIONS")) 
        {
          Program.GetSECFilingsOpenPositions();
        }
        else if (arg.Equals("UPDATESECFILINGS"))
        {
          Program.UpdateSECFilings();
        }
        else if (arg.Equals("UPDATEALLCIK")) 
        {
          Program.UpdateAllCIK();
        }
        else if (arg.Equals("UPDATEALLMISSINGCIK")) 
        {
          Program.UpdateAllMissingCIK();
        }
        else if (arg.Equals("UPDATECIKSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATECIKSYMBOL MISSING SYMBOL");return 0;}
          Program.UpdateCIKSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("UPDATELATESTPRICEOPENPOSITIONS")) 
        {
          Program.UpdateLatestPriceOpenPositions();
        }
        else if (arg.Equals("UPDATELATESTPRICEWATCHLIST")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("WATCHLIST")){Console.WriteLine("UPDATELATESTPRICEWATCHLIST MISSING WATCHLIST");return 0;}
          Program.UpdateLatestPriceWatchList(commandArgs.Coalesce<String>("WATCHLIST"));
        }
        else if (arg.Equals("DELETEPRICEWATCHLIST")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("WATCHLIST,DATE")){Console.WriteLine("DELETEPRICEWATCHLIST REQUIRES WATCHLIST,DATE");return 0;}
          Program.DeletePriceWatchList(commandArgs.Coalesce<String>("WATCHLIST"),commandArgs.Coalesce<String>("DATE"));
        }
        else if (arg.Equals("FINDALLSYMBOLSMISSINGPRICEON")) 
        {
          bool rollForward=false;
          String strFilter=null;
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("DATE")){Console.WriteLine("FINDALLSYMBOLSMISSINGPRICEON REQUIRES DATE");return 0;}
          if(commandArgs.Has("ROLLFORWARD"))rollForward=commandArgs.Get<bool>("ROLLFORWARD");
          if(commandArgs.Has("FILTER"))strFilter=commandArgs.Get<String>("FILTER");
          Program.FindAllSymbolsMissingPriceOn(commandArgs.Coalesce<DateTime>("DATE"),rollForward,strFilter);
        }
      //MDTrace.WriteLine(LogLevel.DEBUG,"    ROLLPRICEFORWARD /SYMBOL: /FROMDATE: /TODATE:  Roll price forward from the given date to the specified date.");
        else if(arg.Equals("ROLLPRICEFORWARD"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,FROMDATE,TODATE")){Console.WriteLine("ROLLPRICEFORWARD REQUIRES SYMBOL,FROMDATE,TODATE");return 0;}  
          Program.RollPriceForward(commandArgs.Get<String>("SYMBOL"),commandArgs.Get<DateTime>("FROMDATE"),commandArgs.Get<DateTime>("TODATE"));
        }
        else if (arg.Equals("UPDATEPRICESASOF")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("DATE")){Console.WriteLine("UPDATEPRICESASOF REQUIRES DATE");return 0;}
          Program.UpdatePricesAsOf(commandArgs.Coalesce<DateTime>("DATE"));
        }
        else if (arg.Equals("UPDATEPRICEASOFSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DATE")){Console.WriteLine("UPDATEPRICEASOFSYMBOL REQUIRES SYMBOL,DATE");return 0;}
          Program.UpdatePricesAsOfSymbol(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<DateTime>("DATE"));
        }
        else if(arg.Equals("UPDATEPRICEASOFSYMBOLYAHOO"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DATE")) { Console.WriteLine("UPDATEPRICEASOFSYMBOL REQUIRES SYMBOL,DATE"); return 0; }
          Program.UpdatePricesAsOfSymbolYahoo(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<DateTime>("DATE"));
        }
        else if (arg.Equals("UPDATELATESTPRICESYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATEPRICEASOFSYMBOL REQUIRES SYMBOL");return 0;}
          Program.UpdateLatestPriceSymbol(commandArgs.Coalesce<String>("SYMBOL").ToUpper());
        }
        else if (arg.Equals("UPDATELATESTPRICESALL")) 
        {
          Program.UpdateLatestPriceAll();
        }
        else if (arg.Equals("DELETELATESTPRICESYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("DELETELATESTPRICESYMBOL REQUIRES SYMBOL");return 0;}
          Program.DeleteLatestPriceSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("DELETEPRICESASOF"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("DATE")){Console.WriteLine("DELETEPRICESASOF REQUIRES DATE");return 0;}
          Program.DeletePricesAsOf(commandArgs.Coalesce<String>("DATE"));
        }
        else if (arg.Equals("UPDATEPRICESDATE")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("DATE")){Console.WriteLine("UPDATEPRICESDATE REQUIRES DATE");return 0;}
          Program.UpdatePricesDate(commandArgs.Coalesce<String>("DATE"));
        }
        else if (arg.Equals("UPDATEPRICESSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATEPRICESSYMBOL REQUIRES SYMBOL");return 0;}
          Program.UpdatePricesSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("LOADALLPRICESWATCHLIST")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("WATCHLIST")){Console.WriteLine("LOADALLPRICESWATCHLIST REQUIRES WATCHLIST");return 0;}
          Program.LoadAllPricesWatchList(commandArgs.Coalesce<String>("WATCHLIST"));
        }
        else if (arg.Equals("LOADALLPRICESSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADALLPRICESSYMBOL REQUIRES SYMBOL");return 0;}
          Program.LoadAllPricesSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("SHOWALLPRICESSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADALLPRICESSYMBOL REQUIRES SYMBOL");return 0;}
          Program.ShowAllPricesSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("LOADALLPRICESSYMBOLDATE")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADALLPRICESSYMBOLDATE REQUIRES SYMBOL");return 0;}
          if(!commandArgs.Has("DATE")){Console.WriteLine("LOADALLPRICESSYMBOLDATE REQUIRES DATE");return 0;}
          Program.LoadAllPricesSymbolDate(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<DateTime>("DATE"));
        }
        else if (arg.Equals("LOADFINANCIALSTATEMENTSSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADFINANCIALSTATEMENTSSYMBOL REQUIRES SYMBOL");return 0;}
          Program.LoadFinancialStatementsSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("LOADFINANCIALSTATEMENTS"))        
        {
          Program.LoadFinancialStatements();
        }
        else if (arg.Equals("LOADFUNDAMENTAL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADFUNDAMENTAL REQUIRES SYMBOL");return 0;}
          Program.LoadFundamental(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("LOADFUNDAMENTALS")) 
        {
          Program.LoadFundamentals();
        }
        else if (arg.Equals("LOADFUNDAMENTALFINVIZ")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADFUNDAMENTALFINVIZ REQUIRES SYMBOL");return 0;}
          Program.LoadFundamentalFinViz(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("LOADFUNDAMENTALSFINVIZ")) 
        {
          Program.LoadFundamentalsFinViz();
        }
        else if (arg.Equals("LOADHISTORICAL")) 
        {
          Program.LoadHistorical();
        }
        else if (arg.Equals("LOADHISTORICALSYMBOL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADHISTORICALSYMBOL REQUIRES SYMBOL");return 0;}
          Program.LoadHistorical(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("ADDPRICE"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DATE,OPEN,HIGH,LOW,CLOSE,VOLUME")){Console.WriteLine("ADDPRICE REQUIRES SYMBOL,DATE,OPEN,HIGH,LOW,CLOSE,VOLUME");return 0;}
          Program.AddPrice(
            commandArgs.Coalesce<String>("SYMBOL"),
            commandArgs.Coalesce<DateTime>("DATE"),
            commandArgs.Coalesce<double>("OPEN"),
            commandArgs.Coalesce<double>("HIGH"),
            commandArgs.Coalesce<double>("LOW"),
            commandArgs.Coalesce<double>("CLOSE"),
            commandArgs.Coalesce<long>("VOLUME"));
        }
        else if (arg.Equals("DELETEPRICE")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DATE")){Console.WriteLine("DELETEPRICE REQUIRES SYMBOL,DATE");return 0;}
          Program.DeletePriceSymbol(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<String>("DATE"));
        }
        // ****************** A N A L Y S I S 
        else if (arg.Equals("FINDSWINGTRADESSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DAYCOUNT")){Console.WriteLine("FINDSWINGTRADESSYMBOL REQUIRES SYMBOL,DAYCOUNT");return 0;}
          Program.FindSwingTrades(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"));
        }
        else if (arg.Equals("FINDCURRENTSWINGTRADES")) 
        {
          Program.FindCurrentSwingTrades(false);
        }
        else if (arg.Equals("FINDCURRENTSWINGTRADESBARGAIN")) 
        {
          Program.FindCurrentSwingTrades(true);
        }
        else if (arg.Equals("CALCSTICKERSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("CALCSTICKERSYMBOL REQUIRES SYMBOL");return 0;}
          else Program.CalcStickerSymbol(commandArgs.Coalesce<String>("SYMBOL"),false);
        }
        else if (arg.Equals("CALCACQUIRERSMULTIPLE"))
        {
          Program.CalcAcquirersMultiple();
        }
        else if (arg.Equals("CALCACQUIRERSMULTIPLESYMBOL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          Program.CalcAcquirersMultipleSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("CALCTLBRANKS"))
        {
          Program.CalcTLBRanks();
        }
        else if (arg.Equals("CALCSTICKER"))
        {
          Program.CalcSticker();
        }
        else if (arg.Equals("FINDETFMOS"))
        {
          Program.FindETFMOS();
        }
        else if (arg.Equals("CALCSTICKERETF"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("CalcStickerETF REQUIRES SYMBOL");return 0;}
          Program.CalcStickerETF(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("CALCPORTFOLIOBETA"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          if (commandArgs.Has("ACCOUNT"))Program.CalcPortfolioBeta(commandArgs.Coalesce<String>("ACCOUNT"));
          else Program.CalcPortfolioBeta();
        }
        else if (arg.Equals("CALCBETA")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("CALCBETA REQUIRES SYMBOL");return 0;}
          Program.CalcBeta(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("CALCBETAALL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          Program.CalcBetaAll();
        }
        else if (arg.Equals("CALCDCF")) 
        {
          Program.CalcDCF();
        }
        // ****************** I N S I D E R   T R A N S A C T I O N S***************** 
        else if (arg.Equals("LOADINSIDERTRANSACTIONS")) 
        {
          Program.LoadInsiderTransactions();
        }
        else if (arg.Equals("LOADINSIDERTRANSACTIONSYEAR")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("YEAR"))
          {
            Console.WriteLine("LOADINSIDERTRANSACTIONSYEARGREATEREQUAL REQUIRES YEAR");
            return 0;
          }
          Program.LoadInsiderTransactionsYearGreaterEqual(commandArgs.Coalesce<int>("YEAR"));
        }
        else if (arg.Equals("LOADINSIDERTRANSACTIONSSYMBOL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADINSIDERTRANSACTIONSSYMBOL REQUIRES SYMBOL");return 0;}
          Program.LoadInsiderTransactionsSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("LOADINSIDERTRANSACTIONSWATCHLISTS")) 
        {
          Program.LoadInsiderTransactionsWatchLists();
        }
        // ****************** C H A R T I N G   F U N C T I O N A L I T Y ***************** 
        else if (arg.Equals("GENERATESTOCHASTICS"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DAYCOUNT")){Console.WriteLine("GENERATESTOCHASTICS REQUIRES SYMBOL,DAYCOUNT");return 0;}
          else if(commandArgs.Has("SYMBOL,DAYCOUNT,PERIOD-N,PERIOD-K"))Program.GenerateStochastics(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"),commandArgs.Coalesce<int>("PERIOD-N"),commandArgs.Coalesce<int>("PERIOD-K"));
          else if(commandArgs.Has("SYMBOL,DAYCOUNT,PERIOD-N"))Program.GenerateStochastics(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"),commandArgs.Coalesce<int>("PERIOD-N"));
          else if(commandArgs.Has("SYMBOL,DAYCOUNT"))Program.GenerateStochastics(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"));
          else if(commandArgs.Has("SYMBOL"))Program.GenerateStochastics(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("GENERATESTOCHASTICSSHEET"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DAYCOUNT")){Console.WriteLine("GENERATESTOCHASTICS REQUIRES SYMBOL,DAYCOUNT");return 0;}
          else if(commandArgs.Has("SYMBOL,DAYCOUNT,PERIOD-N,PERIOD-K"))Program.GenerateStochasticsSheet(commandArgs.Coalesce<String>("PATHTEMPLATE"),commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"),commandArgs.Coalesce<int>("PERIOD-N"),commandArgs.Coalesce<int>("PERIOD-K"));
          else if(commandArgs.Has("SYMBOL,DAYCOUNT,PERIOD-N"))Program.GenerateStochasticsSheet(commandArgs.Coalesce<String>("PATHTEMPLATE"),commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"),commandArgs.Coalesce<int>("PERIOD-N"));
          else if(commandArgs.Has("SYMBOL,DAYCOUNT"))Program.GenerateStochasticsSheet(commandArgs.Coalesce<String>("PATHTEMPLATE"),commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"));
          else if(commandArgs.Has("SYMBOL"))Program.GenerateStochasticsSheet(commandArgs.Coalesce<String>("PATHTEMPLATE"),commandArgs.Coalesce<String>("SYMBOL"));
          else MDTrace.WriteLine(LogLevel.DEBUG,"Insufficient number of arguments.");
        }
        else if (arg.Equals("GENERATEBOLLINGERBANDS"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,MOVINGAVERAGEDAYS,HISTORICALDAYS")){Console.WriteLine("GENERATEBOLLINGERBANDS REQUIRES SYMBOL,MOVINGAVERAGEDAYS,HISTORICALDAYS");return 0;}
          else if(commandArgs.Has("SYMBOL"))Program.GenerateBollingerBands(commandArgs.Coalesce<String>("SYMBOL"));
          else if(commandArgs.Has("SYMBOL,MOVINGAVERAGEDAYS"))Program.GenerateBollingerBands(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("MOVINGAVERAGEDAYS"));
          else if(commandArgs.Has("SYMBOL,MOVINGAVERAGEDAYS,HISTORICALDAYS"))Program.GenerateBollingerBands(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("MOVINGAVERAGEDAYS"),commandArgs.Coalesce<int>("HISTORICALDAYS"));
          else MDTrace.WriteLine(LogLevel.DEBUG,"Insufficient number of arguments.");
        }
        else if (arg.Equals("GENERATEBOLLINGERBANDSHEET"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("STRPATHTEMPLATE,SYMBOL,MOVINGAVERAGEDAYS,HISTORICALDAYS")){Console.WriteLine("GENERATEBOLLINGERBANDS REQUIRES STRPATHTEMPLATE,SYMBOL,MOVINGAVERAGEDAYS,HISTORICALDAYS");return 0;}
          else if(commandArgs.Has("STRPATHTEMPLATE,SYMBOL"))Program.GenerateBollingerBandSheet(commandArgs.Coalesce<String>("STRPATHTEMPLATE"),commandArgs.Coalesce<String>("SYMBOL"));
          else if(commandArgs.Has("STRPATHTEMPLATE,SYMBOL,MOVINGAVERAGEDAYS"))Program.GenerateBollingerBandSheet(commandArgs.Coalesce<String>("STRPATHTEMPLATE"),commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("MOVINGAVERAGEDAYS"));
          else if(commandArgs.Has("STRPATHTEMPLATE,SYMBOL,MOVINGAVERAGEDAYS,HISTORICALDAYS"))Program.GenerateBollingerBandSheet(commandArgs.Coalesce<String>("STRPATHTEMPLATE"),commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("MOVINGAVERAGEDAYS"),commandArgs.Coalesce<int>("HISTORICALDAYS"));
          else MDTrace.WriteLine(LogLevel.DEBUG,"Insufficient number of arguments.");
        }
        else if (arg.Equals("GENERATEMOVINGAVERAGESHEET"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("STRPATHTEMPLATE,SYMBOL")){Console.WriteLine("GENERATEMOVINGAVERAGESHEET REQUIRES STRPATHTEMPLATE,SYMBOL");return 0;}
          else if(commandArgs.Has("STRPATHTEMPLATE,SYMBOL"))Program.GenerateMovingAverageSheet(commandArgs.Coalesce<String>("STRPATHTEMPLATE"),commandArgs.Coalesce<String>("SYMBOL"));
        }
        // ************************************* S T O C H A S T I C S    ***************************
        else if (arg.Equals("RUNSTOCHASTICSSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("RUNSTOCHASTICSSYMBOL REQUIRES SYMBOL");return 0;}
          else if(commandArgs.Has("SYMBOL"))Program.GenerateStochastics(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("RUNSTOCHASTICSSIGNALSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("RUNSTOCHASTICSSIGNALSYMBOL REQUIRES SYMBOL");return 0;}
          else if(commandArgs.Has("SYMBOL"))Program.GenerateStochasticsSignals(commandArgs.Coalesce<String>("SYMBOL"));
        }
        // ************************************* M A C D   A N D   S I G N A L   ***************************
        else if (arg.Equals("RUNPIVOTS")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DAYCOUNT")){Console.WriteLine("RUNPIVOTS REQUIRES SYMBOL,DAYCOUNT");return 0;}
          else if(commandArgs.Has("SYMBOL"))Program.RunPivots(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"));
        }
        else if (arg.Equals("RUNMACDSIGNALSYMBOL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(commandArgs.Has("SYMBOL,MACD"))Program.RunMACDSignalSymbol(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<String>("MACD"));
          else if(commandArgs.Has("SYMBOL"))Program.RunMACDSignalSymbol(commandArgs.Coalesce<String>("SYMBOL"));
          else {Console.WriteLine("RUNMACDSYMBOL REQUIRES SYMBOL,MACD");return 0;}
        }

        else if (arg.Equals("TRADESYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,SHARES,STARTDATE,HOLDINGDAYS")){Console.WriteLine("TRADESYMBOL REQUIRES SYMBOL,SHARES,STARTDATE,HOLDINGDAYS");return 0;}
          else Program.TradeSymbol(
            commandArgs.Coalesce<String>("SYMBOL"),
            commandArgs.Coalesce<int>("SHARES"),
            commandArgs.Coalesce<DateTime>("STARTDATE"),
            commandArgs.Coalesce<int>("HOLDINGDAYS"));
        }
        // ************************************* Y I E L D  C U R V E    ***************************
        else if (arg.Equals("UPDATEYIELDCURVE")) 
        {
          Program.UpdateYieldCurve();
        }
        else if (arg.Equals("UPDATEYIELDCURVEHIST")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("YEARS")){Console.WriteLine("UPDATEYIELDCURVEHIST REQUIRES YEARS");return 0;}
          else Program.UpdateYieldCurve(commandArgs.Coalesce<int>("YEARS"));
        }
        // ************************************* D I V I D E N D  H I S T O R Y    ***************************
        else if (arg.Equals("UPDATEDIVIDENDHISTORY")) 
        {
          Program.UpdateDividendHistory();
        }
        else if (arg.Equals("UPDATEDIVIDENDHISTORYSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATEDIVIDENDHISTORYSYMBOL REQUIRES SYMBOL");return 0;}
          else Program.UpdateDividendHistory(commandArgs.Coalesce<String>("SYMBOL"));
        }
        // ************************************* M I S C E L L A N E O U S   ***************************
        else if (arg.Equals("GETETFHOLDINGS")) 
        {
          Program.GetETFHoldings();
        }
        else if (arg.Equals("GETETFHOLDINGSSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("GETETFHOLDINGSSYMBOL REQUIRES SYMBOL");return 0;}
          else Program.GetETFHoldingsSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("UPDATEOPTIONSCHAINS"))
        {
          Program.UpdateOptionsChains();
        }
        else if (arg.Equals("UPDATEOPTIONSCHAINSSYMBOL")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATEOPTIONSCHAINSSYMBOL REQUIRES SYMBOL");return 0;}
          else Program.UpdateOptionsChains(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if (arg.Equals("UPDATEOPTIONSCHAINSSYMBOLS")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOLS")){Console.WriteLine("UPDATEOPTIONSCHAINSSYMBOLS REQUIRES SYMBOLS");return 0;}
          else Program.UpdateOptionsChains(commandArgs.Coalesce<String>("SYMBOLS"));
        }
        else if (arg.Equals("UPDATEOPTIONSCHAINSWATCHLIST")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("WATCHLIST")){Console.WriteLine("UPDATEOPTIONSCHAINSWATCHLIST REQUIRES WATCHLIST");return 0;}
          else Program.UpdateOptionsChainsWatchList(commandArgs.Coalesce<String>("WATCHLIST"));
        }
        else if (arg.Equals("DISPLAYAVAILABLEOPTIONS"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(commandArgs.Has("DAYSOUT,VERBOSE"))DisplayAvailableOptions(commandArgs.Coalesce<int>("DAYSOUT"),commandArgs.Coalesce<bool>("VERBOSE"));
          else if(commandArgs.Has("DAYSOUT"))Program.DisplayAvailableOptions(commandArgs.Coalesce<int>("DAYSOUT"));
          else Program.DisplayAvailableOptions();
        }
        else if (arg.Equals("GETVAR"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("DAYCOUNT,CONFIDENCE,RETURNDAYS")){Console.WriteLine("GETVAR REQUIRES DAYCOUNT,CONFIDENCE,RETURNDAYS");return 0;}
          else Program.GetVaR(commandArgs.Coalesce<String>("DAYCOUNT"),commandArgs.Coalesce<String>("CONFIDENCE"),commandArgs.Coalesce<String>("RETURNDAYS"));
        }
        else if (arg.Equals("GETOPTIMALPOSITIONFROMWATCHLIST")) 
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("WATCHLIST,MARKETVALUE,DAYCOUNT,CONFIDENCE,RETURNDAYS")){Console.WriteLine("GETOPTIMALPOSITIONFROMWATCHLIST REQUIRES WATCHLIST,MARKETVALUE,DAYCOUNT,CONFIDENCE,RETURNDAYS");return 0;}
          else Program.GetOptimalPositionFromWatchList(
            commandArgs.Coalesce<String>("WATCHLIST"),
            commandArgs.Coalesce<String>("MARKETVALUE"),
            commandArgs.Coalesce<String>("DAYCOUNT"),
            commandArgs.Coalesce<String>("CONFIDENCE"),
            commandArgs.Coalesce<String>("RETURNDAYS"));
        }
        else if (arg.Equals("UPDATEMISSINGPRICES"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(commandArgs.Has("DATE"))Program.GetMissingPrices(commandArgs.Coalesce<DateTime>("DATE"));
          else Program.GetMissingPrices();
        }
        else if (arg.Equals("UPDATEMISSINGPRICESSYMBOL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("UPDATEMISSINGPRICESSYMBOL REQUIRES SYMBOL");return 0;}
          else Program.GetMissingPricesSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if(arg.Equals("LOADGDP"))
        {
          Program.LoadGDPPerCapita();
        }
        else if(arg.Equals("LOADPREMARKETDATA"))
        {
          Program.LoadPremarketData();
        }
        else if(arg.Equals("LOADHEADLINESWATCHLIST"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("WATCHLIST")){Console.WriteLine("LOADHEADLINESWATCHLIST REQUIRES WATCHLIST");return 0;}
          else Program.LoadHeadlinesWatchList(commandArgs.Coalesce<String>("WATCHLIST"));
        }
        else if(arg.Equals("LOADHEADLINESSYMBOL"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL")){Console.WriteLine("LOADHEADLINESSYMBOL REQUIRES SYMBOL");return 0;}
          else Program.LoadHeadlinesSymbol(commandArgs.Coalesce<String>("SYMBOL"));
        }
        else if(arg.Equals("FINDCOEFFICIENTS"))
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SYMBOL,DAYCOUNT")){Console.WriteLine("FINDCOEFFICIENTS REQUIRES SYMBOL,DAYCOUNT");return 0;}
          Program.FindCoefficients(commandArgs.Coalesce<String>("SYMBOL"),commandArgs.Coalesce<int>("DAYCOUNT"),commandArgs.Coalesce<DateTime>("STARTDATE",new DateTime()));
        }
        else if (arg.Equals("DISPLAYVOLATILITY"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          DateTime? startDate=null;
          if (!commandArgs.Has("SYMBOLS,DAYCOUNT")) { Console.WriteLine("DISPLAYVOLATILITY REQUIRES SYMBOLS,DAYCOUNT"); return 0; }
          if (commandArgs.Has("STARTDATE")) startDate = commandArgs.Coalesce<DateTime>("STARTDATE");
          Program.DisplayVolatility(Utility.ToList(commandArgs.Coalesce<String>("SYMBOLS")), commandArgs.Coalesce<int>("DAYCOUNT"),startDate);
        }
        else if (arg.Equals("DISPLAYSHARPERATIO"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          DateTime? startDate = null;
          int months = 12;
          if (!commandArgs.Has("SYMBOLS")) { Console.WriteLine("DISPLAYSHARPERATIO REQUIRES SYMBOLS"); return 0; }
          if (commandArgs.Has("STARTDATE")) startDate = commandArgs.Coalesce<DateTime>("STARTDATE");
          if (commandArgs.Has("MONTHS")) months = commandArgs.Coalesce<int>("MONTHS");
          Program.DisplaySharpeRatio(Utility.ToList(commandArgs.Coalesce<String>("SYMBOLS")), months, startDate);
        }
// *************************************************************************************************************************************************************************************************************************
// ************************************************************************************************** C M T M O M E N T U M   *************************************************************************************************
// *************************************************************************************************************************************************************************************************************************
        else if(arg.Equals("RUNCMTREND"))
        {
          Program.RunCMTrend(args);
        }
        else if(arg.Equals("CMTSESSION"))
        {
          Program.HandleCMTSession(args);
        }
// *************************************************************************************************************************************************************************************************************************
// ************************************************************************************************** M G S H   M O M E N T U M   *************************************************************************************************
// *************************************************************************************************************************************************************************************************************************
        else if(arg.Equals("MGSHSESSION"))
        {
          MGSHMomentumHelper.HandleMGSHSession(args);
        }
        else if(arg.Equals("MGSHRUNBACKTEST"))
        {
          MGSHMomentumHelper.HandleMGSHRunBacktest(args);
        }
        else if(arg.Equals("MGSHRUNDAILY"))
        {
          MGSHMomentumHelper.HandleMGSHRunDaily(args);
        }        
// *************************************************************************************************************************************************************************************************************************
// ************************************************************************************************** M G    M O M E N T U M   *************************************************************************************************
// *************************************************************************************************************************************************************************************************************************
        else if (arg.Equals("RUNMOMENTUM"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          if (!commandArgs.Has("STARTDATE,MAXPOSITIONS")) return 0;
          Program.RunMomentum(commandArgs.Coalesce<DateTime>("STARTDATE"), commandArgs.Coalesce<int>("MAXPOSITIONS"));
        }
        else if (arg.Equals("RUNBACKTEST"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          MGConfiguration mgParams=new MGConfiguration();
          if (!commandArgs.Has("STARTDATE,MAXPOSITIONS,INITIALCASH,HOLDINGPERIOD"))
          {
            if (!commandArgs.Has("STARTDATE")) MDTrace.WriteLine(LogLevel.DEBUG, "Missing STARTDATE");
            if (!commandArgs.Has("MAXPOSITIONS")) MDTrace.WriteLine(LogLevel.DEBUG, "Missing MAXPOSITIONS");
            if (!commandArgs.Has("INITIALCASH")) MDTrace.WriteLine(LogLevel.DEBUG, "Missing INITIALCASH");
            if (!commandArgs.Has("HOLDINGPERIOD")) MDTrace.WriteLine(LogLevel.DEBUG, "Missing HOLDINGPERIOD");
            return 0;
          }
          mgParams.MaxPositions=commandArgs.Coalesce<int>("MAXPOSITIONS");
          mgParams.InitialCash=commandArgs.Coalesce<int>("INITIALCASH");
          mgParams.HoldingPeriod=commandArgs.Coalesce<int>("HOLDINGPERIOD");

          if(commandArgs.Has("INCLUDETRADEMASTERFORSYMBOLSHELD"))
          {
            mgParams.IncludeTradeMasterForSymbolsHeld=commandArgs.Get<bool>("INCLUDETRADEMASTERFORSYMBOLSHELD");
          }

          if(commandArgs.Has("USESTOCHASTICS")) 
          {
            mgParams.UseStochastics=commandArgs.Coalesce<bool>("USESTOCHASTICS",true);
          }

// ** M A C D 
          if(commandArgs.Has("USEMACD"))
          {
            mgParams.UseMACD=commandArgs.Coalesce<bool>("USEMACD",true);
          }
          if(commandArgs.Has("MACDREJECTSTRONGSELLSIGNALS"))
          {
            mgParams.MACDRejectStrongSellSignals=commandArgs.Coalesce<bool>("MACDREJECTSTRONGSELLSIGNALS",true);
          }
          if(commandArgs.Has("MACDREJECTWEAKSELLSIGNALS"))
          {
            mgParams.MACDRejectWeakSellSignals=commandArgs.Coalesce<bool>("MACDREJECTWEAKSELLSIGNALS",true);
          }
          if(commandArgs.Has("MACDSIGNALDAYS"))
          {
            mgParams.MACDSignalDays=commandArgs.Coalesce<int>("MACDSIGNALDAYS",mgParams.MACDSignalDays);
          }
          if(commandArgs.Has("MACDSETUP"))
          {
            mgParams.MACDSetup=commandArgs.Coalesce<String>("MACDSETUP",mgParams.MACDSetup);
          }
// **
          QualityIndicator qualityIndicator=new QualityIndicator(QualityIndicator.QualityType.IDIndicator);
          if(commandArgs.Has("QUALITYINDICATORTYPE")) qualityIndicator.Quality=QualityIndicator.ToQuality(commandArgs.Coalesce<String>("QUALITYINDICATORTYPE","IDINDICATOR"));
          mgParams.QualityIndicatorType=qualityIndicator.ToString();

          mgParams.UseLowSlopeBetaCheck=true;
          if(commandArgs.Has("USELOWSLOPEBETACHECK")) mgParams.UseLowSlopeBetaCheck=commandArgs.Coalesce<bool>("USELOWSLOPEBETACHECK",true);

          DateTime startDate = commandArgs.Coalesce<DateTime>("STARTDATE");
          DateTime endDate=commandArgs.Coalesce<DateTime>("ENDDATE",new DateTime());

          String pathSessionFileName = commandArgs.Coalesce<String>("SESSIONFILE", null);
          if(null!=pathSessionFileName)pathSessionFileName=pathSessionFileName.Trim();

          mgParams.DisplayHeader();
          List<BacktestResult> results=new List<BacktestResult>();
          MomentumBacktest backtestMomentum=new MomentumBacktest();
          results.Add(backtestMomentum.PerformBacktest(startDate,endDate,pathSessionFileName,mgParams));
        }
        else if (arg.Equals("MGSESSION"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          if(!commandArgs.Has("SESSIONFILE")) { MDTrace.WriteLine(LogLevel.DEBUG,"Missing SESSIONFILE"); return 0; }
          MomentumBacktest momentumBacktest = new MomentumBacktest();
          momentumBacktest.DisplaySession(commandArgs.Coalesce<String>("SESSIONFILE"));
        }
        else if(arg.Equals("MGGAINLOSS"))
        {
          CommandArgs commandArgs = new CommandArgs(args);
          if(!commandArgs.Has("SESSIONFILE")) { MDTrace.WriteLine(LogLevel.DEBUG,"Missing SESSIONFILE"); return 0; }
          MomentumBacktest momentumBacktest = new MomentumBacktest();
          MomentumBacktest.DisplayGainLoss(commandArgs.Coalesce<String>("SESSIONFILE"));
        }
        else if (arg.Equals("MGLIQUIDATE"))
        {
          DateTime? tradeDate = null;
          CommandArgs commandArgs = new CommandArgs(args);
          if (!commandArgs.Has("SESSIONFILE")) return 0;
          if (commandArgs.Has("TRADEDATE")) tradeDate = commandArgs.Coalesce<DateTime>("TRADEDATE");
          MomentumBacktest momentumBacktest = new MomentumBacktest();
          momentumBacktest.MGLiquididate(commandArgs.Coalesce<String>("SESSIONFILE"), tradeDate);
        }
// *************************************************************************************************************************************************************************************************************************
// ************************************************************************************************** C M M O M E N T U M  *************************************************************************************************
// *************************************************************************************************************************************************************************************************************************
        else if(arg.Equals("RUNCMBACKTEST"))   // CMMOMENTUM
        {
				  RunCMMomentum(args);  
        }
        else if (arg.Equals("CMSESSION"))			 // CMMOMENTUM
        {
          CommandArgs commandArgs = new CommandArgs(args);
          if (!commandArgs.Has("SESSIONFILE")) {MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Missing SESSIONFILE"));return 0;}
          CMMomentumBacktest cmBacktest = new CMMomentumBacktest();
          cmBacktest.DisplaySession(commandArgs.Coalesce<String>("SESSIONFILE"));
        }
        else if(arg.Equals("CMGAINLOSS"))			// CMMOMENTUM
        {
          CommandArgs commandArgs=new CommandArgs(args);
          if(!commandArgs.Has("SESSIONFILE")) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Missing SESSIONFILE")); return 0; }
          CMMomentumBacktest cmBacktest=new CMMomentumBacktest();
          cmBacktest.DisplayGainLoss(commandArgs.Coalesce<String>("SESSIONFILE"));
        }
        else if (arg.Equals("CMCANDIDATELASTRESORT"))		 // CMMOMENTUM
        {
          CMParams cmParams = new CMParams();
          List<String> candidates = Utility.ToList(cmParams.FallbackCandidateBestOf);
          CommandArgs commandArgs = new CommandArgs(args);
          if (!commandArgs.Has("TRADEDATE")) { MDTrace.WriteLine(LogLevel.DEBUG, "TRADEDATE required"); return 0; }
          CMCandidate cmCandidate = CMCandidateGenerator.GetFallbackCandidateOfLastResort(candidates, commandArgs.Coalesce<DateTime>("TRADEDATE"), commandArgs.Coalesce<DateTime>("TRADEDATE"), cmParams);
          if (null == cmCandidate) { MDTrace.WriteLine(LogLevel.DEBUG, "Unable to determine candidate of last resort."); return 0; }
          foreach (String candidate in candidates)
          {
            MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Candidate examined..{0}", candidate));
          }
          MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Best candidate is {0}", cmCandidate.Symbol));
        }
        else
        {
          DisplayUsage();
          return 1;
        }
				return 0;
			}
			catch (Exception exception)
			{
				MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
				return 1;
			}
      finally
      {
        LocalPriceCache.GetInstance().Dispose();
        GBPriceCache.GetInstance().Dispose();
      }
    }     // main
// *****************************************************************************************************************************************************************************
// *****************************************************************************************************************************************************************************
// *****************************************************************************************************************************************************************************
    public static void RunPriceCheckOpenPositions()
    {
      PortfolioTrades portfolioTrades=PortfolioDA.GetTrades();
      portfolioTrades=portfolioTrades.GetOpenTradesOn(PricingDA.GetLatestDate());
      List<String> symbols=portfolioTrades.Symbols;
      symbols.Sort();
      foreach(String symbol in symbols)
      {
        DateTime latestDate=PricingDA.GetLatestDate(symbol);
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} {1}",symbol,Utility.DateTimeToStringMMSDDSYYYY(latestDate)));
      }
    }
    public static void SendSMSEmail(String message)
    {
      try
      {
        String smsSMTPAddress = ConfigurationManager.AppSettings["sms_smtpaddress"];
        String smsUserName = ConfigurationManager.AppSettings["sms_smsusername"];
        String smsPassword = ConfigurationManager.AppSettings["sms_smspassword"];
        String[] smsRecipients = ConfigurationManager.AppSettings["sms_smsrecipients"].Split(',');
        SMSClient.SendSMSEmail(message, smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword);
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Done."));
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("SendSMSEmail: Exception: {0}.",exception.ToString()));
      }
    }
    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 ProcessAllSplits()
    {
      MDTrace.WriteLine("Processing all splits");
      Splits splits=SplitsDA.GetUnappliedSplits();
      if(null==splits||0==splits.Count)return;
      SplitHelper.ProcessSplits(splits);
    }
    public static void ProcessSplit(String symbol)
    {
      if(null==symbol)return;
      symbol=symbol.ToUpper();
      SplitHelper.ProcessSplit(symbol);
    }
    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 CheckPrices()
    {
      List<String> symbols=PricingDA.GetSymbols();
      DateGenerator dateGenerator=new DateGenerator();
      int maxDaysBetween=100;

      foreach(String symbol in symbols)
      {
        DateTime minDate=PricingDA.GetEarliestDate(symbol);
        DateTime maxDate=PricingDA.GetLatestDate(symbol);
        DateTime earliestDate=DateTime.Parse("10-23-2003");
        if(minDate<earliestDate)minDate=earliestDate;
        Prices prices=PricingDA.GetPrices(symbol,maxDate,minDate);
        if(null==prices||0==prices.Count)continue;
        for(int index=0;index<prices.Count;index++)
        {
          if(!(index<prices.Count-2))continue;
          int daysBetween=dateGenerator.DaysBetween(prices[index].Date,prices[index+1].Date);
          if(daysBetween>maxDaysBetween)
          {
            DateTime problemDate=prices[index].Date;
            DateTime problemDateEnd=prices[index+1].Date;
            Prices pricesAfter=PricingDA.GetPrices(symbol,maxDate,problemDate);
            Prices pricesBefore=PricingDA.GetPrices(symbol,problemDate,minDate);
            int countPricesBefore=0;
            int countPricesAfter=0;
            double stddevBefore=0.00;
            double stddevAfter=0.00;
            if(null!=pricesAfter)
            {
              countPricesAfter=pricesAfter.Count;
              float[] returnsAfter=pricesAfter.GetReturns();
              stddevAfter=Numerics.StdDev(ref returnsAfter);
            }
            if(null!=pricesBefore)
            {
              countPricesBefore=pricesBefore.Count;
              float[] returnsBefore=pricesBefore.GetReturns();
              stddevBefore=Numerics.StdDev(ref returnsBefore);
            }
            if(countPricesBefore>countPricesAfter&&double.IsNaN(stddevAfter))  
            {
              PricingDA.DeletePriceOnOrAfter(symbol,problemDate);
              MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Found price discontinuity at symbol:{0} for date : {1}, gap is {2} days, prices prior {3}, prices after {4}.  deviation before {5}, deviation after {6}",symbol,prices[index].Date,daysBetween,countPricesBefore,countPricesAfter,Utility.FormatNumber(stddevBefore,2),Utility.FormatNumber(stddevAfter,2)));
              MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Delete symbol:{0} for date >= {1}",symbol,Utility.DateTimeToStringMMHDDHYYYY(prices[index].Date)));
            }
            else if(countPricesAfter>countPricesBefore&&double.IsNaN(stddevBefore))
            {
              PricingDA.DeletePriceOnOrBefore(symbol,problemDate);
              MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Found price discontinuity at symbol:{0} for date : {1}, gap is {2} days, prices prior {3}, prices after {4}.  deviation before {5}, deviation after {6}",symbol,prices[index].Date,daysBetween,countPricesBefore,countPricesAfter,Utility.FormatNumber(stddevBefore,2),Utility.FormatNumber(stddevAfter,2)));
              MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Delete symbol:{0} for date <= {1}",symbol,Utility.DateTimeToStringMMHDDHYYYY(prices[index].Date)));
            }
          }
        }
      }
    }
// *************************************************************************************************************************
// *********************************************** U P D A T E   D A I L Y   ************************************************
// *************************************************************************************************************************
    public static void UpdateDaily()
    {
      UpdateDaily2(DateTime.Now);
    }
// *************************************************************************************************************************************************************************************
// **************************************************************************** U P D A T E D A I L Y P R I C E S *******************************************************************************
// *************************************************************************************************************************************************************************************
    public static void UpdateDailyPrices(DateTime startDate) 
    {
      DateGenerator dateGenerator=new DateGenerator();
      String smsSMTPAddress = ConfigurationManager.AppSettings["sms_smtpaddress"];
      String smsUserName = ConfigurationManager.AppSettings["sms_smsusername"];
      String smsPassword = ConfigurationManager.AppSettings["sms_smspassword"];
      String[] smsRecipients = ConfigurationManager.AppSettings["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(!CheckRunCriteria())
      {
        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_FINAL=2;
      DeletePriceWatchList("valuations", startDate.ToShortDateString());
      DeletePriceWatchList("Momentum", startDate.ToShortDateString());

      ManualResetEvent[] resetEvents = new ManualResetEvent[STAGE_FINAL+1];
      for(int index=0;index<resetEvents.Length;index++)resetEvents[index] = new ManualResetEvent(false);

      resetEvents[STAGE_1].Reset();

// The monitor thread should always be STAGE_FINAL so make whatever adjustments are necessary to make this hold going forward
      ThreadPool.QueueUserWorkItem(delegate
      {
        List<ManualResetEvent> manualResetEventsList = resetEvents.ToList<ManualResetEvent>();

        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("UPDATEDAILYPRICES Network monitor activated", smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword);
        while (running)
        {
          if (!NetworkStatus.IsInternetConnected())
          {
            connectionIssue = true;
            SMSClient.SendSMSEmail("UPDATEDAILYPRICES Network is not connected", smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword);
          }
          else if (connectionIssue)
          {
            connectionIssue = false;
            SMSClient.SendSMSEmail("UPDATEDAILYPRICES 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("UPDATEDAILYPRICES 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("UPDATEDAILYPRICES UPDATEPRICESBIGCHARTS/YAHOO done.", smsUserName, smsRecipients, smsSMTPAddress, smsUserName, smsPassword);
      });
      resetEvents[STAGE_1].WaitOne();  // wait for pricing to finish

      WaitHandle.WaitAll(resetEvents);
    }
// *************************************************************************************************************************************************************************************
// **************************************************************************** U P D A T E D A I L Y 2 *******************************************************************************
// *************************************************************************************************************************************************************************************
    public static void UpdateDaily2(DateTime startDate) 
    {
      DateGenerator dateGenerator=new DateGenerator();
      String smsSMTPAddress = ConfigurationManager.AppSettings["sms_smtpaddress"];
      String smsUserName = ConfigurationManager.AppSettings["sms_smsusername"];
      String smsPassword = ConfigurationManager.AppSettings["sms_smspassword"];
      String[] smsRecipients = ConfigurationManager.AppSettings["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<resetEvents.Length;index++)resetEvents[index] = new ManualResetEvent(false);

      resetEvents[STAGE_1].Reset();

// This thread serves as network monitor thread.  It will live for the duration of the other threads and exit when they are all completed
// The monitor thread should always be STAGE_FINAL so make whatever adjustments are necessary to make this hold going forward
      ThreadPool.QueueUserWorkItem(delegate
      {
        List<ManualResetEvent> manualResetEventsList = resetEvents.ToList<ManualResetEvent>();

        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
      {
//        UpdateOptionsChainsWatchList("valuations");           // www.nasdaq.com   OPTIONS CHAINS ARE NOT WORKING : THIS NEEDS TO BE OBSOLETED
        resetEvents[STAGE_12].Set();
      });   
      WaitHandle.WaitAll(resetEvents);
    }
// *************************************************************************************************************************
// *********************************************** U P D A T E   A L L   ************************************************
// *************************************************************************************************************************
    public static void UpdateAll()
    {
      try
      {
        //UpdateMissingAnalystRatings();    // runs daily as well
        UpdatePrices();
        GetMissingPrices();
        UpdateEarningsAnnouncements();    // runs daily as well
        LoadFundamentals();
        LoadFinancialStatements();
        LoadHistorical();
        LoadInsiderTransactions();        // runs daily as well
        UpdateYieldCurve();               // runs daily as well
        UpdateAllMissingCIK();            // runs daily as well
        UpdateDividendHistory();          // runs daily as well
        //UpdateAnalystRatings(null, true); // runs daily as well
        UpdateLatestAnalystRatings(true);
        UpdateCompanyProfiles();          // runs daily as well
        UpdateSECFilings();
        GetETFHoldings();                 // runs daily as well
        LoadGDPPerCapita();               // runs daily as well
        UpdateOptionsChains();
        UpdateAnalystPriceTarget();       // runs daily as well
        CalcSticker();
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void UpdateAllNoPrices()
    {
      try
      {
        //UpdateMissingAnalystRatings();
        LoadFundamentals();
        LoadFinancialStatements();
        LoadHistorical();
        CalcSticker();
        LoadInsiderTransactions();
        UpdateYieldCurve();
        UpdateAllMissingCIK();
        UpdateDividendHistory();
        UpdateLatestAnalystRatings(true);
        //UpdateAnalystRatings(null, true);
        UpdateCompanyProfiles();
        UpdateSECFilings();
        GetETFHoldings();
        LoadGDPPerCapita();
        UpdateOptionsChains();
        UpdateAnalystPriceTarget();
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
// *************************************************************************************************************************
// *********************************************** Z A C K S  R A N K     ************************************************
// *************************************************************************************************************************
  public static void LoadZacksRank()
  {
    ZacksRankMarketDataHelper zacksRankMarketDataHelper=new ZacksRankMarketDataHelper();
    zacksRankMarketDataHelper.LoadZacksRank();
  }
  public static void LoadZacksRank(String symbol)
  {
    ZacksRankMarketDataHelper zacksRankMarketDataHelper=new ZacksRankMarketDataHelper();
    zacksRankMarketDataHelper.LoadZacksRank(symbol);
  }
// *************************************************************************************************************************
// *********************************************** D I V I D E N D  H I S T O R Y    ************************************************
// *************************************************************************************************************************
		public static void UpdateDividendHistory(String symbol)
		{
			DividendHistoryMarketDataHelper dividendHistoryMarketDataHelper=new DividendHistoryMarketDataHelper();
			dividendHistoryMarketDataHelper.UpdateDividendHistory(symbol);
		}
		public static void UpdateDividendHistory()
		{
			DividendHistoryMarketDataHelper dividendHistoryMarketDataHelper=new DividendHistoryMarketDataHelper();
			dividendHistoryMarketDataHelper.UpdateDividendHistory();
		}
// *****************************************************************************************************************************
// *************************************************** A N A L Y S T   P R I C E  T A R G E T    *******************************
// *****************************************************************************************************************************
    public static void UpdateAnalystPriceTarget()
    {
      MDTrace.WriteLine(LogLevel.DEBUG,"[UPDATEANALYSTPRICETARGET]");
      AnalystPriceTargetMarketDataHelper analystPriceTargetMarketDataHelper=new AnalystPriceTargetMarketDataHelper();
      analystPriceTargetMarketDataHelper.LoadAnalystPriceTarget();
      MDTrace.WriteLine(LogLevel.DEBUG,"[UPDATEANALYSTPRICETARGET] Done");
    }
// *****************************************************************************************************************************
// *************************************************** A N A L Y S T   R A T I N G S   *****************************************
// *****************************************************************************************************************************
    public static void UpdateMissingAnalystRatings()
    {
      try
      {
        DateGenerator dateGenerator = new DateGenerator();
        List<String> 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 UpdateAnalystRatings(String paramSymbol = null,DateTime? minDate=null)
    {
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG, "[UPDATEANALYSTRATINGS]");
        List<String> symbols = new List<String>();
        if (paramSymbol == null) symbols = PricingDA.GetSymbols();
        else symbols.Add(paramSymbol);
        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 duplicateList = new AnalystRatings();
          if (null != minDate)
          {
            MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Minimum Rating Date of {0} is specified.", minDate.Value.ToShortDateString()));
            analystRatings = new AnalystRatings((from AnalystRating analystRating in analystRatings where analystRating.Date >= minDate.Value select analystRating).ToList());
          }
          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);
      }
      finally
      {
        MDTrace.WriteLine(LogLevel.DEBUG, "[UPDATEANALYSTRATINGS]");
      }
    }
    public static void UpdateLatestAnalystRatings(Boolean createSecurityMaster = true)
    {
      try
      {
        DateGenerator dateGenerator = new DateGenerator();
        MDTrace.WriteLine(LogLevel.DEBUG, "[UPDATELATESTANALYSTRATINGS]");
        AnalystRatings analystRatings = MarketDataHelper.GetLatestAnalystRatings();
        List<String> 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);
      }
    }
// *************************************************************************************************************************
// *********************************************** O P T I O N S   D A T A   ************************************************
// *************************************************************************************************************************
    public static void UpdateOptionsChainsWatchList(String watchList)   // get options chains from NASDAQ
    {
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UpdateOptionsChainWatchList {0}",watchList));
        List<String> symbols = WatchListDA.GetWatchList(watchList);
        OptionsChainsMarketDataHelper optionsChainsMarketDataHelper = new OptionsChainsMarketDataHelper();
        optionsChainsMarketDataHelper.LoadOptionsChains(symbols);
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void UpdateOptionsChains()   // get options chains from NASDAQ
    {
      try
      {
        List<String> symbols = PricingDA.GetSymbols();
        OptionsChainsMarketDataHelper optionsChainsMarketDataHelper = new OptionsChainsMarketDataHelper();
        optionsChainsMarketDataHelper.LoadOptionsChains(symbols);
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void UpdateOptionsChains(String symbol)   // get options chains from NASDAQ
    {
      try
      {
        if (null == symbol) return;
        if(!symbol.Contains(','))
        {
          symbol = symbol.ToUpper();
          OptionsChainsMarketDataHelper optionsChainsMarketDataHelper = new OptionsChainsMarketDataHelper();
          optionsChainsMarketDataHelper.LoadOptionsChains(symbol);
        }
        else
        {
          String[] symbolArray=symbol.Split(',');
          List<String> symbols=symbolArray.ToList<String>();
          for(int index=0;index<symbols.Count;index++)symbols[index]=symbols[index].ToUpper();
          OptionsChainsMarketDataHelper optionsChainsMarketDataHelper = new OptionsChainsMarketDataHelper();
          optionsChainsMarketDataHelper.LoadOptionsChains(symbols);
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
// *****************************************************************************************************************************
// *************************************************** P R I C I N G   D A T A  ************************************************
// *****************************************************************************************************************************
		public static void UpdatePricesAsOf(DateTime asOf)   // get prices from BigCharts
		{
			PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			pricingMarketDataHelper.UpdatePricesAsOf(asOf);
		}
		public static void UpdatePricesAsOfSymbol(String symbol,DateTime asOf)
		{
			PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			pricingMarketDataHelper.UpdatePricesAsOfSymbol(symbol,asOf);
		}
    public static void UpdatePricesAsOfSymbolYahoo(String symbol,DateTime asOf)
    {
      PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
      pricingMarketDataHelper.UpdatePriceAsOfSymbolYahoo(symbol,asOf);
    }
		public static void UpdatePricesBigCharts(DateTime startDate)
		{
			PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			pricingMarketDataHelper.UpdatePricesBigCharts(startDate);
		}
    public static void UpdatePricesYahoo(DateTime startDate)
    {
      PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
      pricingMarketDataHelper.UpdatePricesYahoo(startDate);
    }
    public static void UpdatePricesYahooSweep(DateTime startDate)
    {
      PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
      pricingMarketDataHelper.UpdatePricesYahooSweep(startDate);
    }
		public static void UpdateLatestPriceAll()
		{
			PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			pricingMarketDataHelper.UpdateLatestPriceAll();
		}
		public static void UpdateLatestPriceSymbol(String symbol)
		{
			PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			pricingMarketDataHelper.UpdateLatestPriceSymbol(symbol);
		}
    public static void DeletePricesAsOf(String strDate)
    {
      try
      {
        DateTime asof=DateTime.Parse(strDate);
        List<String> symbols = PricingDA.GetSymbols();
        for(int index=0;index<symbols.Count;index++)
        {
          String symbol=symbols[index];
          symbol = symbol.ToUpper();
          MDTrace.WriteLine(LogLevel.DEBUG,"Removing price for '" + symbol + "' on " + Utility.DateTimeToStringMMSDDSYYYY(asof));
          PricingDA.DeletePrice(symbol, asof);
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void DeleteLatestPriceSymbol(String symbol)
    {
      try
      {
        symbol = symbol.ToUpper();
        Price latestPrice = MarketDataHelper.GetLatestPrice(symbol);
        MDTrace.WriteLine(LogLevel.DEBUG,"Removing price for '" + symbol + "' on " + Utility.DateTimeToStringMMSDDSYYYY(latestPrice.Date));
        PricingDA.DeletePrice(symbol, latestPrice.Date);
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
   public static void UpdateLatestPriceWatchList(String watchListName)
   {
     try
     {
        if(!CheckRunCriteria())return;
        List<String> symbols = WatchListDA.GetWatchList(watchListName);
			  PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			  pricingMarketDataHelper.UpdateLatestPrices(symbols);
     }
     catch (Exception exception)
     {
       MDTrace.WriteLine(LogLevel.DEBUG,exception);
     }
   }
   public static void UpdateLatestPriceOpenPositions()
   {
     try
     {
       if(!CheckRunCriteria())return;
       PortfolioTrades portfolioTrades=PortfolioDA.GetOpenTrades();
       List<String> symbols=(from PortfolioTrade portfolioTrade in portfolioTrades select portfolioTrade.Symbol).Distinct().ToList();
       if(symbols.Any(x=>x.Equals("SPY")))symbols.Add("SH");
			 PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			 pricingMarketDataHelper.UpdateLatestPrices(symbols);
     }
     catch (Exception exception)
     {
       MDTrace.WriteLine(LogLevel.DEBUG,exception);
     }
   }
   public static void DeletePriceWatchList(String watchListName,String strDate)
   {
     try
     {
       List<String> 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 RollPriceForward(String symbol,DateTime fromDate,DateTime toDate)
   {
     try
     {
       DateGenerator dateGenerator=new DateGenerator();
       if(!PricingDA.CheckPricingOn(symbol,fromDate))
       {
         MDTrace.WriteLine(LogLevel.DEBUG,String.Format("There is no price for {0} on {1}",symbol,fromDate.ToShortDateString()));
         return;
       }
       if(PricingDA.CheckPricingOn(symbol,toDate))
       {
         MDTrace.WriteLine(LogLevel.DEBUG,String.Format("There is already a price for {0} on {1}",symbol,toDate.ToShortDateString()));
         return;
       } 
       if(!dateGenerator.IsMarketOpen(toDate))
       {
         MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The market is not open on {0}",toDate.ToShortDateString()));
         return;
       }
       Price price=PricingDA.GetPrice(symbol,fromDate);
       price.Date=toDate;
       MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Rolling forward price for {0}.  Source date is {1} destination date is {2}",symbol,fromDate.ToShortDateString(),toDate.ToShortDateString()));
       PricingDA.InsertPrice(price);
     }
     catch(Exception exception)
     {
       MDTrace.WriteLine(LogLevel.DEBUG,exception);
     }
     
   }
   public static void FindAllSymbolsMissingPriceOn(DateTime date,bool rollForward=false,String strFilter=null)
   {
     int countOfValid=0;
     int countOfInvalid=0;
     DateGenerator dateGenerator=new DateGenerator();

     try
     {
       if(null!=strFilter)strFilter=strFilter.ToUpper();
       List<String> symbols=PricingDA.GetSymbols();
       if(null==symbols||0==symbols.Count)
       {
         MDTrace.WriteLine(LogLevel.DEBUG,String.Format("There are no symbols.  Nothing to do."));
         return;
       }
       foreach (String symbol in symbols)
       {
         DateTime previousBusinessDate=dateGenerator.FindPrevBusinessDay(date);
         bool hasPriceOnPreviousBusinessDate=PricingDA.CheckPricingOn(symbol,previousBusinessDate);
         bool hasPriceOnDate=PricingDA.CheckPricingOn(symbol,date);

         if(hasPriceOnDate && hasPriceOnPreviousBusinessDate)
         {
           countOfValid++;
         }
         else if(!hasPriceOnDate && !hasPriceOnPreviousBusinessDate)
         {
           countOfInvalid++;
         }
         else if(!hasPriceOnDate && hasPriceOnPreviousBusinessDate)
         {
           countOfInvalid++;
           MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}.",symbol,date.ToShortDateString()));
           if(rollForward)
           {
             if(null!=strFilter && !strFilter.Equals(symbol))continue;
             Price price=PricingDA.GetPrice(symbol,previousBusinessDate);
             price.Date=date;
             MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Rolling forward price for {0}.  Source date is {1} destination date is {2}",symbol,previousBusinessDate.ToShortDateString(),date.ToShortDateString()));
             PricingDA.InsertPrice(price);
           }
         }
         else if(hasPriceOnDate && !hasPriceOnPreviousBusinessDate)
         {
           countOfValid++;
         }
       }
       MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Symbols with price {0}, Symbols without price {1}.",countOfValid,countOfInvalid));
     }
     catch (Exception exception)
     {
       MDTrace.WriteLine(LogLevel.DEBUG,exception);
     }
   }
//******************************************************************************************************************
    public static void AddPrice(String symbol,DateTime pricingDate,double open,double high,double low,double close,long volume)
    {
      try
      {
        Price price=new Price();
        price.Symbol=symbol;
        price.Date=pricingDate;
        price.Open=open;
        price.High=high;
        price.Low = low;
        price.Close = close;
        price.AdjClose = close;
        price.Volume = volume;
        MDTrace.WriteLine(LogLevel.DEBUG,"Delete price '" + symbol + "' for " + Utility.DateTimeToStringMMSDDSYYYY(pricingDate));
        PricingDA.DeletePrice(symbol, pricingDate);
        MDTrace.WriteLine(LogLevel.DEBUG,"Add price "+price.ToString());
        if (!PricingDA.InsertPrice(price)) MDTrace.WriteLine(LogLevel.DEBUG,"Error adding price for '" + symbol+"'");
        else MDTrace.WriteLine(LogLevel.DEBUG,"Price added for '"+symbol+"'"); 
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    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 LoadAllPricesSymbol(String symbol)
    {
      DateTime startDate =Constants.MIN_PRICING_DATE;
      DateTime endDate = DateTime.Now;
      Prices prices=MarketDataHelper.GetDailyPrices(symbol,startDate,endDate);    // use the Yahoo JSON bulk feed
      if(null==prices||0==prices.Count)
      {
        if(!Utility.GetVerificationToProceed(String.Format("No prices from Yahoo for symbol{0}.  Would you like to try BigCharts?",symbol)))
        {
          return;
        }
      }
      if (null == prices || 0==prices.Count) 
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"No prices for '" + symbol + "'");
        return;
      }
      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.");
    }
    public static void ShowAllPricesSymbol(String symbol)
    {
      DateTime startDate =Constants.MIN_PRICING_DATE;
      DateTime endDate = DateTime.Now;
      Prices prices=MarketDataHelper.GetDailyPrices(symbol,startDate,endDate);    // use the Yahoo JSON bulk feed
      if (null == prices || 0==prices.Count)    // if less than 252 days of prices then forget it
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"No prices for '" + symbol + "'");
        return;
      }
      MDTrace.WriteLine(LogLevel.DEBUG,Price.Header);
      for (int secIndex = 0; secIndex < prices.Count; secIndex++)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,prices[secIndex].ToString());
      }
      MDTrace.WriteLine(LogLevel.DEBUG,"Done.");
    }
    public static void LoadAllPricesSymbolDate(String symbol,DateTime startDate)
    {
      DateTime endDate = DateTime.Now;
      Prices prices=MarketDataHelper.GetDailyPrices(symbol,startDate,endDate);    // use the Yahoo JSON bulk feed
      //if(null==prices||0==prices.Count)prices=MarketDataHelper.GetPricesAsOf(symbol,startDate,endDate);
      if (null == prices || 0==prices.Count)    // if less than 252 days of prices then forget it
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"No prices for '" + symbol + "'");
        return;
      }
      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.");
    }
    public static void LoadAllPricesWatchList(String watchListName)
    {
      List<String> symbols = WatchListDA.GetWatchList(watchListName);
      for (int index = 0; index < symbols.Count; index++)
      {
        DateTime startDate=Constants.MIN_PRICING_DATE;
        DateTime endDate=DateTime.Now;
        Prices prices = MarketDataHelper.GetDailyPrices(symbols[index], startDate, endDate);
        if (null == prices)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"No prices for '" + symbols[index] + "'");
          continue;
        }
        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.");
        }
      }
    }
    public static void UpdatePricesAndYield()
    {
      UpdatePrices();
      UpdateYieldCurve();
    }
		public static void UpdatePrices()
		{
			List<String> symbols=PricingDA.GetSymbols();
			PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			pricingMarketDataHelper.LoadPrices(symbols);
		}
    public static void UpdatePricesDate(String strDate)
    {
      DateTime pricingDate = DateTime.Parse(strDate);
      List<String> symbols = PricingDA.GetSymbols();
      for (int index = 0; index < symbols.Count; index++)
      {
        Prices prices = MarketDataHelper.GetDailyPrices(symbols[index], pricingDate, pricingDate);
        if (null == prices)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"No prices for '" + symbols[index] + "' on "+Utility.DateTimeToStringMMSDDSYYYY(pricingDate));
          continue;
        }
        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.");
        }
      }
    }
    public static void UpdatePricesSymbol(String symbol)
    {
      DateGenerator dateGenerator = new DateGenerator();
      DateTime startDate = DateTime.Now;    // the lest recent date
      DateTime endDate = DateTime.Now;      // 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.GetDailyPrices(symbol, startDate, endDate);
      if (null == prices)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"No prices 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.");
      }
    }
		public static void GetMissingPrices(DateTime? marketDate=null)
		{
			PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			pricingMarketDataHelper.GetMissingPrices(marketDate);
		}
		public static void GetMissingPricesSymbol(String symbol)
		{
			PricingMarketDataHelper pricingMarketDataHelper=new PricingMarketDataHelper();
			pricingMarketDataHelper.GetMissingPricesSymbol(symbol);
		}
// *****************************************************************************************************************************
// ************************************************ H I S T O R I C A L   D A T A  *********************************************
// *****************************************************************************************************************************
		public static void LoadHistorical(String symbol)
		{
			HistoricalMarketDataHelper historicalMarketDataHelper=new HistoricalMarketDataHelper();
			historicalMarketDataHelper.LoadHistorical(symbol);
		}
		public static void LoadHistorical()
		{
			HistoricalMarketDataHelper historicalMarketDataHelper=new HistoricalMarketDataHelper();
			historicalMarketDataHelper.LoadHistorical();
		}
// *******************************************************************************************************************************
//****************************************F U N D A M E N T A L   D A T A ************************************************
// *******************************************************************************************************************************
		public static void LoadFundamentals()
		{
      FundamentalMarketDataHelper fundamentalMarketDataHelper=new FundamentalMarketDataHelper();
			fundamentalMarketDataHelper.LoadFundamentals();
		}
		public static void LoadFundamental(String symbol)
		{
      FundamentalMarketDataHelper fundamentalMarketDataHelper=new FundamentalMarketDataHelper();
			fundamentalMarketDataHelper.LoadFundamentals(symbol);
		}
		public static void LoadFundamentalsFinViz()
		{
      FundamentalMarketDataHelper fundamentalMarketDataHelper=new FundamentalMarketDataHelper();
			fundamentalMarketDataHelper.LoadFundamentalsFinViz();
		}
		public static void LoadFundamentalFinViz(String symbol)
		{
      FundamentalMarketDataHelper fundamentalMarketDataHelper=new FundamentalMarketDataHelper();
			fundamentalMarketDataHelper.LoadFundamentalsFinViz(symbol);
		}
// *******************************************************************************************************************************
// ************************************ I N C O M E  S T A T E M E N T  A N D  B A L A N C E  S H E E T****************************
// *******************************************************************************************************************************
    public static void LoadFinancialStatements()
		{
			FinancialStatementsMarketDataHelper financialStatementsMarketDataHelper=new FinancialStatementsMarketDataHelper();
			financialStatementsMarketDataHelper.LoadFinancialStatements();
		}
		public static void LoadFinancialStatementsSymbol(String symbol)
		{
			FinancialStatementsMarketDataHelper financialStatementsMarketDataHelper=new FinancialStatementsMarketDataHelper();
			financialStatementsMarketDataHelper.LoadFinancialStatements(symbol);
		}
// *******************************************************************************************************************************
// **************************************************** M A C D  A N A L Y S I S  ************************************************
// *******************************************************************************************************************************
    public static void RunPivots(String symbol, int dayCount)
    {
      try
      {
        Prices prices = PricingDA.GetPrices(symbol,dayCount);
        MDTrace.WriteLine(LogLevel.DEBUG,ResistanceSupport.Header);
        for (int index = 0; index < prices.Count; index++)
        {
          ResistanceSupport resistanceAndSupport = new ResistanceSupport(prices[index]);
          MDTrace.WriteLine(LogLevel.DEBUG,resistanceAndSupport.ToString());
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
      }
    }
    public static void GenerateMovingAverageSheet(String strFileTemplate,String symbol)
    {
      try
      {
        String currentWorkingDirectory = Directory.GetCurrentDirectory();
        MDTrace.WriteLine(LogLevel.DEBUG,"GenerateMovingAverageSheet " + currentWorkingDirectory + "\\" + strFileTemplate + " for " + symbol );
        MovingAverageHelperSheet.GenerateMovingAverageSheet(currentWorkingDirectory + "\\" + strFileTemplate, symbol);
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
      }
    }
    public static void RunMACDSignalSymbol(String symbol,String macd="MACD(8,17,9)")
    {
      DateGenerator dateGenerator = new DateGenerator();
      int pricingDays = 120;  // 90

      try
      {
        DateTime startDate = PricingDA.GetLatestDate(symbol); ;
        if (Utility.IsEpoch(startDate))
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"No price dates for '" + symbol + "'");
          return;
        }
        DateTime historicalDate = dateGenerator.GenerateHistoricalDate(startDate, pricingDays);
        Prices prices = PricingDA.GetPrices(symbol, startDate, historicalDate);
        String companyName = PricingDA.GetNameForSymbol(symbol);
        MACDSetup macdSetup = new MACDSetup(macd);
        MACDSignals macdSignals = MACDGenerator.GenerateMACD(prices, macdSetup);
        MDTrace.WriteLine(LogLevel.DEBUG,"Company:" + Utility.AddQuotes(companyName));
        Signals signals = SignalGenerator.GenerateSignals(macdSignals);

        MDTrace.WriteLine(LogLevel.DEBUG,"Symbol,Date,Indicator,Reason");
        StringBuilder sb = new StringBuilder();
        for (int index = 0; index < signals.Count; index++)
        {
          Signal signal = signals[index];
          sb.Append(symbol).Append(",");
          sb.Append(Utility.DateTimeToStringMMHDDHYYYY(signal.SignalDate)).Append(",");
          sb.Append(signal.SignalIndicatorString).Append(",");
          sb.Append(Utility.AddQuotes(signal.Reason));
          MDTrace.WriteLine(LogLevel.DEBUG,sb.ToString());
          sb.Clear();
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
      }
    }
    //************************************************************************************************************************
    //********************************************** S I G N A L  T R A D E **************************************************
    //************************************************************************************************************************
    public static void TradeSymbol(String symbol,int shares,DateTime startDate,int holdingDays)
    {
      DateGenerator dateGenerator = new DateGenerator();
      DateTime endDate = DateTime.Now;
      startDate = dateGenerator.GetNextBusinessDay(startDate);
      endDate=dateGenerator.FindForwardBusinessDay(startDate,holdingDays-1);
      Price startPrice = PricingDA.GetPrice(symbol,startDate);
      Price endPrice = PricingDA.GetPrice(symbol, endDate);
      double beginMarketValue = 0.00;
      double endMarketValue = 0.00;

      if (null == endPrice)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Ending price is not available on " + Utility.DateTimeToStringMMHDDHYYYY(endDate));
        endPrice = PricingDA.GetPrice(symbol);
        endDate = endPrice.Date;
        MDTrace.WriteLine(LogLevel.DEBUG,"Using latest available price " + Utility.DateTimeToStringMMHDDHYYYY(endPrice.Date));
        
      }
      if (null == startPrice)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Starting price is not available on " + Utility.DateTimeToStringMMHDDHYYYY(startDate));
        return;
      }
      MDTrace.WriteLine(LogLevel.DEBUG, "");
      MDTrace.WriteLine(LogLevel.DEBUG,"Buy " + shares + " " + symbol + " @ " + Utility.FormatCurrency(startPrice.Open) + " on " + Utility.DateTimeToStringMMHDDHYYYY(startDate));
      MDTrace.WriteLine(LogLevel.DEBUG,"Sell " + shares + " " + symbol + " @ " + Utility.FormatCurrency(endPrice.Close) + " on "+Utility.DateTimeToStringMMHDDHYYYY(endDate));
      beginMarketValue = shares * startPrice.Open;
      endMarketValue = shares * endPrice.Close;
      MDTrace.WriteLine(LogLevel.DEBUG,"Beginning market value:"+Utility.FormatNumber(beginMarketValue));
      MDTrace.WriteLine(LogLevel.DEBUG,"Ending market value:" + Utility.FormatNumber(endMarketValue));
      MDTrace.WriteLine(LogLevel.DEBUG,"Gain/Loss:" + Utility.FormatNumber(endMarketValue - beginMarketValue));
      MDTrace.WriteLine(LogLevel.DEBUG,"Return:" + Utility.FormatNumber(((endMarketValue - beginMarketValue) / beginMarketValue)*100.00)+"%");
    }
// ***************************************** T R A D E  S I G N A L  W A T C H L I S T **********************
    public static void TradeSignalWatchListDateProgressHandler(String symbol)
    {
      MDTrace.WriteLine(LogLevel.DEBUG,"Working on "+symbol);
    }
// ***************************************************************************************************************
    public static void CalcPortfolioBeta(String account=null)
    {
      try
      {
        DateTime analysisDate = DateTime.Now;
        PortfolioTrades portfolioTrades = PortfolioDA.GetOpenTrades();
        if (null != account) portfolioTrades = portfolioTrades.FilterAccount(account);
        PortfolioHoldings portfolioHoldings = PortfolioHoldings.GetPortfolioHoldings(portfolioTrades, 1, analysisDate);
        PortfolioHoldingsWithBeta portfolioHoldingsWithBeta = new PortfolioHoldingsWithBeta(portfolioHoldings, analysisDate);
        MDTrace.WriteLine("Holding,Weight,Beta,Weighted Beta,Contribution To Beta");
        foreach (PortfolioHoldingWithBeta portfolioHoldingWithBeta in portfolioHoldingsWithBeta)
        {
          MDTrace.WriteLine(LogLevel.DEBUG, String.Format("{0},{1},{2},{3},{4}",
            portfolioHoldingWithBeta.Symbol,
            Utility.FormatNumber(portfolioHoldingWithBeta.WeightExp, 2),
            Utility.FormatNumber(portfolioHoldingWithBeta.Beta, 2),
            Utility.FormatNumber(portfolioHoldingWithBeta.WeightedBeta, 4),
            Utility.FormatPercent(portfolioHoldingWithBeta.BetaContribution)));
        }
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("36 month portfolio beta is {0}", Utility.FormatNumber(portfolioHoldingsWithBeta.PortfolioBeta, 2)));
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, exception.ToString());
      }
    }
    public static void CalcBeta(String symbol)
    {
      try
      {
        double beta = BetaGenerator.Beta(symbol);
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("36 month beta for {0} is {1}", symbol, beta));
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void CalcBetaAll()
    {
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Symbol,Beta,Months");
        List<String> symbols = PricingDA.GetSymbols();
        
        for (int index = 0; index < symbols.Count; index++)
        {
          String symbol = symbols[index];
          double beta = BetaGenerator.Beta(symbol);
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0},{1},{2}", symbol,beta,36));
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
//****************************************************************************************************************************
//****************************************************************************************************************************
//*************************************************** D I S C O U N T E D  C A S H F L O W  M O D E L ************************

//****************************************************************************************************************************
    public static void CalcDCF()
    {
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Generating valuations..");
        List<String> symbols = PricingDA.GetSymbols();
        MDTrace.WriteLine(LogLevel.DEBUG,DCFValuation.Header);
        foreach(String symbol in symbols)
        {
          DCFValuation dcfValuation = DCFGenerator.GenerateDCFValuation(symbol);
          MDTrace.WriteLine(LogLevel.DEBUG,dcfValuation.ToString());
        }
        MDTrace.WriteLine(LogLevel.DEBUG,"Done.");
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
//****************************************************************************************************************************
//*************************************************** S T I C K E R  P R I C E ***********************************************
//****************************************************************************************************************************

    public static void FindETFMOS()
    {
      try
      {
        List<String> etfSymbols=ETFHoldingsDA.GetETFSymbols();
        List<String> etfsInMOS=new List<String>();
        foreach(String symbol in etfSymbols)
        {
          ETFHoldings etfHoldings = ETFHoldingsDA.GetETFHoldings(symbol);
          if(null==etfHoldings||0==etfHoldings.Count)
          {
            MDTrace.WriteLine(LogLevel.DEBUG,String.Format("ETF {0} has no holdings.",symbol));
            return;
          }
          List<String> symbolsInETF=(from ETFHolding etfHolding in etfHoldings select etfHolding.HoldingSymbol).ToList();
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Generating valuation for ETF {0}",symbol));
          Valuations valuations= ValuationGenerator.GenerateValuations(symbolsInETF,null,null);
          if(null==valuations||0==valuations.Count)continue;
          int countMOSInLine=0;
          foreach(Valuation valuation in valuations)
          {
            if(!(valuation.LatestPrice<=valuation.MOS))continue;
            countMOSInLine++;
          }
          if(countMOSInLine.Equals(etfHoldings.Count))
          {
            MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Adding ETF {0}",symbol));
            etfsInMOS.Add(symbol);
          }
        }
        MDTrace.WriteLine("**************************************************");
        foreach(String etfSymbol in etfsInMOS)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("ETF {0}",etfSymbol));
        }
        MDTrace.WriteLine(LogLevel.DEBUG,"Done.");
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void CalcStickerETF(String symbol)
    {
      try
      {
        ETFHoldings etfHoldings = ETFHoldingsDA.GetETFHoldings(symbol);
        if(null==etfHoldings||0==etfHoldings.Count)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("ETF {0} has no holdings.",symbol));
          return;
        }
        List<String> etfSymbols=(from ETFHolding etfHolding in etfHoldings select etfHolding.HoldingSymbol).ToList();
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Generating valuation for ETF {0}",symbol));
        Valuations valuations= ValuationGenerator.GenerateValuations(etfSymbols,new ValuationGenerator.OnItemCompleteHandler(OnItemCompleteHandler),new ValuationGenerator.OnErrorItemHandler(OnErrorItemHandler));
        foreach(Valuation valuation in valuations)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0},{1},{2}",valuation.Symbol,Utility.FormatCurrency(valuation.LatestPrice),Utility.FormatCurrency(valuation.MOS)));
        }
        MDTrace.WriteLine(LogLevel.DEBUG,"Done.");
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void CalcAcquirersMultiple()
    {
      MDTrace.WriteLine("Generating aqcuirers multiple valuations...");
      AcquirersMultipleCollection collection=AcquirersMultipeGenerator.ApplyRanks();
      MDTrace.WriteLine(LogLevel.DEBUG,AcquirersMultipleItem.Heading);
      foreach(AcquirersMultipleItem acquirersMultipleItem in collection)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,acquirersMultipleItem.ToString());
      }
    }
    public static void CalcAcquirersMultipleSymbol(String symbol)
    {
      MDTrace.WriteLine("Generating aqcuirers multiple valuations...");
      AcquirersMultipleCollection collection=AcquirersMultipeGenerator.ApplyRanks(symbol);
      MDTrace.WriteLine(LogLevel.DEBUG,AcquirersMultipleItem.Heading);
      foreach(AcquirersMultipleItem acquirersMultipleItem in collection)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,acquirersMultipleItem.ToString());
      }
    }
    public static void CalcTLBRanks()
    {
      TLBItemList tlbItemList=TLBRankGenerator.ApplyTLBRanks();
      MDTrace.WriteLine(LogLevel.DEBUG,"Symbol,EBIT,EarningsYield,EnterpriseValue,WorkingCapital,PPE,ROIC,TLBRankRROIC,ROC,TLBRankROC");
      for(int index=0;index<tlbItemList.Count;index++)
      {
        TLBItem item=tlbItemList[index];
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}",item.Symbol,item.EBIT,item.EarningsYield,item.EnterpriseValue,item.WorkingCapital,item.PPE,item.ROIC,item.TLBRankROIC,item.ROC,item.TLBRankROC));
      }
    }
    public static void CalcSticker()
    {
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Generating valuations..");
        Valuations valuations = ValuationGenerator.GenerateValuations(new ValuationGenerator.OnItemCompleteHandler(OnItemCompleteHandler),new ValuationGenerator.OnErrorItemHandler(OnErrorItemHandler));
        MDTrace.WriteLine(LogLevel.DEBUG,"Updating database.");
        if (!ValuationDA.AddValuations(valuations))
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"Error adding valuations to database");
        }
        MDTrace.WriteLine(LogLevel.DEBUG,"Done.");
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void CalcStickerSymbol(String symbol,bool suppressHeading)
    {
      try
      {
        Prices pricesIndex90 = PricingDA.GetPrices("SPY", 90);
        Prices pricesIndex720 = PricingDA.GetPrices("SPY", 720);
        Valuation valuation = ValuationGenerator.GenerateValuation(symbol,pricesIndex90,pricesIndex720,null,new ValuationGenerator.OnErrorItemHandler(OnErrorItemHandler));
        if (null==valuation) return;
        Valuations valuations = new Valuations();
        valuations.Add(valuation);
        ValuationDA.AddValuations(valuations);
        if (!suppressHeading) MDTrace.WriteLine(LogLevel.DEBUG,ValuationGenerator.Heading());
        MDTrace.WriteLine(LogLevel.DEBUG,ValuationGenerator.ToString(valuation));
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Error calculating sticker for '"+symbol+"', exception was "+exception.ToString());
      }
    }
    public static bool OnItemCompleteHandler(Valuation valuation)
    {
      MDTrace.WriteLine(LogLevel.DEBUG,"Completed '"+valuation.Symbol+"' '"+valuation.Company+"'");
      return true;
    }
    public static void OnErrorItemHandler(String symbol,String message)
    {
      MDTrace.WriteLine(LogLevel.DEBUG,"Error '" + symbol + "' "+message);
      return;
    }
    //****************************************************************************************************************************
//*********************************** G E N E R A T E  B O L L I N G E R  B A N D S ***********************************************
//****************************************************************************************************************************
    public static void GenerateBollingerBands(String symbol, int movingAverageDays=20,int historicalDays=180)
    {
      try
      {
        Prices prices = PricingDA.GetPrices(symbol,historicalDays);
        BollingerBands bollingerBands=BollingerBandGenerator.GenerateBollingerBands(prices, movingAverageDays);
        MDTrace.WriteLine(LogLevel.DEBUG,BollingerBands.GetHeader(movingAverageDays));
        for (int index = 0; index < bollingerBands.Count; index++)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,bollingerBands[index].ToString());
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void GenerateBollingerBandSheet(String strTemplateFile, String symbol, int movingAverageDays=20, int historicalDays = 180)
    {
      try
      {
        String currentWorkingDirectory = Directory.GetCurrentDirectory();
        MDTrace.WriteLine(LogLevel.DEBUG,"GenerateBollingerBandSheet " + currentWorkingDirectory + "\\" + strTemplateFile + " for " + symbol + " " + movingAverageDays + " " + historicalDays);
        if (!BollingerBandSheetHelper.GenerateBollingerBandSheet(currentWorkingDirectory + "\\" + strTemplateFile, symbol, movingAverageDays, historicalDays))
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"GenerateBollingerBandSheet failed.");
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
//****************************************************************************************************************************
//*********************************** G E N E R A T E  S T O C H A S T I C S  ***********************************************
//***************************************************************************************************************************
    public static void GenerateStochasticsSignals(String symbol, int periodN = 9, int periodK = 3, int dayCount = 180)
    {
      Prices prices = PricingDA.GetPrices(symbol, dayCount);
      Stochastics stochastics = StochasticsGenerator.GenerateStochastics(prices, periodN, periodK);
      Signals signals=SignalGenerator.GenerateSignals(stochastics);
      for (int index = 0; index < signals.Count; index++)
      {
        Signal signal = signals[index];
        MDTrace.WriteLine(LogLevel.DEBUG,signal.ToString()+","+signal.Reason);
      }
    }
    public static void GenerateStochastics(String symbol, int periodN = 9, int periodK = 3, int dayCount = 180)
    {
      Prices prices = PricingDA.GetPrices(symbol, dayCount);
      Stochastics stochastics=StochasticsGenerator.GenerateStochastics(prices,periodN,periodK);
      if (null == stochastics)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Error generating stochastics.");
        return;
      }
      MDTrace.WriteLine(LogLevel.DEBUG,Stochastics.GetHeader());
      for (int index = 0; index < stochastics.Count; index++)
      {
        StochasticElement stochasticElement = stochastics[index];
        MDTrace.WriteLine(LogLevel.DEBUG,stochasticElement.ToString());
      }
    }
    public static void GenerateStochasticsSheet(String strTemplateFile,String symbol, int periodN = 9, int periodK = 3, int dayCount = 180)
    {
      try
      {
        String currentWorkingDirectory = Directory.GetCurrentDirectory();
        String strPathTemplateFile= currentWorkingDirectory + "\\" + strTemplateFile;
        MDTrace.WriteLine(LogLevel.DEBUG,"GenerateStochasticsSheet " + strPathTemplateFile + " for " + symbol + " N=" + periodN + ",K= " + periodK+", dayCount=" +dayCount);
        if (!StochasticsSheetHelper.GenerateStochasticsSheet(currentWorkingDirectory + "\\" + strTemplateFile, symbol, dayCount, periodN,periodK))
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"GenerateStochasticsSheet failed.");
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    //****************************************************************************************************************************
    //******************************************* F I N D   S W I N G  T R A D E S ***********************************************
    //****************************************************************************************************************************
    public static void FindCurrentSwingTrades(bool filterBargain)
    {
      try
      {
        int historicalDays = 180;
        DateGenerator dateGenerator = new DateGenerator();
        List<String> symbols = PricingDA.GetSymbols();
        MDTrace.WriteLine(LogLevel.DEBUG,"CompanyName," + SwingTrade.Header + ",MOS,MOS80,LatestPricedate,LatestPrice,Bargain,ROIC(Avg%),AvgEquityGrowth(AvgBVPS%),AvgEquityGrowth_2Y(AvgBVPS%),AvgEquityGrowth_4Y(AvgBVPS%),EPSGrowth(Avg%),EPSGrowth_2Y(Avg%),EPSGrowth_4Y(Avg%),RevenueGrowth(Avg%),RevenueGrowth_2Y(Avg%),RevenueGrowth_4Y(Avg%),FreeCashflowGrowth(Avg%),OperatingCashflow(Avg),WorkingCapital(Avg),Comment");
        for (int index = 0; index < symbols.Count; index++)
        {
          String symbol = symbols[index];
          bool bargain = false;
          String companyName = PricingDA.GetNameForSymbol(symbol);
          Prices prices = PricingDA.GetPrices(symbol, historicalDays);
          if (null == prices || 0 == prices.Count) continue;
          Price latestPrice = prices[0];
          DMAPrices ma21 = MovingAverageGenerator.GenerateMovingAverage(prices, 21);
          if (null == ma21) continue;
          BollingerBands bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
          if (null == bollingerBands) continue;
          SwingTrades swingTrades = SwingTradeHelper.FindSwingTrades(prices, ma21.GetDMAPricesByDate(),bollingerBands.GetBollingerBandElementsByDate());
          if (null == swingTrades || 0 == swingTrades.Count) continue;
          SwingTrade lastSwingTrade = swingTrades[swingTrades.Count - 1];
          if (!Utility.IsEpoch(lastSwingTrade.CloseDate) && dateGenerator.DaysBetween(latestPrice.Date, lastSwingTrade.CloseDate) > 5) continue;
          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);
          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);
          StickerPrice stickerPrice = new StickerPrice(symbol);
          bargain = latestPrice.Close < stickerPrice.MarginOfSafety ? true : false;
          if (filterBargain && !bargain) continue;
          StringBuilder sb=new StringBuilder();
          sb.Append(companyName.Replace(",", "")).Append(",");
          sb.Append(lastSwingTrade.ToString()).Append(",");
          sb.Append(Utility.FormatNumber(stickerPrice.MarginOfSafety)).Append(",");
          sb.Append(Utility.FormatNumber(stickerPrice.MarginOfSafety80Pcnt)).Append(",");
          sb.Append(Utility.DateTimeToStringMMHDDHYYYY(latestPrice.Date)).Append(",");
          sb.Append(Utility.FormatNumber(latestPrice.Close)).Append(",");
          sb.Append(latestPrice.Close<stickerPrice.MarginOfSafety?true:false).Append(",");
          sb.Append(Utility.FormatNumber(roic / 100.00)).Append(",");
          sb.Append(Utility.FormatNumber(averageGrowth)).Append(",");
          sb.Append(Utility.FormatNumber(averageGrowth2Year)).Append(",");
          sb.Append(Utility.FormatNumber(averageGrowth4Year)).Append(",");
          sb.Append(Utility.FormatNumber(epsGrowth)).Append(",");
          sb.Append(Utility.FormatNumber(epsGrowth2Year)).Append(",");
          sb.Append(Utility.FormatNumber(epsGrowth4Year)).Append(",");
          sb.Append(Utility.FormatNumber(revenueGrowth)).Append(",");
          sb.Append(Utility.FormatNumber(revenueGrowth2Year)).Append(",");
          sb.Append(Utility.FormatNumber(revenueGrowth4Year)).Append(",");
          sb.Append(Utility.FormatNumber(freeCashflowGrowth)).Append(",");
          sb.Append(Utility.FormatNumber(averageOperatingCashflow)).Append(",");
          sb.Append(Utility.FormatNumber(averageWorkingCapital)).Append(",");
          if (lastSwingTrade.CloseDate.Equals(Utility.Epoch)) sb.Append("buy day after close above ").Append(Utility.FormatNumber(lastSwingTrade.CandleHigh));
          MDTrace.WriteLine(LogLevel.DEBUG,sb.ToString());
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
    public static void FindSwingTrades(String symbol, int historicalDays)
    {
      try
      {
        Prices prices = PricingDA.GetPrices(symbol, historicalDays);
        if (null == prices || 0 == prices.Count)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"No prices for symbol.");
          return;
        }
        String companyName = PricingDA.GetNameForSymbol(symbol);
        DMAPrices ma21 = MovingAverageGenerator.GenerateMovingAverage(prices, 21);
        Price latestPrice = prices[0];
        StickerPrice stickerPrice = new StickerPrice(symbol);
        BollingerBands bollingerBands = BollingerBandGenerator.GenerateBollingerBands(prices);
        if (null == bollingerBands)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"Insufficient historical days, increase day count.");
          return;
        }
        SwingTrades swingTrades = SwingTradeHelper.FindSwingTrades(prices,ma21.GetDMAPricesByDate(),bollingerBands.GetBollingerBandElementsByDate());
        if (null == swingTrades || 0 == swingTrades.Count)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"No swing trades found.");
          return;
        }
        MDTrace.WriteLine(LogLevel.DEBUG,"CompanyName,"+SwingTrade.Header+",MOS,MOS80,LatestPriceDate,LatestPrice,Bargain,Comment");
        for (int index = 0; index < swingTrades.Count; index++)
        {
          String comment = "";
          StringBuilder sb = new StringBuilder();
          SwingTrade swingTrade = swingTrades[index];
          if (swingTrade.CloseDate.Equals(Utility.Epoch)) comment = "buy day after close above "+Utility.FormatNumber(swingTrade.CandleHigh);
          sb.Append(companyName).Append(",");
          sb.Append(swingTrade.ToString()).Append(",");
          sb.Append(Utility.FormatNumber(stickerPrice.MarginOfSafety)).Append(",");
          sb.Append(Utility.FormatNumber(stickerPrice.MarginOfSafety80Pcnt)).Append(",");
          sb.Append(Utility.DateTimeToStringMMHDDHYYYY(latestPrice.Date)).Append(",");
          sb.Append(Utility.FormatNumber(latestPrice.Close)).Append(",");
          sb.Append(latestPrice.Close<stickerPrice.MarginOfSafety?true:false).Append(",");
          sb.Append(comment);
          MDTrace.WriteLine(LogLevel.DEBUG,sb.ToString());
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
// ********************************************** C E N T R A L  I N D E X  K E Y ******************************
    public static void UpdateCIKSymbol(String symbol)
    {
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"UPDATECIKSYMBOL");
        MDTrace.WriteLine(LogLevel.DEBUG,"Symbol   CIK");
        String cik = MarketDataHelper.GetCIK(symbol);
        if (null == cik)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,symbol + ",null");
        }
        else
        {
          PricingDA.UpdateCIKForSymbol(symbol, cik);
          MDTrace.WriteLine(LogLevel.DEBUG,symbol + "," + cik);
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
      }
    }
    public static void UpdateAllCIK()
    {
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"UPDATEALLCIK");
        MDTrace.WriteLine(LogLevel.DEBUG,"Symbol   CIK");
        List<String> symbols = PricingDA.GetSymbols();
        foreach (String symbol in symbols)
        {
          String cik = MarketDataHelper.GetCIK(symbol);
          if (null == cik)
          {
            MDTrace.WriteLine(LogLevel.DEBUG,symbol+",null");
            continue;
          }
          PricingDA.UpdateCIKForSymbol(symbol, cik);
          MDTrace.WriteLine(LogLevel.DEBUG,symbol + "," + cik);
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
      }
    }
		public static void UpdateAllMissingCIK()
		{
			CIKMarketDataHelper cikMarketDataHelper=new CIKMarketDataHelper();
			cikMarketDataHelper.UpdateAllMissingCIK();
		}
    public static void UpdateCompanyProfiles()
		{
			try
			{
				CompanyProfileMarketDataHelper companyProfileMarketDataHelper=new CompanyProfileMarketDataHelper();
				companyProfileMarketDataHelper.UpdateCompanyProfiles();
			}
			catch(Exception exception)
			{
				MDTrace.WriteLine(LogLevel.DEBUG,exception);
			}
		}
		public static void UpdateCompanyProfile(String symbol)
		{
			try
			{
				CompanyProfileMarketDataHelper companyProfileMarketDataHelper=new CompanyProfileMarketDataHelper();
				companyProfileMarketDataHelper.UpdateCompanyProfile(symbol);
			}
			catch(Exception exception)
			{
				MDTrace.WriteLine(LogLevel.DEBUG,exception);
			}
		}
		public static void UpdateCompanyProfileSymbol(String symbol)
		{
			try
			{
				CompanyProfileMarketDataHelper companyProfileMarketDataHelper=new CompanyProfileMarketDataHelper();
				companyProfileMarketDataHelper.UpdateCompanyProfile(symbol);
			}
			catch(Exception exception)
			{
				MDTrace.WriteLine(LogLevel.DEBUG,exception);
			}
		}
		public static void DisplayCompanyProfiles()
		{
			try
			{
        List<String> symbols = PricingDA.GetSymbols();
        foreach (String symbol in symbols)
        {
          CompanyProfile companyProfile=MarketDataHelper.GetCompanyProfile(symbol);
          if(null==companyProfile)
          {
            MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No profile for {0}",symbol));
            continue;
          }
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Symbol:'{0}' Sector:'{1}' Industry:'{2}'",symbol,companyProfile.Sector,companyProfile.Industry));
        }
			}
			catch(Exception exception)
			{
				MDTrace.WriteLine(LogLevel.DEBUG,exception);
			}
		}
		public static void GetSECFilingsWatchList(String watchListName)
		{
      List<String> symbols = WatchListDA.GetWatchList(watchListName);
			SECFilingMarketDataHelper secFilingMarketDataHelper=new SECFilingMarketDataHelper();
			secFilingMarketDataHelper.UpdateSECFilings(symbols);
		}
    public static void UpdateSECFilings()
		{
			SECFilingMarketDataHelper secFilingMarketDataHelper=new SECFilingMarketDataHelper();
			secFilingMarketDataHelper.UpdateSECFilings();
		}
    public static void GetSECFilingsOpenPositions()
		{
			List<String> symbols=PortfolioDA.GetOpenSymbols();
			SECFilingMarketDataHelper secFilingMarketDataHelper=new SECFilingMarketDataHelper();
			secFilingMarketDataHelper.UpdateSECFilings(symbols);
		}
		public static void GetSECFilingsSymbol(String symbol)
		{
			List<String> symbols=new List<String>();
			symbols.Add(symbol);
			SECFilingMarketDataHelper secFilingMarketDataHelper=new SECFilingMarketDataHelper();
			secFilingMarketDataHelper.UpdateSECFilings(symbols);
		}
		public static void GetETFHoldings()
		{
			ETFHoldingsMarketDataHelper etfHoldingsMarketDataHelper=new  ETFHoldingsMarketDataHelper();
			etfHoldingsMarketDataHelper.LoadETFHoldings();
		}
		public static void GetETFHoldingsSymbol(String symbol)
		{
			ETFHoldingsMarketDataHelper etfHoldingsMarketDataHelper=new  ETFHoldingsMarketDataHelper();
			etfHoldingsMarketDataHelper.LoadETFHoldings(symbol);
		}
// *********************************** U P D A T E   Y I E L D   C U R V E *****************************************
    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 UpdateYieldCurve(int numYears)   // gets last numYears of yield curve data
    {
      List<int> years = DateGenerator.GenerateHistoricalYear(DateTime.Now.Year, numYears);
      for (int index = 0; index < years.Count; index++)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Retrieving yield curve for year " + years[index]);
        YieldCurve yieldCurve = MarketDataHelper.GetYieldCurve(years[index]);
        if (null == yieldCurve || 0 == yieldCurve.Count)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"No yield curve data for "+years[index]);
          break;
        }
        MDTrace.WriteLine(LogLevel.DEBUG,"got " + yieldCurve.Count + " points for " + years[index]);
        YieldCurveDA.InsertOrUpdate(yieldCurve);
      }
    }
// ****************************************************************************************************
// *********************** E C O N O M I C  I N D I C A T O R S -  W O R L D  B A N K  ****************
// ****************************************************************************************************
    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<String> 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()));
      }
    }
// ****************************************************************************************************
// *********************** C O N S U M E R  P R I C E  I N D E X  - B U R E A U  O F  L A B O R  S T A T I S T I C S *************************************************
    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()));
      }
    }
// ****************************************************************************************************
// ****************************************************************************************************
// ************************************ V A L U E   A T   R I S K *************************************
// ****************************************************************************************************
// calculate the best new position to enter given the watchList, marketValue
    public class VaRResultSymbol : VaRResult, IComparable
    {
      private String symbol;
      public VaRResultSymbol(String symbol, VaRResult varResult)
        : base(varResult)
      {
        this.symbol = symbol;
      }
      public String Symbol
      {
        get { return symbol; }
        set { symbol = value; }
      }
      public int CompareTo(Object obj)
      {
        if (!obj.GetType().IsInstanceOfType(this)) throw new Exception("Expected VaRResultSymbol");
        return VaRExpectedLoss.CompareTo((obj as VaRResultSymbol).VaRExpectedLoss);
      }
    }
    public static void GetOptimalPositionFromWatchList(String watchListName,String strMarketValue,String strDayCount,String strConfidence,String strReturnDays)
    {
      List<String> watchListSymbols = null;
      double marketValue=double.Parse(strMarketValue);
      int dayCount=int.Parse(strDayCount);
      double confidence=double.Parse(strConfidence);
      int returnDays=int.Parse(strReturnDays);

      confidence /= 100.00;
      MDTrace.WriteLine(LogLevel.DEBUG,"GETOPTIMALPOSITIONFROMWATCHLIST");
      MDTrace.WriteLine(LogLevel.DEBUG,"MarketValue:" + Utility.FormatCurrency(marketValue));
      MDTrace.WriteLine(LogLevel.DEBUG,"DayCount:"+dayCount);
      MDTrace.WriteLine(LogLevel.DEBUG,"Confidence:"+Utility.FormatPercent(confidence));
      MDTrace.WriteLine(LogLevel.DEBUG,"ReturnDays:"+returnDays);
      List<VaRResultSymbol> varResults = new List<VaRResultSymbol>();
      PortfolioHoldings portfolioHoldings = new PortfolioHoldings();
      if ("{All}".Equals(watchListName)) watchListSymbols = PricingDA.GetSymbols();
      watchListSymbols = WatchListDA.GetWatchList(watchListName);
      PortfolioTrades portfolioTrades = PortfolioDA.GetOpenTrades();
      List<String> portfolioTradeSymbols = (from portfolioTrade in portfolioTrades select portfolioTrade.Symbol).Distinct().ToList();
      watchListSymbols = (from watchListSymbol in watchListSymbols select watchListSymbol).Except(portfolioTradeSymbols).ToList();

      for (int index = 0; index < portfolioTradeSymbols.Count; index++)
      {
        String symbol = portfolioTradeSymbols[index];
        List<PortfolioTrade> trades = (from portfolioTrade in portfolioTrades where portfolioTrade.Symbol.Equals(symbol) select portfolioTrade).ToList();
        double totalShares = (from portfolioTrade in trades select portfolioTrade.Shares).Sum();
        PortfolioHolding portfolioHolding = new PortfolioHolding();
        portfolioHolding.Symbol = symbol;
        portfolioHolding.Shares = totalShares;
        portfolioHolding.Prices = PricingDA.GetPrices(symbol, dayCount + 1);
        portfolioHolding.Weight = 0;
        portfolioHolding.MarketValue = portfolioHolding.Prices[0].Close * totalShares;
        portfolioHoldings.Add(portfolioHolding);
      }
      for (int index = 0; index < watchListSymbols.Count; index++)
      {
        PortfolioHolding portfolioHolding = new PortfolioHolding();
        String symbol = watchListSymbols[index];
        portfolioHolding.Symbol = symbol;
        portfolioHolding.Prices = PricingDA.GetPrices(symbol, dayCount + 1);
        portfolioHolding.Weight = 0;
        portfolioHolding.MarketValue = marketValue;
        portfolioHoldings.Add(portfolioHolding);
        VaRResult varResult = HistoricalVaR.GetVaR(portfolioHoldings, confidence);
        portfolioHoldings.Remove(portfolioHolding);
        VaRResultSymbol varResultSymbol = new VaRResultSymbol(symbol, varResult);
        varResults.Add(varResultSymbol);
      }
      varResults.Sort();
      MDTrace.WriteLine(LogLevel.DEBUG,"Symbol,Expected Loss");
      for (int index = 0; index < varResults.Count; index++)
      {
        VaRResultSymbol varResult = varResults[index];
        MDTrace.WriteLine(LogLevel.DEBUG,varResult.Symbol + "," + varResult.VaRExpectedLoss);
      }
    }
    public static void GetVaR(String strDayCount, String strConfidence, String strReturnDays)
    {
      DateTime startdDate = DateTime.Now;
      int dayCount=30;
      int returnDays = 1;
      double confidence=95;


      dayCount = int.Parse(strDayCount);
      confidence = double.Parse(strConfidence);
      returnDays = int.Parse(strReturnDays);
      confidence /= 100.00;
      MDTrace.WriteLine(LogLevel.DEBUG,"GETVAR");
      MDTrace.WriteLine(LogLevel.DEBUG,"DayCount:" + dayCount);
      MDTrace.WriteLine(LogLevel.DEBUG,"Confidence:" + Utility.FormatPercent(confidence));
      MDTrace.WriteLine(LogLevel.DEBUG,"ReturnDays:" + returnDays);
      PortfolioTrades portfolioTrades = PortfolioDA.GetOpenTrades();
      PortfolioHoldings portfolioHoldings = PortfolioHoldings.GetPortfolioHoldings(portfolioTrades, dayCount, startdDate);
      VaRResult varResult = HistoricalVaR.GetVaR(portfolioHoldings, confidence);
      MDTrace.WriteLine(LogLevel.DEBUG,"Symbol,Shares,MarketValue,Weight");
      for (int index = 0; index < portfolioHoldings.Count; index++)
      {
        StringBuilder sb = new StringBuilder();
        PortfolioHolding portfolioHolding = portfolioHoldings[index];
        sb.Append(portfolioHolding.Symbol).Append(" ");
        sb.Append(Utility.FormatNumber(portfolioHolding.Shares)).Append(" ");
        sb.Append(Utility.FormatCurrency(portfolioHolding.MarketValue)).Append(" ");
        sb.Append(Utility.FormatPercent(portfolioHolding.Weight));
        MDTrace.WriteLine(LogLevel.DEBUG,sb.ToString());
      }
      MDTrace.WriteLine(LogLevel.DEBUG,"Daily VaR with " + dayCount + " days of history");
      MDTrace.WriteLine(LogLevel.DEBUG,"The maximum loss over "+returnDays+" days with " + Utility.FormatPercent(confidence) + " confidence is " + Utility.FormatCurrency(varResult.VaRExpectedLoss) + " (" + Utility.FormatPercent(varResult.VaRPercent)+")");
      MDTrace.WriteLine(LogLevel.DEBUG,"Total market value "+Utility.FormatCurrency(portfolioHoldings.GetMarketValue()));
      return;
    }
// *********************************************************************************************************************************
    public static void LoadInsiderTransactionsWatchLists()
    {
      MDTrace.WriteLine(LogLevel.DEBUG,"LoadInsiderTransactionsWatchLists");
      List<String> allSymbols=new List<String>();
      List<String> watchLists = WatchListDA.GetWatchLists();

      foreach (String watchList in watchLists)
      {
        List<String> symbols = WatchListDA.GetWatchList(watchList);
        foreach (String symbol in symbols)
        {
          allSymbols.Add(symbol);
        }
      }
      InsiderTransactionMarketDataHelper insiderTransactionMarketDataHelper=new InsiderTransactionMarketDataHelper();
      insiderTransactionMarketDataHelper.LoadInsiderTransactions(allSymbols);
    }
    public static void LoadInsiderTransactions()
    {
      List<String> symbols = PricingDA.GetSymbols();
      InsiderTransactionMarketDataHelper insiderTransactionMarketDataHelper = new InsiderTransactionMarketDataHelper();
      insiderTransactionMarketDataHelper.LoadInsiderTransactions(symbols);
    }
    public static void LoadInsiderTransactionsYearGreaterEqual(int yearGreaterEqual)
    {
      List<String> symbols = PricingDA.GetSymbols();
      InsiderTransactionMarketDataHelper insiderTransactionMarketDataHelper = new InsiderTransactionMarketDataHelper();
      insiderTransactionMarketDataHelper.LoadInsiderTransactionsYearGreaterEqual(symbols,yearGreaterEqual);
    }
    public static void LoadInsiderTransactionsSymbol(String symbol)
    {
      InsiderTransactionMarketDataHelper insiderTransactionMarketDataHelper = new InsiderTransactionMarketDataHelper();
      insiderTransactionMarketDataHelper.LoadInsiderTransactions(symbol);
    }
// **********************************************************************************************************************************************
// ************************************************** L I S T  G A I N / L O S S   F O R   C O V E R E D   C A L L S ****************************
// **********************************************************************************************************************************************
// need to get the standard deviation over number of days to expiration.  if the strike price > (market price + standard deviation) 
// likewie if the market price - standard deviation 
    public static void DisplayAvailableOptions(int maxDaysToExpiration=45,bool verbose=false)
    {
      OptionsParams optionsParams = new OptionsParams();
      List<String> symbols = PricingDA.GetSymbols();
      DateGenerator dateGenerator = new DateGenerator();
      double investment = 10000.00;
      double requiredReturn=.05;   // .075;  // minimum  return for dollar for premium
      double minimumCashGain = investment * requiredReturn;
      long recordsProcessed = 0;
      double targetShockRank = -.10; ////-.15;    // test gain/loss using the -15% shock rank
      double volatility;

      MDTrace.WriteLine(String.Format("DISPLAYAVAILABLEOPTIONS {0}",maxDaysToExpiration));
      MDTrace.WriteLine(LogLevel.DEBUG,OptionsParams.Header+",DaysBelowShockRank");
      for (int symbolIndex = 0; symbolIndex < symbols.Count; symbolIndex++)
      {
        String symbol=symbols[symbolIndex];
        String companyName = PricingDA.GetNameForSymbol(symbol);

        TimeSeriesCollection bvpsSeries=HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.BVPS);
        TimeSeriesCollection epsSeries=HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.EPS);

        if (null == bvpsSeries || 0 == bvpsSeries.Count) { if (verbose)MDTrace.WriteLine(String.Format("No BVPS for {0}",symbol)); continue; }
        if (null == epsSeries || 0 == epsSeries.Count) { if (verbose)MDTrace.WriteLine(String.Format("No EPS for {0}",symbol)); continue; }
        if (bvpsSeries[0].Value < 0) { if (verbose)MDTrace.WriteLine(String.Format("BVPS[0]<0 for {0}",symbol)); continue; }
        if (epsSeries[0].Value < 0) { if (verbose)MDTrace.WriteLine(String.Format("EPS<0 for {0}",symbol)); continue; }

        Prices allPrices = PricingDA.GetPrices(symbol);
        if (null == allPrices) { if (verbose)MDTrace.WriteLine(String.Format("No prices for {0}",symbol)); continue; }
        Options options = OptionsDA.GetOptions(symbol, DateTime.Now, OptionTypeEnum.CallOption);
        for (int optionIndex = 0; optionIndex < options.Count; optionIndex++)                  
        {
          recordsProcessed++;
          Option option=options[optionIndex];

          if (option.Volume.Equals(0)){if (verbose)MDTrace.WriteLine(String.Format("Volume is zero for {0}",symbol)); continue;}
          if (option.Bid.Equals(double.NaN) || option.Strike.Equals(double.NaN)) { if (verbose)MDTrace.WriteLine(String.Format("Bid or Strike is NaN for {0}",symbol)); continue; }
          int daysToExpiration = dateGenerator.DaysBetweenActual(option.Expiration, DateTime.Now);   // must be expiring within range

// calculate the volatility
          Prices currentPrices = allPrices.Top(daysToExpiration);
          if (null == currentPrices || 0==currentPrices.Count) { if (verbose)MDTrace.WriteLine(String.Format("No price for {0}", symbol)); continue; }
          Price currentPrice = currentPrices[0];
          if (null == currentPrice) continue;
          volatility = currentPrices.Volatility();
          if (!PriceInRange(symbol, currentPrices)) { if (verbose)MDTrace.WriteLine(String.Format("PriceInRange fails for {0}", symbol)); continue; }

          optionsParams.Symbol = symbol;
          optionsParams.CompanyName = companyName;
          optionsParams.Cashdown = investment;
          optionsParams.ExpirationDate = option.Expiration;
          optionsParams.Bid = option.Bid;
          optionsParams.Strike = option.Strike;
          optionsParams.OpenInterest = option.OpenInterest;
          optionsParams.Contracts =(int)( (investment / currentPrice.Close) / 100.00);
          optionsParams.MarketPrice = currentPrice.Close;
          optionsParams.Premium = optionsParams.Shares * optionsParams.Bid;
          optionsParams.Volatility = volatility;
          optionsParams.VolatilityDays = daysToExpiration;
          EquityPriceShocks equityPriceShocks = EquityPriceShocks.CreateEquityPriceShocks(currentPrice, optionsParams);

// get the number of instances where the stock returned less than targetShockRank  (i.e.) where the stocks return < .15
          int lossBelowShockCount = 0;
          float[] returns = allPrices.GetReturns(daysToExpiration);
          for (int index = 0; index < returns.Length; index++)
          {
            if (returns[index] <= targetShockRank) lossBelowShockCount++;
          }

          bool discard=false;
          double equityPriceShockGLViolation=double.NaN;
          foreach (EquityPriceShock equityPriceShock in equityPriceShocks)
          {
            if (equityPriceShock.Rank == targetShockRank && equityPriceShock.TransactionGL < minimumCashGain)
            {
              equityPriceShockGLViolation = equityPriceShock.TransactionGL;
              discard = true;
              break;
            }
          }
          if (discard) { if (verbose)MDTrace.WriteLine(String.Format("PriceShockGL vs minimum cash gain fails for {0}, {1}<{2}", symbol,equityPriceShockGLViolation,minimumCashGain)); continue; }
          if (optionsParams.Premium < minimumCashGain) { if (verbose)MDTrace.WriteLine(String.Format("Premium check vs cash gain fails for {0}", symbol)); continue; }
          if (daysToExpiration > maxDaysToExpiration || daysToExpiration < 0) { if (verbose)MDTrace.WriteLine(String.Format("Days to expiration check fails for {0}", symbol)); continue; }
          if (optionsParams.OpenInterest < 100) { if (verbose)MDTrace.WriteLine(String.Format("Open Interest check fails for {0}", symbol)); continue; }
          if (optionsParams.MarketPrice < 2.00) { if (verbose)MDTrace.WriteLine(String.Format("MarketPrice check fails for {0}", symbol)); continue; }
          if (optionsParams.Premium < 0.00) { if (verbose)MDTrace.WriteLine(String.Format("Premium < 0 check fails for  {0}", symbol)); continue; }

          MDTrace.WriteLine(LogLevel.DEBUG, optionsParams.ToString()+",\""+Utility.FormatNumber(lossBelowShockCount,0,true)+"\"");
        }  // for all options
      }  // for all symbols
      MDTrace.WriteLine(LogLevel.DEBUG,String.Format("processed {0} records",recordsProcessed));
    }
// Using the volatility This method checks to see if prices fall outside of (multipler*standard deviation)
// Essentially, we are checking for outlier prices in the set.
    private static bool PriceInRange(String symbol,Prices currentPrices,int multiplier=4)
    {
      DateGenerator dateGenerator = new DateGenerator();
      DateTime nextBusinessDay = dateGenerator.FindNextBusinessDay(DateTime.Now);
      if (null == currentPrices || 0 == currentPrices.Count()) return false;
      Price currentPrice = currentPrices[0];
      double volatility = currentPrices.Volatility();
      double average = currentPrices.Mean();
      volatility *=multiplier;
      double upperBound = average + volatility;
      double lowerBound = average - volatility;
      for (int index = 0; index < currentPrices.Count; index++)
      {
        currentPrice = currentPrices[index];
        if (currentPrice.Close > upperBound || currentPrice.Close < lowerBound) return false;
      }
      return true;
    }

    private static void LoadPremarketData()
    {
      int retries=3;
      int sleepTime=2000;
      PremarketElements premarketElements=null;

      if(!CheckRunCriteria())return;
      for(int retry=0;retry<retries && (null==premarketElements || 0==premarketElements.Count);retry++,Thread.Sleep(sleepTime))
      {
        premarketElements=MarketDataHelper.GetPremarketData();
      }
      if(null==premarketElements||0==premarketElements.Count)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Failed to retrieve premarket data."));
        return;
      }
      PremarketDA.AddElements(premarketElements);
      foreach(PremarketElement premarketElement in premarketElements)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} {1} {2}",premarketElement.Market,Utility.FormatNumber(premarketElement.ChangeValue),Utility.FormatPercent(premarketElement.ChangePercent/100.00)));
      }
    }

    public static bool CheckRunCriteria()
    {
      DateGenerator dateGenerator = new DateGenerator();
      DateTime currentDate = DateTime.Now;

      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} ({1}), please confirm Y/N:?",currentDate.ToShortDateString(),description));
        String result=Console.ReadLine();
        if(null==result||!(result.ToUpper().Equals("Y")||result.ToUpper().Equals("YES"))) return false;
      }
			if(!NetworkStatus.IsInternetConnected())
			{
        Console.WriteLine(String.Format("The internet is not connected."));
        return false;
			}
      return true;
    }

    private static void LoadHeadlinesWatchList(String watchList)
    {
      if(!CheckRunCriteria())return;
      MDTrace.WriteLine(LogLevel.DEBUG,String.Format("LoadHeadlinesWatchList {0}",watchList));
      List<String> symbols = WatchListDA.GetWatchList(watchList);
      HeadlinesMarketDataHelper headlinesMarketDataHelper= new HeadlinesMarketDataHelper();
      headlinesMarketDataHelper.LoadHeadlines(symbols);
    }

    private static void LoadHeadlinesSymbol(String symbol)
    {
      List<String> symbols=new List<String>();
      symbols.Add(symbol);
      HeadlinesMarketDataHelper headlinesMarketDataHelper= new HeadlinesMarketDataHelper();
      headlinesMarketDataHelper.LoadHeadlines();
    }

// ********************
    public class Item
    {
      public Item()
      {
      }
      public Item(String symbol,float coefficient)
      {
        this.Symbol=symbol;
        this.Coefficient=coefficient;
      }
      public String Symbol{get;set;}
      public float Coefficient{get;set;}
    }
    public class ItemComparator : IComparer<Item>
    {
      public int Compare(Item v1,Item v2)
      {
        if(null==v1&&null==v2)return 0;
        if(null==v1)return 1;
        if(null==v2)return -1;
        return v1.Coefficient.CompareTo(v2.Coefficient);
      }
    }
    public static void DisplayVolatility(List<String> symbols, int dayCount, DateTime? startDate)
    {
      if (null == startDate) startDate = PricingDA.GetLatestDate();
      foreach (String symbol in symbols)
      {
        Prices prices = PricingDA.GetPrices(symbol, startDate.Value,dayCount);
        if (null == prices || 0 == prices.Count)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No prices for {0}",symbol));
          continue;
        }
        double volatility=prices.Volatility();
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Symbol:{0} Volatility:{1} Days:{2} StartDate:{3}", symbol, Utility.FormatNumber(volatility, 4), prices.Count, startDate.Value.ToShortDateString()));
      }
    }
    public static void DisplaySharpeRatio(List<String> symbols, int months, DateTime? startDate)
    {
      if (null == startDate) startDate = PricingDA.GetLatestDate();
      foreach (String symbol in symbols)
      {
        double sharpeRatio = SharpeRatioGenerator.GenerateSharpeRatio(symbol, startDate.Value, months);
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Symbol:{0} SharpeRatio:{1} Months:{2} StartDate:{3}", symbol, Utility.FormatNumber(sharpeRatio, 4), months,startDate.Value.ToShortDateString()));
      }
    }
    public static void FindCoefficients(String symbol,int dayCount,DateTime startDate)
    {
      List<String> symbols=PricingDA.GetSymbols();
      symbols=(from currSymbol in symbols where !currSymbol.Equals(symbol) select currSymbol).ToList();
      Dictionary<String,Item> matrix=new Dictionary<String,Item>();

      if(Utility.IsEpoch(startDate))MDTrace.WriteLine(LogLevel.DEBUG,String.Format("FINDCOEFFICIENTS: {0} {1}",symbol,dayCount));
      else MDTrace.WriteLine(LogLevel.DEBUG,String.Format("FINDCOEFFICIENTS: {0} {1} {2}",symbol,dayCount,Utility.DateTimeToStringMMHDDHYYYY(startDate)));
      Prices stockPrices=null;
      if(!Utility.IsEpoch(startDate))stockPrices=PricingDA.GetPrices(symbol,startDate,dayCount);
      else stockPrices=PricingDA.GetPrices(symbol,dayCount);
      float[] stockReturns=stockPrices.GetReturns();
      Console.WriteLine("Working");
      foreach(String masterSymbol in symbols)
      {
        Prices prices=null;
        if(!Utility.IsEpoch(startDate))prices=PricingDA.GetPrices(masterSymbol,startDate,dayCount);
        else prices=PricingDA.GetPrices(masterSymbol,dayCount);
        if(null==prices||0==prices.Count)continue;
        float[] returns=prices.GetReturns();
        if(null==stockReturns||null==returns)continue;

        float correlationReturns=Numerics.Correlation(ref stockReturns,ref returns);
        if(!matrix.ContainsKey(masterSymbol))matrix.Add(masterSymbol,new Item(masterSymbol,(float)((correlationReturns)/2.00)));
      }
      List<Item> items=new List<Item>(matrix.Values);
      items=(from item in items where !double.IsNaN(item.Coefficient) select item).ToList();
      items.Sort(new ItemComparator());
      Console.WriteLine("Symbol,Coefficient");
      Console.WriteLine(String.Format("Strongest Inverse:{0},{1}",items[0].Symbol,items[0].Coefficient));
      Console.WriteLine(String.Format("Strongest Inverse:{0},{1}",items[1].Symbol,items[1].Coefficient));
      Console.WriteLine(String.Format("Strongest Inverse:{0},{1}",items[2].Symbol,items[2].Coefficient));
      Console.WriteLine(String.Format("Strongest Inverse:{0},{1}",items[3].Symbol,items[3].Coefficient));
      Console.WriteLine(String.Format("Strongest Positive:{0},{1}",items[items.Count-4].Symbol,items[items.Count-4].Coefficient));
      Console.WriteLine(String.Format("Strongest Positive:{0},{1}",items[items.Count-3].Symbol,items[items.Count-3].Coefficient));
      Console.WriteLine(String.Format("Strongest Positive:{0},{1}",items[items.Count-2].Symbol,items[items.Count-2].Coefficient));
      Console.WriteLine(String.Format("Strongest Positive:{0},{1}",items[items.Count-1].Symbol,items[items.Count-1].Coefficient));
    }
    public static void RunMomentum(DateTime analysisDate,int maxPositions)
    {
      MGConfiguration config=new MGConfiguration();
      MomentumCandidates momentumCandidates=MomentumGenerator.GenerateMomentum(analysisDate,config);
      MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",MomentumCandidate.Header()));
      for(int index=0;index<momentumCandidates.Count;index++)
      {
        MomentumCandidate momentumCandidate=momentumCandidates[index];
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0}",momentumCandidate.ToString()));
      }
    }

// **********************************************************************************************************************************************************************************************
// *************************************************************************** C M M O M E N T U M ( B A C K T E S T & M O N T H L Y) ***********************************************************
// **********************************************************************************************************************************************************************************************
		public static void RunCMMomentum(String[] args)
    {				  
				CommandArgs commandArgs=new CommandArgs(args);
				if(!commandArgs.Has("STARTDATE,MAXPOSITIONS,INITIALCASH,HOLDINGPERIOD"))
				{
					if(!commandArgs.Has("STARTDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"Missing STARTDATE");
					if(!commandArgs.Has("MAXPOSITIONS")) MDTrace.WriteLine(LogLevel.DEBUG,"Missing MAXPOSITIONS");
					if(!commandArgs.Has("INITIALCASH")) MDTrace.WriteLine(LogLevel.DEBUG,"Missing INITIALCASH");
					if(!commandArgs.Has("HOLDINGPERIOD")) MDTrace.WriteLine(LogLevel.DEBUG,"Missing HOLDINGPERIOD");
					return;
				}

				CMParams cmParams=new CMParams();
				cmParams.AnalysisDate=commandArgs.Get<DateTime>("STARTDATE");
				cmParams.MaxPositions=commandArgs.Get<int>("MAXPOSITIONS");
				cmParams.InitialCash=commandArgs.Get<double>("INITIALCASH");
				cmParams.HoldingPeriod=commandArgs.Get<int>("HOLDINGPERIOD");

				if(commandArgs.Has("USECNN"))
				{
				  if(!commandArgs.Has("USECNNCLIENT,USECNNDAYCOUNT"))
					{
						MDTrace.WriteLine(LogLevel.DEBUG,"Missing USECNNCLIENT, USECNNDAYCOUNT");
						return;
					}
					cmParams.UseCNN=true;
					cmParams.UseCNNHost=commandArgs.Get<String>("USECNNHOST");
					cmParams.UseCNNDayCount=commandArgs.Get<int>("USECNNDAYCOUNT");
          if(commandArgs.Has("USECNNREWARDPERCENTDECIMAL"))cmParams.UseCNNRewardPercentDecimal=commandArgs.Get<double>("USECNNREWARDPERCENTDECIMAL");
				}

				if(commandArgs.Has("USEOVEREXTENDEDINDICATOR"))
				{
					if(!commandArgs.Has("USEOVEREXTENDEDINDICATORDAYS,USEOVEREXTENDEDINDICATORVIOLATIONTHRESHHOLD,USEOVEREXTENDEDINDICATORMARGINPERCENT"))
					{
						MDTrace.WriteLine(LogLevel.DEBUG,"Missing USEOVEREXTENDEDINDICATORDAYS, USEOVEREXTENDEDINDICATORVIOLATIONTHRESHHOLD, USEOVEREXTENDEDINDICATORMARGINPERCENT");
						return;
					}
					cmParams.UseOverExtendedIndicator=commandArgs.Get<bool>("USEOVEREXTENDEDINDICATOR");
					cmParams.UseOverExtendedIndicatorDays=commandArgs.Get<int>("USEOVEREXTENDEDINDICATORDAYS");
					cmParams.UseOverExtendedIndicatorViolationThreshhold=commandArgs.Get<int>("USEOVEREXTENDEDINDICATORVIOLATIONTHRESHHOLD");
					cmParams.UseOverExtendedIndicatorMarginPercent=commandArgs.Get<double>("USEOVEREXTENDEDINDICATORMARGINPERCENT");
				}


				if(commandArgs.Has("USEMAXPOSITIONBUCKETWEIGHT"))   // UseMaxPositionBucketWeight
				{
					if(!commandArgs.Has("USEMAXPOSITIONBUCKETWEIGHTMAXWEIGHT"))     // UseMaxPositionBucketWeightMaxWeight
					{
						MDTrace.WriteLine(LogLevel.DEBUG,"Missing USEMAXPOSITIONBUCKETWEIGHTMAXWEIGHT");
						return;
					}
					cmParams.UseMaxPositionBucketWeight=commandArgs.Get<bool>("USEMAXPOSITIONBUCKETWEIGHT");
					cmParams.UseMaxPositionBucketWeightMaxWeight=commandArgs.Get<double>("USEMAXPOSITIONBUCKETWEIGHTMAXWEIGHT");
				}
				else
				{
					cmParams.UseMaxPositionBucketWeight=false;
					cmParams.UseMaxPositionBucketWeightMaxWeight=0;
				}

				if(commandArgs.Has("TARGETBETA"))cmParams.TargetBeta=commandArgs.Get<double>("TARGETBETA");
				else cmParams.TargetBeta=1.00;

				DateTime endDate=DateTime.Now;
				String pathSessionFileName=commandArgs.Coalesce<String>("SESSIONFILE",null);
				if(null!=pathSessionFileName) pathSessionFileName=pathSessionFileName.Trim();
				cmParams.DisplayHeader();

				CMMomentumBacktest backtestMomentum=new CMMomentumBacktest();
				List<CMBacktestResult> results=new List<CMBacktestResult>();
				results.Add(backtestMomentum.PerformBacktest(cmParams.AnalysisDate,endDate,pathSessionFileName,cmParams));
		}
// ******************************************************************************************************************************************************************************************
// ********************************************************************** C M T T R E N D   M O D E L  R U N N E R  A N D  C M T T R E N D  R E L A T E D ***********************************
// ******************************************************************************************************************************************************************************************
//CMTSESSION /SESSIONFILE: 
    public static void HandleCMTSession(String[] args)
    {
      CommandArgs commandArgs=new CommandArgs(args);

      if (!commandArgs.Has("SESSIONFILE")) {MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Missing SESSIONFILE"));return;}
      CMTTrendModel trendModel=new CMTTrendModel();
      trendModel.DisplaySession(commandArgs.Coalesce<String>("SESSIONFILE"));
    }
    public static int RunCMTrend(String[] args)
    {
      CommandArgs commandArgs=new CommandArgs(args);
      String mode;

      if(!commandArgs.Has("MODE"))
      {
        if(!commandArgs.Has("MODE")) MDTrace.WriteLine(LogLevel.DEBUG,"MODE is a required paramater.");
        MDTrace.WriteLine(LogLevel.DEBUG,"RUNMMTREND  /MODE:DAILY|BACKTEST|RUNTRENDTEMPLATE|ANALYZE|DISPLAY|CLOSEPOSITION /SELLDATE:{CLOSEPOSITION}  /PRICE:{CLOSEPOSITION} /SYMBOL:{for mode ANALYZE,CLOSEPOSITION} /TRADEDATE:{for mode DAILY,RUNTRENDTEMPLATE,ANALYZE,CLOSEPOSITION) /STARTDATE:(for mode BACKTEST) /ENDDATE:(for mode BACKTEST) /INITIALCASH: /SESSIONFILE: MAXOPENPOSITIONS: /MAXDAILYPOSITIONS: Runs Mark Minervini trend");
        return 0;
      }
      mode=commandArgs.Get<String>("MODE");
      if("ENTRYTEST".Equals(mode))
      {
        CMTParams cmtParams=new CMTParams();
        if(!commandArgs.Has("SYMBOL")||!commandArgs.Has("STARTDATE"))
        {
          if(!commandArgs.Contains("SYMBOL")) MDTrace.WriteLine(LogLevel.DEBUG,"SYMBOL is a required parameter when MODE=ENTRYTEST");
          if(!commandArgs.Contains("STARTDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"STARTDATE is a required parameter when MODE=ENTRYTEST");
          return 0;
        }
        CMTTrendModel trendModel=new CMTTrendModel();
        trendModel.EntryTest(commandArgs.Get<String>("SYMBOL"),commandArgs.Get<DateTime>("STARTDATE"));
      }
      else if("CLOSEPOSITION".Equals(mode))
      {
        CMTParams cmtParams=new CMTParams();
        if(!commandArgs.Has("PURCHASEDATE,SYMBOL,SESSIONFILE,PRICE,SELLDATE"))
        {
          if(!commandArgs.Contains("PURCHASEDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"PURCHASEDATE is a required parameter when MODE=CLOSEPOSITION");
          if(!commandArgs.Contains("SYMBOL")) MDTrace.WriteLine(LogLevel.DEBUG,"SYMBOL is a required parameter when MODE=CLOSEPOSITION");
          if(!commandArgs.Contains("SESSIONFILE")) MDTrace.WriteLine(LogLevel.DEBUG,"SESSIONFILE is a required parameter when MODE=CLOSEPOSITION");
          if(!commandArgs.Contains("PRICE")) MDTrace.WriteLine(LogLevel.DEBUG,"PRICE is a required parameter when MODE=CLOSEPOSITION");
          if(!commandArgs.Contains("SELLDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"SELLDATE is a required parameter when MODE=CLOSEPOSITION");
          return 0;
        }
        CMTTrendModel trendModel=new CMTTrendModel();
        trendModel.ClosePosition(commandArgs.Get<String>("SYMBOL"),commandArgs.Get<DateTime>("PURCHASEDATE"),commandArgs.Get<DateTime>("SELLDATE"),commandArgs.Get<double>("PRICE"),commandArgs.Get<String>("SESSIONFILE"));
      }
      else if("DAILY".Equals(mode))
      {
        CMTParams cmtParams=new CMTParams();
        if(!commandArgs.Has("TRADEDATE,SESSIONFILE"))
        {
          if(!commandArgs.Contains("TRADEDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"TRADEDATE is a required parameter when MODE=DAILY");
          if(!commandArgs.Contains("SESSIONFILE")) MDTrace.WriteLine(LogLevel.DEBUG,"SESSIONFILE is a required parameter when MODE=DAILY");
          return 0;
        }
        if(commandArgs.Contains("INITIALCASH")) cmtParams.InitialCash=commandArgs.Get<double>("INITIALCASH");
        if(commandArgs.Contains("MAXDAILYPOSITIONS")) cmtParams.MaxDailyPositions=commandArgs.Get<int>("MAXDAILYPOSITIONS");
        if(commandArgs.Contains("MAXOPENPOSITIONS")) cmtParams.MaxOpenPositions=commandArgs.Get<int>("MAXOPENPOSITIONS");

        if(commandArgs.Has("ONLYTRADESYMBOLS")) cmtParams.OnlyTradeSymbols=commandArgs.Get<String>("ONLYTRADESYMBOLS");

        if(commandArgs.Contains("POSITIONRISKPERCENTDECIMAL"))
        {
          cmtParams.PositionRiskPercentDecimal=commandArgs.Get<double>("POSITIONRISKPERCENTDECIMAL");
        }

        if(commandArgs.Contains("ENTRYTYPE"))
        {
          List<String> entryTypes=Utility.ToList(commandArgs.Get<String>("ENTRYTYPE"));
          List<String> constraints=new List<String> { "OVEREXTENDED","MVP","NARROWRANGE","MACD","PRICETREND","VOLUMETREND" };
          bool results=entryTypes.All(i => constraints.ContainsIgnoreCase(i));
          if(!results)
          {
            MDTrace.WriteLine(LogLevel.DEBUG,"ENTRYTYPE must consist of one or more OVEREXTENDED, MVP, NarrowRange, MACD, PriceTrend, VolumeTrend");
            return 0;
          }
          cmtParams.EntryType=commandArgs.Get<String>("ENTRYTYPE");
        }
        CMTTrendModel trendModel=new CMTTrendModel();

				if(commandArgs.Contains("USETRADEONLYSECTORS"))
				{
					cmtParams.UseTradeOnlySectors=commandArgs.Get<bool>("USETRADEONLYSECTORS");
					if(cmtParams.UseTradeOnlySectors)
					{
						cmtParams.UseTradeOnlySectorsSectors=commandArgs.Get<String>("USETRADEONLYSECTORSSECTORS");
					}
				}
        CMTTrendModelResult result=trendModel.RunDaily(commandArgs.Get<DateTime>("TRADEDATE"),commandArgs.Get<String>("SESSIONFILE"),cmtParams);
      }
      else if("BACKTEST".Equals(mode))
      {
        CMTParams cmtParams=new CMTParams();
				bool sellAtEndOfSimulation=true;
        if(!commandArgs.Has("STARTDATE,ENDDATE,SESSIONFILE"))
        {
          if(!commandArgs.Contains("STARTDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"STARTDATE is a required parameter");
          if(!commandArgs.Contains("ENDDATE")) MDTrace.WriteLine(LogLevel.DEBUG,"ENDDATE is a required parameter");
          if(!commandArgs.Contains("SESSIONFILE")) MDTrace.WriteLine(LogLevel.DEBUG,"SESSIONFILE is a required parameter");
          return 0;
        } 

        CMTTrendModel trendModel=new CMTTrendModel();

				if(commandArgs.Contains("USETRADEONLYSECTORS"))
				{
					cmtParams.UseTradeOnlySectors=commandArgs.Get<bool>("USETRADEONLYSECTORS");
					if(cmtParams.UseTradeOnlySectors)
					{
						cmtParams.UseTradeOnlySectorsSectors=commandArgs.Get<String>("USETRADEONLYSECTORSSECTORS");
					}
				}

        if(commandArgs.Contains("USEPROFITMAXIMIZATION"))
        {
          cmtParams.UseProfitMaximization=commandArgs.Get<bool>("USEPROFITMAXIMIZATION");
          if(commandArgs.Contains("USEPROFITMAXIMIZATIONEXPRESSION"))
          {
            cmtParams.UseProfitMaximizationExpression=commandArgs.Get<String>("USEPROFITMAXIMIZATIONEXPRESSION");
          }
        }

        if(commandArgs.Contains("MAXDAILYPOSITIONS")) cmtParams.MaxDailyPositions=commandArgs.Get<int>("MAXDAILYPOSITIONS");
        if(commandArgs.Contains("MAXOPENPOSITIONS")) cmtParams.MaxOpenPositions=commandArgs.Get<int>("MAXOPENPOSITIONS");
        if(commandArgs.Contains("BENCHMARKMOVINGAVERAGEDAYS")) cmtParams.BenchmarkMovingAverageDays=commandArgs.Get<int>("BENCHMARKMOVINGAVERAGEDAYS");
        if(commandArgs.Contains("BENCHMARKMOVINGAVERAGEHORIZON")) cmtParams.BenchmarkMovingAverageHorizon=commandArgs.Get<int>("BENCHMARKMOVINGAVERAGEHORIZON");

        if(commandArgs.Has("ONLYTRADESYMBOLS")) cmtParams.OnlyTradeSymbols=commandArgs.Get<String>("ONLYTRADESYMBOLS");

        if(commandArgs.Contains("POSITIONRISKPERCENTDECIMAL"))
        {
          cmtParams.PositionRiskPercentDecimal=commandArgs.Get<double>("POSITIONRISKPERCENTDECIMAL");
        }

        if(commandArgs.Contains("ENTRYTYPE"))
        {
          List<String> entryTypes=Utility.ToList(commandArgs.Get<String>("ENTRYTYPE"));
          List<String> constraints=new List<String> { "OVEREXTENDED","MVP","NARROWRANGE","MACD","PRICETREND","VOLUMETREND" };
          bool results=entryTypes.All(i => constraints.ContainsIgnoreCase(i));
          if(!results)
          {
            MDTrace.WriteLine(LogLevel.DEBUG,"ENTRYTYPE must consist of one or more OVEREXTENDED, MVP, NarrowRange, MACD, PriceTrend, VolumeTrend");
            return 0;
          }
          cmtParams.EntryType=commandArgs.Get<String>("ENTRYTYPE");
        }
				if(commandArgs.Contains("SELLATENDOFSIMULATION"))
				{
				  sellAtEndOfSimulation=commandArgs.Get<bool>("SELLATENDOFSIMULATION");
				}
        CMTTrendModelResult result=trendModel.RunBacktestMode(commandArgs.Get<DateTime>("STARTDATE"),commandArgs.Get<DateTime>("ENDDATE"),sellAtEndOfSimulation,commandArgs.Get<String>("SESSIONFILE"),cmtParams);
      }
      else if("DISPLAY".Equals(mode))
      {
        if(!commandArgs.Contains("SESSIONFILE")) { MDTrace.WriteLine(LogLevel.DEBUG,"SESSIONFILE is a required parameter"); return 0; }
        CMTTrendModel trendModel=new CMTTrendModel();
        trendModel.DisplaySession(commandArgs.Get<String>("SESSIONFILE"));
      }
      else if("RUNTRENDTEMPLATE".Equals(mode))
      {
        if(!commandArgs.Contains("TRADEDATE"))
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"TRADEDATE is a required parameter when MODE=DAILY");
          return 0;
        }
        CMTTrendModel trendModel=new CMTTrendModel();
        trendModel.RunTrendTemplate(commandArgs.Get<DateTime>("TRADEDATE"));
      }
      else
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"RUNCMTREND  /MODE:DAILY|BACKTEST /TRADEDATE:{for mode DAILY) /STARTDATE:(for mode BACKTEST) /ENDDATE:(for mode BACKTEST) /INITIALCASH: /SESSIONFILE: /MAXPOSITIONS Runs Mark Minervini trend");
      }
      return 0;
    }
  }
}
