Je veux écrire une fonction, qui représente une simulation de trading. J'ai une base de données des prix des actifs financiers et je souhaite créer une stratégie de trading basée sur des signaux.
Voici ma base de données:
(open = cours d'ouverture, fermeture = cours de clôture, rendement = taux de variation en%)
structure(list(date = structure(c(16455, 16456, 16457, 16458, 16459, 16460, 16461, 16462, 16463, 16464), class = "Date"), open = c(212.91, 211.38, 227.32, 233.52, 232.7, 247.35, 254.08, 273.17, 263.35, 233.35), close = c(211.32, 226.9, 233.41, 232.88, 247.85, 253.72, 273.47, 263.48, 233.91, 233.51), return = c(-1, 7, 3, 0, 7, 3, 8, -4, -11, 0), signal = c(0, 1, 0, 0, 1, 0, 1, 0, 0, 0)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L))
Ma stratégie de trading est décrite comme suit: s'il y a un signal le jour t
, alors acheter le suivant le jour t + 1
au cours d'ouverture et vendre au cours de clôture. Dans mon exemple de jeu de données, il y a un signal le jour 2, donc j'achète le jour 3 et je vends au cours de clôture du jour 3. J'investis 100 $, donc j'ai un gain au jour 3 de 3 $. Le signal suivant arrive le jour 5, donc j'investis mes 103 $ le jour 6 et j'obtiens 3 dollars supplémentaires. Ce tableau illustre ma stratégie de trading:
date open close return signal trading.strategy capital <date> <dbl> <dbl> <dbl> <dbl> 1 2015-01-20 213. 211. -1 0 - 100 2 2015-01-21 211. 227. 7 1 - 100 3 2015-01-22 227. 233. 3 0 buy+sell 103 4 2015-01-23 234. 233. 0 0 - 103 5 2015-01-24 233. 248. 7 1 - 103 6 2015-01-25 247. 254. 3 0 buy+sell 106 7 2015-01-26 254. 273. 8 1 - 106 8 2015-01-27 273. 263. -4 0 buy+sell 102 9 2015-01-28 263. 234. -11 0 - 102 10 2015-01-29 233. 234. 0 0 - 102
Quelqu'un peut-il m'aider à écrire une fonction, qui exécute ma stratégie de trading?
Voici mes données:
date open close return signal <date> <dbl> <dbl> <dbl> <dbl> 1 2015-01-20 213. 211. -1 0 2 2015-01-21 211. 227. 7 1 3 2015-01-22 227. 233. 3 0 4 2015-01-23 234. 233. 0 0 5 2015-01-24 233. 248. 7 1 6 2015-01-25 247. 254. 3 0 7 2015-01-26 254. 273. 8 1 8 2015-01-27 273. 263. -4 0 9 2015-01-28 263. 234. -11 0 10 2015-01-29 233. 234. 0 0
3 Réponses :
Vous pouvez faire quelque chose comme ceci:
library(tidyverse) df %>% mutate(trading.strategy = if_else(lag(signal) == 1, "buy+sell", "-")) %>% filter(trading.strategy == "buy+sell") %>% mutate(capital = 100 + cumsum(return)) %>% right_join(df) %>% fill(capital) %>% mutate(capital = if_else(is.na(capital), 100, capital), trading.strategy = if_else(is.na(trading.strategy), "-", trading.strategy)) date open close return signal trading.strategy capital <date> <dbl> <dbl> <dbl> <dbl> <chr> <dbl> 1 2015-01-20 213. 211. -1 0 - 100 2 2015-01-21 211. 227. 7 1 - 100 3 2015-01-22 227. 233. 3 0 buy+sell 103 4 2015-01-23 234. 233. 0 0 - 103 5 2015-01-24 233. 248. 7 1 - 103 6 2015-01-25 247. 254. 3 0 buy+sell 106 7 2015-01-26 254. 273. 8 1 - 106 8 2015-01-27 273. 263. -4 0 buy+sell 102 9 2015-01-28 263. 234. -11 0 - 102 10 2015-01-29 233. 234. 0 0 - 102
@Lennyy. Notez que cela ne donnera un résultat correct que lorsque le capital initial est de 100 et est incorrect sinon, voir les modifications que j'ai apportées à ma réponse
@Lennyy, dans le dernier mutation
, vous pouvez utiliser par exemple capital = replace_na (capital, 100)
, la même chose pourrait être appliquée à la trading.strategy
.
library(dplyr) initial_capital <- 10000 df %>% mutate( trade = ifelse(lag(signal, default = 0), 1, 0), trading.strategy = ifelse(trade, "buy+sell", "-"), days_return = trade * (close - open) / (open), cum_return = cumsum(days_return), capital = initial_capital * (1 + cum_return) ) %>% select(-trade,-return) # A tibble: 10 x 8 date open close signal trading.strategy days_return cum_return capital <date> <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <dbl> 1 2015-01-20 213. 211. 0 - 0 0 10000 2 2015-01-21 211. 227. 1 - 0 0 10000 3 2015-01-22 227. 233. 0 buy+sell 0.0268 0.0268 10268. 4 2015-01-23 234. 233. 0 - 0 0.0268 10268. 5 2015-01-24 233. 248. 1 - 0 0.0268 10268. 6 2015-01-25 247. 254. 0 buy+sell 0.0258 0.0525 10525. 7 2015-01-26 254. 273. 1 - 0 0.0525 10525. 8 2015-01-27 273. 263. 0 buy+sell -0.0355 0.0171 10171. 9 2015-01-28 263. 234. 0 - 0 0.0171 10171. 10 2015-01-29 233. 234. 0 - 0 0.0171 10171.
Je ne fais que développer la stratégie @Lennyy, veuillez ne pas considérer cela comme une solution indépendante:
library(tidyverse) CPTL = 100 right_join( filter(dat, lag(signal == 1)) %>% mutate( trading.strategy = 'buy+sell', capital = CPTL + cumsum(return / 100) * CPTL ), dat ) %>% mutate( capital = replace_na(fill(., capital)$capital, CPTL), trading.strategy = replace_na(trading.strategy, '-') ) # A tibble: 10 x 7 # date open close return signal trading.strategy capital # <date> <dbl> <dbl> <dbl> <dbl> <chr> <dbl> # 1 2015-01-20 213. 211. -1 0 - 100 # 2 2015-01-21 211. 227. 7 1 - 100 # 3 2015-01-22 227. 233. 3 0 buy+sell 103 # 4 2015-01-23 234. 233. 0 0 - 103 # 5 2015-01-24 233. 248. 7 1 - 103 # 6 2015-01-25 247. 254. 3 0 buy+sell 106 # 7 2015-01-26 254. 273. 8 1 - 106 # 8 2015-01-27 273. 263. -4 0 buy+sell 102 # 9 2015-01-28 263. 234. -11 0 - 102 #10 2015-01-29 233. 234. 0 0 - 102
BTW, dans ma réponse, j'ai supposé que
majuscule
devrait être102
dansligne 8
, puisquesignal
était1
à laligne 7
etreturn
était-4
à laligne 8
.De plus, est-ce que
return
est donné ou cette colonne doit-elle être générée en fonction des variablesopen
etclose
?@Lennyy oui vous avez raison. J'ai changé ce numéro.
@ Lennyy la colonne de retour est calculée sur les variables
open
etclose
:return = (open-close) / open
@Lennyy avez-vous des idées sur la façon dont je peux considérer les coûts de transaction? Par exemple, chaque transaction entraîne des coûts de 2%.
@ Tobkel: pensez à poser une nouvelle question à ce sujet