Google bigquery 使用Bigquery列出回溯测试的损益表

Google bigquery 使用Bigquery列出回溯测试的损益表,google-bigquery,back-testing,Google Bigquery,Back Testing,我有一个Bigquery数据框,其中长/短输入中的1表示当时进入交易,并对应一个长/短位置。而1英寸多头或空头退出意味着退出交易。我想有两个新的栏目,一个叫做long_pnl,它将单个多头交易产生的pnl制成表格,另一个叫做short_pnl,它将单个短头交易产生的pnl制成表格 此回测在任何时间点最多只能有1笔交易/头寸 下面是我的数据框架。如我们所见,多头交易于2019年2月26日开始,2019年3月1日结束,Pnl将为64.45美元,而短头交易于2019年3月4日开始,2019年3月5日结

我有一个Bigquery数据框,其中长/短输入中的1表示当时进入交易,并对应一个长/短位置。而1英寸多头或空头退出意味着退出交易。我想有两个新的栏目,一个叫做long_pnl,它将单个多头交易产生的pnl制成表格,另一个叫做short_pnl,它将单个短头交易产生的pnl制成表格

此回测在任何时间点最多只能有1笔交易/头寸

下面是我的数据框架。如我们所见,多头交易于2019年2月26日开始,2019年3月1日结束,Pnl将为64.45美元,而短头交易于2019年3月4日开始,2019年3月5日结束,Pnl为-119.11美元(损失)

我希望有一个这样的输出,另一个列的缩写是_pnl:

        date    price       long_entry  long_exit   short_entry short_exit  long_pnl         
0   24/2/2019   4124.25           0          0           0             0    NaN  
1   25/2/2019   4130.67           0          0           0             0    NaN
2   26/2/2019   4145.67           1          0           0             0  64.45
3   27/2/2019   4180.10           0          0           0             0    NaN
4   28/2/2019   4200.05           0          0           0             0    NaN
5   1/3/2019    4210.12           0          1           0             0    NaN
6   2/3/2019    4198.10           0          0           0             0    NaN
7   3/3/2019    4210.34           0          0           0             0    NaN
8   4/3/2019    4100.12           0          0           1             0    NaN
9   5/3/2019    4219.23           0          0           0             1    NaN

下面是BigQuery标准SQL

#standardSQL
WITH temp1 AS (
  SELECT PARSE_DATE('%d/%m/%Y', dt) dt, CAST(price AS numeric) price, long_entry, long_exit, short_entry, short_exit
  FROM `project.dataset.table`
), temp2 AS (
  SELECT dt, price, long_entry, long_exit, short_entry, short_exit,
    SUM(long_entry) OVER(ORDER BY dt) + SUM(long_exit) OVER(ORDER BY dt ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) long_grp,
    SUM(short_entry) OVER(ORDER BY dt) + SUM(short_exit) OVER(ORDER BY dt ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) short_grp
  FROM temp1
)
SELECT dt, price, long_entry, long_exit, short_entry, short_exit,
  IF(long_entry = 0, NULL, 
    FIRST_VALUE(price) OVER(PARTITION BY long_grp ORDER BY dt DESC) - 
    LAST_VALUE(price) OVER(PARTITION BY long_grp ORDER BY dt DESC)
  ) long_pnl,
  IF(short_entry = 0, NULL, 
    LAST_VALUE(price) OVER(PARTITION BY short_grp ORDER BY dt DESC) - 
    FIRST_VALUE(price) OVER(PARTITION BY short_grp ORDER BY dt DESC)
  ) short_pnl
FROM temp2
如果要将上述内容应用于您问题中的样本数据

#standardSQL
WITH `project.dataset.table` AS (
  SELECT '24/2/2019' dt, 4124.25 price, 0 long_entry, 0 long_exit, 0 short_entry, 0 short_exit UNION ALL
  SELECT '25/2/2019', 4130.67, 0, 0, 0, 0 UNION ALL
  SELECT '26/2/2019', 4145.67, 1, 0, 0, 0 UNION ALL
  SELECT '27/2/2019', 4180.10, 0, 0, 0, 0 UNION ALL
  SELECT '28/2/2019', 4200.05, 0, 0, 0, 0 UNION ALL
  SELECT '1/3/2019', 4210.12, 0, 1, 0, 0 UNION ALL
  SELECT '2/3/2019', 4198.10, 0, 0, 0, 0 UNION ALL
  SELECT '3/3/2019', 4210.34, 0, 0, 0, 0 UNION ALL
  SELECT '4/3/2019', 4100.12, 0, 0, 1, 0 UNION ALL
  SELECT '5/3/2019', 4219.23, 0, 0, 0, 1 
), temp1 AS (
  SELECT PARSE_DATE('%d/%m/%Y', dt) dt, CAST(price AS numeric) price, long_entry, long_exit, short_entry, short_exit
  FROM `project.dataset.table`
), temp2 AS (
  SELECT dt, price, long_entry, long_exit, short_entry, short_exit,
    SUM(long_entry) OVER(ORDER BY dt) + SUM(long_exit) OVER(ORDER BY dt ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) long_grp,
    SUM(short_entry) OVER(ORDER BY dt) + SUM(short_exit) OVER(ORDER BY dt ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) short_grp
  FROM temp1
)
SELECT dt, price, long_entry, long_exit, short_entry, short_exit,
  IF(long_entry = 0, NULL, 
    FIRST_VALUE(price) OVER(PARTITION BY long_grp ORDER BY dt DESC) - 
    LAST_VALUE(price) OVER(PARTITION BY long_grp ORDER BY dt DESC)
  ) long_pnl,
  IF(short_entry = 0, NULL, 
    LAST_VALUE(price) OVER(PARTITION BY short_grp ORDER BY dt DESC) - 
    FIRST_VALUE(price) OVER(PARTITION BY short_grp ORDER BY dt DESC)
  ) short_pnl
FROM temp2
-- ORDER BY dt
结果将是

Row dt          price   long_entry  long_exit   short_entry short_exit  long_pnl    short_pnl    
1   2019-02-24  4124.25 0           0           0           0           null        null     
2   2019-02-25  4130.67 0           0           0           0           null        null     
3   2019-02-26  4145.67 1           0           0           0           64.45       null     
4   2019-02-27  4180.1  0           0           0           0           null        null     
5   2019-02-28  4200.05 0           0           0           0           null        null     
6   2019-03-01  4210.12 0           1           0           0           null        null     
7   2019-03-02  4198.1  0           0           0           0           null        null     
8   2019-03-03  4210.34 0           0           0           0           null        null     
9   2019-03-04  4100.12 0           0           1           0           null        -119.11  
10  2019-03-05  4219.23 0           0           0           1           null        null     

我觉得应该有一个“较短”的解决方案——但我认为上面的方法仍然足够好,可以使用

这可能是一个幼稚的问题——但为什么64.45肯定和119.11否定——它们在我看来都是积极的?请澄清卖空意味着你以当前价格卖出,当你结束卖空交易时买入。因此,你以4100.12美元卖出,以4219.23美元买入,这是一个损失。喜欢为我学习新东西:o)你认为你能帮我做这件事吗?当然,看起来是可行的。肯定有人会回答的。我也会仔细检查一下。嗨,先生,你能和我分享一下长组和短组是如何工作的吗?sum(long_entry)+sum(long_exit)是如何组成团队的?感谢您了解其工作原理的最佳方法是逐步运行并查看中间结果。剧本非常简单,而且是自我描述的——你应该自己玩它来获得洞察力——如果你在“旅程”中有具体问题的话——我很乐意通过解释来帮助你
Row dt          price   long_entry  long_exit   short_entry short_exit  long_pnl    short_pnl    
1   2019-02-24  4124.25 0           0           0           0           null        null     
2   2019-02-25  4130.67 0           0           0           0           null        null     
3   2019-02-26  4145.67 1           0           0           0           64.45       null     
4   2019-02-27  4180.1  0           0           0           0           null        null     
5   2019-02-28  4200.05 0           0           0           0           null        null     
6   2019-03-01  4210.12 0           1           0           0           null        null     
7   2019-03-02  4198.1  0           0           0           0           null        null     
8   2019-03-03  4210.34 0           0           0           0           null        null     
9   2019-03-04  4100.12 0           0           1           0           null        -119.11  
10  2019-03-05  4219.23 0           0           0           1           null        null