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.
#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;
}
#import "msxml3.dll" rename("EOF", "MSXMLEndOfFile"), rename_namespace("MSXML")
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);
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;
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"");
pHttp->send();
_bstr_t bstrText = pHttp->responseText;
pHttp =0;
::CoUninitialize();
string strLine;
strstream is((char*) bstrText, bstrText.length(), ios_base::in);
std::getline(is, strLine);
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, ',');
double openPrice, highPrice, lowPrice, closePrice, Volume, adjClose;
char chComma;
isLine >> openPrice >> chComma >> highPrice >> chComma >> lowPrice >> chComma >> closePrice;
*it++ = closePrice;
}
return n;
}
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)));
}
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;
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); }
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;
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());
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.);
double error = sigma / sqrt(2. *nDays);
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;
}