如何在MySQL中计算投资组合回报?

时间:2018-10-05 11:58:41

标签: mysql

我陷入MySQL问题。我正在尝试使用以下方法计算投资组合的回报序列:

 for(i = startdate+1; i <= enddate; i++) {
   return[i]=0;
   for(n = 0;  n < count(instruments); n++) {
     return[i] += price[i,n] / price[i-1, n] * weight[n];
   }
 }

因此,今天的投资组合收益是按price_today / price_yesterday *权重乘以投资组合中的工具的总和来计算的。

我在http://rextester.com/FUC35243创建了一个涂鸦。

如果它不起作用,则代码为:

DROP TABLE IF EXISTS x_ports;
DROP TABLE IF EXISTS x_weights;
DROP TABLE IF EXISTS x_prices;

CREATE TABLE IF NOT EXISTS x_ports (id INT NOT NULL AUTO_INCREMENT, name VARCHAR(20), PRIMARY KEY (id));
CREATE TABLE IF NOT EXISTS x_weights (id INT NOT NULL AUTO_INCREMENT, port_id INT, inst_id INT, weight DOUBLE, PRIMARY KEY (id));
CREATE TABLE IF NOT EXISTS x_prices (id INT NOT NULL AUTO_INCREMENT, inst_id INT, trade_date DATE, price DOUBLE, PRIMARY KEY (id));

INSERT INTO x_ports (name) VALUES ('PORT A');
INSERT INTO x_ports (name) VALUES ('PORT B');

INSERT INTO x_weights (port_id, inst_id, weight) VALUES (1, 1, 20.0);
INSERT INTO x_weights (port_id, inst_id, weight) VALUES (1, 2, 80.0);
INSERT INTO x_weights (port_id, inst_id, weight) VALUES (2, 1, 100.0);

INSERT INTO x_prices (inst_id, trade_date, price) VALUES (1, '2018-01-01', 1.12);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (1, '2018-01-02', 1.13);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (1, '2018-01-03', 1.12);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (1, '2018-01-04', 1.12);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (1, '2018-01-05', 1.13);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (1, '2018-01-06', 1.14);

INSERT INTO x_prices (inst_id, trade_date, price) VALUES (2, '2018-01-01', 50.23);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (2, '2018-01-02', 50.45);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (2, '2018-01-03', 50.30);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (2, '2018-01-04', 50.29);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (2, '2018-01-05', 50.40);
INSERT INTO x_prices (inst_id, trade_date, price) VALUES (2, '2018-01-06', 50.66);


# GETTING THE DATES

SET @DtShort='2018-01-01';
SET @DtLong=@DtShort;

SELECT
    @DtShort:=@DtLong as date_prev,
    @DtLong:=dt.trade_date as date_curent
FROM
    (SELECT DISTINCT trade_date FROM x_prices ORDER BY trade_date) dt;


# GETTING RETURN FOR SINGLE DAY

SET @DtToday='2018-01-03';
SET @DtYesterday='2018-01-02';

SELECT
    x2.trade_date,
    x2.portfolio,
    sum(x2.val*x2.weight)/sum(x2.weight) as ret
FROM

    (SELECT
        x1.trade_date, 
        x1.portfolio,
        sum(x1.weight)/2.0 as weight,
        sum(x1.val_end)/sum(x1.val_start) as val, 
        sum(x1.val_start) as val_start,
        sum(x1.val_end) as val_end
    FROM

        (SELECT
            @DtToday as trade_date,
            prt.name as portfolio,
            wts.inst_id as iid,
            wts.weight,
            if(prc.trade_date=@DtToday,prc.price*wts.weight,0) as val_start,
            if(prc.trade_date=@DtYesterday,prc.price*wts.weight,0) as val_end
        FROM
            x_ports prt,
            x_weights wts,
            x_prices prc
        WHERE
            wts.port_id=prt.id and 
            prc.inst_id=wts.inst_id and
            (prc.trade_date=@DtToday or prc.trade_date=@DtYesterday)) x1

    GROUP BY x1.portfolio) x2

GROUP BY x2.portfolio;

我希望能够产生如下所示的结果:

Date        Port A      Port B
--------------------------------------------
01/01/2010      
02/01/2010  1.005289596 1.004379853
03/01/2010  0.995851496 0.997026759
04/01/2010  0.999840954 0.999801193
05/01/2010  1.003535565 1.002187314
06/01/2010  1.005896896 1.00515873

2018年2月1日端口A的收益应计算为1.13 / 1.12 * 20 /(20 + 80)+ 50.45 / 50.23 * 80 /(20 + 80)。

端口2在2018年1月1日的回报应计算为50.45 / 50.23 * 100/100,或者可能是1.13 / 1.12 * 0 /(0 + 100)+ 50.45 / 50.23 * 100 /(0+ 100)。

FYI,在上面的循环函数中,我仅按提名者(或未按比例分配的权重)进行计算,因此端口A的计算公式为1.13 / 1.12 * 20 + 50.45 / 50.23 * 80,这是关键步骤在计算收益时。然后将收益除以权重之和即可找到收益。

虽然当然可以做得更好,但我可以得到日期,也可以计算一天的收益,但是我无法将两者合计。

1 个答案:

答案 0 :(得分:0)

模拟分析很有趣! Demo

对此,我觉得数学不正确;因为我离您的“看起来像结果”没关系

我希望能够重用CurDay,但是由于版本较低,我无法使用公共表表达式。

这是什么:

  • X1生成表的联接
  • X2为我们提供了稍后用于数学的投资组合中的各种工具
  • r生成一个用户变量,我们可以在其上分配行@rn和@ Rn2
  • CurDay生成正确排序的行号,以便我们可以加入
  • NextDay会生成CurDay的副本,因此我们可以在RN + 1上将当前日期加入第二天
  • Z允许我们按当天进行数学和分组,并准备对投资组合名称进行透视。
  • 最外层选择允许我们透视数据,因此我们有date + 2列

FileNotFoundException