# MAD Portfolio optimization

**URL:** <https://discuss.ampl.com/t/mad-portfolio-optimization/880>\
**Category:** Support\
**Created:** [January 3, 2024, 6:25pm UTC](https://discuss.ampl.com/t/mad-portfolio-optimization/880 "2024-01-03T18:25:04Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Firdevs\_Uykun](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.ampl.com/firdevs_uykun/32/528_2.png) [@Firdevs\_Uykun](https://discuss.ampl.com/u/Firdevs_Uykun)\
**Post date:** [January 3, 2024, 6:25pm UTC](https://discuss.ampl.com/t/mad-portfolio-optimization/880/1 "2024-01-03T18:25:04Z")

</div>

I want to solve three AMPL model,I want to insert first two model output to final model as minimum return,minimum risk,max return,max risk.I wrote the following:  
tscv = TimeSeriesSplit(max\_train\_size=11, test\_size=1)  
for train\_index, test\_index in tscv.split(assets):  
train\_assets = assets.iloc[train\_index]  
test\_assets = assets.iloc[test\_index]

```
    daily_returns = train_assets.pct_change().dropna()
    mean_return = daily_returns.mean()
    
    daily_returns["Date"] = daily_returns.index.format()
    daily_returns.set_index("Date", inplace=True)
    #min
    ampl = AMPL()
    ampl.read("mad_portfolio.mod")

    ampl.set["ASSETS"] = list(assets.columns)
    ampl.set["TIME"] = daily_returns.index
    ampl.param["daily_returns"] = daily_returns
    ampl.param["mean_return"] = mean_return
    #ampl.getParameter("daily_returns").setValues(daily_returns_train.stack())
    #ampl.getParameter("mean_return").setValues(mean_return_train)
    ampl.param["w_lb"] = 0
    ampl.param["w_ub"] = 0.2
    ampl.param["R"] = 0.001
    ampl.option["solver"] = SOLVER
    ampl.solve()
    #ampl.var["w"].to_pandas()
    #ampl.get_data("w").to_pandas().plot.barh()
    #ampl.get_data["w"].to_pandas()
    weights_df = ampl.var["w"].to_pandas()
   # all_weights.append(weights_df)
    R_min=mean_return.dot(weights_df)
    G_min=ampl.get_value('sum{t in TIME}(u[t] + v[t]) / card(TIME)')
    #max
    maxi = AMPL()
    maxi.read("mad_portfolio_risk_free_max.mod")

    maxi.set["ASSETS"] = list(assets.columns)
    maxi.set["TIME"] = daily_returns.index
    maxi.param["daily_returns"] = daily_returns
    maxi.param["mean_return"] = mean_return
    #ampl.getParameter("daily_returns").setValues(daily_returns_train.stack())
    #ampl.getParameter("mean_return").setValues(mean_return_train)
    maxi.param["w_lb"] = 0
    maxi.param["w_ub"] = 0.2
    maxi.param["R"] = 0.001
    maxi.option["solver"] = SOLVER
    maxi.solve()
    #ampl.var["w"].to_pandas()
    #ampl.get_data("w").to_pandas().plot.barh()
    #ampl.get_data["w"].to_pandas()
    weights_df_max = maxi.var["w"].to_pandas()
    #all_weights.append(weights_df)
    R_max=mean_return.dot(weights_df_max)
    G_max=maxi.get_value('sum{t in TIME}(u[t] + v[t]) / card(TIME)')
    

    #daily_returns_test = test_assets.pct_change().dropna()
    #mean_return_test = daily_returns_test.mean()
    m = AMPL()
    m.read("mad_portfolio_risk_free_max.mod")

    m.set["ASSETS"] = list(assets.columns)
    m.set["TIME"] = daily_returns.index
    m.param["daily_returns"] = daily_returns
    m.param["mean_return"] = mean_return
    #ampl.getParameter("daily_returns").setValues(daily_returns_train.stack())
    #ampl.getParameter("mean_return").setValues(mean_return_train)
    m.param["R_min"] = R_min
    m.param["R_max"] = R_max
    m.param["G_min"] = G_min
    m.param["G_max"] = G_max
    m.param["risk_aversion"] = ml(assets)
    m.param["w_lb"] = 0
    m.param["w_ub"] = 0.2
    m.param["R"] = 0.001
    m.option["solver"] = SOLVER
    m.solve()
    #ampl.var["w"].to_pandas()
    #ampl.get_data("w").to_pandas().plot.barh()
    #ampl.get_data["w"].to_pandas()
    weights_df_max = m.var["w"].to_pandas()
    #all_weights.append(weights_df)
    #R_max.append(mean_return.dot(weights_df_max))
    #G_max.append(m.get_value('sum{t in TIME}(u[t] + v[t]) / card(TIME)'))
    #print(R_max)

```

But I got following error:

 ![image](https://us1.discourse-cdn.com/flex019/uploads/ampl/original/1X/bab17dcc24a03c2418b2d6e547ccdb03108fb09f.png)

---

<div class="post-metadata">

**Author:** ![Firdevs\_Uykun](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.ampl.com/firdevs_uykun/32/528_2.png) [@Firdevs\_Uykun](https://discuss.ampl.com/u/Firdevs_Uykun)\
**Post date:** [January 3, 2024, 8:21pm UTC](https://discuss.ampl.com/t/mad-portfolio-optimization/880/2 "2024-01-03T20:21:14Z")

</div>

my m model as follows:  
param R default 0;  
param rf default 0;  
param w\_lb default 0;  
param w\_ub default 1;

set ASSETS;  
set TIME;

param daily\_returns{TIME, ASSETS};  
param mean\_return{ASSETS};  
param R\_min{TIME};  
param R\_max{TIME};  
param G\_min{TIME};  
param G\_max{TIME};  
param risk\_aversion{TIME};

var w{ASSETS};  
var u{TIME} \>= 0;  
var v{TIME} \>= 0;

maximize MAD:(sum{j in ASSETS} mean\_return{ASSETS}-R\_min)/(R\_min-R\_max)_w[j]-risk\_aversion_((sum{t in TIME}(u[t] + v[t]) / card(TIME))-G\_min)/(G\_max-G\_min);

s.t. portfolio\_returns {t in TIME}:  
u[t] - v[t] == sum{j in ASSETS}(w[j] \* (daily\_returns[t, j] - mean\_return[j]));

s.t. sum\_of\_weights: sum{j in ASSETS} w[j] \<= 1;

s.t. mean\_portfolio\_return: sum{j in ASSETS}(w[j] \* (mean\_return[j] - rf)) \>= R - rf;

s.t. no\_short {j in ASSETS}: w[j] \>= w\_lb;

s.t. diversify {j in ASSETS}: w[j] \<= w\_ub;

---

<div class="post-metadata">

**Author:** ![Firdevs\_Uykun](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.ampl.com/firdevs_uykun/32/528_2.png) [@Firdevs\_Uykun](https://discuss.ampl.com/u/Firdevs_Uykun)\
**Post date:** [January 3, 2024, 8:41pm UTC](https://discuss.ampl.com/t/mad-portfolio-optimization/880/3 "2024-01-03T20:41:56Z")

</div>

Then I changed my code as follows:

tscv = TimeSeriesSplit(max\_train\_size=11, test\_size=1)  
for train\_index, test\_index in tscv.split(assets):  
train\_assets = assets.iloc[train\_index]  
test\_assets = assets.iloc[test\_index]

```
    daily_returns = train_assets.pct_change().dropna()
    mean_return = daily_returns.mean()
    
    daily_returns["Date"] = daily_returns.index.format()
    daily_returns.set_index("Date", inplace=True)
    #min
    ampl = AMPL()
    ampl.read("mad_portfolio.mod")

    ampl.set["ASSETS"] = list(assets.columns)
    ampl.set["TIME"] = daily_returns.index
    ampl.param["daily_returns"] = daily_returns
    ampl.param["mean_return"] = mean_return
    #ampl.getParameter("daily_returns").setValues(daily_returns_train.stack())
    #ampl.getParameter("mean_return").setValues(mean_return_train)
    ampl.param["w_lb"] = 0
    ampl.param["w_ub"] = 0.2
    ampl.param["R"] = 0.001
    ampl.option["solver"] = SOLVER
    ampl.solve()
    #ampl.var["w"].to_pandas()
    #ampl.get_data("w").to_pandas().plot.barh()
    #ampl.get_data["w"].to_pandas()
    weights_df = ampl.var["w"].to_pandas()
   # all_weights.append(weights_df)
    R_min=mean_return.dot(weights_df)
    G_min=ampl.get_value('sum{t in TIME}(u[t] + v[t]) / card(TIME)')
    #max
    maxi = AMPL()
    maxi.read("mad_portfolio_risk_free_max.mod")

    maxi.set["ASSETS"] = list(assets.columns)
    maxi.set["TIME"] = daily_returns.index
    maxi.param["daily_returns"] = daily_returns
    maxi.param["mean_return"] = mean_return
    #ampl.getParameter("daily_returns").setValues(daily_returns_train.stack())
    #ampl.getParameter("mean_return").setValues(mean_return_train)
    maxi.param["w_lb"] = 0
    maxi.param["w_ub"] = 0.2
    maxi.param["R"] = 0.001
    maxi.option["solver"] = SOLVER
    maxi.solve()
    #ampl.var["w"].to_pandas()
    #ampl.get_data("w").to_pandas().plot.barh()
    #ampl.get_data["w"].to_pandas()
    weights_df_max = maxi.var["w"].to_pandas()
    #all_weights.append(weights_df)
    R_max=mean_return.dot(weights_df_max)
    G_max=maxi.get_value('sum{t in TIME}(u[t] + v[t]) / card(TIME)')
    

    #daily_returns_test = test_assets.pct_change().dropna()
    #mean_return_test = daily_returns_test.mean()
    m = AMPL()
    m.read("mad_portfolio_risk_adjusted.mod")

    m.set["ASSETS"] = list(assets.columns)
    m.set["TIME"] = daily_returns.index
    m.param["daily_returns"] = daily_returns
    m.param["mean_return"] = mean_return
    #ampl.getParameter("daily_returns").setValues(daily_returns_train.stack())
    #ampl.getParameter("mean_return").setValues(mean_return_train)
    m.param["R_min"] = R_min
    m.param["R_max"] = R_max
    m.param["G_min"] = G_min
    m.param["G_max"] = G_max
    m.param["risk_aversion"] = ml(assets)
    m.param["w_lb"] = 0
    m.param["w_ub"] = 0.2
    m.param["R"] = 0.001
    m.option["solver"] = SOLVER
    m.solve()
    #ampl.var["w"].to_pandas()
    #ampl.get_data("w").to_pandas().plot.barh()
    #ampl.get_data["w"].to_pandas()
    weights_df_final = m.var["w"].to_pandas()

```

my m AMPL model is:  
param R default 0;  
param rf default 0;  
param w\_lb default 0;  
param w\_ub default 1;

set ASSETS;  
set TIME;

param daily\_returns{TIME, ASSETS};  
param mean\_return{ASSETS};  
param R\_min{ASSETS};  
param R\_max{ASSETS};  
param G\_min{TIME};  
param G\_max{TIME};  
param risk\_aversion{TIME};

var w{ASSETS};  
var u{TIME} \>= 0;  
var v{TIME} \>= 0;

maximize MAD:risk\_aversion[t in Time]_(sum{j in ASSETS}(mean\_return[j]-R\_min[j])/(R\_min[j]-R\_max[j]))-(1-risk\_aversion[t in TIME])_(((sum{t in TIME}(u[t] + v[t]) / card(TIME))-G\_min[t])/(G\_max[t]-G\_min[t]));

s.t. portfolio\_returns {t in TIME}:  
u[t] - v[t] == sum{j in ASSETS}(w[j] \* (daily\_returns[t, j] - mean\_return[j]));

s.t. sum\_of\_weights: sum{j in ASSETS} w[j] \<= 1;

s.t. mean\_portfolio\_return: sum{j in ASSETS}(w[j] \* (mean\_return[j] - rf)) \>= R - rf;

s.t. no\_short {j in ASSETS}: w[j] \>= w\_lb;

s.t. diversify {j in ASSETS}: w[j] \<= w\_ub;  
Warning:  
mad\_portfolio\_risk\_adjusted.mod  
line 22 offset 380  
t is not defined  
context: maximize MAD:risk\_aversion[t \>\>\> in \<\<\< Time]_(sum{j in ASSETS}(mean\_return[j]-R\_min[j])/(R\_min[j]-R\_max[j]))-(1-risk\_aversion[t in TIME])_(((sum{t in TIME}(u[t] + v[t]) / card(TIME))-G\_min[t])/(G\_max[t]-G\_min[t]));

---

<div class="post-metadata">

**Author:** ![Firdevs\_Uykun](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.ampl.com/firdevs_uykun/32/528_2.png) [@Firdevs\_Uykun](https://discuss.ampl.com/u/Firdevs_Uykun)\
**Post date:** [January 3, 2024, 8:52pm UTC](https://discuss.ampl.com/t/mad-portfolio-optimization/880/4 "2024-01-03T20:52:05Z")

</div>

In the final part of the MAD in python AMPL book,for loop iterates to two model,  
for color, m in zip([“ro”, “go”], [mad\_portfolio(assets), mad\_portfolio\_cash(assets)]):  
for R in np.linspace(0, mean\_return.max(), 20):  
m.param[“R”] = R  
m.option[“solver”] = SOLVER  
m.solve()  
mad\_portfolio\_weights = m.var[“w”].to\_pandas()  
portfolio\_returns = daily\_returns.dot(mad\_portfolio\_weights)  
portfolio\_mean\_return = portfolio\_returns.mean()  
portfolio\_mean\_absolute\_deviation = abs(  
portfolio\_returns - portfolio\_mean\_return  
).mean()  
ax.plot(portfolio\_mean\_absolute\_deviation, portfolio\_mean\_return, color, ms=10)  
I don t understand,I want to use one model?How?
