24 void javaGraph(
int g,
string xtra_var =
"",
string xtra_label =
"",
int followup_mnth = 0);
26 void parse_javaGraph(
int g,
string xtra_var =
"",
string xtra_label =
"");
51 void expand_cf(
float amount,
string freq =
"M",
string fromStr=
"",
string tillStr=
"",
int goal_nbr = 0);
92 means.insert (std::pair<int,float>(i, 0.0) );
93 means_left.insert (std::pair<int,float>(i, 0.0) );
94 means_used.insert (std::pair<int,float>(i, 0.0) );
96 means_tmp.insert (std::pair<int,float>(i, 0.0) );
124 string s, the_curr =
"";
130 while (
db.
res->next())
132 the_curr =
db.
res->getString(
"currency");
147 this->
means.at(0) = theSum;
160 struct tm tm1;
struct tm tm2;
161 if (freq ==
"M") step = 1;
162 else if (freq ==
"A") step = 12;
163 else if (freq ==
"Q") step = 3;
164 else if (freq ==
"S") step = 6;
165 else if (freq ==
"W")
170 else if (freq ==
"D")
185 means.at(m) += amount;
189 goalZ[goal_nbr].means_goal.at(m) += amount;
204 string s =
"", d1, d2, the_curr;
209 while (
db.
res->next())
211 d1 =
db.
res->getString(
"from_date");
212 d2 =
db.
res->getString(
"till_date");
213 the_curr =
db.
res->getString(
"currency");
233 debug_info = debug_info +
"<BR>goal_type_s2i[\"amount@date\"] = " + to_string(
goal_type_s2i[
"amount@date"]);
234 debug_info = debug_info +
"<BR>goal_type_s2i[\"income from/to\"] = " + to_string(
goal_type_s2i[
"income from/to"]);
236 while (
db.
res->next())
241 this->
goalZ[nbr].set_from_db();
243 debug_info = debug_info +
"<BR>---goal: " + to_string(nbr);
244 debug_info = debug_info +
"<BR>goal_type = " + to_string(
goalZ[nbr].goal_type);
253 goalZ[nbr].target_amount = 0;
263 goalZ[nbr].target_amount = 0;
303 s =
"SELECT MIN(priority) as theMin, MAX(priority) as theMax FROM " +
oConfig.
tbl_prefix +
"_goals WHERE investor = " + to_string(this->
investor_id) +
" AND goal_type != " + to_string(
goal_type_s2i[
"unallocated"]) +
";";
305 while (
db.
res->next())
343 int nbr = 0, count = 0, p, ac;
345 string s =
"SELECT portfolio_id FROM " +
oConfig.
tbl_prefix +
"_portfolios ORDER BY portfolio_id;";
347 while (
db.
res->next())
349 nbr =
db.
res->getInt(
"portfolio_id");
398 int g = 1,m, k, freeFrom, unallocated_goal_nbr = 0;
399 float opt_perc, amnt_used, currency_conversion;
407 for(m=0;m<=
goalZ[g].realization_monthNbr;m++)
426 if (currency_conversion != 0)
428 for(m=0;m<=
goalZ[g].realization_monthNbr;m++)
435 currency_conversion = 1;
440 unallocated_goal_nbr = g;
455 for(m=0; m<=
goalZ[g].realization_monthNbr; m++)
471 goalZ[g].realization_monthNbr = k;
503 for (k = freeFrom; k <=
goalZ[g].realization_monthNbr; k++)
517 for (k = 0; k <=
goalZ[g].realization_monthNbr; k++)
522 means_left[k] = (means_left[k] - amnt_used) / currency_conversion;
523 goalZ[g].saving_plan[k] = amnt_used;
550 goalZ[g].success =
true;
555 goalZ[g].color =
"brightgreen";
560 goalZ[g].color =
"green";
565 goalZ[g].success =
false;
570 goalZ[g].color =
"red";
575 goalZ[g].color =
"darkred";
580 goalZ[g].color =
"amber";
590 goalZ[g].remarks =
"<u>" +
goalZ[g].remarks +
"</u>"
591 +
"<br>The portoflio corresponding to this benchmark is called " +
portfolios[
goalZ[g].optimal_portf].description +
"."
592 +
"<br>The shortfall of this portfolio with the given savings plan is estimated to be "
594 + to_string((
int)((1-
goalZ[g].alpha)*10000)/100) +
"%."
595 +
"<br>The sum of all savings (not discounted) is " +
606 int k, optimal_portf;
607 if (unallocated_goal_nbr == 0)
626 goalZ[unallocated_goal_nbr].optimal_portf = optimal_portf;
632 goalZ[unallocated_goal_nbr].benchmark[k] =
portfolios[optimal_portf].weights[k-1];
635 goalZ[unallocated_goal_nbr].remarks =
goalZ[unallocated_goal_nbr].remarks +
"This is not really a "goal"."
636 +
"This is simply all the assets that are not or cannot be used by other goals.<br>"
637 +
"The non-discounted sum of this savings is: "
639 goalZ[unallocated_goal_nbr].color =
"brightgreen";
643 error_message =
error_message +
"<li>Failed to create the unallocated goal, so after all the goals mentioned here, some means might be left</li>";
658 for (m = 0; m <=
goalZ[g].realization_monthNbr; m++)
goalZ[g].means_goal[m] = 0;
679 int p, optimal_portf = 0;
681 float* perc_bloc_used = NULL;
682 float* new_block = NULL;
683 new_block = (
float*) realloc(perc_bloc_used,
nbr_portfolios *
sizeof(
float));
684 if (new_block != NULL)
686 perc_bloc_used = new_block;
690 free(perc_bloc_used);
692 debug_info = debug_info +
"<br/>realloc() failed in get_optimal_portfolio()";
707 perc_bloc_used[p-1] = opt_perc + 1;
715 if (perc_bloc_used[p-1] <= opt_perc)
717 opt_perc = perc_bloc_used[p-1];
727 goalZ[g].optimal_portf = optimal_portf;
754 for(m = 0; m <=
goalZ[g].realization_monthNbr; m++)
means_tmp[m] = 0;
795 {*perc += pow(2,-k);}
797 {*perc -= pow(2,-k);}
819 float const my_errf =
erfinv(2 *
goalZ[g].alpha - 1);
824 for (m = 1; m <=
goalZ[g].realization_monthNbr; m++)
828 if (abs(V) + abs(delta) != 0)
830 mnt_avg = (abs(V) * (mnt_avg) + abs(delta) * 1) / (abs(V) + abs(delta));
833 V_min = V_min * exp(
portfolios[p].
pLogR +sqrt(2) * s * (sqrt(mnt_avg) - sqrt(mnt_avg-1)) * my_errf) + delta;
837 else {
return (
goalZ[g].target_amount - V_min);}
947 int k, max_month = 0;
950 for (k = g + 1; k <= this->
nbr_goals; k++)
953 if (
goalZ[k].goal_type != 0 &&
goalZ[k].realization_monthNbr > max_month) {max_month =
goalZ[k].realization_monthNbr;}
973 string s1, s2, s3, s4, comma;
974 float Vlow, Vhigh, Vmed, Vexp, Vexp_evol,
975 sigma, the_diff, age_now =
age(0), age_at_cutoff, diff_cum, erf_low, erf_high, erf_med, age_at_k,
978 int p = goalZ[g].optimal_portf;
979 s1 = s2 = s3 = s4 =
"";
981 erf_low =
erfinv(2 * goalZ[g].alpha - 1);
982 erf_high =
erfinv(2 * (1-goalZ[g].alpha) - 1);
986 if (followup_mnth == 0)
988 Vlow = Vhigh = Vmed = diff_cum = Vexp = goalZ[g].saving_plan[0] - goalZ[g].means_goal[0];
992 Vlow = Vhigh = Vmed = diff_cum = Vexp = goalZ[g].saving_plan[followup_mnth] - goalZ[g].means_goal[followup_mnth] + goalZ[g].simulation_endvalue;
994 age_at_cutoff = age_now + (float)followup_mnth / 12;
996 if ( followup_mnth < mnth_max)
998 s1 =
"[" + to_string(age_at_cutoff) +
", " + to_string(Vexp) +
"]";
999 s2 =
"[" + to_string(age_at_cutoff) +
", " + to_string(Vexp) +
"]";
1000 s3 =
"[" + to_string(age_at_cutoff) +
", " + to_string(Vexp) +
"]";
1004 s1 = s2 = s3 =
"[]";
1008 for (k=followup_mnth + 1; k <= mnth_max; k++)
1014 the_diff = goalZ[g].saving_plan[k] - goalZ[g].means_goal[k];
1015 diff_cum += the_diff;
1017 Vexp = Vexp_evol + the_diff;
1019 if (abs(Vexp) + abs(the_diff) != 0)
1021 mnt_avg = (abs(Vexp) * (mnt_avg) + abs(the_diff) * 1) / (abs(Vexp) + abs(the_diff));
1025 Vlow = Vlow * exp(
portfolios[p].
pLogR +sqrt(2) * (sqrt(mnt_avg) - sqrt(mnt_avg-1)) * sigma * erf_low) + the_diff;
1026 Vmed = Vmed * exp(
portfolios[p].
pLogR +sqrt(2) * (sqrt(mnt_avg) - sqrt(mnt_avg-1)) * sigma * erf_med) + the_diff;
1027 Vhigh = Vhigh * exp(
portfolios[p].
pLogR +sqrt(2) * (sqrt(mnt_avg) - sqrt(mnt_avg-1)) * sigma * erf_high) + the_diff;
1028 Vexp = Vexp_evol + the_diff;
1029 age_at_k = age_now + (float)k / 12;
1030 s1 = s1 +
", [" + to_string(age_at_k) +
", " + to_string(Vlow) +
"]";
1031 #ifdef SHOW_Vexp_not_Vmed
1032 s2 = s2 +
", [" + to_string(age_at_k) +
", " + to_string(Vexp) +
"]";
1034 s2 = s2 +
", [" + to_string(age_at_k) +
", " + to_string(Vmed) +
"]";
1036 s3 = s3 +
", [" + to_string(age_at_k) +
", " + to_string(Vhigh) +
"]";
1039 if (goalZ[g].goal_type ==
goal_type_s2i[
"rainy day savings"])
1041 s4 = s4 +
"[" + to_string(age_now) +
", " + to_string(goalZ[g].target_amount) +
"]";
1042 for (k=1; k <= mnth_max; k++)
1044 age_at_k = age_now + (float)k / 12;
1045 s4 = s4 +
", [" + to_string(age_at_k) +
", " + to_string(goalZ[g].target_amount) +
"]";
1050 s4 =
"[" + to_string(age_now + ((
float)goalZ[g].realization_monthNbr)/12) +
"," + to_string(goalZ[g].target_amount) +
"]";
1057 goalZ[g].s_low = s1;
1058 goalZ[g].s_exp = s2;
1059 goalZ[g].s_high = s3;
1060 goalZ[g].s_goal = s4;
1062 if (followup_mnth > 0)
1064 if (followup_mnth + 1 > goalZ[g].realization_monthNbr)
1105 string xtra_var_name;
1106 cout <<
"<div id=\"chartOverview"<<g<<
"\" style=\"height:400px; width:700px;\"></div>";
1107 cout <<
"<script class=\"code\" type=\"text/javascript\">$(document).ready(function(){ \n";
1108 cout <<
"var l1 = [" + this->
goalZ[g].s_low +
"]; \n";
1109 cout <<
"var l2 = [" + this->
goalZ[g].s_exp +
"]; \n";
1110 cout <<
"var l3 = [" + this->
goalZ[g].s_high +
"]; \n";
1111 cout <<
"var l4 = [" + this->
goalZ[g].s_goal +
"]; \n";
1114 cout <<
"var l5 = [" + xtra_var +
"]; ";
1115 xtra_var_name =
", l5";
1122 cout <<
"var overviewPlot" << g <<
" = var" << g <<
" = $.jqplot ('chartOverview" << g <<
"', [l1, l2, l3, l4" << xtra_var_name <<
"] ";
1124 cout <<
"seriesDefaults: {";
1125 cout <<
"showMarker: false ,";
1126 cout <<
"rendererOptions: { smooth: false },";
1127 cout <<
"markerOptions: { style:\"o\", size:5 }, ";
1128 cout <<
"lineWidth:7 ";
1130 cout <<
"legend: {show: true, location: 'e', fontSize: '2em', placement: 'outside', marginRight: \"600px\",";
1132 if (xtra_var !=
"") cout <<
", '" << xtra_label <<
"'";
1198 cout <<
"seriesDefaults: {rendererOptions: { smooth: false }},";
1199 cout <<
"legend: {show: true, location: 'e', placement: 'outside', marginRight: \"600px\",";
1200 cout <<
"labels:['negative scenario', 'expected evolution', 'good scenario', 'YOUR GOAL #"<<g<<
"'";
1201 if (xtra_var !=
"") cout <<
", '" << xtra_label <<
"'";
1206 cout <<
"series:[{showMarker: false},{showMarker:false,lineWidth:5},{showMarker: false},";
1212 cout <<
"{markerOptions: { show: true, style: 'circle', size: 12, shadow: false, shadowDepth: 6, shadowAlpha: 0.07, shapeRenderer: new $.jqplot.customMarkerRenderer() }}";
1216 cout <<
"{showMarker: false}";
1218 if (xtra_var !=
"") cout <<
", {markerOptions: { style:\"o\", size:5 }, lineWidth:1}";
1223 cout <<
"axesDefaults: {labelRenderer: $.jqplot.CanvasAxisLabelRenderer},";
1225 cout <<
"axes: {xaxis: {label: \"age\" }, yaxis: {label: \"" <<
goalZ[g].currency <<
"\"}}";
1226 cout <<
" } ); }); </script>";
1237 if (Vlow > this->
goalZ[g].target_amount) this->
goalZ[g].color_followup =
"green";
1238 else if (Vmed > this->
goalZ[g].target_amount) this->
goalZ[g].color_followup =
"amber";
1239 else this->
goalZ[g].color_followup =
"red";
1248 if (V > this->
goalZ[g].target_amount) this->
goalZ[g].color_followup =
"green";
1249 else if (V > this->
goalZ[g].target_amount * (1 -
MIN_ALPHA)) this->
goalZ[g].color_followup =
"amber";
1250 else this->
goalZ[g].color_followup =
"red";
1263 float V0, Vhigh,sigma, logR, Vexp;
1264 if (p == 0) p =
goalZ[g].optimal_portf;
1265 Vhigh = Vexp = V0 =
goalZ[g].saving_plan[0] -
goalZ[g].means_goal[0];
1268 for (k=1; k <=
goalZ[g].realization_monthNbr; k++)
1272 logR = log(Vexp / V0);
1287 bool success =
true;
1291 +
" AND goal_type = " + to_string(
goal_type_s2i[
"unallocated"]) +
";";
1325 catch (sql::SQLException &e)
1328 debug_info =
"<br>" + s +
"<br>";
1329 debug_info = debug_info +
"# ERR: SQLException in " + __FILE__ +
"(" + __FUNCTION__
1330 +
") on line " + to_string(__LINE__) +
"<br># ERR: " + e.what()
1331 +
" (MySQL error code: " + to_string(e.getErrorCode())
1332 +
", SQLState: " + e.getSQLState() +
" )<br>";
1347 int p, the_portfolio = 1;
1357 return the_portfolio;
1365 int p, the_portfolio = 1;
1375 return the_portfolio;
int nbr_portfolios
the number of standard portfolios
#define RAINY_DAY_MONTH_NBR
the artificial horizon in months for the "rainy day goal"
void load_covar(int person, char person_type= 'i')
bool is_valid_dateStr(string theDate)
float pLogR
the MONTHLY log-return
void set_followup_color_post(float V, int g)
#define ALPHA_UPPER_LIMIT
the upper limit for all alpha's to be used
const string seriesColorsGoalPlot
string currency
the default currency for that customer
unordered_map< string, string > t_feedback
int nbr_goals
the total number of goals
std::map< int, float > means
sum of cash flows and assets per month (not to be changed)
float calc_V_high(int g, int p=0)
calculates the 1-alpha quantile portfolio for the goal alpha at realization_monthNbr ...
int goal_type
(0, "unallocated"), (1, "amount@date"), (2, "income from/to"), (3, "rainy day savings"), (4, "amount asap");
int get_max_month_for_lower_goals(int g)
void expand_cf(float amount, string freq="M", string fromStr="", string tillStr="", int goal_nbr=0)
float weights[NBR_ASSET_CLASSES]
the weights of the asset classes (ordered as the asset classes)
unordered_map< int, string > t_plotlabels_evol
#define MIN_ALPHA
= (1 - confidence_level) for the most important goal
bool get_portf_from_db(int id)
unordered_map< int, string > goal_type_i2s
#define ALPHA_PLOT_HIGH
the high alpha to plot
std::map< int, portfolio > portfolios
the standard portfolios
investment_problem(int investor)
Constructor.
#define NBR_ASSET_CLASSES
the nunmber of asset classes (not dynamically updated!)
string error_message
global message variables
void prepare_javaVars_colors(int g, int followup_mnth)
float pSigma
the MONTHLY volatility
int age2monthNbr(float theAge)
const string tbl_prefix
tables start with "" + oConfig.tbl_prefix + "_" if the prefix is eg. "tbl" then we have "tbl_invesotr...
std::map< int, bool > portfolio_suitable
#define PRECISSION
equals roundup (1 / 2^NBR_ITERATIONS)
tm get_tm(int monthNbr=0)
global functions
int get_portfolio_safest()
returns the portfolio id of the safest acceptable portfolio
string curr_format(float dv, string the_curr="")
bool set_unallocated_goal()
std::map< int, float > means_left
the percentage left to be invested of each cash-flow (carried over to next goal)
int get_portfolio_riskiest()
returns the portfolio id of the riskiest acceptable portfolio
#define ALPHA_LOWER_LIMIT
the lower limit for all alpha's to be used
void solve()
allocates means (with a benchmark) to goals
html_helper hh
own c++ classes
void set_goal_color(int g, float opt_perc)
allocates a color to each goal after the benchmark is found
#define NBR_ITERATIONS
number of iterations in goalseek procedures
void set_goal_remarks(int g)
adds remarks about the benchmark afther the benchmark is found
std::map< int, float > means_used
the means already used for THIS particular goal
bool set_curr(string the_curr)
#define MAX_MONTHS_TO_SAFEST
the maximum number of months for realization_monthNbr to be forced to the safest portfolio ...
void load_ER(int person=0, char person_type= 'i')
void set_priorityLimits()
sets priorityMax and priorityMin
float calc_alpha(int priority, int monthNbr)
estimates $$
std::map< int, float > means_block
next block of means to be used for a certain percentage
float assetClass_mu[(NBR_ASSET_CLASSES+1)]
note: index 0 not used
int dateStr2Mnbr(string dStr)
void set_means_goal(int g)
set the cash flows that are implied by the goal (eg. regular income from portfolio) ...
void javaGraph(int g, string xtra_var="", string xtra_label="", int followup_mnth=0)
std::map< int, float > means_tmp
copy of block for goal-seek
std::map< int, float > max_exposure
the maximum exposure per asset class
float get_optimal_portfolio(int g)
finds the portfolio with minimal investment
void goal_seek_tmp_means(float *perc, int g, int p)
finds the minimal percentage needed of tmp_means
unordered_map< string, string > t_errMsg
void dateStr2tm(string dStr, tm *target_tm)
void set_followup_color_prae(float Vlow, float Vmed, float Vhigh, int g)
#define MAX_ALPHA
= (1 - confidence_level) for the least important goal
float to_curr(float amnt, string the_curr)
void allocate_to_unallocated_goal(int unallocated_goal_nbr)
if necessary create an unallocated goal and put the means_left there
float calc_risk(int g, int p)
calculate the risk
void load_preferences()
sets the experience, knowledge and desirability vectors
void set_assets()
add the assets to means[1]
config oConfig
mysql connection mysql connector from dev.mysql.com
int load_from_db(string investorID)
std::map< int, aGOAL > goalZ
map containing all goals
int nbr_cfs
the total number of cash flows
void parse_javaGraph(int g, string xtra_var="", string xtra_label="")
plots the chartOverview
float flSum(std::map< int, float > *theMap, int N)
int nbr_assets
the total number of assets
void set_portfolios()
sets the portfolios
unordered_map< string, int > goal_type_s2i
Global lists.
float goal_seek_means(int g, int p)
finds the minimal means needed (first free, then remaining, etc); sets tmp_means and calls the next f...