/// <summary> /// Downloads and processes historical data for given stock symbol. /// </summary> /// <param name="symbol">stock symbol, e.g. "msft"</param> /// <param name="numYearsOfHistory">years of history > 0, e.g. 10</param> private static void ProcessStockSymbol(string symbol, int numYearsOfHistory) { try { StockData data = DownloadData.GetHistoricalData(symbol, numYearsOfHistory); int N = data.Prices.Count; Task <decimal> T_min = Task.Factory.StartNew <decimal>(() => { return(data.Prices.Min()); } ); Task <decimal> T_max = Task.Factory.StartNew <decimal>(() => { return(data.Prices.Max()); } ); Task <decimal> T_avg = Task.Factory.StartNew <decimal>(() => { return(data.Prices.Average()); } ); Task <double> T_stddev = Task.Factory.StartNew(() => { // Standard deviation: double sum = 0.0; decimal l_avg = data.Prices.Average(); foreach (decimal value in data.Prices) { sum += Math.Pow(Convert.ToDouble(value - l_avg), 2.0); } // // NOTE: want to test exception handling? Uncomment the following to trigger // divide-by-zero, and notice you get 2 task exceptions, one from this code // and one from the continuation task (stderr) that fails because we fail. // //int abc = 0; //int x = 1000 / abc; return(Math.Sqrt(sum / N)); } ); Task <double> T_stderr = T_stddev.ContinueWith((antecedent) => { return(antecedent.Result / Math.Sqrt(N)); } ); // // Wait and harvest results when done: // // NOTE: even though WaitAll is not required for correctness (calls to .Result do // an implicit .Wait), we use WaitAll for efficiency so that we process tasks in // order as they finish (versus an arbitrary order implied by calls to .Result). // try { Task.WaitAll(new Task[] { T_min, T_max, T_avg, T_stddev, T_stderr }); } catch (AggregateException) // tasking errors: { throw; // re-throw, output error messages below: } decimal min = T_min.Result; decimal max = T_max.Result; decimal avg = T_avg.Result; double stddev = T_stddev.Result; double stderr = T_stderr.Result; // // Output: // Console.WriteLine(); Console.WriteLine("** {0} **", symbol); Console.WriteLine(" Data source: '{0}'", data.DataSource); Console.WriteLine(" Data points: {0:#,##0}", N); Console.WriteLine(" Min price: {0:C}", min); Console.WriteLine(" Max price: {0:C}", max); Console.WriteLine(" Avg price: {0:C}", avg); Console.WriteLine(" Std dev/err: {0:0.000} / {1:0.000}", stddev, stderr); } catch (AggregateException ae) { Console.WriteLine(); Console.WriteLine("** {0} **", symbol); ae = ae.Flatten(); // could have a tree of exceptions, so flatten first: foreach (Exception ex in ae.InnerExceptions) { Console.WriteLine("Tasking error: {0}", ex.Message); } } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("** {0} **", symbol); Console.WriteLine("Error: {0}", ex.Message); } }
/// <summary> /// Processes command-line arguments, and outputs to the user. /// </summary> /// static void ProcessCmdLineArgs(string[] args, out string version, out string platform, out string symbol, out int numYearsOfHistory) { #if DEBUG version = "debug"; #else version = "release"; #endif #if _WIN64 platform = "64-bit"; #elif _WIN32 platform = "32-bit"; #else platform = "any-cpu"; #endif symbol = ""; // in case user does not supply: numYearsOfHistory = 10; string usage = "Usage: StockHistory.exe [-? /? symbol ]"; if (args.Length > 1) { Console.WriteLine("** Error: incorrect number of arguments (found {0}, expecting 1)", args.Length); Console.WriteLine(usage); System.Environment.Exit(-1); } for (int i = 0; i < args.Length; i++) { string arg = args[i]; if (arg == "-?" || arg == "/?") { Console.WriteLine(usage); System.Environment.Exit(-1); } else // assume arg is stock symbol: { symbol = arg; } } //for if (symbol == "") { Console.WriteLine(); Console.Write("Please enter stock symbol (e.g. 'msft'): "); symbol = Console.ReadLine(); } symbol = symbol.Trim(); // delete any leading/trailing spaces: if (symbol == "") { Console.WriteLine(); Console.WriteLine("** Error: you must enter a stock symbol, e.g. 'msft'"); Console.WriteLine(usage); Console.WriteLine(); System.Environment.Exit(-1); } Console.WriteLine(); Console.WriteLine("** Parallel-Async Stock History App [{0}, {1}] **", platform, version); Console.WriteLine(" Stock symbol: {0}", symbol); Console.WriteLine(" Time period: last {0} years", numYearsOfHistory); Console.WriteLine(" Internet access? {0}", DownloadData.IsConnectedToInternet()); }
/// <summary> /// Downloads and processes historical data for given stock symbol. /// </summary> /// <param name="symbol">stock symbol, e.g. "msft"</param> /// <param name="numYearsOfHistory">years of history > 0, e.g. 10</param> private static void ProcessStockSymbol(string symbol, int numYearsOfHistory) { try { StockData data = DownloadData.GetHistoricalData(symbol, numYearsOfHistory); int N = data.Prices.Count; Task <decimal> t_min = Task.Factory.StartNew(() => { decimal min = data.Prices.Min(); return(min); }); Task <decimal> t_max = Task.Factory.StartNew(() => { decimal max = data.Prices.Max(); return(max); }); Task <decimal> t_avg = Task.Factory.StartNew(() => { decimal avg = data.Prices.Average(); return(avg); }); // Standard deviation: Task <double> t_stddev = Task.Factory.StartNew(() => { double sum = 0.0; decimal avg = data.Prices.Average(); foreach (decimal value in data.Prices) { sum += Math.Pow(Convert.ToDouble(value - avg), 2.0); } double stddev = Math.Sqrt(sum / N); return(stddev); }); Task <double> t_stderr = t_stddev.ContinueWith((a) => { // Standard error: double stderr = a.Result / Math.Sqrt(N); return(stderr); }); // // Output: // Task[] tasks = { t_min, t_max, t_avg, t_stddev, t_stderr }; Task.WaitAll(tasks); Console.WriteLine(); Console.WriteLine("** {0} **", symbol); Console.WriteLine(" Data source: '{0}'", data.DataSource); Console.WriteLine(" Data points: {0:#,##0}", N); Console.WriteLine(" Min price: {0:C}", t_min.Result); Console.WriteLine(" Max price: {0:C}", t_max.Result); Console.WriteLine(" Avg price: {0:C}", t_avg.Result); Console.WriteLine(" Std dev/err: {0:0.000} / {1:0.000}", t_stddev.Result, t_stderr.Result); } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("** {0} **", symbol); Console.WriteLine("Error: {0}", ex.Message); } }
/// <summary> /// Downloads and processes historical data for given stock symbol. /// </summary> /// <param name="symbol">stock symbol, e.g. "msft"</param> /// <param name="numYearsOfHistory">years of history > 0, e.g. 10</param> private static void ProcessStockSymbol(string symbol, int numYearsOfHistory) { try { StockData data = DownloadData.GetHistoricalData(symbol, numYearsOfHistory); int N = data.Prices.Count; decimal min = 0, max = 0, avg = 0; Task t_min = Task.Run(() => { min = data.Prices.Min(); }); Task t_max = Task.Run(() => { max = data.Prices.Max(); }); Task t_avg = Task.Run(() => { avg = data.Prices.Average(); }); // Standard deviation: double sum = 0.0; foreach (decimal value in data.Prices) { sum += Math.Pow(Convert.ToDouble(value - avg), 2.0); } double stddev = Math.Sqrt(sum / N); // Standard error: double stderr = stddev / Math.Sqrt(N); // // Output: // Console.WriteLine(); Console.WriteLine("** {0} **", symbol); Console.WriteLine(" Data source: '{0}'", data.DataSource); Console.WriteLine(" Data points: {0:#,##0}", N); t_min.Wait(); Console.WriteLine(" Min price: {0:C}", min); t_max.Wait(); Console.WriteLine(" Max price: {0:C}", max); t_avg.Wait(); Console.WriteLine(" Avg price: {0:C}", avg); Console.WriteLine(" Std dev/err: {0:0.000} / {1:0.000}", stddev, stderr); } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("** {0} **", symbol); Console.WriteLine("Error: {0}", ex.Message); } }
/// <summary> /// Downloads and processes historical data for given stock symbol. /// </summary> /// <param name="symbol">stock symbol, e.g. "msft"</param> /// <param name="numYearsOfHistory">years of history > 0, e.g. 10</param> private static void ProcessStockSymbol(string symbol, int numYearsOfHistory) { try { Task t_error = Task.Factory.StartNew(() => { int i = 10; int j = 10 / i; }); StockData data = DownloadData.GetHistoricalData(symbol, numYearsOfHistory); int N = data.Prices.Count; Task <decimal> t_min = Task.Factory.StartNew(() => { decimal min = data.Prices.Min(); return(min); }); Task <decimal> t_max = Task.Factory.StartNew(() => { decimal max = data.Prices.Max(); return(max); }); Task <decimal> t_avg = Task.Factory.StartNew(() => { decimal avg = data.Prices.Average(); return(avg); }); // Standard deviation: Task <double> t_stddev = Task.Factory.StartNew(() => { double sum = 0.0; decimal l_avg = data.Prices.Average(); foreach (decimal value in data.Prices) { sum += Math.Pow(Convert.ToDouble(value - l_avg), 2.0); } int i = 10; int j = 10 / i; double stddev = Math.Sqrt(sum / N); return(stddev); }); // Standard error: Task <double> t_stderr = t_stddev.ContinueWith((antecedent) => { //t_stddev.Wait(); double stderr = antecedent.Result / Math.Sqrt(N); return(stderr); }); // // Output: // //t_min.Wait(); //t_max.Wait(); //t_avg.Wait(); //t_stddev.Wait(); //t_stderr.Wait(); Task[] tasks = { t_min, t_max, t_avg, t_stddev, t_stderr, t_error }; Task.WaitAll(tasks); //lock (Console.Out) //{ // Console.WriteLine(); // Console.WriteLine("** {0} **", symbol); // Console.WriteLine(" Data source: '{0}'", data.DataSource); // Console.WriteLine(" Data points: {0:#,##0}", N); // Console.WriteLine(" Min price: {0:C}", t_min.Result); // Console.WriteLine(" Max price: {0:C}", t_max.Result); // Console.WriteLine(" Avg price: {0:C}", t_avg.Result); // Console.WriteLine(" Std dev/err: {0:0.000} / {1:0.000}", t_stddev.Result, t_stderr.Result); //} decimal min0 = t_min.Result; decimal max0 = t_max.Result; decimal avg0 = t_avg.Result; double stddev0 = t_stddev.Result; double stderr0 = t_stderr.Result; // // Output: // // NOTE: we build a single output string and then write to the console in one op. // Otherwise, if we output one value at a time, our output might get intermixed // with the output from another, parallel task. Note that Console class is thread- // safe, so this works as long as we make only a single call for our output. // string output = string.Format("\n** {0} **", symbol); output = string.Format("{0}\n Data source: '{1}'", output, data.DataSource); output = string.Format("{0}\n Data points: {1:#,##0}", output, N); output = string.Format("{0}\n Min price: {1:C}", output, min0); output = string.Format("{0}\n Max price: {1:C}", output, max0); output = string.Format("{0}\n Avg price: {1:C}", output, avg0); output = string.Format("{0}\n Std dev/err: {1:0.000} / {2:0.000}", output, stddev0, stderr0); Console.WriteLine(output); } catch (AggregateException ae) { //lock (Console.Out) //{ // Console.WriteLine(); // ae = ae.Flatten(); // foreach (var ex in ae.InnerExceptions) // { // Console.WriteLine("Tasking Error: {0}", ex.Message); // } //} string output = string.Format("\n** {0} **", symbol); ae = ae.Flatten(); // could have a tree of exceptions, so flatten first: foreach (Exception ex in ae.InnerExceptions) { output = string.Format("{0}\nError: {1}", output, ex.Message); } Console.WriteLine(output); } catch (Exception ex) { //lock (Console.Out) //{ // Console.WriteLine(); // Console.WriteLine("** {0} **", symbol); // Console.WriteLine("Error: {0}", ex.Message); //} string output = string.Format("\n** {0} **\nError: {1}", symbol, ex.Message); Console.WriteLine(output); } }
/// <summary> /// Downloads and processes historical data for given stock symbol. /// </summary> /// <param name="symbol">stock symbol, e.g. "msft"</param> /// <param name="numYearsOfHistory">years of history > 0, e.g. 10</param> private static void ProcessStockSymbol(string symbol, int numYearsOfHistory) { try { //Create .Net exception //Task t_error = Task.Factory.StartNew(() => //{ // int i = 0; // int j = 1000 / i; //}); StockData data = DownloadData.GetHistoricalData(symbol, numYearsOfHistory); int N = data.Prices.Count; //decimal min = 0, max = 0, avg = 0; //Create parallel tasks Task <decimal> t_Min = Task.Factory.StartNew(() => { return(data.Prices.Min()); }); //decimal min = t_Min.Result; Task <decimal> t_Max = Task.Factory.StartNew(() => { return(data.Prices.Max()); }); Task <decimal> t_Avg = Task.Factory.StartNew(() => { return(data.Prices.Average()); }); // Standard deviation: //double sum = 0.0, stddev = 0.0, stderr = 0.0; Task <double> t_stddev = Task.Factory.StartNew(() => { //Use local calculated average value instead of waiting for the global value decimal local_avg = data.Prices.Average(); double sum = 0; foreach (decimal value in data.Prices) { sum += Math.Pow(Convert.ToDouble(value - local_avg), 2.0); } return(Math.Sqrt(sum / N)); }); // double stddev = t_stddev.Result; // Standard error: //Task<double> t_stderr = Task.Factory.StartNew(() => { Task <double> t_stderr = t_stddev.ContinueWith((t) => { //t_stddev.Wait(); //Wait until task is finished return(t.Result / Math.Sqrt(N)); }); //Array of tasks Task[] tasks = { t_Min, t_Max, t_Avg, t_stddev, t_stderr }; //Wait for completion of all tasks Task.WaitAll(tasks); // // Output: // Console.WriteLine(); Console.WriteLine("** {0} **", symbol); Console.WriteLine(" Data source: '{0}'", data.DataSource); Console.WriteLine(" Data points: {0:#,##0}", N); //t_Min.Wait(); //Wait until task is finished Console.WriteLine(" Min price: {0:C}", t_Min.Result); //t_Max.Wait(); //Wait until task is finished Console.WriteLine(" Max price: {0:C}", t_Max.Result); //t_Avg.Wait(); //Wait until task is finished Console.WriteLine(" Avg price: {0:C}", t_Avg.Result); //t_stderr.Wait(); //Wait until task is finished Console.WriteLine(" Std dev/err: {0:0.000} / {1:0.000}", t_stddev.Result, t_stderr.Result); } catch (AggregateException ae) { Console.WriteLine(); //Console.WriteLine("Tasking Error: {0}", ae.InnerException.Message); //Flatten all exceptions since there could be many of them ae = ae.Flatten(); foreach (var err in ae.InnerExceptions) { Console.WriteLine("Tasking Error: {0}", err.Message); } } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("** {0} **", symbol); Console.WriteLine("Error: {0}", ex.Message); } }