/*
First version obtained using PcNaive, then adjusted to load HooverPerez(1999) data
*/
///////////////////////////////////////////////////////////
#include <oxstd.h>
// Use the PcGive class for estimation instead of PcFiml:
#define USE_PCGIVE
#import <packages/PcNaive/pcnaive_mc>

///////////////////////////////////////////////////////////
class CMyModel : CPcNaiveModel
{	// Allows customization for additional coefficients and tests
	CMyModel();                                // constructor

	virtual GetCoefName(const eval);
	virtual GetTestName(const eval);
	virtual GetTestIsTwoSided(const eval);
	virtual GetCoef(const eval);
	virtual GetTest(const eval);
};
CMyModel::CMyModel()
{
	CPcNaiveModel();     // call base class constructor
}
CMyModel::GetCoefName(const eval)
{	// return an array of strings with additional COEF_ names
	return {};
}
CMyModel::GetTestName(const eval)
{	// return an array of strings with additional TEST_ names
	return {};
}
CMyModel::GetTestIsTwoSided(const eval)
{	// return a row vector with a zero for each one-sided test,
	// and 1 for two-sided
	return <>;
}
CMyModel::GetCoef(const eval)
{	// return a row vector with the COEF_ estimates
	return <>;
}
CMyModel::GetTest(const eval)
{	// return a 2 x c matrix with the TEST_ statistics in the
	// first row, and p-values in the second row
	return <>;
}
///////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////
// Custom class to load data from file
class CMyPcFimlDgp : CPcFimlDgp
{
    CMyPcFimlDgp(const cY, const cZ);                   // constructor

	virtual GenerateZ(const cT, const mC0t, const mV);
};
CMyPcFimlDgp::CMyPcFimlDgp(const cY, const cZ)
{
	CPcFimlDgp(cY, cZ);
}
CMyPcFimlDgp::GenerateZ(const cT, const mC0t, const mV)
{
	decl db = new Database();
	db.Load("../data/HooverPerez(1999).xls");
	db.Info();
	// x3 and x11
	decl mz = diff0(diff0(db.GetVar("GGEQ"))) ~ diff0(db.GetVar("FM1DQ"));
	delete db;
	return mz; // 5 discarded will line up data to use 1960(3) - 1995(1) in estimation
}
///////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////
class CPcNaiveExp : CPcNaive
{
	CPcNaiveExp();					// constructor
	~CPcNaiveExp();					// destructor
	Generate(const iRep, const cT,	// generate replication
		const mxT);
};
CPcNaiveExp::CPcNaiveExp()
{
	decl lambda = 1.0;
	CPcNaive(<139>+1, 5, 0, 100000, 1, -1, 0, 
		<0.1,0.05>, 
		<0>);

	m_dgp = new CMyPcFimlDgp(1, 2);	// create the DGP

	m_dgp.Create(4, 1960, 3, 5, 1, 139+1);

	m_dgp.UseObsLoop(0);
	m_dgp.SetYParameter(
<0.75;
 -0.046;  0.0345;
  0.0;	  0.0;
 0;
 0 >);
	m_dgp.SetZParameter(
<0,0;
 0,0 >);
	m_dgp.SetDistribution(U_DGP, NORMAL,
<0 >,
matrix(sqr(0.073 * lambda)));
	m_dgp.SetDistribution(Z_DGP, NORMAL,
<0;
 0 >,
<1;
 1 >);
									// formulate the DGP
	m_dgp.Select(Y_VAR, { "Ya", 0, 1} );
	m_dgp.Select(X_VAR, { "Za", 0, 1} );
	m_dgp.Select(X_VAR, { "Zb", 0, 1} );
	m_dgp.Select(X_VAR, { "Constant", 0, 0} );
	m_dgp.Select(X_VAR, { "Trend", 0, 0} );
	SetRecursive(0);

	m_sys = new CMyModel();			// create the system/model
	CPcNaive::CreateData(1, 2);		// create the system database

									// formulate the model
	m_sys.Select(Y_VAR, { "Ya", 0, 0} );
	m_sys.Select(Y_VAR, { "Ya", 1, 1} );
	m_sys.Select(X_VAR, { "Za", 0, 0} );
	m_sys.Select(X_VAR, { "Za", 1, 1} );
	m_sys.Select(U_VAR, { "Constant", 0, 0} );
	m_sys.SetMethod(M_OLS);

	m_sys.SetEval(139, 139, 0);
	m_sys.AddEvalCoef(COEF_BETA, 0, 0);
	m_sys.AddEvalCoef(COEF_GFIT, 0, 0);
	m_sys.AddEvalTest(TEST_TVAL      , 0, 0);
	SetPlotStep(0);

	Update();
	println("PcNaive run: ", oxfilename(0));
	println("\n####### lambda=", lambda, "\n"); 
	Report(1, 1, 1);
}
CPcNaiveExp::~CPcNaiveExp()
{
	~CPcNaive();					// call base destructor
}

CPcNaiveExp::Generate(const iRep, const cT, const mxT)
{
	m_sys.RestoreModel();				// first reset to initial specification

	CPcNaive::Generate(iRep, cT, mxT);	// update data; set sample

	//	m_sys.SetPrint(1);				// print every estimation
	m_sys.Estimate();					// estimate the model
	//	println(m_sys.GetW());			// print regressor matrix
										// get and store the statistics:
	m_mTest = m_sys.GetEvalTest();		// 2nd row: p-values
	m_mCoef = m_sys.GetEvalCoef();		// row vector
	m_mCoef ~= m_sys.EvaluateSelection(m_dgp);
return TRUE;
}
///////////////////////////////////////////////////////////

main()
{
	decl exp = new CPcNaiveExp();
	exp.Simulate();
	delete exp;
}
