豆粕、白糖期货涨跌幅的可视化分析

豆粕、白糖期货涨跌幅的可视化分析

在之前的一篇文章中,也就是《matlab 从 wind 量化借口获取数据》 中已经介绍了如何获取数据,现在要对已经获取的数据进行一些基础的分析。

涨跌幅的统计

首先对涨跌幅进行统计。交易员要求统计的是开盘收盘的涨跌幅,也就日频率吧。当然,这里的日不是指交易日而是每个开收盘。交易员要求将日盘和夜盘分开然后按照时间串联起来。wind 上是没有提供这样频率的一个数据的。所以在之前这文章中我们提取数据的频率是 30 分钟的,然后自己从 60 分钟的数据中提取出开收盘的价格。

当然,你可能会奇怪。既然只要开盘和收盘那数据中为什么有个涨跌幅呢?因为我不知道 wind 中这个涨跌幅是怎么定义的,所以我想看一下 wind 自带涨跌幅的意思,所以特别提取出来。事后证明这个字段就是代表每个 K 线的涨跌幅。

那我们要得到涨跌幅必须自己计算。如何计算呢?我们先提取特点的时间点的 K 线。这个涨跌幅是这么定义的 (开盘-收盘) / 收盘。因此需要早上 9 点的开盘价,下午 3 点的收盘价。晚上 9 点的看盘价,晚上 11:30 的收盘价。但是如果认真观察会发现 wind 取的数据实在奇怪,有很多没有交易的时段也有数据,真是另人伤心,行业老大水平也如此另人堪忧,还是得自己搞数据库啊。所以,我再认真比对了 K 线图后取的 K 线是 9:30 ,15:00,12:30,23:30 时刻的。先看代码吧:

function future = calcdata(future)
% 传入参数和传出参数都为结构体future
name = fieldnames(future);
% 有np个期货品种
np = length(name);
% 需要的时间点
do = 930; dc = 1500;
no = 2130; nc = 2330;
for j = 1:np
    %     t = datestr(future.SR801.time);
    %     t = cellstr(t);
    eval(['t = future.',name{j},'.time;']);
    tv = datevec(t);
    tnum = tv(:,4)*100 + tv(:,5);
    ido = tnum == do;
    idc = tnum ==dc;
    ino = tnum == no;
    inc = tnum == nc;
    % % id1(find(id1 == 1,1)) = 0;
    % % id2(find(id2 == 1,1)) = 0;
    % tdo = t(ido);
    % tdc = t(idc);
    % tno = t(ino);
    % tnc = t(inc);
    % ind = ido + idc + ino + inc;
    % ind = logical(ind);
    % nt = t(ind);
    id = ido + inc;
    in = ino + idc;
    id = logical(id);
    in = logical(in);
    % dt 和 nt 即日夜盘的时间,以便与核对是否计算错误
    dt = t(id);
    nt = t(in);
    % 这里定义日盘涨跌幅为日盘开盘减夜盘收盘
    % 夜盘涨跌幅为夜盘开盘减日盘收盘
    % 我们通过 id 和 in 这两个下标剥离出了日夜盘涨跌的索引
    % ld 和 ln 记录长度
    ld = length(dt);
    ln = length(nt);
    % 找出日盘和夜盘涨幅在整个时间序列中的位置
    iid = find(id ==1);
    iin = find(in ==1);
    % 计算日盘涨跌幅
    n = 3:2:ld;
    m = 0;
    pd = nan(length(n),1);
    pdt = nan(length(n),1);
    % 将pd重新赋值为[pdt pd]
    for i = n
        m = m + 1;
        pd(m) = (future.SR801.data(iid(i),1) - future.SR801.data(iid(i-1),2)) / future.SR801.data(iid(i-1),1);
        pdt(m) = t(iid(i));
    end
    % 百分化
    pd = pd * 100;
    pd = [pdt pd];
    % 夜盘
    % 计算日盘涨跌幅
    n = 2:2:ln;
    m = 0;
    pn = nan(length(n),1);
    pnt = nan(length(n),1);
    for i = n
        m = m + 1;
        pn(m) = (future.SR801.data(iin(i),1) - future.SR801.data(iin(i-1),2)) / future.SR801.data(iin(i-1),1);
        pnt(m) = t(iin(i));
    end
    % 百分化
    pn = pn * 100;
    pn = [pnt pn];
    % 将pd和pn写入到future中
    eval(['future.',name{j},'.pd=pd;']);
    eval(['future.',name{j},'.pn=pn;']);
end
end

我们通过 for 循环都对结构体的每个期货品种进行循环操作。也就是所计算涨跌幅的算法是通用的。首先将时间进行向量化处理,得到我们感兴趣的数值化的时间,比如 930.然后生成逻辑向量以标记我们需要的时间点。然后通过索引分开日夜盘,之后根据实际情况设计算法计算涨跌幅。最后将计算的数据重新写入到 future 中。

涨跌幅的可视化

统计出了涨跌幅自然要考虑如何展示,以便更好地分析。我们可以做一些基础的描述性统计。这里我机智的分开了日夜盘,接下来的数据分析中都有分日盘、夜盘还有日夜盘,这个日夜盘就是将日盘和夜盘合并的数据。

先描出数据的散点图,然后利用饼图和直方图进行初步统计。

function plotfuture(future)

name = fieldnames(future);
np = length(name);
for i = 1:np
    eval(['p=future.',name{i},';']);
    pa = catdn(p.pd,p.pn);
    % 统计
    mua = mean(pa(:,2));
    sigmaa = std(pa(:,2));
    mina = min(pa(:,2));
    maxa = max(pa(:,2));

    f1 = figure;
    f1.Units = 'normalized';
    f1.Position = [ 0.0847  0.0544  0.8194  0.8033];
    %     a1 = axes('Position',[0.05 0.05 0.8 0.75]);
    plot(pa(:,1),pa(:,2),'r--*');
    a1 = gca;
    a1.Position = [0.16 0.11 0.8 0.82];
    hold on
    l1 = line([pa(1,1) pa(end,1)],[mua mua]);
    l1.Color = 'b';
    l1.LineWidth = 1;
    l2 = line([pa(1,1) pa(end,1)],[mua+2*sigmaa,mua+2*sigmaa]);
    l2.Color = 'g';
    l2.LineWidth = 1;

    l3 = line([pa(1,1) pa(end,1)],[mua-2*sigmaa,mua-2*sigmaa]);
    l3.Color = 'g';
    l3.LineWidth = 1;
    legend('涨跌','均值','mu+2*sigma','mu-2*sigma');
    datetick('x',1);
    xtickangle(50);
    axis tight
    title([name{i},'合约日夜盘合并的情况']);
    hold off
    % 画出统计量
    t1 = uitable(f1,'data',[mua;sigmaa;mina;maxa]);
    t1.Units = 'normalized';
    t1.Position = [0 0.4 0.135 0.14];
    t1.ColumnName = {'值'};
    t1.RowName = {'mu','sigma','min','max'};
    tick = 0.2;
    newsort(pa,tick,name{i},1)
    %%

    f2 = figure;
    f2.Units = 'normalized';
    f2.Position = [ 0.0847  0.0544 0.8194  0.8033];

    % 统计
    pd = p.pd;
    pn = p.pn;

    mud = mean(pd(:,2));
    sigmad = std(pd(:,2));
    mind = min(pd(:,2));
    maxd = max(pd(:,2));

    % 统计
    mun = mean(pn(:,2));
    sigman = std(pn(:,2));
    minn= min(pn(:,2));
    maxn = max(pn(:,2));

    subplot(2,1,1);
    plot(pd(:,1),pd(:,2),'r--*');
    datetick('x',1,'keeplimits');
    title([name{i},' 合约日盘涨跌情况']);
    a2 = gca;
    a2.Position = [0.16 0.56 0.8 0.341];
    axis tight
    subplot(2,1,2);
    plot(pn(:,1),pn(:,2),'r--*');
    datetick('x',1,'keeplimits');
    title([name{i},' 合约夜盘涨跌情况']);
    axis tight
    a3 = gca;
    a3.Position = [0.16 0.11 0.8 0.341];



    td = uitable(f2,'data',[mud;sigmad;mind;maxd]);
    td.Units = 'normalized';
    td.Position = [0 0.6 0.135 0.14];
    td.ColumnName = {'值'};
    td.RowName = {'mu','sigma','min','max'};

    tn = uitable(f2,'data',[mun;sigman;minn;maxn]);
    tn.Units = 'normalized';
    tn.Position = [0 0.3 0.135 0.14];
    tn.ColumnName = {'值'};
    tn.RowName = {'mu','sigma','min','max'};

    newsort(pd,tick,name{i},2)
    newsort(pn,tick,name{i},3)
end

end

这整个的函数还是以 future 为操作对象。可以看到调用了 catdn 这个函数。该函数代码如下:

function dn = catdn(d,n)
% 该函数把日盘的涨跌幅和夜盘的涨跌幅拼接起来
dnt = [d(:,1);n(:,1)];
[dnt,ind] = sort(dnt);
dn = [d(:,2);n(:,2)];
dn = dn(ind);
dn = [dnt dn];
end

也就是说这个函数得出了日夜盘的涨跌幅。然后统计最大值、最小值、方差、均值。然后进行绘图,本来应该很简单。但是可以看到代码比较多,这是因为对图形进行了一些具体的调整以便与观察,这就不详细解释。还有最后还调用了 newsort 函数,这个函数的作用是绘制饼图和直方图。代码如下:

function newsort(p,tick,name,c)
% 该函数对涨跌幅进行分类,并且绘制饼图
% p 为要分类的数据,而 tick 为分类的尺度
% name 合约名
% c 取值为 1 2 3,分别代表日夜盘,日盘,夜盘
if c == 1
    addname = '日夜盘';
elseif c == 2
    addname = '日盘';
else
    addname = '夜盘';
end
p = p(:,2);
np = abs(p);
maxp = max(np);
n = ceil(maxp/tick);
edges = tick * ones(n,1);
edges = cumsum(edges)';
edges = [0 edges];
vnp = discretize(np,edges);
% 对绝对值序列绘图
% 统计np中各分类的个数
str_vnp = nan(size(vnp));
for i = 1:n
    str_vnp(vnp == i) = tick*i;
end
str_vnp = num2str(str_vnp);
str_vnp(:,end+1) = '%';
str_vnp = cellstr(str_vnp);
str_vnp = categorical(str_vnp);
f1 = figure;
f1.Units = 'normalized';
f1.Position = [0.1 0.05 0.8 0.8];

subplot(2,2,1);
pie(str_vnp);
title([name,addname,'涨跌幅绝对值饼图']);
a1 = gca;
a1.Position = [0.05 0.5 0.25 0.5];
%% 绘制直方图
subplot(2,2,2);
histogram(str_vnp);
title([name,addname,'涨跌幅绝对值直方图']);
a2 = gca;
a2.Position = [0.5 0.55 0.45 0.4];
%% 对原始序列绘图
len = length(p);
vp = nan(len,1);
edge_n = 0.2 * ones(1,n);
edge_n = cumsum(edge_n);
edge_n = fliplr(edge_n);
edges = [-edge_n edges];

vp = discretize(p,edges);
str_vp = nan(size(vp));
for i = 1:2*n
    if i <= 4
        str_vp(vp == i) = edges(i);
    else
        str_vp(vp == i) = edges(i+1);
    end
end

str_vp = num2str(str_vp);
str_vp(:,end+1) = '%';
str_vp = cellstr(str_vp);
str_vp = categorical(str_vp);

subplot(2,2,3);
pie(str_vp);
title([name,addname,'涨跌幅原始值饼图']);
a3 = gca;
a3.Position = [0.05 0.04 0.25 0.5];
%% 绘制直方图
subplot(2,2,4);
histogram(str_vp);
title([name,addname,'涨跌幅原始值直方图']);
a4 = gca;
a4.Position = [0.5 0.05 0.45 0.4];

end

这里要批评一下 matlab 自带的函数绘制饼图和直方图效果实在不敢恭维,费了好大的劲才调整到一个比较恰当的效果。这边值得一提的是这个 categorical 变量类型。这是为了在饼图中比较好的标上百分比才用的这个新的变量类型。其实费了很大的劲,也就是说这个变量类型 matlab 还有很大的改进空间。

很有意思,我之前在公司电脑运行还正常。但是这次我在版本上运行还出现了错误提示:

2018-01-25-22-48-04

这估计是我笔记本性能太低的缘故。

2018-01-25-22-50-14

内存已经不足了,还是应该努力赚钱改善生活。

结果展示

我们的 future 中一共有 6 个品种的数据,每个品种这里有产生 5 张图,因此一共有 30 张图。这里仅展示一个品种的图,而至于图片中所体现出来的信息就很值得深入挖掘了。

2018-01-25-22-52-19

可以看到,图片的显示效果不好。其实我之前是在公司 27 寸的显示器上调整的,笔记本屏幕只有 14 寸,所以显示效果不好。大家如果屏幕够大,相信效果会很好。

2018-01-25-22-54-20

这里的百分比已经叠住了,惨不忍睹。努力赚钱啊,年轻人。

2018-01-25-22-55-23

2018-01-25-22-55-51

2018-01-25-22-56-19

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半美人

动力源于鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值