
#include <stdio.h>
#include "dat_class.h"
#include "callfdk.h"

#include "M_IrNoteVanilla.h"
#include "M_IrNoteOut.h"

#define DUMP_MSG(m) \
	aDump.Clear(); \
	m.Dump(&aDump); \
	printf("--------------\n"); \
	printf("%s\n", (char *)aDump.GetData())


void MakeInMsg(M_IrNoteVanilla *p_pIn);

int
main(int argc, char **argv)
{
	int iRet;
	CCallFdkError aError;
	CStream aDump;

	try {
		iRet = CCallFdk::Initialize("callfdk.cfg", &aError);
		if (iRet < 0) {
			printf("Error: %s\n", (char *)aError.Repr());
			getchar();
			return -1;
		}

		M_IrNoteVanilla mIn;
		M_IrNoteOut mOut;

		MakeInMsg(&mIn);

		printf("CallService 2106 ...\n");
		iRet = CCallFdk::CallService(2106, &mIn, &mOut, &aError);
		if (iRet < 0) {
			printf("Error: %s\n", (char *)aError.Repr());
			getchar();
			return -2;
		}

		DUMP_MSG(mOut);
		printf("OK.\n");
	} catch (CException &e) {
		printf("Error: %d, %s\n", e.GetCode(), e.GetText());
		getchar();
		return -3;
	}
	getchar();

	return 0;
}


void
MakeInMsg(M_IrNoteVanilla *p_pIn)
{
	int i;
	int iIdx;
	struct _RateCrv {
		char szRateType[10];
		double dRate;
		char szDateType[5];
		char szMatur[10];
		char szCmpndFreq3[10];
		char szDayCntConv[10];
	};
	struct _Sched {
		int iPeriodNo;
		char szFormerDate[9];
		char szAfterDate[9];
		char szCashflowDate[9];
	};


	p_pIn->mIrNotionalInfo.dNotionAmt = 10000.;
	p_pIn->mIrNotionalInfo.sCcy = "KRW";
	p_pIn->mIrNotionalInfo.iDisCrvId = 1;

	iIdx = p_pIn->mIrNotionalInfo.maIrAmortSchedule.Grow();
	M_IrAmortSchedule *pAmort = &p_pIn->mIrNotionalInfo.maIrAmortSchedule[iIdx-1];
	pAmort->iPeriodNo = 7;
	pAmort->dAmortAmt = 3000.;

	iIdx = p_pIn->mIrNotionalInfo.maIrAmortSchedule.Grow();
	pAmort = &p_pIn->mIrNotionalInfo.maIrAmortSchedule[iIdx-1];
	pAmort->iPeriodNo = 8;
	pAmort->dAmortAmt = 7000.;


	p_pIn->mIrVanilla.sPayRcvSect = "P";
	p_pIn->mIrVanilla.sPayTmPtC = "R";
	p_pIn->mIrVanilla.iFixedPeriodNo = 1;
	p_pIn->mIrVanilla.dFixedRate = 0.03;
	p_pIn->mIrVanilla.sDayCntConv = "A365";


	struct _Sched taSched[8] = {
		{1, "20150625", "20150925", "20150925"},
		{2, "20150925", "20151225", "20151225"},
		{3, "20151225", "20160325", "20160325"},
		{4, "20160325", "20160625", "20160625"},
		{5, "20160625", "20160925", "20160925"},
		{6, "20160925", "20161225", "20161225"},
		{7, "20160925", "20170325", "20170325"},
		{8, "20170325", "20170625", "20170625"}
	};

	for (i = 0; i < 8; i++) {
		iIdx = p_pIn->mIrVanilla.maIrCpnSchedule.Grow();
		M_IrCpnSchedule *pSch = &p_pIn->mIrVanilla.maIrCpnSchedule[iIdx-1];
		pSch->iPeriodNo = taSched[i].iPeriodNo;
		pSch->nFormerDate   = taSched[i].szFormerDate;
		pSch->nAfterDate    = taSched[i].szAfterDate;
		pSch->nCashflowDate = taSched[i].szCashflowDate;
	}

	M_FdkRateIndexB *pRateIdx = &p_pIn->mIrVanilla.mIrVanillaCpn.mFdkRateIndexB;
	pRateIdx->sRateIndexCode = "CD91D";
	pRateIdx->sCcy = "KRW";
	pRateIdx->sRateType = "S";
	pRateIdx->sRateMatur = "91D";
	pRateIdx->sCmpndFreq3 = "I";
	pRateIdx->sDayCntConv = "A365";
	pRateIdx->iRateCrvId = 1;
	pRateIdx->dGearing = 1.;
	p_pIn->mIrVanilla.mIrVanillaCpn.dMargin = 0.;
	p_pIn->mIrVanilla.mIrVanillaCpn.sDayCntConv = "A365";

	iIdx = p_pIn->mIrVanilla.maIrVanillaMon.Grow();
	M_IrVanillaMon *pMon = &p_pIn->mIrVanilla.maIrVanillaMon[iIdx-1];
	pMon->iPeriodNo = 2;
	pMon->bCouponFixingYN = true;
	pMon->dCouponRate = 0.023;


	// Parameter setting
	p_pIn->mIrParam.nCalcDate = "20150625";

	iIdx = p_pIn->mIrParam.maFdkRateCrvB.Grow();
	M_FdkRateCurveB *pCrv = &p_pIn->mIrParam.maFdkRateCrvB[iIdx-1];
	pCrv->iRateCrvId = 1;
	pCrv->sCcy = "KRW";
	pCrv->sInterpMethod = "L";

	struct _RateCrv taRateCrv[] = {
		{"S", 0.0223,   "S", "1D", "I", "ACTB"},
		{"Y", 0.0235,   "S", "3M", "Q", "A365"},
		{"Y", 0.022775, "S", "6M", "Q", "A365"},
		{"Y", 0.022575, "S", "9M", "Q", "A365"}
	};

	// Rate Curve
	for (i = 0; i < 4; i++) {
		iIdx = pCrv->maRateCrvTenor.Grow();
		M_RateCurveTenor *pTnr = &pCrv->maRateCrvTenor[iIdx-1];
		pTnr->sRateType = taRateCrv[i].szRateType;
		pTnr->dRate = taRateCrv[i].dRate;
		pTnr->mTivMatur.sDateType = taRateCrv[i].szDateType;
		pTnr->mTivMatur.sMatur = taRateCrv[i].szMatur;
		pTnr->sCmpndFreq3 = taRateCrv[i].szCmpndFreq3;
		pTnr->sDayCntConv = taRateCrv[i].szDayCntConv;
	}

	struct _RateCrv taRateCrv2[] = {
		{"Y", 0.022375,  "S", "1Y",   "Q", "A365"},
		{"Y", 0.022725,  "S", "2Y",   "Q", "A365"},
		{"Y", 0.02305,   "S", "2Y6M", "Q", "A365"},
		{"Y", 0.023375,  "S", "3Y",   "Q", "A365"},
		{"Y", 0.024725,  "S", "5Y",   "Q", "A365"},
		{"Y", 0.02575,   "S", "7Y",   "Q", "A365"},
		{"Y", 0.02705,   "S", "10Y",  "Q", "A365"}
	};

	// Rate Curve 2
	for (i = 0; i < 7; i++) {
		iIdx = pCrv->maRateCrvTenor2.Grow();
		M_RateCurveTenor *pTnr = &pCrv->maRateCrvTenor2[iIdx-1];
		pTnr->sRateType = taRateCrv2[i].szRateType;
		pTnr->dRate = taRateCrv2[i].dRate;
		pTnr->mTivMatur.sDateType = taRateCrv2[i].szDateType;
		pTnr->mTivMatur.sMatur = taRateCrv2[i].szMatur;
		pTnr->sCmpndFreq3 = taRateCrv2[i].szCmpndFreq3;
		pTnr->sDayCntConv = taRateCrv2[i].szDayCntConv;
	}

	// Forward curve
	iIdx = pCrv->maFwdCrvTenor.Grow();
	M_FwdCurveTenor *pFwd = &pCrv->maFwdCrvTenor[iIdx-1];
	pFwd->dRate = 0.027;
	pFwd->nFwdEndDate = "20160126";
	pFwd->sMatur = "3M";
	pFwd->sCmpndFreq3 = "I";
	pFwd->sDayCntConv = "A365";

	iIdx = pCrv->maFwdCrvTenor.Grow();
	pFwd = &pCrv->maFwdCrvTenor[iIdx-1];
	pFwd->dRate = 0.029;
	pFwd->nFwdEndDate = "20160226";
	pFwd->sMatur = "3M";
	pFwd->sCmpndFreq3 = "I";
	pFwd->sDayCntConv = "A365";


	// flags
	p_pIn->mIrEffSensTreeParam.bDeltaYN = false;
	p_pIn->mIrEffSensTreeParam.sRDeltaType = "RP";
	p_pIn->mIrEffSensTreeParam.bVegaYN = false;
	p_pIn->mIrEffSensTreeParam.bFxVegaYN = false;
	p_pIn->mIrEffSensTreeParam.bThetaYN = true;
	p_pIn->mIrEffSensTreeParam.bReCalibYN = true;
	p_pIn->mIrEffSensTreeParam.bSpotDeltaYN = true;
	p_pIn->mIrEffSensTreeParam.bAccumDeltaYN = true;
	p_pIn->mIrEffSensTreeParam.sThetaType = "T";

	p_pIn->bDiffSensYN = true;
}



