程式碼
import csv #輸入import輸出export,輸入csv套件
import math #輸入math套件
from tkinter import * #或者import tkinter as tk
scale = 2000 # 放大倍率
base = 600 # 圖形中心高度
def transposeMatrix(m): #自訂轉置transpose函數
N = []
for j in range(len(m[0])):
row = []
for i in range(len(m)):
row.append(m[i][j])
N.append(row)
return N
def getMatrixMinor(m,i,j):
return [row[:j] + row[j+1:] for row in (m[:i]+m[i+1:])]
def getMatrixDeternminant(m):
#base case for 2x2 matrix
if len(m) == 2:
return m[0][0]*m[1][1]-m[0][1]*m[1][0]
determinant = 0
for c in range(len(m)):
determinant += ((-1)**c)*m[0][c]*getMatrixDeternminant(getMatrixMinor(m,0,c))
return determinant
def getMatrixInverse(m):
determinant = getMatrixDeternminant(m)
if len(m) == 2: #處理2x2方陣
return [[m[1][1]/determinant, -1*m[0][1]/determinant],
[-1*m[1][0]/determinant, m[0][0]/determinant]]
cofactors = []
for r in range(len(m)):
cofactorRow = []
for c in range(len(m)):
minor = getMatrixMinor(m,r,c)
cofactorRow.append(((-1)**(r+c))*getMatrixDeternminant(minor))
cofactors.append(cofactorRow)
cofactors = transposeMatrix(cofactors)
for r in range(len(cofactors)):
for c in range(len(cofactors)):
cofactors[r][c] = cofactors[r][c]/determinant
return cofactors
def draw_circle(x, y, label):
canvas.create_oval(100+x-5, base-y-5, 100+x+5, base-y+5, fill="black")
canvas.create_text(100+x+20, base-y, text=label, anchor='w', font=('微軟正黑體',20))
file = open('C:/Users/user/Downloads/20260521.csv','r',encoding='utf-8')
read = csv.reader(file)
header, rows = [], []
header = next(read)
for item in read:
rows.append(item)
file.close()
num = len(rows) #資料表長度,以下2603,2606,2609,2615,2637,00960,0050
mean, meanTemp= [0,0,0,0,0,0,0], [0,0,0,0,0,0,0]
vari = [[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],
[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]]
for k in range(num):
for i in range(7):
meanTemp[i]=float(rows[k][i+1])/100 #轉換為小數
mean[i] += meanTemp[i]
for j in range(i+1):
vari[i][j] += meanTemp[i]*meanTemp[j]
for i in range(7):
mean[i] = mean[i]/num
for j in range(i+1):
vari[i][j]=(vari[i][j] - mean[i]*mean[j]*num)/(num-1)
for i in range(7):
for j in range(i+1,7):
vari[i][j]=vari[j][i]
tk = Tk() #建構視窗名為tk
tk.geometry('1200x900')#視窗 寬1200像素
tk.title("蕭瑜分析航運股票日報酬")#第71與112列寫上自己的名字然後截圖
canvas = Canvas(tk, width=1200, height=900, bg='white')
canvas.grid(row=0,column=0,padx=5,pady=5,columnspan=3)
canvas.create_line(100, base, 1100, base, arrow=LAST,width=3)
for i in range(1,8): #X軸 0 3 6 9 12 15 18
canvas.create_text(100+i*120, base, text = i*3, anchor='n', font=('微軟正黑體',20))
canvas.create_line(100, 800, 100, 50, arrow=LAST,width=3)
for i in range(-3,7): #Y軸 -4 -3 -2 -1 0 1 2 3 4
canvas.create_text(94, base-i*80, text = i, anchor='e', font=('微軟正黑體',20))
canvas.create_text(1100, base+5, text = '標準差', anchor='n', font=('微軟正黑體',20))
canvas.create_text(95, 50, text = '報酬率', anchor='e', font=('微軟正黑體',20))
for i in range(7):
x = math.sqrt(vari[i][i]*250)*scale
y = 250*mean[i]*scale
draw_circle(x, y, header[i+1] )
print(header[i+1], f"{x/scale:.4f}", f"{y/scale:.4f}")
OmegaInverse = getMatrixInverse(vari[:5][:5])
#----------------2026/03/04增加計算GMV(GMV=Σ⁻¹ × 1/1' Σ⁻¹ 1) OmegaInverse就是Σ⁻¹
ones = [1,1,1,1,1]
w_gmv = [0,0,0,0,0]
for i in range(5):
for j in range(5):
w_gmv[i] += OmegaInverse[i][j] * ones[j]
den = 0
for i in range(5):
den += w_gmv[i]
for i in range(5):
w_gmv[i] = w_gmv[i] / den
print("GMV weights:")
for i in range(5):
print(header[i+1], w_gmv[i])
# ---------畫 GMV 點---------
gmv_mean = 0
gmv_var = 0
for i in range(5):
gmv_mean += w_gmv[i]*mean[i]
for j in range(5):
gmv_var += w_gmv[i]*vari[i][j]*w_gmv[j]
gmv_y = 250*gmv_mean*scale
gmv_x = math.sqrt(gmv_var*250)*scale
canvas.create_text(100+gmv_x, base-gmv_y, text="★", fill="red", font=('Arial',28))
canvas.create_text(100+gmv_x-40, base-gmv_y+20, text="劉任昌GMV,Global Minimum Variance最小變異數投資組合", fill="red", font=('微軟正黑體',16))
'''
y_text = 120
canvas.create_text(900,y_text,text="GMV Weights",font=('Arial',16,'bold'))
for i in range(6):
txt = header[i+1] + " : " + format(w_gmv[i],".3f")
canvas.create_text(900, y_text + (i+1)*30, text=txt, font=('Arial',14))
'''
A, B, C, D = 0, 0, 0, 0
for i in range(5):
for j in range(5):
A += mean[i]*OmegaInverse[i][j]
B += mean[i]*OmegaInverse[i][j]*mean[j]
C += OmegaInverse[i][j]
D = B*C - A*A
meanP = 0
while meanP <= 0.5:
meanP += 0.00002 #效率前緣線密集度
y = 250*meanP*scale
temp = meanP - A/C
x = math.sqrt(250 * (C*temp*temp/D+1/C))*scale
canvas.create_oval(100+x-1, base-y-1,
100+x+1, base-y+1, fill="red")
'''
step = 0.1
w=[0,0,0,0,0,0]
while w[0] <= 1:
while w[0]+w[1] <= 1:
while w[0]+w[1]+w[2] <= 1:
while w[0]+w[1]+w[2]+w[3] <= 1:
while w[0]+w[1]+w[2]+w[3]+w[4] <= 1:
temp4=w[0]+w[1]+w[2]+w[3]+w[4]
if temp4 < 1:
w[5] = 1 - temp4
else:
w[5] = 0
meanP, variP = 0, 0
for i in range(6):
meanP += w[i]*mean[i]
for j in range(6):
variP += w[i]*vari[i][j]*w[j]
y = 250*meanP*scale
x = math.sqrt(variP*250)*scale
canvas.create_oval(100+x-1,base-y-1,
100+x+1,base-y+1, fill="blue")
w[4] += step
w[3] += step
w[4] = 0
w[2] += step
w[3],w[4] = 0,0
w[1] += step
w[2],w[3],w[4] = 0,0,0
w[0] += step
w[1],w[2],w[3],w[4] = 0,0,0,0
'''
tk.mainloop()
留言
張貼留言