// LookUp Today, int da, WAHDD wahdd) /// <summary> /// Load up the Factor matrix. /// Factor(i,j,k) is i=0,3 for ActHDD, MAHDD, LagSprd, & actual stock; /// j=1,3 for currrent, forecast, and last Fri.; /// k=1,2 for Now & Then. /// </summary> /// <param name="MinYear"></param> /// <param name="Factor"></param> /// <param name="Var"></param> /// <param name="Today"></param> /// <param name="da"></param> public void Matrices(int MinYear, double[, ,] Factor, VarClass[, ,] Var, LookUp Today, WAHDD wahdd, StreamWriter log) { // // Load up the Factor matrix. // // Before advancing the date, record the factors for the current Fri. // Factor[i,j,k) is i=0,3 for ActHDD, MAHDD, LagSprd, & actual stock; // j=1,3 for currrent, forecast, and last Fri.; // k=1,2 for Now & Then. // // Factor[1, 1, 1] = wahdd.DevForStocks(Today.Year, Today.Mon, Today.Day, Var, da); Factor[1, 1, 1] = wahdd.DevForStocks(Today.Year, Today.Mon, Today.Day, Var, log); ActStkCurWeek = Var[Today.Year, Today.Mon, Today.Day].ActStk; Factor[3, 1, 1] = ActStkCurWeek; // // Do not Lag spread in this app. as is done in forecasting. // LookUp Temp = new LookUp(); Temp.Year = Today.Year; Temp.Mon = Today.Mon; Temp.Day = Today.Day; Factor[2, 1, 1] = Var[Temp.Year, Temp.Mon, Temp.Day].Spread; // // Drop back a day. // Temp.DateShift(Temp.Year, Temp.Mon, Temp.Day, -1); Factor[0, 1, 1] = Var[Temp.Year, Temp.Mon, Temp.Day].ActHDD; // // Get this year's current & forecast stocks back to the 5th week being // careful to check for missing values as we back up over early Oct. // Temp.DateShift(Temp.Year, Temp.Mon, Temp.Day, -6); Factor[3, 3, 1] = Var[Temp.Year, Temp.Mon, Temp.Day].ActStk; //Last week's stocks // Temp.DateShift(Temp.Year, Temp.Mon, Temp.Day, -1); // // Move ahead 1 week to the forecast date, which also steps ahead to the // next current date. // 11-16: Do not lag spread. // Today.DateShift(Today.Year, Today.Mon, Today.Day, 6); Factor[0, 2, 1] = Var[Today.Year, Today.Mon, Today.Day].ActHDD; Today.DateShift(Today.Year, Today.Mon, Today.Day, 1); // 1 week ahead Factor[2, 2, 1] = Var[Today.Year, Today.Mon, Today.Day].Spread; ActStkNextWeek = Var[Today.Year, Today.Mon, Today.Day].ActStk; // // Factor[1, 2, 1] = wahdd.DevForStocks(Today.Year, Today.Mon, Today.Day, Var, da); Factor[1, 2, 1] = wahdd.DevForStocks(Today.Year, Today.Mon, Today.Day, Var, log); Factor[3, 2, 1] = ActStkNextWeek; // return; }
LookUp Temp = new LookUp(); // Use to retrieve shifted date. #endregion Fields #region Methods // public double DevForStocks(int JY, int JM, int JD, VarClass[, ,] Var, int da) /// <summary> /// Method to find the weighted mean HDDs for the stock equation. /// </summary> /// <param name="JY"></param> /// <param name="JM"></param> /// <param name="JD"></param> /// <param name="Var"></param> /// <param name="da"></param> /// <returns></returns> public double DevForStocks(int JY, int JM, int JD, VarClass[, ,] Var, StreamWriter log) { //string FileName = @"c:\\CSharp\\HeatingOil\\StockAdjReg15\\WAHDDDetail.txt"; //StreamWriter waDetail = new StreamWriter(FileName); Dev = 0; int j = 0; // // The Fortran version had the equivalent of // for (int i=da; i >= da-MAHDDLagLength+1; i--) // In DailyForecast we found that da (days ahead) is always zero in this // application. In this ap., da is not assigned a value in the main program, // or in Load, so it appears it is always zero here, too. 8/29/14 // // for (int i = da; i >= da - MAHDDLagLength + 1; i--) double Weight = 0, TotalWeight = 0; bool MissingHDD = false; //for (int i = 0; i >= 0 - MAHDDLagLength + 1; i--) for (int i = 0; i >= -12; i--) { j = j + 1; // Indexes the weight vector. // // The first observation in the HHD forecast file is for 2001-9-30. // So, checking the date tells us whether to use an actual or a // forecast for today's observation (i=0). // Weight = MAHDDStkWght[-i]; if (i == 0 && (JY > 2001 || (JY == 2001 && JM >= 10))) // 9-11-14, changed to >= { Temp.DateShift(JY, JM, JD, -1); // Use yesterday's forecast of today. if (Var[Temp.Year, Temp.Mon, Temp.Day].HDDForeDev[j] == -9999) { Weight = 0; // This keeps the missing value from contributing. log.WriteLine("Missing forecast HDD at " + Temp.Year + "-" + Temp.Mon + "-" + Temp.Day); MissingHDD = true; } Dev = Dev + Var[Temp.Year, Temp.Mon, Temp.Day].HDDForeDev[j] * Weight; //if (Temp.Year == 2011 && Temp.Mon == 11) // Console.ReadKey(); log.WriteLine(JY + "-" + JM + "-" + JD + " " + i + " " + Var[Temp.Year, Temp.Mon, Temp.Day].HDDForeDev[j] + " " + Weight); } else // Use actual. { Temp.DateShift(JY, JM, JD, i); if (Var[Temp.Year, Temp.Mon, Temp.Day].HDDDev == -9999) { Weight = 0; log.WriteLine("Missing actual HDD at " + Temp.Year + "-" + Temp.Mon + "-" + Temp.Day); MissingHDD = true; } Dev = Dev + Var[Temp.Year, Temp.Mon, Temp.Day].HDDDev * Weight; log.WriteLine(i + " " + Var[Temp.Year, Temp.Mon, Temp.Day].HDDDev + " " + Weight); } TotalWeight = TotalWeight + Weight; if (MissingHDD) log.WriteLine("Total weight = " + TotalWeight); } //Environment.Exit(-1); log.WriteLine("Sum of products = " + Dev); log.WriteLine("Total Weight = " + TotalWeight); if (TotalWeight == 0) Dev = -9999; else Dev = Dev / TotalWeight; log.WriteLine("Dev = " + Dev); return Dev; }
// Estimate the relationship between spread & stock deviations from normal // adjusted for day of season & recent HDD deviations. The result // provides a nonlinear transformation of spread that is used in other // regressions (with prefix SC) to represent the nonlinear relationship // between spread & stocks. Run annually. // By Asa Janney, autumn 2009 // V4: Functions the same as V3 but all the irrelevant code carried over // from the parent program has been deleted. // 12-4-13: Replaced input files with updated data. // 8-26-14: Started coding C#. // 8-29-14: Finished draft coding; program runs; start debugging. // V5: Edits to fit into the system. // V6, 12-19-14: Edits to output file writes to match existing file. // V7, 12-21-15: Added season dummies to SAS file & removed HDD as ind. var. because // it is always insig. now. It is retained w/ a zero in the coef file to remind // that it is not in service but could be brought back. // Added code to weight Spread cats & season dummies by freq. // V8, 5-13-16: Edits to analyze only the last 6 seasons. // static void Main(string[] args) { Console.WriteLine(); int d, DiS, Y5, M5, D5, Y12, M12, D12, RunDoW, DiSda, Season, Mon, FirstDay, Year, Day, i, j, k, m, n, NSeasons = 0, NFri = 0, ID = 0; int NObs; NObs = 0; int[] CountByGroup = new int[9]; // CountByGroup[0:8) int[] CountBySeason = new int[2020]; // 12-22-15 int GetMon, GetDay, GetYr; string FileName, input; string Bell = new string((char)7, 1); // // Weights for the moving-average HDD. Originally estimated in // HDDAdjustedStocks3.xlsx on ForwardSpread2/SSModels. Signs are reversed // from the original to get positive weights. // WAHDD wahdd = new WAHDD(); double[] MAHDDStkCoef = new double[4] {0, 0.04926, //Intercept 0.03000, //Linear term -0.002493}; //Quadratic term int MAHDDLagLength = 13; double[] MAHDDStkWght = new double[21]; // 0:20 double TotMAW = 0, DepVarMean = 0; // // Compute the weights & transfer the coefs to the wahdd object. // for (i = 0; i <= MAHDDLagLength; i++) { MAHDDStkWght[i] = MAHDDStkCoef[1] + MAHDDStkCoef[2] * i + MAHDDStkCoef[3] * i * i; if (MAHDDStkWght[i] <= 0) Warning.Message("Negative MA HDD weight.", "Terminate", 1); TotMAW = TotMAW + MAHDDStkWght[i]; // Used to normalize weigths. wahdd.MAHDDStkWght[i] = MAHDDStkWght[i]; } //double LastStk, LastActStk, NextActStk; double Intercept; double[] HoldHDD = new double[21]; // HoldHDD(0:20) double[] MeanSprdByGroup = new double[9]; // MeanSprdByGroup[0:8) //bool FirstDA; int EndDataYear = 2020; // Later, make this into an input. // // VarClass holds all the essential daily data indexed by year, month, & day. // It is used like a Fortran structure. In this application it works better // as an object than as a struct. Note that here & elsewhere the array size // is set one larger in every dimension because the program rarely uses the // first (zero) element. // VarClass[, ,] Var = new VarClass[EndDataYear + 1, 13, 32]; // // Fill with missing value indicator before reading in data so that every // cell that we don"t read in will show as missing. // for (Year = 1987; Year <= EndDataYear; Year++) //Changed to EndDataYear { for (Mon = 1; Mon <= 12; Mon++) { for (Day = 1; Day <= 31; Day++) { // Each element of Var has to have this: // Var[Year, Mon, Day] = new VarClass(); Var[Year, Mon, Day].DaysInto = -9999; Var[Year, Mon, Day].Spread = -9999; Var[Year, Mon, Day].ActStk = -9999; Var[Year, Mon, Day].NormStk = -9999; Var[Year, Mon, Day].RelStkDev = -9999; Var[Year, Mon, Day].ActHDD = -9999; Var[Year, Mon, Day].HDDDev = -9999; for (i = 1; i <= 7; i++) { Var[Year, Mon, Day].HDDForeAct[i] = -9999; Var[Year, Mon, Day].HDDForeDev[i] = -9999; } } // End Day } // End Mon } // End Year // int[] DaysInMon = new int[13] { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int[] MoS = new int[7] { 0, 10, 11, 12, 1, 2, 3 }; //Month of season string[] CoefLabel = new string[40] {"", "Intercept","Sprd Int 1","Sprd Int 2","Sprd Int 3","Sprd Int 4", "Sprd Int 5","Sprd Int 6","Day -20","Day -10","Day 0","Day 10","Day 20", "Day 30","Day 40","Day 50","Day 60","Day 70","Day 80","Day 90","Day 100", "Day 110","Day 120","Day 130","Day 140","Day 150","HS2009","HS2010","HS2011", "HS2012","HS2013","HS2014","WAHDDDev","","","","","","",""}; // // X & Y matrices for stock/sprd regression // double[, ,] Factor = new double[4, 4, 3]; // Factor[0:3,3,2) double[,] Z = new double[1001, 40]; // Z(1000,26) double[] B = new double[1001]; double[] Spread = new double[1001]; // 9-23-15 Actual spread, not just its category. double[,] XPrimeX = new double[40, 40]; // (27,27) double[,] XPrimeXInv = new double[40, 40]; //(27,27), double[] Beta = new double[40]; double[] XPrimeY = new double[40]; // StreamWriter log = new StreamWriter(@"c:\\CSharp\\HeatingOil\\StockAdjReg15\\Log.txt"); //FileName = @"c:\\CSharp\\HeatingOil\\StockSpreadPiecewiseLinearCoefsV5.txt"; // // Save last season's file & assign new, tentative name for 2016. // FileName = @"c:\\CSharp\\HeatingOil\\StockSpreadPiecewiseLinearCoefsV6.txt"; // 9-18-16 StreamWriter StkSprdPLOut = new StreamWriter(FileName); // Console.WriteLine( "\n************************************************************\n" + "* Program run annually to estimate stock adjustment as a *\n" + "* piecewise function of spread. The regression results *\n" + "* are written to StockSpreadPiecewiseLinearCoefs.txt. *\n" + "* Written by Asa Janney: Fortran versions, autumn 2009 *\n" + "* C# version, August 2014 *\n" + "************************************************************\n" + "\nThe file for SAS analysis produced by this program is called\n" + "StockAdjSASDataYY-MM-DD.txt on the StockAdjReg15 directory.\n" + "The original version of this program did not run the piece-\n" + "wise regression; SAS did that. Now StockAdjReg15 can run the\n" + "regression, but SAS is still used for more extensive stats &\n" + "to test alternative models."); // Hesitate.ThisLong(100); // // Get starting & ending years of data to process. // int StartSampleYear = 2050; // Set higher than EndYear going into the next routine. int EndSampleYear = 2050; // Does not have to be at the end of the data. bool FirstPass = true; while (EndSampleYear <= StartSampleYear) { if (!FirstPass) { Console.WriteLine(Bell + " *** Invalid entry, try again.\n"); Hesitate.ThisLong(100); } FirstPass = false; Console.WriteLine( "\nEnter start sample year (2009 or later) & ending sample year\n" + "(eg, 2010 2015). Remember that seasons are designated by" + "the years they start in. The program will use only the last 6\n" + "seasons in the regression."); input = Console.ReadLine(); Hesitate.ThisLong(800); StartSampleYear = Convert.ToInt32(input.Substring(0, 4)); EndSampleYear = Convert.ToInt32(input.Substring(5, 4)); //EndDataYear = Convert.ToInt32(input.Substring(10, 4)); // Made this fix above. if (StartSampleYear <= 0) { StartSampleYear = 2009; if (EndSampleYear - StartSampleYear > 5) StartSampleYear = EndSampleYear - 5; Console.WriteLine("Starting year reset to " + StartSampleYear); Hesitate.ThisLong(100); } } // End while int NVar = 26 + EndSampleYear - StartSampleYear + 1; // Counting-year dummies. // DateTime TimeNow = DateTime.Now; log.WriteLine("Run time: " + TimeNow); // Put run time on log file. GetYr = TimeNow.Year; GetMon = TimeNow.Month; GetDay = TimeNow.Day; LookUp Today = new LookUp(); if (EndSampleYear > GetYr - 1) { EndSampleYear = GetYr - 1; //Highest number possible Console.WriteLine("Ending year reset to " + EndSampleYear); Hesitate.ThisLong(1200); } // // File for regression results // StreamWriter regResults = new StreamWriter(@"c:\\CSharp\\HeatingOil\\StockAdjReg15\\RegressionResults.txt"); // //************************************************************************* // Open an output file to hold the data for SAS. Use the date in the name // to indentify it. // FileName = @"c:\\CSharp\\HeatingOil\\StockAdjReg15\\StockAdjSASData" + TimeNow.Year + "-" + TimeNow.Month + "-" + TimeNow.Day + ".txt"; StreamWriter SASOut = new StreamWriter(FileName); // // Write heading onto SAS input file. // SASOut.WriteLine( "MM DD YYYY DiS Stocks Spread I HDDDevFS _Spread Category DiS Dummies ===> " + " Heating-Season Dummies"); // // Read in forward spread from late 1988. // FileName = @"c:\\CSharp\\HeatingOil\\UnadjustedSprdThru2015Season.txt"; // Updated 4-11-16 StreamReader spreadInput = new StreamReader(FileName); //string Dum1, Dum2; //double DumGDPDef; while (!spreadInput.EndOfStream) { input = spreadInput.ReadLine(); Year = Convert.ToInt32(input.Substring(0, 4)); Mon = Convert.ToInt32(input.Substring(8, 2)); Day = Convert.ToInt32(input.Substring(12, 2)); // // Check that an object for this day exists; if not, create it. // if (Var[Year, Mon, Day] == null) Var[Year, Mon, Day] = new VarClass(); Var[Year, Mon, Day].Spread = Convert.ToDouble(input.Substring(40, 9)); // 8-24-15 Changed from 41, 8. //int IX = 1; } // // Read in the latest HDD data. // FileName = @"c:\\CSharp\\HeatingOil\\HDDWithRevisedNormals.txt"; StreamReader HDDIn = new StreamReader(FileName); FileName = @"c:\\CSharp\\HeatingOil\\MAHDDOut.txt"; StreamWriter HDDOut = new StreamWriter(FileName); // input = HDDIn.ReadLine(); // Skip heading. while (!HDDIn.EndOfStream) { input = HDDIn.ReadLine(); Year = Convert.ToInt32(input.Substring(0, 4)); Mon = Convert.ToInt32(input.Substring(4, 3)); if (Year > EndDataYear + 1 || (Year > EndDataYear && Mon > 4)) break; Day = Convert.ToInt32(input.Substring(7, 3)); Var[Year, Mon, Day].ActHDD = Convert.ToDouble(input.Substring(10, 8)); Var[Year, Mon, Day].NormHDD = Convert.ToDouble(input.Substring(18, 8)); Var[Year, Mon, Day].HDDDev = Convert.ToDouble(input.Substring(26, 8)); Var[Year, Mon, Day].DaysInto = Convert.ToInt32(input.Substring(34, 4)); // if (Year < 1987) { Console.WriteLine("Year = " + Year); Warning.Message("Error reading HDD input file; year < 1987", "Terminate", 1); } // Season = Year; int LastSeason = 0; if (Mon < 4) Season = Season - 1; if (Season > LastSeason) LastSeason = Season; // // Slide the HDDs a day into the past & put the new one into the zero pos. // for (i = MAHDDLagLength; i >= 1; i--) HoldHDD[i] = HoldHDD[i - 1]; // // Find the WA HDD. // double X4 = 0; for (i = 0; i <= MAHDDLagLength; i++) X4 = X4 + HoldHDD[i] * MAHDDStkWght[i] / TotMAW; HDDOut.WriteLine(Year + " " + Mon + " " + Day + " " + Var[Year, Mon, Day].MAHDDDev); } // End while not end of stream // // Read in actual Friday stocks & find adjusted stocks. // This file has every season as wide as we can process. // FileName = @"c:\\CSharp\\HeatingOil\\StocksActualThru2015Season.txt"; // Updated 4-11-16 StreamReader stocksIn = new StreamReader(FileName); while (!stocksIn.EndOfStream) { input = stocksIn.ReadLine(); Year = Convert.ToInt32(input.Substring(0, 4)); Mon = Convert.ToInt32(input.Substring(8, 2)); Day = Convert.ToInt32(input.Substring(10, 6)); Var[Year, Mon, Day].ActStk = Convert.ToDouble(input.Substring(16, 8)); // // Counts by heating season. // Season = Year; if (Mon < 4) Season = Season - 1; if (Mon >= 10 || Mon <= 3) CountBySeason[Season] = CountBySeason[Season] + 1; // // Check for out of bounds. // if (Var[Year, Mon, Day].ActStk > 64.128) { string msg = " *** Stocks of " + string.Format("{0,7:###.000}", Var[Year, Mon, Day].ActStk) + " higher than historical max. on " + Year + "-" + Mon + "-" + Day; Warning.Message(msg, "Warning", 1); } if (Var[Year, Mon, Day].ActStk < 14.0) // Edited { string msg = " *** Stocks of " + string.Format("{0,7:###.000}", Var[Year, Mon, Day].ActStk) + " lower than 14 on " + Year + "-" + Mon + "-" + Day; // Edited Warning.Message(msg, "Warning", 1); } } // End of while stocksIn.Close(); // // Fill in days-into-season. // for (Year = 1988; Year <= 2015; Year++) { i = -31; for (n = 1; n <= 6; n++) { m = MoS[n]; d = DaysInMon[m]; if (m == 2 && (Year / 4) * 4 == Year) d = 29; //leap year day FirstDay = 1; for (Day = 1; Day <= d; Day++) { if (i > 150) continue; Var[Year, m, Day].DaysInto = i; i = i + 1; } // End for Day } // End for n } // End for Year // // Interpolated stocks are not needed in this program, so all this does now // is to fill in day of the week. // // The first day of October 1988 was a Saturday, so the day of week number, n, is // set to 7 to begin. // n = 7; for (Year = 1988; Year <= 2019; Year++) // 5-12-16 Changed upper bound to 2019. { for (Mon = 1; Mon <= 12; Mon++) { if (Year == 1988 && Mon < 10) continue; //Start in Oct. 1988. if (Year == EndDataYear + 1 && Mon > 4) break; //End after last season of data. d = DaysInMon[Mon]; if (Mon == 2 && (Year / 4) * 4 == Year) d = 29; //leap year day for (Day = 1; Day <= d; Day++) { Var[Year, Mon, Day].DoW = n; //Assign day of week. n = n + 1; //Increment day of week index. if (n > 7) n = 1; } //Days } //Months } //Years // // Read in HDD projections. All of Oct. is present for all years. // StreamReader HDDFore = new StreamReader(@"c:\\CSharp\\HeatingOil\\HDDAugmentedForecast.txt"); // Updated 4-11-16 while (!HDDFore.EndOfStream) { input = HDDFore.ReadLine(); Year = Convert.ToInt32(input.Substring(0, 4)); Mon = Convert.ToInt32(input.Substring(4, 7)); Day = Convert.ToInt32(input.Substring(11, 4)); for (i = 1; i <= 7; i++) { if (Var[Year, Mon, Day] == null) Var[Year, Mon, Day] = new VarClass(); Var[Year, Mon, Day].HDDForeAct[i] = Convert.ToDouble(input.Substring(15 + 11 * (i - 1), 11)); } } // ******************************* // Find projected HDD deviations. // Index values of 1 - 7 correspond to tomorrow, the next day, etc. // 9-9-14: Make file of HDD deviations for debug. // FileName = @"c:\\CSharp\\HeatingOil\\StockAdjReg15\\HDDDeviations.txt"; StreamWriter HDDDevs = new StreamWriter(FileName); for (Year = 2001; Year <= EndDataYear; Year++) { for (Mon = 1; Mon <= 12; Mon++) { if (Year == 2001 && Mon < 9) continue; //Start on 30 Sept. 2001. if (Year == EndDataYear && Mon >= 4) break; int MaxDays = DaysInMon[Mon]; //Edit 11-18-13 if (Mon == 2 && (Year / 4) * 4 == Year) MaxDays = 29; //leap year day for (Day = 1; Day <= MaxDays; Day++) //31 Limit to DaysInMon. { if (Year == 2001 && Mon == 9 && Day < 30) continue; //Start on 30 Sept. 2001. for (j = 1; j <= 7; j++) { Today.Year = Year; Today.Mon = Mon; Today.Day = Day; Today.DateShift(Today.Year, Today.Mon, Today.Day, j); //Normal is stored j days ahead. if (Today.Year > EndDataYear) { break; } if (Var[Today.Year, Today.Mon, Today.Day] == null) { // 9-9-14: This is not happening, but w/ a 1-sec hesitation it will be // apparent if it ever does. // Console.WriteLine("In HDD dev, object created for " + Today.Year + " " + Today.Mon + " " + Today.Day); Var[Today.Year, Today.Mon, Today.Day] = new VarClass(); Hesitate.ThisLong(1000); } double XNorm = Var[Today.Year, Today.Mon, Today.Day].NormHDD; if (XNorm == -9999 && (Mon <= 3 || Mon >= 10)) // 9-22-15 { log.WriteLine("Missing input for normal HDD at " + Year + "-" + Mon + "-" + Day + "-" + j); HDDDevs.WriteLine("Missing input for normal HDD at " + Year + "-" + Mon + "-" + Day + "-" + j + " XNorm = " + XNorm + " ForeAct = " + Var[Year, Mon, Day].HDDForeAct[j]); } // // Because HDD projections are stored by the day they are made rather // than the day they are received, you have to grab yesterday's actual, and // the normal temp is one day off from the day-zero projection. // if (Var[Year, Mon, Day].HDDForeAct[j] == -9999 && (Mon <= 3 || Mon >= 10)) // 9-22-15 { log.WriteLine("Missing input for HDD Dev at " + Year + "-" + Mon + "-" + Day + "-" + j); HDDDevs.WriteLine("Missing input for HDD Dev at " + Year + "-" + Mon + "-" + Day + "-" + j + " XNorm = " + XNorm + " ForeAct = " + Var[Year, Mon, Day].HDDForeAct[j]); } else { Var[Year, Mon, Day].HDDForeDev[j] = Var[Year, Mon, Day].HDDForeAct[j] - XNorm; //Edit, deleted prefix L. HDDDevs.WriteLine(Year + "-" + Mon + "-" + Day + " " + j + " " + " XNorm = " + string.Format("{0,10:###0.00000}", XNorm) + " ForeAct = " + string.Format("{0,10:###0.00000}", Var[Year, Mon, Day].HDDForeAct[j]) + string.Format("{0,10:###0.00000}", Var[Year, Mon, Day].HDDForeDev[j])); } if (Day == 20 && j == 1) { log.WriteLine("HDDForeDev = " + Year + " " + Mon + " " + Day + " " + Var[Year, Mon, Day].HDDForeDev[j]); //Console.ReadKey(); } //4 } //3 } //2 } //1 } //0 HDDFore.Close(); // // Add DaysInto for March 31 in leap years. // Var[1992, 3, 31].DaysInto = 151; Var[1996, 3, 31].DaysInto = 151; Var[2000, 3, 31].DaysInto = 151; Var[2004, 3, 31].DaysInto = 151; Var[2008, 3, 31].DaysInto = 151; Var[2012, 3, 31].DaysInto = 151; Var[2016, 3, 31].DaysInto = 151; //***************************************************************** // // Top of loop by season // //for (i = StartSampleYear; i <= EndSampleYear; i++) for (i = 1999; i <= EndSampleYear; i++) { log.WriteLine("Season = " + i); Console.WriteLine("Season = " + i); Today.Season = i; Today.Year = Today.Season; Today.Day = 4; // Start on the 1st Fri. in Oct. on or after the 4th. Today.Mon = 10; // // Go thru day by day until you have a Friday. // while (Var[Today.Year, Today.Mon, Today.Day].DoW != 6) { Today.Day = Today.Day + 1; if (Today.Day > 12) Warning.Message("Error finding 1st Fri. in Oct.", "Terminate", 1); } Load load = new Load(); //**************************************************************************** // B E G I N W E E K L Y S T E P S // // In this routine: // Today.xxx indicates the run day today, which steps forward 7 days AAT. // Limit is the date packed into a single interger, YYYYMMDD. // int Limit = 10000 * (Today.Season + 1) + 331; while (10000 * Today.Year + 100 * Today.Mon + Today.Day < Limit) { int ConcatDate = 10000 * Today.Year + 100 * Today.Mon + Today.Day; // // Load up the Factor & X matrices. Set the unused MinYear variable to // the now year. Note that the Today is advanced 7 days in this subr. // for (not process observations w/ missing HDD. // int MinYear = Today.Year; load.Matrices(MinYear, Factor, Var, Today, wahdd, log); if (Today.Mon > 3 && Today.Mon < 10) continue; // // Skip if current or forecast WAHDD is missing: // if (Factor[1, 1, 1] == -9999 || Factor[1, 2, 1] == -9999) { Console.WriteLine(Today.Year + "-" + Today.Mon + "-" + Today.Day + " Warning, Missing MAHDD"); continue; //Skip missing. 9-1-14 } // // Factor[i,j,k] is i=0,3 for ActHDD, MAHDD, LagSprd, & actual stock; // j=1,2 for currrent & forecast Fri.; // k=1,2 for Now & Then. // "Then" was a past year used in pattern matching, which has been retired. // ID = Var[Today.Year, Today.Mon, Today.Day].DaysInto; int[,] YrDummy = new int[20, 500]; // Heating-season dummies // // Move the factor matrix into the B (ind) & Z (dep) matrices for the // weekly stock regression if this season is between the limits set // by the user. // 12-16-15: Always include 3 obs from 2000 as priors for high spreads that // have not occurred since then. // if ((Today.Season >= StartSampleYear && Today.Season <= EndSampleYear) || (Today.Year == 2000 && Today.Mon == 1 && Today.Day == 21) || (Today.Year == 2000 && Today.Mon == 1 && Today.Day == 28) || (Today.Year == 2000 && Today.Mon == 2 && Today.Day == 4)) { if (Factor[3, 2, 1] == -9999) continue; // Missing dep. var. NObs = NObs + 1; log.WriteLine("NObs = " + NObs); // // B holds the dep. var. // Factor[3, 2, 1] is actual stocks, forecast, Now. // B[NObs] = Factor[3, 2, 1]; // // Fill in Z, the ind. var. array. // 12-21-15: WAHDD is insignificant in this model, so move it to the end of the array. // That way, it can be dropped from the regession in this program, but still provide // the option to be written out to the SAS file, so that the SAS program can continue // to check whether it is still insig. in future seasons. // //for (j = 1; j <= 25; j++) // 25 = intercept, categories, & DiS dummies for (j = 1; j <= 31; j++) // 31 = intercept, categories, DiS dummies, & seasonal dummies Z[NObs, j] = 0; // Initialize. Z[NObs, 1] = 1; //Intercept Z[NObs, 32] = Factor[1, 2, 1]; //wahdd.DevForStocks CN 12-21-15 is insig. so move to end. Spread[NObs] = Factor[2, 2, 1]; // // Find the interval number for Factor[2,2,1], lagged spread, forecast, Now. // double[] Boundary = new double[6] { 1000, .5, .25, 0.10, 0.05, -0.05 }; int cat = 0; // // Find the category of this obs. // for (j = 1; j <= 5; j++) { if (Today.Season == 2002 && j == 1) // Special check on this season; prob. pointless now. { log.WriteLine("2002-" + Today.Mon + " " + Today.Day + " " + "Spread = " + Factor[2, 2, 1]); } if (Factor[2, 2, 1] > Boundary[j]) { cat = j; log.WriteLine(Today.Mon + " " + Today.Day + " " + "cat = " + cat); break; } } if (cat == 0) cat = 6; // Spread was <= -0.05. // // Spread dummies at intervals selected by examination of a // plot of the data. Accumulate totals to get mean spreads within group. // switch (cat) // Branch according to category. { case 1: Z[NObs, 2] = 1; //Sprd1 *** 12-21-15: Here & below reducing index by 1. MeanSprdByGroup[2] = MeanSprdByGroup[2] + Factor[2, 2, 1]; CountByGroup[2] = CountByGroup[2] + 1; break; // case 2: Z[NObs, 3] = 1; //Sprd2 MeanSprdByGroup[3] = MeanSprdByGroup[3] + Factor[2, 2, 1]; CountByGroup[3] = CountByGroup[3] + 1; break; // case 3: Z[NObs, 4] = 1; //Sprd3 MeanSprdByGroup[4] = MeanSprdByGroup[4] + Factor[2, 2, 1]; CountByGroup[4] = CountByGroup[4] + 1; break; ; // case 4: Z[NObs, 5] = 1; //Sprd4 MeanSprdByGroup[5] = MeanSprdByGroup[5] + Factor[2, 2, 1]; CountByGroup[5] = CountByGroup[5] + 1; break; ; // case 5: Z[NObs, 6] = 1; //Sprd5 MeanSprdByGroup[6] = MeanSprdByGroup[6] + Factor[2, 2, 1]; CountByGroup[6] = CountByGroup[6] + 1; break; ; // case 6: Z[NObs, 7] = 1; //Sprd6 MeanSprdByGroup[7] = MeanSprdByGroup[7] + Factor[2, 2, 1]; CountByGroup[7] = CountByGroup[7] + 1; break; } // end switch // // Accumulate a count & total for all obs & store in element 0. // CountByGroup[0] = CountByGroup[0] + 1; MeanSprdByGroup[0] = MeanSprdByGroup[0] + Factor[2, 2, 1]; // // Dummies for normal stocks every 10 days thru the season. // int IDays = -30; for (j = 8; j <= 25; j++) { IDays = IDays + 10; double ten = 10; if (Math.Abs(ID - IDays) < 10) Z[NObs, j] = 1.0 - (double)Math.Abs(ID - IDays) / ten; } // // Heating-season (year) dummies // //Z[NObs, 26 + Today.Season - 2009] = 1; Z[NObs, 26 + Today.Season - StartSampleYear] = 1; // // Write file to use in regression. // WriteSAS.Line(SASOut, Today, ID, B, Z, NObs, Spread, NVar); // 9-23-15 added spread } // End if; checks season. // NFri = NFri + 1; } // End while // NSeasons = NSeasons + 1; } // End for i, StartSampleYear, EndYear //************************************************************* // Get means within spread groups before adding in the priors. // for (i = 2; i <= 7; i++) MeanSprdByGroup[i] = MeanSprdByGroup[i] / CountByGroup[i]; MeanSprdByGroup[0] = MeanSprdByGroup[0] / CountByGroup[0]; // // Read in smoothness priors for DiS dummies. // FileName = @"c:\\CSharp\\HeatingOil\\StockAdjReg15\\Priors.txt"; StreamReader priors = new StreamReader(FileName); string Type; // Type of constraint goes in 1st 3 cols. Edited while (!priors.EndOfStream) { input = priors.ReadLine(); NObs = NObs + 1; Type = input.Substring(0, 3); switch (Type) { case "DiS": for (j = 8; j <= 25; j++) Z[NObs, j] = Convert.ToDouble(input.Substring(3 + (j - 8) * 5, 5)); break; case "Cat": for (j = 2; j <= 7; j++) Z[NObs, j] = Convert.ToDouble(input.Substring(3 + (j - 2) * 5, 5)); break; default: Console.WriteLine("Key word " + Type); Console.WriteLine("Is invalid. Hit return to stop."); Console.ReadKey(); Environment.Exit(-1); break; } // // Write priors to bottom of SAS file. // WriteSAS.Line(SASOut, Today, ID, B, Z, NObs, Spread, NVar); } // End while // // Finally, add 3 constraints to make the spread cats, DiS dummies, & season // dummies have zero means. // NObs = NObs + 1; for (j = 2; j <= 7; j++) Z[NObs, j] = CountByGroup[j]; // 12-22-15: 6 Spread dummies set to counts. // WriteSAS.Line(SASOut, Today, ID, B, Z, NObs, Spread, NVar); // 9-23-15 Added Spread // NObs = NObs + 1; for (j = 8; j <= 25; j++) Z[NObs, j] = 1; //DiS dummies set to 1. WriteSAS.Line(SASOut, Today, ID, B, Z, NObs, Spread, NVar); // NObs = NObs + 1; for (j = 26; j <= 26 + EndSampleYear - StartSampleYear; j++) { Z[NObs, j] = CountBySeason[j - 26 + 2009]; // 12-22-15: Heating-season dummies set to num obs. } WriteSAS.Line(SASOut, Today, ID, B, Z, NObs, Spread, NVar); SASOut.Close(); //********************************** // Call regression routines. // Piecewise piecewise = new Piecewise(); piecewise.Reg(regResults, NObs, Z, Beta, NVar, DepVarMean, B, StkSprdPLOut, CoefLabel); // // Add means within spread groups to the bottom of the output file. // StkSprdPLOut.WriteLine(); // Inserted 12-19-14 StkSprdPLOut.WriteLine("Mean Spreads within Interval"); StkSprdPLOut.WriteLine("----------------------------"); StkSprdPLOut.WriteLine(); // Inserted 12-19-14 StkSprdPLOut.WriteLine(" Interval Count Mean"); StkSprdPLOut.WriteLine(" -------- ----- ---------"); for (i = 2; i <= 7; i++) StkSprdPLOut.WriteLine(" " + string.Format("{0,9:#########0}", i - 1) + string.Format("{0,6:#####0}", CountByGroup[i]) + string.Format("{0,10:###0.00000}", MeanSprdByGroup[i])); // StkSprdPLOut.WriteLine(" -------- ----- ---------"); StkSprdPLOut.WriteLine(" Total" + string.Format("{0,6:#####0}", CountByGroup[0]) + string.Format("{0,10:###.00000}", MeanSprdByGroup[0])); // // Compute the intercepts & slopes of linear pieces. // StkSprdPLOut.WriteLine(); // Inserted 12-19-14 StkSprdPLOut.WriteLine(); StkSprdPLOut.WriteLine("Intercepts & slopes of linear pieces"); StkSprdPLOut.WriteLine("------------------------------------"); StkSprdPLOut.WriteLine(" Interval Intercept Slope"); StkSprdPLOut.WriteLine(" -------- --------- ---------"); // for (i = 3; i <= 7; i++) { double Slope = (Beta[i - 1] - Beta[i]) / (MeanSprdByGroup[i - 1] - MeanSprdByGroup[i]); Intercept = Beta[i - 1] - Slope * MeanSprdByGroup[i - 1]; StkSprdPLOut.WriteLine(string.Format(" " + "{0,11:###########0}", i - 2) + string.Format("{0,10:###0.00000}", Intercept) + string.Format("{0,10:####0.0000}", Slope)); } // // 12-4-13: Add starting & ending years to improve audit trail. // StkSprdPLOut.WriteLine(); StkSprdPLOut.WriteLine(" Span of Input Years: " + string.Format("{0,4:###0}", StartSampleYear) + "-" + string.Format("{0,4:###0}", EndSampleYear)); StkSprdPLOut.Close(); // // Termination message // Console.WriteLine("See the output file:\n" + " StockSpreadPiecewiseLinearCoefs*.txt"); regResults.Close(); log.Close(); HDDOut.Close(); HDDDevs.Close(); Console.ReadKey(); }