SeanChenTaipei 2 years ago
commit b5582fef3b
  1. 51
      main.py
  2. 1044
      static/img/Strategy Page.html
  3. 9
      static/img/Strategy Page_files/all.min.css
  4. 2018
      static/img/Strategy Page_files/bootstrap-icons.css
  5. 7
      static/img/Strategy Page_files/bootstrap.bundle.min.js
  6. 6
      static/img/Strategy Page_files/bootstrap.min.css
  7. 4
      static/img/Strategy Page_files/font-awesome.min.css
  8. 10881
      static/img/Strategy Page_files/jquery-3.6.0.js
  9. 1
      static/img/Strategy Page_files/tailwind.min.css
  10. 30
      static/js/addStock.js
  11. 236
      templates/base.html
  12. 4
      templates/login.html
  13. 5
      templates/result.html
  14. 32
      templates/result_view.html
  15. 334
      templates/strategy_tw.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
@ -243,20 +243,7 @@ def submit_stock_list():
conn.close()
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 in portfolio'},
xaxis= {'anchor': 'y', 'domain': [0.0, 1.0], 'title': {'text': '日期'}},
yaxis= {'anchor': 'x', 'domain': [0.0, 1.0], 'title': {'text': '價格'}}
)
fig.update_layout(legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
))
fig['layout'] = {}
print(type(stock_list))
# 序列化
@ -271,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'])
@ -348,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>'''
@ -386,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)

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -1,5 +1,18 @@
// Initialize empty stock list
let stockList = ['2330.TW'];
let currentList = [];
const layout={'autosize': true, 'title': {'text': 'Assets'},
'xaxis': {'anchor': 'y', 'domain': [0.0, 1.0],
'rangeslider': {'visible': true},
'rangeselector':{'rangeselector':
{'buttons': [
{'count': 1, 'label': '1m', 'step': 'month', 'stepmode': 'backward'},
{'count': 6, 'label': '6m', 'step': 'month', 'stepmode': 'backward'},
{'count': 1, 'label': 'YTD', 'step': 'year', 'stepmode': 'todate'},
{'count': 1, 'label': '1y', 'step': 'year', 'stepmode': 'backward'}, {'step': 'all'}]}, 'rangeslider': {'visible': true},'type': 'date'}},
'yaxis': {'anchor': 'x', 'domain': [0.0, 0.9]},
'legend': {'yanchor': 'top', 'y': 1.8, 'xanchor': 'left', 'x': 0.01}, 'margin': {'l': 25, 'r': 5, 't': 10, 'b': 5},
}
// Cache frequently-used DOM elements
const $stockForm = $('#stock-form');
// const $stockSelect = $('#stock-select');
@ -58,7 +71,6 @@ $addStockBtn.click(function(event) {
var text = $('input[name=assetSelect]').val();
// const selectedStock = text;
// var text = $('#stock-select option:selected').text();
console.log(text)
if (text != null && text!= '' && stockList.indexOf(text)===-1) {
// Add new item to list
@ -125,9 +137,15 @@ $submitBtn.click(function(event) {
// console.log(event.target)
// console.log(stockList)
// console.log(cacheList.value, stockList);
if (stockList.length > 0) {
var texts = [];
$('#stock-list span').each(function(){
texts.push($(this).text());
});
// alert(currentList.includes(texts));
if (stockList.length > 0 && JSON.stringify(currentList)!==JSON.stringify(stockList)) {
// cacheList = stockList;
$('#graph').html('<div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div>')
$.ajax({
url: '/postStock', //todo create_strategy
method: 'POST',
@ -135,10 +153,12 @@ $submitBtn.click(function(event) {
success: function(response) {
$('#graph').html('')
var graphs = JSON.parse(response);
console.log(graphs.data);
Plotly.newPlot("graph",
graphs.data, graphs.layout, {responsive: true});
console.log(response.layout);
graphs.data, layout, {responsive: true});
// console.log(response.layout);
currentList = stockList.map(obj => obj);
},
error: function(xhr) {
$('#graph').html('<div><span class="badge bg-warning">錯誤</span></div>')

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="zh-Hant-TW">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
@ -23,9 +23,9 @@
{% endblock %}
<style>
body {
padding-top: 60px;
// padding-top: 60px;
padding-bottom: 10px;
font-family: Georgia, sans-serif !important;
font-family: Georgia, Arial, Geneva, Helvetica, serif !important;
background-color: #eee;
height:100vh;
}
@ -45,6 +45,9 @@
height: 60px;
background-color: #f5f5f5;
}
.navbar-fixed-top {
top:20px;
}
{% block style %}
p {
text-indent: 2em;
@ -57,15 +60,15 @@
{% set navigation_bar = [
('/', 'index', '首頁', 'bi bi-house-fill'),
('/strategy', 'strategy', '建立策略', 'bi bi-piggy-bank-fill'),
('/strategy_tw', 'strategy_tw', '台股建立策略', 'bi bi-piggy-bank-fill'),
('/strategy', 'strategy', '建立策略', 'fa-solid fa-chart-pie'),
('/strategy_tw', 'strategy_tw', '台股建立策略', 'fa-solid fa-chart-pie'),
('/custom', 'custom', '自訂數據建立策略', 'bi bi-database-fill-add'),
('/result', 'result', '分析結果排行', 'bi bi-graph-up-arrow'),
('/result', 'result', '分析結果排行', 'fa-solid fa-chart-simple'),
('mailto:r10246002@ntu.edu.tw', 'error', '錯誤回報', 'bi bi-bug-fill')
] -%}
{% set active_page = active_page|default('index') -%}
<nav class="navbar bg-light fixed-top">
<div class="container-fluid px-3 py-2">
<nav class="navbar bg-light">
<div class="container-fluid p-2">
<a class="navbar-brand mx-2" href="{{ url_for('index') }}">
<h3><strong></i>投資組合大擂台</strong></h3>
</a>
@ -93,10 +96,27 @@
</a>
</li>
</ul>
</li>
</li>
{% endif %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle btn btn-lg" href="" role="button" data-bs-toggle="dropdown" aria-expanded="true">
<i class="fa-solid fa-globe"></i>
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<div id="google_translate_element"></div>
</li>
</ul>
</li>
</ul>
</div>
<button
class="navbar-toggler"
type="button"
@ -145,10 +165,14 @@
</header>
<body>
{% block content %}
<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
<div class="container-lg mx-auto my-2 p-4 bg-white shadow-lg" style="border-radius: 5px;">
<!-- <h1 class="text-4xl font-bold mb-4">Document Title - {{ active_page|e }} </h1> -->
<div class="alert alert-secondary" role="alert">
<ul>
<li><i class="bi bi-caret-right-fill"></i> 本網站讓使用者可以自建投資組合,回測其績效,並與其他使用者比較、討論並改進。</li>
<li><i class="bi bi-caret-right-fill"></i> 使用單位:清華大學、台灣大學、政治大學、明新科大、中華大學、臺北大學、證基會、成功大學。</li>
</ul>
@ -156,39 +180,76 @@
<div class="prose lg:prose-xl p-3">
<h2 class="text-xl font-bold mb-4">平台簡介</h2>
<hr class="mt-0 mb-2">
<p class="font-bold">
「不要把所有的雞蛋放在一個籃子裡。」
</p>
<p>
分散投資是一種投資策略,旨在通過將資金分散投資在不同的資產類別中,從而降低投資風險。
如果兩個資產之間存在高度正相關,則它們的價格通常會同時上漲或下跌。
相反,如果它們之間存在高度負相關,則它們的價格通常會發生相反的變化。
因此,分散投資應選擇具有低相關性的資產,以實現風險的分散。
現代投資組合理論(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>
我們常聽到的「鷄蛋不要放在同個籃子裏」,
爲的就是要分散股市不確定性所帶來的風險。
一般來説,在風險分散的同時,收益也會跟著降低。
於是問題就變成:我們如何在風險與報酬率中取捨。
被稱爲資産配置之父的哈利·馬可維兹(Harry Max Markowitz)就提供了以下的想法。
該投資組合的方差為:
</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>
在給定各個標的(underlying)的權重後,
對該投資組合(portfolio)做均值–變異數分析(mean-variance analysis),
其中平均數爲平均報酬率,變異數爲波動率(意即「風險」)。
在這樣定義不同投資組合的報酬與風險的情况下,
我們可以發現:在不同的預期報酬下,
都可以找到一個投資組合(或權重)使波動率達到最小值。
將這些報酬與對應到的最小風險記錄下來後所形成的開口向右的二維拋物線圖形(如下圖),
就是所謂的「效率前緣(efficient frontier)」。
其中,$\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),即在一定風險水平下,可以實現最大化收益的投資組合集合。
</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">
本網站使用S&P 500、元大臺灣50以及Nasdaq 100指數的成份股的歷史日資料。
每次計算標的權重,都是取六個月的資料,依照馬可維兹的理論,
畫出效率前緣,然後取夏普值最大的權重,再用接下來三個月的資料,
觀察投資組合的價值如何變化。我們每三個月更新一次權重,
再把許多三個月區間內投資組合的價值變動拼接起來,
得到2015年中到2020年中投資組合的價值變動,
再藉此求出平均年報酬、年波動率,再把報酬除以波動率得到整個投資期間的夏普值。
另外我們還算出最大跌幅(maximum drawdown),就是投資過程中,
會從到目前為止的最高點,最多下跌多少幅度。
------
</p>
<div class="row">
<div class="col-sm-6">
@ -197,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\\
@ -216,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\\
@ -230,52 +291,83 @@
</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">
在評估投資組合的表現時,經常使用的是絕對性的指標,
例如報酬率、波動率、夏普指數,MDD等,
不過也有相對性的指標alpha、beta值。
比較投組與另一個標的(例如大盤指數,
我們可以透過回歸式,估計出作為超額報酬的alpha值,
以及作為相關性的beta值。Alpha值表示投組的獲利能力,
越高越好。Beta值代表了投組對系統性風險的曝險程度,越低越好。
投資組合報酬率的Alpha和Beta是投資組合評估中常用的指標。
Alpha代表投資組合的超額收益,Beta則代表投資組合與市場的相關性。
Beta值是衡量資產相對於整個市場的波動性的指標。Beta值的公式如下:
</p>
<p class="my-1">
根據CAPM模型,給定投組報酬 $r_{p}$, 大盤指數 $r_m$ 以及無風險利率 $r_f$ ,
$\beta$ 值可以藉由以下公式得出:
$$ \mathbb{E}[r_p] - r_f = \beta (\mathbb{E}[r_m] - r_f)$$
$\alpha$ 值則是藉由計算實際的投組報酬與由CAPM得到的理論報酬的差得到,公式為:
$$\alpha = r_p - (r_f + \beta (r_m - r_f))$$
<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值相關。
</p>
<p class="my-1">
當給定一組時間序列時,alpha、beta值可以利用線性回歸的方式得出。
我們可以將上述的式子改寫成以下的形式:
$$Y = \alpha + \beta X + \epsilon,$$ 而 $$Y = r_p-r_f , X = r_m-r_f$$
透過此回歸式,我們除了可以得到alpha、beta值外,也可以計算出值,用以衡量此模型的解釋力。
在本擂台上,不限台股的投組使用的大盤指數 ($r_m$) 是SPY,
台股的投組使用的大盤指數是0050.TW,無風險利率暫定為0。
</p>
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>
<h2 class="text-xl font-bold mb-2 mt-4">VaR 簡介</h2>
<hr class="mt-1 mb-3">
<p class="my-1">
Value at Risk(VaR)是一種風險度量方法,用於衡量某個金融投資組合在一定置信水平下的最大可能損失,
即在給定的時間段內,可能出現的最大虧損額度。VaR的置信水平通常為95%或99%,表示對於未來某個時間段,
投資組合的損失不會超過該置信水平對應的虧損額度。VaR的計算需要考慮投資組合的市場風險、信用風險和操作風險等多個因素,
並且常常使用統計方法和模型來估計。常見的VaR模型包括歷史模擬法、蒙特卡羅模擬法和參數化模型等。
以下針對資產報酬率,在常態分配的假設下,10-day 95% VaR 風險值的計算方式如下:
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>
給定資產的每日投組價值後,我們可以計算出該投組的(每日)報酬率與(每日)波動率。利用常態分配的假設,我們假設
$\mu$為$n$日報酬率(亦即(每日)報酬率 x n), $\sigma$為$n$日波動率亦即(每日)波動率
則 n-day 5% VaR 的公式為: $$-(\mu - 1.645\times\sigma)$$
其中,$F_X(x)$ 是 $X$ 的累積分布函數。這個公式的意思是,我們尋找一個最小的數值 $x$,使得資產或投資組合在未來一定時間內的損失額大於 $x$ 的機率不超過 $1-p$。這個最小的數值就是 VaR,通常表示為負數,因為它是損失額。
例如,假設我們選取信心水平 $p=0.95$,並且假設資產或投資組合在未來一周內的報酬率的分布是正態分布 $N(\mu,\sigma^2)$,那麼根據上述公式,VaR 的值為:
</p>
<p class="my-1">
其中,置信水平的標準正態分位數是指標準正態分布累積分布函數在置信水平下的分位數,
可以通過查找標準正態分布表來獲得。在這個式子中,第一項是投資組合價值乘以置信水平,
表示投資組合的預期損失;第二項是投資組合價值乘以投資組合日收益的標準差乘以置信水平的標準正態分位數,
表示在一定置信水平下,投資組合可能遭受的最大損失。因此,VaR可以用來幫助投資者評估其投資組合的風險水平,
制定合適的風險管理策略。
<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 是一個單一數字,只反映了資產或投資組合在一定時間內的最大可能損失額,
不能反映風險的分布情況。因此,在使用 VaR 進行風險管理時,
還需要結合其他風險指標和風險管理方法來進行綜合分析和決策。
</p>
<p>
</p>
</div>
</div>
@ -308,6 +400,13 @@
integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
crossorigin="anonymous"
></script>
<script type="text/javascript">
function googleTranslateElementInit() {
new google.translate.TranslateElement({pageLanguage: 'zh-TW',
layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL}, 'google_translate_element');
}
</script>
<script src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
{% block script %}
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.min.js"></script>
@ -319,6 +418,7 @@
};
</script>
{% endblock %}
</body>
</html>

@ -18,11 +18,11 @@
<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" style="border-radius: 25px;">
<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">
<div class="col-md-10 col-lg-6 col-xl-5 order-1 order-lg-1">
<p class="text-center h1 fw-bold mb-5 mx-1 mx-md-2 mt-4">登入</p>
<p class="text-center h1 fw-bold mb-2">登入</p>
<form method="post">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}

@ -59,7 +59,6 @@
</div>
<div class="p-3 table-responsive-sm table-responsive-md table-responsive-xl">
<table class="table caption-top">
<caption></caption>
<thead>
<tr>
<th scope="col">#ID</th>
@ -75,8 +74,8 @@
<thead style="font-size: 1vmin'">
<tr>
<th scope="col" role="alert">
<a href="" class="alert-link">
<span class="badge rounded-pill text-bg-info">{{ info[0] }}</span>
<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>
<td>{{ info[2] }}</td>

@ -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 %}

@ -9,200 +9,207 @@
{% block title %}Strategy Page{% endblock%}
{% block style %}
<!-- .input-group > input {
border: 2px solid #8E8E8E;
border-radius: 7px;
}
.input-group-lg > input {
border: 2px solid #8E8E8E;
border-radius: 7px;
}
.input-group-lg > select {
border: 2px solid #8E8E8E;
border-radius: 7px;
} -->
<!-- .input-group > span{
bg-dark;
font-bold;
} -->
div.input-group > * {
border-radius: 0px;
}
div.card{
border-radius: 2px;
}
.card-header {
color: #000093;
}
@keyframes cursor {
0% {
opacity: 0;
}
40% {
opacity: 0;
}
50% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0.9;
}
}
{% endblock style %}
{% block content %}
<div class="container-md">
<div class="container-md m-1">
<div class="card mb-3 p-4">
<div class="card mb-3">
<!-- <img src="{{ url_for("static", filename="img/stock.jpeg") }}" class="card-img-top" alt="..."> -->
<div class="card-body">
<h5 class="card-title text-xl font-bold">{% if session.tw == 1 %}台股{% endif %}投資組合建立指南 <i class="bi bi-arrow-down-right-circle-fill"></i></h5>
<ol class="list-group list-group-flush list-group-numbered">
<li class="list-group-item"><span class="ps-2">輸入投資組合名稱</span></li>
<li class="list-group-item"><span class="ps-2">選擇所參加的課程或競賽</span></li>
<li class="list-group-item"><span class="ps-2">選擇資產</span></li>
<li class="list-group-item"><span class="ps-2">確認資產後按下<span class="badge bg-info">確認資產</span> , 後查看資產價格動態圖表</span></li>
<li class="list-group-item"><span class="ps-2">選擇建立策略相關參數</span></li>
<li class="list-group-item"><span class="ps-2">確認後按下<span class="badge bg-danger">確認建立</span>, 後查看回傳訊息</span></li>
</ol>
</div>
<div class="container-fliud">
<div class="card p-3">
<div class="card mb-3" style="border-radius:10px;border:0.5rem outset #eee;">
<!-- <img src="{{ url_for("static", filename="img/stock.jpeg") }}" class="card-img-top" alt="..."> -->
<div class="card-body">
<h5 class="card-title text-xl font-bold accordion-header">
{% if session.tw == 1 %}台股{% endif %}投資組合建立指南 <i class="bi bi-caret-left-fill" style="animation: cursor 1s 3;"></i></h5>
<ol class="list-group list-group-flush list-group-numbered" id="collapseExample">
<li class="list-group-item"><span class="ps-2">輸入投資組合名稱</span></li>
<li class="list-group-item"><span class="ps-2">選擇所參加的課程或競賽</span></li>
<li class="list-group-item"><span class="ps-2">選擇資產後按下<span class="badge bg-secondary">加入</span></span></li>
<li class="list-group-item"><span class="ps-2">確認資產後按下<span class="badge bg-info">確認資產</span>後, 查看資產價格動態圖表</span></li>
<li class="list-group-item"><span class="ps-2">選擇建立策略相關參數</span></li>
<li class="list-group-item"><span class="ps-2">確認後按下<span class="badge bg-danger">確認建立</span>後, 查看回傳訊息</span></li>
</ol>
</div>
<div class="card">
<div class="card-header font-bold text-lg">
投資組合名稱
</div>
<div class="card-body">
<input if="imput1" name="portName" type="text" class="form-control" placeholder="EX. 問就是歐應" required>
</div>
</div>
<div class="card" id="buildName">
<div class="card-header font-bold text-lg">
投資組合名稱
</div>
<div class="card-body">
<input if="imput1" name="portName" type="text" class="form-control" placeholder="EX. 韓總 No.1" required>
</div>
<div class="card-header font-bold text-lg">
請選擇所參加的課程/競賽
</div>
<div class="card">
<div class="card-header font-bold text-lg">
請選擇所參加的課程/競賽
<div class="card-body">
<select id="competition" class="form-select" size="1">
{% include 'competitions.html' %}
</select>
</div>
</div>
<hr class="my-3">
<div class="card">
<div class="card-header d-flex">
<div class="py-2 font-bold text-lg">
已選擇的資產
</div>
<div class="card-body">
<select id="competition" class="form-select" size="1">
{% include 'competitions.html' %}
</select>
<div class="btn-group ms-auto">
<button type="button" class="btn btn-outline-primary btn-sm" id="submit-btn">
確認資產
</button>
</div>
</div>
<hr class="my-3">
<div class="card">
<div class="card-header ">
<div class="py-2 font-bold text-lg">
價格動態圖表
</div>
<div class="card-body d-flex mb-0">
<input name="assetSelect" class="form-control" list="datalistOptions" id="stockAll" placeholder="輸入資產名稱...">
<datalist id="datalistOptions">
{% if session.tw==0 %}
{% for key, data in data_us.items() -%}
<option value="{{ key|e }}">{{ key|e }} | {{ data|e }}</option>
{% endfor %}
{% endif %}
{% for key, data in data_tw.items() -%}
<option value="{{ key|e }}">{{ key|e }} | {{ data|e }} </option>
{% endfor %}
</datalist>
<button class="btn btn-secondary btn-sm"
type="button"
id="addStockBtn">
加入
</button>
</div>
<div>
<ol class="list-group list-group-numbered px-3 pb-3" id="stock-list" type="1">
<li class="list-group-item">
<span class="px-2">2330.TW</span>
<a class="btn btn-sm btn-danger float-right delete-btn">
<i class="fas fa-trash-alt"></i>
</a>
</li>
</ol>
</div>
<div class="card-header d-flex">
<div class="py-2 font-bold text-lg">
價格動態圖表
</div>
<div class="card-body">
<div id="graph">
<span>
按下
<button type="button" class="btn btn-outline-primary btn-sm" disabled>確認資產</button>
後,圖表將在此渲染。
</span>
</div>
</div>
<div class="card-body">
<div id="graph" style="max-height:50vh">
<span>
按下
<button type="button" class="btn btn-outline-primary btn-sm" disabled>確認資產</button>
後,圖表將在此渲染。
</span>
</div>
</div>
<div class="card">
<div class="card-header d-flex">
<div class="py-2 font-bold text-lg-center">
已選擇的資產
</div>
<div class="btn-group ms-auto">
<button type="button" class="btn btn-outline-primary btn-sm" id="submit-btn">
確認資產
</button>
<button type="button" class="btn btn-outline-danger btn-sm" id="submit-port">
確認建立
</button>
</div>
</div>
<hr>
<div class="card mt-3">
<div class="d-flex p-2">
<div class="p-2 font-bold text-lg">
策略參數選擇
</div>
<div class="card-body d-flex mb-0">
<input name="assetSelect" class="form-control" list="datalistOptions" id="stockAll" placeholder="輸入資產名稱...">
<datalist id="datalistOptions">
{% if session.tw==0 %}
{% for key, data in data_us.items() -%}
<option value="{{ key|e }}">{{ key|e }} | {{ data|e }}</option>
{% endfor %}
{% endif %}
{% for key, data in data_tw.items() -%}
<option value="{{ key|e }}">{{ key|e }} | {{ data|e }} </option>
{% endfor %}
</datalist>
<button class="btn btn-secondary"
type="button btn-lg"
id="addStockBtn">
加入
<div class="btn-group ms-auto">
<button type="button" class="btn btn-outline-danger btn-sm" id="submit-port">
確認建立
</button>
</div>
<hr class="mb-3">
<div>
<ol class="list-group list-group-numbered px-3 pb-3" id="stock-list" type="1">
<li class="list-group-item">
<span class="px-2">2330.TW | 台積電</span>
<a class="btn btn-sm btn-danger float-right delete-btn">
<i class="fas fa-trash-alt"></i>
</a>
</li>
</ol>
</div>
<div class="input-group">
<span class="input-group-text bg-info">訓練 / 回測數據比</span>
<select id="ratio-select" class="form-select">
<option value="0.5">5:5</option>
<option value="0.6">6:4</option>
<option selected value="0.7">7:3</option>
<option value="0.8">8:2</option>
<option value="0.9">9:1</option>
</select>
</div>
<div class="input-group">
<span class="input-group-text bg-info">最佳化目標函數</span>
<select id="role-select" class="form-select">
<option selected value="max_sharpe">最大化夏普比率</option>
<option value="max_sortino">最大化索提諾比率</option>
<option value="min_volatility">最小化波動率</option>
</select>
</div>
</div>
<div class="modal" id="portModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title font-bold text-xl">確認建立投資組合</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<hr>
<div>
<div class="d-flex p-2 mt-2 font-bold text-lg">策略參數選擇</div>
<div class="input-group">
<span class="input-group-text bg-info">訓練 / 回測數據比</span>
<select id="ratio-select" class="form-select">
<option value="0.5">5:5</option>
<option value="0.6">6:4</option>
<option selected value="0.7">7:3</option>
<option value="0.8">8:2</option>
<option value="0.9">9:1</option>
</select>
</div>
<div class="input-group">
<span class="input-group-text bg-info">最佳化目標函數</span>
<select id="role-select" class="form-select">
<option selected value="max_sharpe">最大化夏普比率</option>
<option value="max_sortino">最大化索提諾比率</option>
<option value="min_volatility">最小化波動率</option>
</select>
<div class="modal-body">
<span>
確認後將會暫時關閉建立按鈕,請等待完成訊息!
</span>
<div class="input-group mt-3">
<span class="input-group-text">輸入筆記</span>
<textarea id="commentPort" class="form-control" aria-label="With textarea"></textarea>
</div>
</div>
</div>
<div class="modal" id="portModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title font-bold text-xl">確認建立投資組合</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<span>
確認後將會暫時關閉建立按鈕,請等待完成訊息!
</span>
<div class="input-group">
<span class="input-group-text">輸入筆記</span>
<textarea id="commentPort" class="form-control" aria-label="With textarea"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button id="sendPort" type="button" class="btn btn-primary" data-bs-dismiss="modal">確認</button>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button id="sendPort" type="button" class="btn btn-primary" data-bs-dismiss="modal">確認</button>
</div>
</div>
</div>
</div>
<div class="modal" id="confirmModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 id='modalTitle' class="modal-title font-bold text-xl">投資組合建立訊息</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<span id="confirmMes">
<div id="sucMes">
<span>投資組合已開始建立,請1分鐘後至結果分析查詢。</span>
</div>
</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">確認</button>
</div>
</div>
<div class="modal" id="confirmModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 id='modalTitle' class="modal-title font-bold text-xl">投資組合建立訊息</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<span id="confirmMes">
<div id="sucMes">
<span>投資組合已開始建立,請1分鐘後至結果分析查詢。</span>
</div>
</span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">確認</button>
</div>
</div>
</div>
</div>
</div>
@ -212,5 +219,6 @@ div.card{
{% block script %}
<script src="{{ url_for('static', filename='js/addStock.js') }}"></script>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
{% endblock script %}

Loading…
Cancel
Save