Mathematics plus C++ equals... money

This small C++ console program pulls out a real market data from www.yahoo.com and estimates a volatility of a stock and an error of the estimation from historical data of the stock. You have to have an internet connection and the Internet Explorer version 5.1 or higher to be able actually connect to the yahoo. You can download a zip archived executable to try the program.
// money.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <vector>
#include <numeric>
#include <functional>
#include <iomanip>
#include <strstream>
#include <sstream>
#include <iostream>
#include <cmath>
#include <time.h>

using namespace std;

double EstimateStockVolatility(const string& symbol, time_t end_time=0, unsigned nDays =180);

int main(int argc, const char* argv[])
{
    cout << "Usage:\n\t" << argv[0] << " SYMBOL1 SYMBOL2 ... \n\n";

    if(argc <=1)
    {
        static const char * ar [] = { 0, "IBM", "GE", "MSFT", };
        argc = sizeof(ar) / sizeof(const char*);
        argv = ar;
    }

    for(std::string stock ; ; cin >> stock , argc = 2 , argv[1] = stock.c_str())
    {
        cout << "\n\n"
                "Symbol\t" "N days\t" "Mean, %\t\t" "STDEV, %\t" "Volatility, %\t" "Error, %\n"
                "------\t" "------\t" "-------\t\t" "--------\t" "-------------\t" "--------\n";

        for(int i = 1 ; i < argc ; ++i)
           EstimateStockVolatility(argv[i]);

        cout << "------------------------------------------------------------------------\n"
                 "Done. Enter stock symbol (or Ctrl-C to quit): ";
    }
    return 0;
}

//
// loads close prices for SYMBOL from yahoo for the period [start_time, start_time -n]
// and puts them into output iterator
//
#import "msxml3.dll" rename("EOF", "MSXMLEndOfFile"), rename_namespace("MSXML") //, no_implementation, no_namespace

template<class OIt>
int getClosePrice(OIt it, const std::string& symbol, time_t t, unsigned int nDays)
{
    cerr << "Loading " << nDays << " days data for " << symbol << "...\r" << flush;
    if(t ==0)
        t = ::time(0);  // current system time if no start time given

    struct tm* ptm =::gmtime(&t);
    stringstream osURL;
    osURL <<    "http://table.finance.yahoo.com/table.csv?y=0&g=d"
                "&s=" << symbol
          <<    "&d=" << ptm->tm_mon
          <<    "&e=" << ptm->tm_mday
          <<    "&f=" << ptm->tm_year +1900;

    //
    // calculate START day assuming: current day may have no data yet, and start day migth have been a holiday
    //
    t -= (nDays +(ptm->tm_wday ==0? 2 : ptm->tm_wday ==6? 1 : 0) +1) *24 *60 *60;
    ptm =::gmtime(&t);
    
    osURL <<    "&a=" << ptm->tm_mon
          <<    "&b=" << ptm->tm_mday
          <<    "&c=" << ptm->tm_year +1900;

    ::CoInitialize(0);
    MSXML::IXMLHTTPRequestPtr pHttp;    
    pHttp.CreateInstance(L"Msxml2.XMLHTTP");
    pHttp->open(L"GET", osURL.str().c_str(), false, L"", L"");  // no-asynch, no-user-name, no-user-password
    pHttp->send();
    _bstr_t bstrText = pHttp->responseText;
    pHttp =0;
    ::CoUninitialize();

//    cout << (char*) bstrText; 
    string strLine;
    strstream is((char*) bstrText, bstrText.length(), ios_base::in);
    std::getline(is, strLine);                                          // get header line

    for(int n = 0 ; std::getline(is, strLine) ; ++n)
    {
        strstream isLine(const_cast<char*>(strLine.c_str()), strLine.length(), ios_base::in); 
        isLine.ignore(200, ',');    // data
        double openPrice, highPrice, lowPrice, closePrice, Volume, adjClose;
        char chComma;
        isLine >> openPrice >> chComma >> highPrice >> chComma >> lowPrice >> chComma >> closePrice;
        *it++ = closePrice;
    }
    return n;
}


//
// Estimates standard deviation based on a sample. The standard deviation is a measure of how 
// widely values are dispersed from the average value (the mean)
//
// sqrt((n * sum(pow(x,2)) - pow(sum(x), 2)) / (n *(n-1)))
//
template<class FIt>
double standard_deviation(FIt first, FIt last)
{
    double powersum =0, sum =0;
    for(int n = 0 ; first != last ; ++n , ++first)
    {
        powersum += *first * *first;
        sum += *first;
    }
    return n <=1? 0 : sqrt((n * powersum - sum *sum) / (n *(n-1)));
}

//
// calculates f(g(x, y)). See www.boost.org for more info
//
template<class OP1, class OP2>  
class compose_f_gxy_t : public std::binary_function< typename OP2::first_argument_type,
                                                     typename OP2::second_argument_type, typename OP1::result_type>
{
public:
    compose_f_gxy_t(const OP1& o1, const OP2& o2) : op1(o1), op2(o2) {}
    typename OP1::result_type operator()(const typename OP2::first_argument_type& x, const typename OP2::second_argument_type& y) const 
    {
        return op1(op2(x,y));
    }
private:
    OP1 op1;    // process: op1(op2(x,y))
    OP2 op2;
};

template<class OP1, class OP2>
inline compose_f_gxy_t<OP1,OP2>
    compose_f_gxy(const OP1& o1, const OP2& o2) { return compose_f_gxy_t<OP1,OP2>(o1,o2); }


//
// Estimates a stock volatility, and error of estimation based on historical trade data
//
double EstimateStockVolatility(const string& strSymbol, time_t end_time, unsigned int nDays)
{
    vector<double> closePrice;
    if(getClosePrice(back_inserter(closePrice), strSymbol, end_time, nDays) <=2)
    {
        cout << "No data or (not enough) for symbol " << strSymbol << endl;
        return 0;
    }

    cerr << "Calculating...                                   \r" << flush;

    //
    // calculating daily returns as ln(p[t]/p[t-1])
    //
    vector<double> dailyReturn;
    dailyReturn.reserve(closePrice.size());
    adjacent_difference(closePrice.begin(), closePrice.end(),
                            back_inserter(dailyReturn), 
                            compose_f_gxy(ptr_fun(log), divides<double>())
                        );
    dailyReturn.erase(dailyReturn.begin());    // ignore very first element, real data starts from i=1 

    //
    // calculating mean, stdev, estimated volatility, and error of estimation
    //
    double mean = accumulate(dailyReturn.begin(), dailyReturn.end(), (double)0) / double(dailyReturn.size());
    double stdev = standard_deviation(dailyReturn.begin(), dailyReturn.end());
    double sigma = stdev * sqrt(252.);                  // ~252 trade days in year in America
    double error = sigma / sqrt(2. *nDays);             // error of estimation

    cout  << left << strSymbol  
          << "\t" << left << closePrice.size() 
          << "\t" << setw(14) << left << mean *100          
          << "\t" << setw(14) << left << stdev *100         
          << "\t" << setw(14) << left << sigma *100         
          << "\t" << setw(14) << left << error *100         
          << endl;
    return sigma;
}