标签 Matlab 下的文章

文章地址:https://caoyongzhuo.cn/archives/902
备用地址:https://cloud.tencent.com/developer/article/2200692
代码如下:

%% 初始操作
cd 'F:\MATLAB\已恢复\本地磁盘(E)\caoyongzhuo\test2022_2\test2022_2' % 切换工作目录
ls % 列出当目录文件以确保工作路径选择正确
clc;
clear;

%% 第一问
clc;
clear;
Price = 3080; % 上证A股综合指数价格
mu = 1.051^(1/250)-1; % 上证A股综合指数平均收益率
sigma = 0.7/sqrt(250); % 上证A股综合指数标准差
N = 250*2; % 依据上课作业文件,我们可知一年的交易日为250天,两年极为250*2
dist = 'norm'; % 确定随机的模式(正态分布)
Price = RandnPrice(dist,Price,mu,sigma,N); % 上证A股综合指数预测价格
plot(Price(:,1)); % 行列转换
xlabel('time');
ylabel('price');

%% 第二问
clear % 清楚workspace中的数据文件
clc % 清楚窗口中的所有代码

% 设置时间序列数据
ftsdatas = ascii2fts('data.txt',2,2) % 设置时间序列数据
save ftsdatas.mat %将时间序列数据的mat文件保存在工作目录下

% MACD指标
% 绘制收盘价
load ftsdatas.mat
macdc = macd(ftsdatas)
plot(macdc)
% 绘制开盘价
macdo = macd(ftsdatas,'open')
plot(macdo)

% 威廉指标
wms = willpctr(ftsdatas)
plot(wms) % 绘制wms图像
hold on % 保持绘图窗口保持不变
plot(wms.dates,-80*ones(1,length(wms)),'color',[0.5 0 0],'linewidth',3) % 绘制的是横轴为时间,纵轴为一列,wms长度行的线条
plot(wms.dates,-20*ones(1,length(wms)),'color',[0 0.5 0],'linewidth',3)
hold off %关闭绘图窗口

% RSI技术指标
load ftsdatas.mat
rsi = rsindex(ftsdatas)
plot(rsi)
hold on
plot(rsi.dates,30*ones(1,length(rsi)),'color',[0.5 0 0],'linewidth',2) % 绘制的是横轴为时间,纵轴为一列,rsi长度行的线条
plot(rsi.dates,30*ones(1,length(rsi)),'color',[0 0.5 0],'linewidth',2)
hold off

% OBV指数
load ftsdatas.mat %% 从本地mat文件中调用数据
obv = onbalvol(ftsdatas) %%% 从workspace中调用数据
plot(obv)

% 绘制candle图
load ftsdatas.mat;
candle(ftsdatas)

% 绘制合并图
load ftsdatas.mat;
subplot(2,2,4)
candle(ftsdatas) %%绘制candle图

subplot(2,2,3)
plot(willpctr(ftsdatas))

subplot(2,2,1)
plot(macd(ftsdatas))

subplot(2,2,2)
rsi = rsindex(ftsdatas)
plot(rsi)
hold on
plot(rsi.dates,30*ones(1,length(rsi)),'color',[0.5 0 0],'linewidth',2) % 绘制的是横轴为时间,纵轴为一列,rsi长度行的线条
plot(rsi.dates,30*ones(1,length(rsi)),'color',[0 0.5 0],'linewidth',2)
hold off

%% 第三问
%存放20股票的100天的收盘价
clc 
clear
load gp20.txt 
gps1=20
%%1﹣计算期望收益
price20 = mean(gp20)
%%2﹣计算收益率矩阵
retu =price2ret(gp20);
%%3﹣计算期望收益
expv = mean(retu);
%%%4﹣计算协方差矩阵% aita( X , Y )= sigama ( Xi - X )( Yi - Y ) Pi
aita = cov ( retu );
eig56= eig ( aita );
%协方差矩阵非半正定,进行修正
aita = aita+eye (gps1,gps1)*0.00001;%若非半正定,加很小的数使其为半正定矩阵

%% 第四问
clc
clear  %三个资产的投资选择问题
returns=[0.1 0.18 0.15] % 期望收益向量
stds=[0.15 0.25 0.2]    %标准差-表示每个资产的波动性
correlations=[1 0.9 0.1;0.9 1 0.4;0.1 0.4 1] %相关系数-对称矩阵
covariances=corr2cov(stds,correlations)  %计算协方差矩阵
portopt(returns,covariances,10) %选择10个点
hold on
rand('state',0)

weights=rand(500,3)
total=sum(weights,2) %weights矩阵的行相加
weights(:,1)=weights(:,1)./total %对权重做标准化处理
weights(:,2)=weights(:,2)./total
weights(:,3)=weights(:,3)./total
[portrisk,portreturn]=portstats(returns,covariances,weights)
plot(portrisk,portreturn,'.r')
title('均值-方差有效前沿以及各个资产组合的风险与收益')
xlabel('风险(标准差)')
ylabel('期望收益率')
hold off

clc
clear
rand('state',0)
figure
% RandSumOneTest
M=500;
N=3;
% method=1;
% X1=RandSumOne(M,N,method);
X1=rand(M,N)   
total1=sum(X1,2)       % 按行求和
for i=1:N             % 比例 标准化,变成了权重矩阵
    X1(:,i)=X1(:,i)./total1;
end
X2=rand(M,N)   
total2=sum(X2,2)       
for j=1:N             
    X2(:,j)=X2(:,j)./total2;
end
% method=2;
% X2=RandSumOne(M,N,method);

%预期收益率向量
ExpReturn = [0.1 0.18 0.15]; 
%协方差矩阵 
ExpCovariance = [0.0225000000000000,0.0337500000000000,0.00300000000000000
                0.0337500000000000,0.0625000000000000,0.0200000000000000
                 0.00300000000000000,0.0200000000000000,0.0400000000000000];
%变量初始化
PortRisk1=zeros(M,1);
PortReturn1=zeros(M,1);
PortRisk2=zeros(M,1);
PortReturn2=zeros(M,1);

for i=1:M
    [PortRisk1(i), PortReturn1(i)] = portstats(ExpReturn, ExpCovariance,X1(i,:));
    [PortRisk2(i), PortReturn2(i)] = portstats(ExpReturn, ExpCovariance,X2(i,:));
end
plot(PortRisk1, PortReturn1,'r.')
hold on
plot(PortRisk2, PortReturn2,'bo')
xlabel('PortRisk')
ylabel('PortReturn')
legend('X1','X2')

山东财经大学 2022 -- 2023 学年第 一 学期期末综合实验

说明:

1、 答卷要有分析过程、主要计算结果与图、Matlab程序,注意单倍行距;

2、 答卷的文件以“学号与姓名”组成,提交时不要有座位电脑的编号目录;

3、 电子答卷提交后,再提交书面打印文件,答卷最好不要超过6页,左边二钉装订。

1、上证A股综合指数当前为3080,假如未来1年投资上证指数的年收益率5.1%,上证指数的年波动率标准差为0.7,如果上证指数在未来2年服从正太分布,请画出未来2年内的上证指数模拟走势图。

答:

img

2、对于古井贡的交易数据,分别画出这个股票的九日均线图MACD,相对强弱指数RSI,威廉指数WMS 和 蜡烛图candle,四个子图显示在同一窗口中。交易数据见附件。

答:

img

3、附件中的数据给出了20只股票100个交易日的价格信息,请计算该20只股票的期望价格、预期收益率和20只股票的协方差矩阵。

答:

期望收益:

1

期望收益率:

img

img

协方差:

img

4、ABC三种资产的预期收益、标准差和相关系数如下表,请在一个图中画出由10个有效投资组合构成的有效前沿、由500个可行投资方案构成的可行域。

项目相关系 数矩阵 资产A 资产B 资产C
资产A 1 0.9 0.1
资产B 0.9 1 0.4
资产C 0.1 0.4 1
预期回报 0.10 0.18 0.15
各资产标准差 0.15 0.25 0.2

注:已知资产组合的标准差和相关系数后,求解协方差矩阵的函数COV=corr2cov(标准差,相关系数)

img

img

一、ACF(自相关系数检验周期)

%% 通过autocorr和xcorr自相关求周期
clear ;clc
%加载TOP13家供货商240周的供货量数组文件
load FFt.mat;
%使用autocorr函数
Randi = randi([2 14],1,1)
A = FFt([1:96],Randi) ;
len = length(A) ;
[ACF,lags,bounds] = autocorr(A,len-1) ;
subplot(2,1,1) ;
plot(lags(1:end),ACF(1:end)) ;
title('autocorr求S-top13的自相关') ;
%使用xcorr函数
B = A - mean(A) ;%减掉均值
[c,lags] = xcorr(B) ;
d = c ./ c(len) ;%归一化
subplot(2,1,2) ;
plot(lags(len:end),d(len:end)) ;%取中点n为起始的后面n个序列
title('xcorr求S-top13的自相关') ;
from statsmodels.tsa.stattools import acf

# Expected time period
for lag in fft_periods:
    # lag = fft_periods[np.abs(fft_periods - time_lag).argmin()]
    acf_score = acf(data["value"].values, nlags=lag)[-1]
    print(f"lag: {lag} fft acf: {acf_score}")

expected_lags = np.array([timedelta(hours=12)/timedelta(minutes=5), timedelta(days=1)/timedelta(minutes=5), timedelta(days=7)/timedelta(minutes=5)]).astype(int)
for lag in expected_lags:
    acf_score = acf(data["value"].values, nlags=lag, fft=False)[-1]
    print(f"lag: {lag} expected acf: {acf_score}")

周期检验图

1.autocorr求S-top13的自相关

2.corr求S-top13的自相关

xcorr求S-top13的自相关

二、FFt(傅里叶变换计算周期)

%% 判断TOP13家供货商的供货量(S)是否为周期波动。如果周期波动,求出周期。
clear;clc;
%加载TOP13家供货商240周的供货量数组文件
load FFt.mat;
%将首列的240个周次作为横坐标(Weeks)
weeks = FFt([1:240],1);
%随机生成2到14中的一个整数用以随机择取13个供货商中的一家
Randi = randi([2 14],1,1)
SNumbers = FFt([1:240],Randi);
%绘制该供货商未经fft(傅里叶函数)变换的原始图像并观察是否存在周期此性
plot(weeks,SNumbers)
xlabel('Weeks')
ylabel('SNumbers')
title('FFt Data')
%大致判断该原始图像是否具有周期性
judge = input("请输入观察该供货商的供货量(S)数据是否具有周期性,'是'请输入'1','不是'请输入'0':")
if judge == 1
    %如果具有周期性,则使用FFt(傅里叶变换)函数将随机择取的供货商所在列的供货量(S)进行变换
    y = fft(SNumbers);
    y(1) = [];
    plot(y,'ro')
    %绘制经过fft(傅里叶函数)变换后的图像
    xlabel('real_SNumbers(y)')
    ylabel('imag_SNumbers(y)')
    title('傅里叶转换')
    %变换数据前半部分的幂
    n = length(y);
    power = abs(y(1:floor(n/2))).^2;
    %最大频率
    maxfreq = 1/2;      
    %等距频率网格
    freq = (1:n/2)/(n/2)*maxfreq;    
    plot(freq,power)
    xlabel('Weeks/Cycle')
    ylabel('Power')
    period = 1./freq;
    plot(period,power);
    %放大最大功率(周次)
    xlim([0 240]); 
    xlabel('Weeks/Cycle')
    ylabel('SNumbers')
end

随机验证周期图

1.Weeks

Weeks

2.Weeks_Cycle

Weeks_Cycle

三、Topsis

(一)Inter2Max

%% 定义Inter2Max函数以备主函数调用
function [posit_x] = Inter2Max(x,a,b)
    r_x = size(x,1);  % row of x 
    M = max([a-min(x),max(x)-b]);
    posit_x = zeros(r_x,1);  
    % 初始化posit_x全为0
    for i = 1: r_x
        if x(i) < a
           posit_x(i) = 1-(a-x(i))/M;
        elseif x(i) > b
           posit_x(i) = 1-(x(i)-b)/M;
        else
           posit_x(i) = 1;
        end
    end
end

(二)Mid2Max

%% 中间型数据转极大型数据
%定义Mid2Max函数以备主函数调用
function [posit_x] = Mid2Max(x,best)
    M = max(abs(x-best));
    posit_x = 1 - abs(x-best) / M;
end```
%% 中间型数据转极大型数据
%定义Mid2Max函数以备主函数调用
function [posit_x] = Mid2Max(x,best)
    M = max(abs(x-best));
    posit_x = 1 - abs(x-best) / M;
end

(三)Min2Max

%% 及小型数据转极大型数据
%定义Min2Max函数以备主函数调用
function [posit_x] = Min2Max(x)
    posit_x = max(x) - x;
    % posit_x = 1 / x; 如果x全部都大于0,需要这样正向化
end

(四)Positivization

%% 调用Mid2Max.m和Min2Max.m和Inter2Max.m函数定义正向化函数
function [posit_x] = Positivization(x,type,i)
% 输入变量有三个:
% x:需要正向化处理的指标对应的原始列向量
% type: 指标的类型(1:极小型, 2:中间型, 3:区间型)
% i: 正在处理的是原始矩阵中的哪一列
% 输出变量posit_x表示:正向化后的列向量
    if type == 1  %极小型
        disp(['第' num2str(i) '列是极小型,正在正向化'] )
        posit_x = Min2Max(x);  %调用Min2Max函数来正向化
        disp(['第' num2str(i) '列极小型正向化处理完成'] )
        disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
    elseif type == 2  %中间型
        disp(['第' num2str(i) '列是中间型'] )
        best = input('请输入最佳的那一个值: ');
        posit_x = Mid2Max(x,best);
        disp(['第' num2str(i) '列中间型正向化处理完成'] )
        disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
    elseif type == 3  %区间型
        disp(['第' num2str(i) '列是区间型'] )
        a = input('请输入区间的下界: ');
        b = input('请输入区间的上界: '); 
        posit_x = Inter2Max(x,a,b);
        disp(['第' num2str(i) '列区间型正向化处理完成'] )
        disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
    else
        disp('没有这种类型的指标,请检查Type向量中是否有除了1、2、3之外的其他值')
    end
end

(五)topsis

%% Step1:清空界面,并加载矩阵X
clear;clc %清空界面
load X.mat %加载数据
%% Step2:判断是否需要正向化处理
[n,m] = size(X);%计算矩阵的大小
disp(['共有' num2str(n) '个评价对象, ' num2str(m) '个评价指标']) %输出共有多少个评价对象
JUDGING = input(['这' num2str(m) '个指标是否需要经过正向化处理,需要请输入1 ,不需要输入0:  ']);%定义是否需要正向化处理
if JUDGING == 1
    Position = input('请输入需要正向化处理的指标所在的列 '); 
    disp('请输入需要处理的这些列的指标类型(1-极小型, 2-中间型, 3-区间型) ')
    TYPE = input('例如:第1列是极小型,第2列是中间型,第3列是区间型,就输入[1,2,3]:  ');%同样为了保证代码逻辑的完整性,此处添加正向化的处理步骤
      for i = 1 : size(Position,2)  %这里需要对这些列分别处理,因此需要知道一共要处理的次数,即循环的次数
        X(:,Position(i)) = Positivization(X(:,Position(i)),TYPE(i),Position(i));
       end
    disp('正向化后的矩阵 X =  ')%输出正向化的矩阵
    disp(X)
end%以end作为结尾
%% Step3:对正向化后的矩阵进行标准化
Z = X ./ repmat(sum(X.*X) .^ 0.5, n, 1);%利用repmat函数
disp('标准化矩阵 Z = ')%输出标准化矩阵Z
disp(Z)
%% Step4:判断是否需要增加权重
disp("请输入是否需要增加权重向量,需要输入1,不需要输入0")%以此作为增加权重步骤的开始
JUDGING = input('请输入是否需要增加权重: ');%判断是否需要增加权重
if JUDGING == 1%用if 和 for 循环来判断是否需要增加权重
    JUDGING = input('使用熵权法确定权重请输入1,否则输入0: ');%确定是否需要用熵权法增加权重
    if JUDGING == 1%==是判断符号
        if sum(sum(Z<0)) >0   % 如果之前标准化后的Z矩阵中存在负数,则重新对X进行标准化
            disp('原来标准化得到的Z矩阵中存在负数,所以需要对X重新标准化')
            for i = 1:n%使用for循环
                for j = 1:m
                    Z(i,j) = [X(i,j) - min(X(:,j))] / [max(X(:,j)) - min(X(:,j))];
                end
            end
            disp('X重新进行标准化得到的标准化矩阵Z为:  ')
            disp(Z)
        end
        weight = Entropy_Method(Z);
        disp('熵权法确定的权重为:')%输出最终权重数据
        disp(weight)
    else
        disp(['如果你有3个指标,你就需要输入3个权重,例如它们分别为0.25,0.25,0.5, 则你需要输入[0.25,0.25,0.5]']);
        weight = input(['你需要输入' num2str(m) '个权数。' '请以行向量的形式输入这' num2str(m) '个权重: ']);
        OK = 0;  % 用来判断用户的输入格式是否正确
        while OK == 0 
            if abs(sum(weight) -1)<0.000001 && size(weight,1) == 1 && size(weight,2) == m  % 注意,Matlab中浮点数的比较要小心
                OK =1;
            else
                weight = input('你输入的有误,请重新输入权重行向量: ');
            end
        end
    end
else
    weight = ones(1,m) ./ m ; %如果不需要加权重就默认权重都相同,即都为1/m
end

%% Step5:计算与最大值的距离和最小值的距离,并算出得分
D_P = sum([(Z - repmat(max(Z),n,1)) .^ 2 ] .* repmat(weight,n,1) ,2) .^ 0.5;   %此为与最大值即最优解的距离
D_N = sum([(Z - repmat(min(Z),n,1)) .^ 2 ] .* repmat(weight,n,1) ,2) .^ 0.5;   %此为与最小值即最劣解的距离
S = D_N ./ (D_P+D_N);    % 这里得到未归一化的得分
disp('最后的得分为:')
stand_S = S / sum(S)%将数据进行归一化处理,以便于比较。
[sorted_S,index] = sort(stand_S ,'descend')%对各个供应商进行排序,得到最终数据

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3svr12kkscyss