master
SeanChenTaipei 2 years ago
parent a730fb7bca
commit fb92301a48
  1. 51
      main.py
  2. 89
      templates/base.html
  3. 2
      templates/result.html
  4. 32
      templates/result_view.html

@ -219,8 +219,8 @@ def submit_stock_list():
if login_required():
pass
else:
print('NOT LOGIN!!')
return redirect(url_for('index'))
flash('使用投組功能請先登入。', 'warning')
return redirect(url_for('login'))
if not 'tw' in session:
return redirect(url_for('index'))
# Update Session
@ -244,21 +244,6 @@ def submit_stock_list():
fig = port.plot(title='資產價格走勢', labels=dict(index="Date", value="Price", variable="Assets"))
fig['layout'] = {}
# dict(
# autosize=True,
# legend={'title': {'text': ''}, 'tracegroupgap': 0},
# title= {'text': 'Assets'},
# xaxis= {'anchor': 'y', 'domain': [0.0, 1.0], 'title': {'text': 'Date'}, 'rangeslider':{'visible':True}},
# yaxis= {'anchor': 'x', 'domain': [0.0, 1.0], 'title': {'text': 'Price'}}
# )
# fig.update_layout(
# legend=dict(yanchor="top",
# y=0.99,
# xanchor="left",
# x=0.01),
# margin=dict(l=20, r=5, t=40, b=40),
# paper_bgcolor="LightSteelBlue")
print(type(stock_list))
# 序列化
@ -273,16 +258,15 @@ def submit_stock_list():
@app.route('/postPort', methods=['POST'])
def buildPort():
# Login Required
if login_required():
pass
else:
print('NOT LOGIN!!')
return redirect(url_for('index'))
flash('使用投組功能請先登入。', 'warning')
return redirect(url_for('login'))
if not 'tw' in session:
return redirect(url_for('index'))
# Stop frequently building strategy
if time.time() - session['lastCreateTime'] < 60:
if time.time() - session['lastCreateTime'] < 10:
print("UNTIL: ", time.time()-session['lastCreateTime'])
return '''<span>投資組合建立時間間隔(或與登入時間間隔)必須大於60秒!</span>'''
print('last_creation', time.time() - session['lastCreateTime'])
@ -350,13 +334,14 @@ def buildPort():
test_info['beta'], test_info['alpha'], test_info['var10'], test_info['R2'], True, comment, stock_list, list(sol))
sql='insert into strategy \
(date, name, username, competition, role, ratio, annual_ret, vol, mdd, annual_sr, beta, alpha, var10, R2, tw, comment, assets, assets_position)\
values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);'
values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) RETURNING id;'
with conn:
with conn.cursor() as curs:
curs.execute(sql, data)
strategy_id = curs.fetchone()[0]
conn.close()
print("\n------Write in Success--------\n")
return '''<span>投資組合已完成建立,請至 <a class="badge rounded-pill text-bg-primary" href="/result">#TODO:insert link</a> 查詢分析結果。</span>'''
return f'''<span>投資組合已完成建立,請至 <a class="badge rounded-pill text-bg-primary" href="/result_view?strategy_id={strategy_id}"><span class="badge bg-success">{strategy_id}</span></a>查詢分析結果。</span>'''
@ -388,14 +373,18 @@ def result():
conn.close()
return render_template('result.html', strategy_data=data)
# @app.route('/result_tw')
# def result_tw():
# if login_required():
# pass
# else:
# flash('使用投組功能請先登入。', 'warning')
# return redirect(url_for('login'))
# return render_template('result_tw.html')
@app.route('/result_view')
def result_view():
if login_required():
pass
else:
flash('使用投組功能請先登入。', 'warning')
return redirect(url_for('login'))
if not 'strategy_id' in request.args:
return redirect(url_for('index'))
strategy_id = request.args.get('strategy_id')
print(strategy_id)
return render_template('result_view.html')
# handle login failed
# @app.errorhandler(401)

@ -188,44 +188,64 @@
如果兩個資產之間存在高度正相關,則它們的價格通常會同時上漲或下跌。
相反,如果它們之間存在高度負相關,則它們的價格通常會發生相反的變化。
因此,分散投資應選擇具有低相關性的資產,以實現風險的分散。
現代投資組合理論(Modern Portfolio Theory, MPT)由哈利·馬科維茨(Harry Markowitz)
於1952年首次提出的,他認為投資者應該根據風險和回報的平衡來選擇投資組合。他提出了“有效前緣”(Efficient Frontier)的概念,
</p>
<p>
Efficient Frontier的建立基於資產收益率和風險的統計分析和優化理論。資產收益率可以通過歷史數據進行計算,而風險則通常使用標準差、協方差等統計指標進行衡量。
假設有n個資產,它們的收益率分別為 $R_1, R_2, ..., R_n$,協方差矩陣為 $\Sigma$。假設現有一個投資組合,其中各資產的權重分別為 $w_1, w_2, ..., w_n$,則該投資組合的收益率為:
</p>
<span style="font-size: 2.5vmin;">
$$R_p = w_1 R_1 + w_2 R_2 + ... + w_n R_n = w^T R$$
</span>
<p>
該投資組合的方差為:
$$\begin{align}\sigma^2_p &= w_1^2 \sigma_1^2 + w_2^2 \sigma_2^2 + ... \\&+ w_n^2 \sigma_n^2 + 2w_1w_2\sigma_{1,2} + 2w_1w_3\sigma_{1,3} + ... \\&+ 2w_{n-1}w_n\sigma_{n-1,n} = w^TRw\end{align}$$
</p>
<span style="font-size: 2.5vmin;">
$$\begin{align}\sigma^2_p
&= w_1^2 \sigma_1^2 + w_2^2 \sigma_2^2 + ...
\\&+ w_n^2 \sigma_n^2 + 2w_1w_2\sigma_{1,2} +
2w_1w_3\sigma_{1,3} + ... \\&+ 2w_{n-1}w_n\sigma_{n-1,n} = w^T\Sigma w\end{align}$$
</span>
<p>
其中,$\sigma_i$ 表示第 i 個資產的標準差,$\sigma_{i,j}$ 表示第 i 和第 j 個資產的協方差。
為了尋找最優投資組合,我們可以使用均值-方差優化方法。該方法的核心思想是通過最小化投資組合的方差,來最大化其收益率。假設有一個投資者的風險偏好係數為 $\gamma$,則該投資者所選擇的最優投資組合為:
</p>
<span style="font-size: 2.5vmin;">
$$\text{min}\ \frac{1}{2}w^T \Sigma w - \gamma w^T R$$
$$\text{s.t.}\ \sum_{i=1}^n w_i = 1, w_i \geq 0$$
</span>
<p>
其中,$w$ 是資產權重向量,$\Sigma$ 是協方差矩陣,$R$ 是收益率向量。目標函數是投資組合方差的一半減去風險偏好係數乘以投資組合收益率,約束條件是權重向量的元素之和為1且每個權重都不小於0。
通過調整風險偏好係數 $\gamma$
,可以獲得不同風險水平下的最優投資組合,這些投資組合形成了有效邊界(Efficient Frontier),即在一定風險水平下,可以實現最大化收益的投資組合集合。
在實際應用中,通常使用投資組合的夏普比率(Sharpe Ratio)作為評估指標。夏普比率可以看作是投資組合每單位風險所帶來的超額收益,其計算公式為:
$$\text{Sharpe Ratio} = \frac{R_p - R_f}{\sigma_p}$$
其中,$R_p$ 是投資組合的預期收益率,$R_f$ 是無風險利率,$\sigma_p$ 是投資組合的標準差。
Efficient Frontier的建立是現代投資組合理論的基石之一。通過將不同資產的收益率和風險納入考慮,投資者可以通過構建有效邊界,實現在不同風險水平下的最優資產配置。這為投資者提供了一個更有效的投資方案,可以實現更穩定的收益和更低的風險水平。</p>
</p>
<div class='d-flex justify-content-center'>
<div class="rounded mx-auto d-block" style="height: 80%; width: 80%;">
<img src="{{ url_for('static', filename='img/frontier.jpg') }}" class="img-fluid" alt="frontier-example">
</div>
</div>
<p>
在實際應用中,通常使用投資組合的夏普比率(Sharpe Ratio)作為評估指標。夏普比率可以看作是投資組合每單位風險所帶來的超額收益,其計算公式為:
</p>
<span style="font-size: 2.5vmin;">
$$\text{Sharpe Ratio} = \frac{R_p - R_f}{\sigma_p}$$
</span>
<p>
其中,$R_p$ 是投資組合的預期收益率,$R_f$ 是無風險利率,$\sigma_p$ 是投資組合的標準差。
Efficient Frontier的建立是現代投資組合理論的基石之一。通過將不同資產的收益率和風險納入考慮,
投資者可以通過構建有效邊界,實現在不同風險水平下的最優資產配置。
這為投資者提供了一個更有效的投資方案,可以實現更穩定的收益和更低的風險水平。
</p>
<p class="p-0">
@ -238,7 +258,7 @@
固定預期報酬 $p$,令投資組合權重為 $w$, 則將波動率最小化的數學問題為:
</div>
<div class="card-body">
<p class="card-text" style="font-size: 1.8vmin;">
<p class="card-text" style="font-size: 2.5vmin;">
$$\begin{equation}
\begin{aligned}
\min_{w} \quad &\frac{1}{2}w^{T}\Sigma w\quad\\
@ -257,7 +277,7 @@
令投資組合權重為 $w$, 則將夏普率最大化的數學問題為:
</div>
<div class="card-body">
<p class="card-text" style="font-size: 1.8vmin;">
<p class="card-text" style="font-size: 2.5vmin;">
$$\begin{equation}
\begin{aligned}
\min_{w} \quad &\frac{w^T R}{\sqrt{w^{T}\Sigma w}}\quad\\
@ -271,20 +291,29 @@
</div>
</div>
</div>
<h2 class="text-xl font-bold mb-2 mt-4">投資組合的$\alpha$、$\beta$值簡介</h2>
<h2 class="text-xl font-bold mb-2 mt-4">投資組合的$\alpha$、$\beta$值</h2>
<hr class="mt-1 mb-3">
<p class="my-1">
投資組合報酬率的Alpha和Beta是投資組合評估中常用的指標。
Alpha代表投資組合的超額收益,Beta則代表投資組合與市場的相關性。
Beta值是衡量資產相對於整個市場的波動性的指標。Beta值的公式如下:
</p>
<span style="font-size: 2.5vmin;">
$$\beta_i = \frac{\text{Cov}(r_i,r_m)}{\text{Var}(r_m)}$$
</span>
<p>
其中,$r_i$表示資產i的收益率,$r_m$表示市場收益率,
$Cov(r_i,r_m)$表示資產i的收益率和市場收益率之間的協方差,
$Var(r_m)$表示市場收益率的方差。Beta值越高,表示資產的波動性越大,
其收益率與市場收益率之間的關聯度也越高。
Beta值可以用來評估投資組合的風險程度,投資者可以通過控制投資組合中資產的Beta值來實現風險管理。
Beta值可以與CAPM(Capital Asset Pricing Model)和線性回歸相關聯。在CAPM中,假設資產的預期收益率可以通過以下公式計算:
</p>
<span style="font-size: 2.5vmin;">
$$E(r_i) = r_f + \beta_i(E(r_m) - r_f)$$
</span>
<p>
其中,$E(r_i)$表示資產i的預期收益率,$r_f$表示無風險收益率,$E(r_m)$表示市場的預期收益率,
$\beta_i$表示資產i的Beta值。該公式表示,資產的預期收益率是無風險收益率和市場風險溢價的加權平均值,
其中市場風險溢價的大小與市場風險的大小成正比,且與資產的Beta值相關。
@ -293,12 +322,18 @@
Alpha 值是指投資組合的實際收益率與其根據 Beta 值預期的收益率之間的差異。如果投資組合的實際收益率高於其根據 Beta 值所預期的收益率,則 Alpha 值為正;反之,如果投資組合的實際收益率低於其預期收益率,則 Alpha 值為負。
Alpha 值可以通過線性回歸分析來計算。假設投資組合的收益率可以表示為以下公式:
</p>
<span style="font-size: 2.5vmin;">
$$r_p = \alpha + \beta_p (r_m-f_f) + \epsilon$$
</span>
<p>
其中,$r_p$ 表示投資組合的收益率,$\alpha$ 表示 Alpha 值,$\beta_p$ 表示投資組合的 Beta 值,$r_m$ 表示市場收益率,$\epsilon$ 表示誤差項。如果我們將上述公式進行線性回歸,可以得到:
</p>
<span style="font-size: 2.5vmin;">
$$\hat{r_p} = \hat{\alpha} + \hat{\beta_p} (r_m-r_f)$$
</span>
<p>
其中,$\hat{r_p}$ 表示預測的投資組合收益率,$\hat{\alpha}$ 表示預測的 Alpha 值,$\hat{\beta_p}$ 表示預測的 Beta 值。如果實際收益率高於預測收益率,則 $\hat{\alpha}$ 為正;反之,如果實際收益率低於預測收益率,則 $\hat{\alpha}$ 為負。
</p>
@ -308,17 +343,23 @@
VaR (Value at Risk) 是用來衡量投資組合或資產在一定時間內可能面臨的最大潛在損失的一種風險管理指標。VaR 通常用機率的形式表達,表示在一定信心水平下,資產或投資組合在未來一定時間內的最大可能損失額。
假設 $X$ 是一個隨機變量,表示資產或投資組合在未來一定時間內的損失額,$p$ 表示所選取的信心水平,VaR 可以表示為:
</p>
<span style="font-size: 2.5vmin;">
$$\text{VaR}_p(X) = - \inf \{ x \in \mathbb{R} : F_X(x) \geq p \}$$
</span>
<p>
其中,$F_X(x)$ 是 $X$ 的累積分布函數。這個公式的意思是,我們尋找一個最小的數值 $x$,使得資產或投資組合在未來一定時間內的損失額大於 $x$ 的機率不超過 $1-p$。這個最小的數值就是 VaR,通常表示為負數,因為它是損失額。
例如,假設我們選取信心水平 $p=0.95$,並且假設資產或投資組合在未來一周內的報酬率的分布是正態分布 $N(\mu,\sigma^2)$,那麼根據上述公式,VaR 的值為:
</p>
<span style="font-size: 2.5vmin;">
$$\begin{align}\text{VaR}_{0.95}(X) &= -\inf\{ x \in \mathbb{R} : F_X(x) \leq 0.05 \} \\
&= -\inf \{x \in \mathbb{R} : \mathbb{P}(z\leq\frac{x-\mu}{\sigma}) \leq 0.05) \} \\
&= -\inf \{x \in \mathbb{R} : \Phi (\frac{x-\mu}{\sigma}) \leq 0.05 \} \\
&= -(\mu - 1.645\times\sigma)\end{align}$$
</span>
<p>
其中,$\Phi(x)$ 是標準常態分布的累積分布函數。
需要注意的是,VaR 是一個單一數字,只反映了資產或投資組合在一定時間內的最大可能損失額,

@ -74,7 +74,7 @@
<thead style="font-size: 1vmin'">
<tr>
<th scope="col" role="alert">
<a href="" class="alert-link">
<a href="{{ url_for('result_view', strategy_id=info[0]) }}" class="alert-link">
<span class="badge rounded-pill text-bg-warning">{{ info[0] }}</span>
</a>
</th>

@ -0,0 +1,32 @@
{% extends 'base.html' %}
{% block title %}Result View{% endblock %}
{% block style %}
.card-body {
<!-- background-image: linear-gradient(rgba(255,255,255,0.5), rgba(255,255,255,0.5)), url({{ url_for('static', filename='img/cat.png') }});
background-attachment: fixed-bottom;
background-position: right bottom -10px;
background-repeat: no-repeat; -->
<!-- background-size: 40%; -->
}
{% endblock %}
{% block content %}
<div class="container-fluid" style="background-color: #eee;min-height:100%;position:relative;">
<div class="container-fluid py-4">
<div class="row d-flex justify-content-center align-items-center h-100">
<div class="col-lg-12 col-xl-11">
<div class="card text-black mt-3" style="border-radius: 25px;">
<div class="card-body p-md-5" style="border-radius: 25px;">
<div class="row justify-content-center">
yeah
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Loading…
Cancel
Save