How to generate integers between min and max using normal distribution? - c++

I learnt that we use
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator (seed);
std::normal_distribution<double> distribution (mean_value,variance_value);
to generate real numbers. But I don't know how to give a range (min and max) to this generation and how to generate only integers in this scenario. In case of uniform_distribution, it is straight forward. Can anyone help please? Thanks!

Well, you could compute probabilities from normal distribution at given points, and use them for discrete sampling.
Along the lines
#include <cmath>
#include <random>
#include <iostream>
constexpr double PI = 3.14159265359;
static inline double squared(const double x) {
return x * x;
}
double GaussPDF(const double x,
const double mu,
const double sigma) {
return exp(-0.5 * squared((x - mu) / sigma)) / (sqrt(2.0 * PI) * sigma);
}
int SampleTruncIntGauss(const int xmin, const int xmax, const double mu, const double sigma, std::mt19937_64& rng) {
int n = xmax - xmin + 1;
std::vector<double> p(n);
for (int k = 0; k != n; ++k)
p[k] = GaussPDF(static_cast<double>(xmin) + k, mu, sigma);
std::discrete_distribution<int> igauss{ p.begin(), p.end() };
return xmin + igauss(rng);
}
int main() {
int xmin = -3;
int xmax = 5;
int n = xmax - xmin + 1;
double mu = 1.2;
double sigma = 2.3;
std::mt19937_64 rng{ 98761728941ULL };
std::vector<int> h(n, 0);
for (int k = 0; k != 10000; ++k) {
int v = SampleTruncIntGauss(xmin, xmax, mu, sigma, rng);
h[v - xmin] += 1;
}
int i = xmin;
for (auto k : h) {
std::cout << i << " " << k << '\n';
++i;
}
return 0;
}
You could make code more optimal, I reinitialize probabilities array each time we sample, but it demonstrates the gist of the idea.
UPDATE
You could also use non-point probabilities for sampling, basically assuming that probability at integer point x means probability to have value in the range [x-0.5...x+0.5]. This could be easily expressed via Gaussian CDF.
constexpr double INV_SQRT2 = 0.70710678118;
double GaussCDF(const double x,
const double mu,
const double sigma) {
double v = INV_SQRT2 * (x - mu) / sigma;
return 0.5 * (1.0 + erf(v));
}
double ProbCDF(const int x,
const double mu,
const double sigma) {
return GaussCDF(static_cast<double>(x) + 0.5, mu, sigma) - GaussCDF(static_cast<double>(x) - 0.5, mu, sigma);
}
and code for probabilities would be
for (int k = 0; k != n; ++k) {
p[k] = ProbCDF(xmin + k, mu, sigma);
Result is slightly different, but still resembles Gaussian

Related

discrete to continuous cumulative density function

My question is that is it possible to convert a vector which stores samples of original CDF (cumulative density function)...
something like this:
class normal
{
public:
float mean;
float sigma;
float variance = sigma * sigma;
float left_margin = mean - 4 * sigma;
float right_margin = mean + 4 * sigma;
normal():mean(0), sigma(1){}
normal(float m, float s):mean(m), sigma(s){}
float cdf(float x);
float pdf(float x);
};
float normal::pdf(float x)
{
if (x < left_margin || x > right_margin) return 0;
float coefficient = 1 / (float)sqrt(2 * PI * variance);
float x_mean = x - mean;
float result = coefficient * exp(-(x_mean * x_mean) / 2 * variance);
return result;
}
float normal::cdf(float x)
{
if (x <= left_margin) return 0;
if (x >= right_margin) return 1;
float x_mean = x - mean;
float result = (float)(0.5 * (1 + erf((x_mean) / sqrt(2 * variance))));
if (result > 1) return 1;
else return result;
}
std::vector<float> discrete_normal_cdf(normal& X)
{
std::vector<float> vec;
float L = (float)(X.left_margin);
float R = (float)(1.2 * X.right_margin);
while (L <= R)
{
vec.push_back(X.cdf(L));
L = (float)(L + 0.1);
}
std::vector<float> tmp;
// take three samples
tmp.push_back(vec.at(1)); // first non_zero element
tmp.push_back(vec.at(40)); // add element with value of 0.5
tmp.push_back(vec.at(80)); // element with value of 0.99
std::vector<float> cdf_v(5, 0);
for (auto i = 0; i < tmp.size(); i++)
cdf_v.push_back(tmp.at(i));
int l = 0;
while (l < 5)
{
cdf_v.push_back(1);
l++;
}
return cdf_v;
}
In fact what I need is this: if we have a normal
normal n1(5, 1);
take samples of its CDF to piece wise linear CDF:
vector<float> foo = discrete_normal_cdf(n1);
then reconstruct the piecewise linear CDF into normal
normal function(foo)
{
return normal(5, 1);
}
Is this function valid?
I wrote a function which takes a vector as an input
and search all the elements of the vector the for the value of 0.5
and returns the index of that element as the mean of the normal
but it not always true.
normal vec2normal(vector<float>& vec)
{
int mean;
mean = std::find(vec.begin(), vec.end(), 0.5) - vec.begin();
return normal(mean, 1);
}
I have no idea how to do this, so any suggestions will be appreciated
thank you.

Trapezoidal integration program doesn't return a reasonable value

Why doesn't this code to integrate the area under a sin curve return a reasonable value? (edited to include a bunch of suggestions)
//I want to write a program that takes the area under a curve by outputting the sum of the areas of n rectangles
#include <vector>
#include <iostream>
#include <cmath>
#include <numeric>
double interval(double d, double n)
{
return d / n;
}
using namespace std;
int main()
{
double xmax = 20; //upper bound
double xmin = 2; //lower bound
double line_length = xmax - xmin; //range of curve
double n = 1000; //number of rectangles
vector<double> areas;
double interval_length = interval(line_length, n);
for (double i = 0; i < n; ++i)
{
double fvalue = xmin + i;
areas.push_back((interval_length * sin(fvalue)) + (0.5 * interval_length * (sin(fvalue + 1) - sin(fvalue))));
//idea is to use A = b*h1 + 1/2 b*h2 to approximate the area under a curve using trapezoid area
}
I added fvalue, interval_length and fixed the logic a bit
double sum_areas = accumulate(areas.begin(), areas.end(), 0.0);
//accumulate takes each element in areas and adds them together, beginning with double 0.0
cout << "The approximate area under the curve is " << '\n';
cout << sum_areas << '\n';
//this program outputs the value 0.353875, the actual value is -.82423
return 0;
}
The code below doesn't mix using loop variable and x. It has a drawback (same as yours code) that error summing dx is accumulated i.e. dx*n != xmax-xmin. To account for this particular error one should calculate current x as function of i (loop variable) on each iteration as x = xmin + (xmax - xmin)*i/n.
#include <iostream>
#include <cmath>
double sum(double xmin, double xmax, double dx)
{
double rv = 0;
for (double x = xmin + dx; x <= xmax; x += dx)
rv += (sin(x) + sin(x-dx)) * dx / 2;
return rv;
}
int main()
{
int n = 1000;
double xmin = 0;
double xmax = 3.1415926;
std::cout << sum(xmin, xmax, (xmax - xmin)/n) << std::endl;
return 0;
}
You are forgetting the interval length in the function argument
double fvalue = xmin + i;
areas.push_back((interval_length * sin(fvalue)) + (0.5 * interval_length * (sin(fvalue + 1) - sin(fvalue))));
Should instead be
double fvalue = xmin + i*interval_length;
areas.push_back((interval_length * sin(fvalue)) + (0.5 * interval_length * (sin(fvalue + interval_length) - sin(fvalue))));
The second line can be better written as
areas.push_back(interval_length * 0.5 * (sin(fvalue + interval_length) + sin(fvalue));

Unknown error using the c++ eigen library

I am a graduate student at Florida State University studying financial mathematics. I am still a bit of a novice with C++ but I am trying to implement the Longstaff-Schwartz method for pricing of American options. Although, the algorithm in the journal is a bit daunting thus I am trying to convert the code that was written in Matlab and change it into C++. Essentially I am using the Matlab code as a guide.
I was referred by some stackexchange users to use the Eigen library which contains a good matrix class. Unfortunately the website here does not show me how to make my own function from the class. What I am stuck on is making a C++ function for the function in Matlab that does this:
Say t = 0:1/2:1 then in Matlab the output will be t = 0 0.500 1
So using the Eigen class I created a function called range to achieve the latter above. The function looks like this:
MatrixXd range(double min, double max, double N){
MatrixXd m(N,1);
double delta = (max-min)/N;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
m(i,j) = min + i*delta;
}
}
return m;
}
I do not have any errors on my IDE (Ecclipse) but when I run my code and test this function I get this error message:
c:\mingw\include\c++\6.2.0\eigen\src/Core/PlainObjectBase.h:736:7:
error: static assertion failed:
FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED
I am not sure what is wrong. Any suggestions on achieving what I am trying to do or any suggestions at all are greatly appreciated.
Taking the suggestion by Martijn Courteaux, I changed $N$ into an int now but I now receive a new error that I do not understand:
c:\mingw\include\c++\6.2.0\eigen\src/Core/Matrix.h:350:7: error: static
assertion failed: THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Matrix, 3)
For sake of completeness I will post my whole code below:
#include <iostream>
#include <cmath>
#include <limits>
#include <algorithm>
#include <Eigen/Dense>
#include <Eigen/Geometry>
using namespace Eigen;
using namespace std;
double LaguerreExplicit(int R, double x); // Generates the (weighted) laguerre value
double payoff_Call(double S, double K); // Pay off of a call option
double generateGaussianNoise(double mu, double sigma); // Generates Normally distributed random numbers
double LSM(int T, double r, double sigma, double K, double S0, int N, int M, int R);
// T Expiration time
// r Riskless interest rate
// sigma Volatility
// K Strike price
// S0 Initial asset price
// N Number of time steps
// M Number of paths
// R Number of basis functions
MatrixXd range(double min, double max, int N);
int main(){
MatrixXd range(0, 1, 2);
}
double payoff_Call(double S, double K){
double payoff;
if((S - K) > 0)
{
payoff = S - K;
}else
{
payoff = 0.0;
}
return payoff;
}
double LaguerreExplicit(int R, double x){
double value;
if(R==0)
{
value = 1;
}
else if(R==1)
{
value = 0.5*(pow(x,2) - 4.0*x + 2);
}
else if(R==3)
{
value = (1.0/6.0)*(-1*pow(x,3) + 9*pow(x,2) - 18*x + 6);
}
else if(R==4)
{
value = (1.0/24.0)*(pow(x,4) - 16*pow(x,3) + 72*pow(x,2) - 96*x + 24);
}
else if(R==5)
{
value = (1.0/120.0)*(-1*pow(x,5) + 25*pow(x,4) - 200*pow(x,3) + 600*pow(x,2) - 600*x + 120);
}
else if (R==6)
{
value = (1.0/720.0)*(pow(x,6) - 36*pow(x,5) + 450*pow(x,4) - 2400*pow(x,3) + 5400*pow(x,2) - 4320*x + 720);
}
else{
cout << "Error!, R is out of range" << endl;
value = 0;
}
value = exp(-0.5*x)*value; // Weighted used in Longstaff-Scwartz
return value;
}
double generateGaussianNoise(double mu, double sigma)
{
const double epsilon = std::numeric_limits<double>::min();
const double two_pi = 2.0*M_PI;
static double z0, z1;
static bool generate;
generate = !generate;
if (!generate)
return z1 * sigma + mu;
double u1, u2;
do
{
u1 = rand() * (1.0 / RAND_MAX);
u2 = rand() * (1.0 / RAND_MAX);
}
while ( u1 <= epsilon );
z0 = sqrt(-2.0 * log(u1)) * cos(two_pi * u2);
z1 = sqrt(-2.0 * log(u1)) * sin(two_pi * u2);
return z0 * sigma + mu;
}
MatrixXd range(double min, double max, int N){
MatrixXd m(N,1);
double delta = (max-min)/N;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
m(i,j) = min + i*delta;
}
}
return m;
}
double LSM(int T, double r, double sigma, double K, double S0, int N, int M, int R){
double dt = T/N;
MatrixXd m(T,1);
return 0;
}
Here is the corrected function code that I fixed:
VectorXd range(double min, double max, int N){
VectorXd m(N + 1);
double delta = (max-min)/N;
for(int i = 0; i <= N; i++){
m(i) = min + i*delta;
}
return m;
}
Mistake is here:
MatrixXd range(double min, double max, double N){
MatrixXd m(N,1);
N is a double. The arguments of MatrixXd::MatrixXd(int, int) are int.
You presumably want to make N an int.
In regard to your edit:
Second mistake is here:
MatrixXd range(0, 1, 2);
in the main() function. Not sure what you are trying to do here, but that constructor is not valid. EDIT: Ah I believe I have an idea. You are trying to call your function named range. Do this like this:
MatrixXd result = range(0.0, 1.0, 2);

C++ while loop using bisection method. Help on break

I need some help here. Please excuse the complexity of the code. Basically, I am looking to use the bisection method to find a value "Theta" and each i increment.
I know that all the calculations work fine when I know the Theta, and I have the code run to just simply calculate all the values, but when I introduce a while loop and the bisection method to have the code approximate Theta, I can't seem to get it to run correctly. I am assuming I have my while loop set up incorrectly....
#include <math.h>
#include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm> // std::max
using namespace std;
double FuncM(double theta, double r, double F, double G, double Gprime, double d_t, double sig);
double FuncM(double theta, double r, double F, double G, double Gprime, double d_t, double sig)
{
double eps = 0.0001;
return ((log(max((r + (theta + F - 0.5 * G * Gprime ) * d_t), eps))) / sig);
}
double FuncJSTAR(double m, double x_0, double d_x);
double FuncJSTAR(double m, double x_0, double d_x)
{
return (int(((m - x_0) / d_x)+ 0.5));
}
double FuncCN(double m, double x_0, double j, double d_x);
double FuncCN(double m, double x_0, double j, double d_x)
{
return (m - x_0 - j * d_x);
}
double FuncPup(double d_t, double cn, double d_x);
double FuncPup(double d_t, double cn, double d_x)
{
return (((d_t + pow(cn, 2.0)) / (2.0 * pow(d_x, 2.0))) + (cn / (2.0 * d_x)));
}
double FuncPdn(double d_t, double cn, double d_x);
double FuncPdn(double d_t, double cn, double d_x)
{
return (((d_t + pow(cn, 2.0)) / (2.0 * pow(d_x, 2.0))) - (cn / (2.0 * d_x)));
}
double FuncPmd(double pd, double pu);
double FuncPmd(double pd, double pu)
{
return (1 - pu - pd);
}
int main()
{
const int Maturities = 5;
const double EPS = 0.00001;
double TermStructure[Maturities][2] = {
{0.5 , 0.05},
{1.0 , 0.06},
{1.5 , 0.07},
{2.0 , 0.075},
{3.0 , 0.085} };
//--------------------------------------------------------------------------------------------------------
vector<double> Price(Maturities);
double Initial_Price = 1.00;
for (int i = 0; i < Maturities; i++)
{
Price[i] = Initial_Price * exp(-TermStructure[i][1] * TermStructure[i][0]);
}
//--------------------------------------------------------------------------------------------------------
int j_max = 8;
int j_range = ((j_max * 2) + 1);
//--------------------------------------------------------------------------------------------------------
// Set up vector of possible j values
vector<int> j_value(j_range);
for (int j = 0; j < j_range; j++)
{
j_value[j] = j_max - j;
}
//--------------------------------------------------------------------------------------------------------
double dt = 0.5;
double dx = sqrt(3 * dt);
double sigma = 0.15;
double mean_reversion = 0.2; // "a" value
//--------------------------------------------------------------------------------------------------------
double r0 = TermStructure[0][1]; // Initialise r(0) in case no corresponding dt rate in term structure
//--------------------------------------------------------------------------------------------------------
double x0 = log(r0) / sigma;
//--------------------------------------------------------------------------------------------------------
vector<double> r_j(j_range); // rate at each j
vector<double> F_r(j_range);
vector<double> G_r(j_range);
vector<double> G_prime_r(j_range);
for(int j = 0; j < j_range; j++)
{
if (j == j_max)
{
r_j[j] = r0;
}
else
{
r_j[j] = exp((x0 + j_value[j]*dx) * sigma);
}
F_r[j] = -mean_reversion * r_j[j];
G_r[j] = sigma * r_j[j];
G_prime_r[j] = sigma;
}
//--------------------------------------------------------------------------------------------------------
vector<vector<double>> m((j_range), vector<double>(Maturities));
vector<vector<int>> j_star((j_range), vector<int>(Maturities));
vector<vector<double>> Central_Node((j_range), vector<double>(Maturities));
vector<double> Theta(Maturities - 1);
vector<vector<double>> Pu((j_range), vector<double>(Maturities));
vector<vector<double>> Pd((j_range), vector<double>(Maturities));
vector<vector<double>> Pm((j_range), vector<double>(Maturities));
vector<vector<double>> Q((j_range), vector<double>(Maturities));// = {}; // Arrow Debreu Price. Initialised all array values to 0
vector<double> Q_dt_sum(Maturities);// = {}; // Sum of Arrow Debreu Price at each time step. Initialised all array values to 0
//--------------------------------------------------------------------------------------------------------
double Theta_A, Theta_B, Theta_C;
int JSTART;
int JEND;
int TempStart;
int TempEnd;
int max;
int min;
vector<vector<int>> Up((j_range), vector<int>(Maturities));
vector<vector<int>> Down((j_range), vector<int>(Maturities));
// Theta[0] = 0.0498039349327417;
// Theta[1] = 0.0538710670441647;
// Theta[2] = 0.0181648634139392;
// Theta[3] = 0.0381183886467521;
for(int i = 0; i < (Maturities-1); i++)
{
Theta_A = 0.00;
Theta_B = TermStructure[i][1];
Q_dt_sum[0] = Initial_Price;
Q_dt_sum[i+1] = 0.0;
while (fabs(Theta_A - Theta_B) >= 0.0000001)
{
max = 1;
min = 10;
if (i == 0)
{
JSTART = j_max;
JEND = j_max;
}
else
{
JSTART = TempStart;
JEND = TempEnd;
}
for(int j = JSTART; j >= JEND; j--)
{
Theta_C = (Theta_A + Theta_B) / 2.0; // If Theta C is too low, the associated Price will be higher than Price from initial term structure. (ie P(Theta C) > P(i+2) for Theta C < Theta)
// If P_C > P(i+2), set Theta_B = Theta_C, else if P_C < P(i+2), set Theta_A = Theta_C, Else if P_C = P(i+2), Theta_C = Theta[i]
//cout << Theta_A << " " << Theta_B << " " << Theta_C << endl;
m[j][i] = FuncM(Theta[i], r_j[j], F_r[j], G_r[j], G_prime_r[j], dt, sigma);
j_star[j][i] = FuncJSTAR(m[j][i], x0, dx);
Central_Node[j][i] = FuncCN(m[j][i], x0, j_star[j][i], dx);
Pu[j][i] = FuncPup(dt, Central_Node[j][i], dx);
Pd[j][i] = FuncPdn(dt, Central_Node[j][i], dx);
Pm[j][i] = FuncPmd(Pd[j][i], Pu[j][i]);
for (int p = 0; p < j_range; p++)
{
Q[p][i] = 0; // Clear Q array
}
Q[j_max][0] = Initial_Price;
Q[j_max -(j_star[j][i]+1)][i+1] = Q[j_max - (j_star[j][i]+1)][i+1] + Q[j][i] * Pu[j][i] * exp(-r_j[j] * dt);
Q[j_max -(j_star[j][i] )][i+1] = Q[j_max - (j_star[j][i] )][i+1] + Q[j][i] * Pm[j][i] * exp(-r_j[j] * dt);
Q[j_max -(j_star[j][i]-1)][i+1] = Q[j_max - (j_star[j][i]-1)][i+1] + Q[j][i] * Pd[j][i] * exp(-r_j[j] * dt);
}
for (int j = 0; j < j_range; j++)
{
Up[j][i] = j_star[j][i] + 1;
Down[j][i] = j_star[j][i] - 1;
if (Up[j][i] > max)
{
max = Up[j][i];
}
if ((Down[j][i] < min) && (Down[j][i] > 0))
{
min = Down[j][i];
}
}
TempEnd = j_max - (max);
TempStart = j_max - (min);
for (int j = 0; j < j_range; j++)
{
Q_dt_sum[i+1] = Q_dt_sum[i+1] + Q[j][i] * exp(-r_j[j] * dt);
cout << Q_dt_sum[i+1] << endl;
}
if (Q_dt_sum[i+1] == Price[i+2])
{
Theta[i] = Theta_C;
break;
}
if (Q_dt_sum[i+1] > Price[i+2])
{
Theta_B = Theta_C;
}
else if (Q_dt_sum[i+1] < Price[i+2])
{
Theta_A = Theta_C;
}
}
cout << Theta[i] << endl;
}
return 0;
}
Ok, my bad. I had a value being called incorrectly.
All good.

Newton's method is divergent for some polynomials

I've tried to implement Newton's method for polynomials. Like:
double xn=x0;
double gxn=g(w, n, xn);
int i=0;
while(abs(gxn)>e && i<100){
xn=xn-(gxn/dg(w, n, xn));
gxn=g(w, n, xn);
i++;
}
where g(w, n, xn) computes the value of the function and dg(w, n, xn) computes the derivative.
As x0 I use starting point M which I found using Sturm's theorem.
My problem is that this method is divergent for some polynomials like x^4+2x^3+2x^2+2x+1. Maybe it's not regular, but I noticed that it happens when the solution of the equation is a negative number. Where can I look for an explanation?
Edit:
dg
double result=0;
for(int i=0; i<n+1; i++)
result+=w[i]*(n-i)*pow(x, n-i-1);
where n is the degree of polynomial
I'm not sure why would you say it's divergent.
I implemented Newton's method similarly to yours:
double g(int w[], int n, double x) {
double result = 0;
for (int i = 0; i < n + 1; i++)
result += w[i] * pow(x, n - i);
return result;
}
double dg_dx(int w[], int n, double x) {
double result = 0;
for (int i = 0; i < n ; i++)
result += w[i] * (n - i) * pow(x, n - i - 1);
return result;
}
int main() {
double xn = 0; // Choose initial value. I chose 0.
double gx;
double dg_dx_x;
int w[] = { 1, 2, 2, 2, 1 };
int i = 0;
int n = 4;
do {
gx = g(w, n, xn);
dg_dx_x = dg_dx(w, n, xn);
xn = xn - (gx / dg_dx_x);
i++;
} while (abs(gx) > 10e-5 && i < 100);
std::cout << xn << '\n';
}
And it yields -0.997576, which is close to the solution -1.