Ejercio práctico de programación en R para el master en IA de mercados de BME. ¡¡ Maldito confinamiento y no echan nada en Netflix !!.
library(dplyr)
library(highcharter)
library(DT)
library(reshape2)
library(tidyr)
df<-read.csv('ibex_data.csv',sep=',',stringsAsFactors = FALSE)
lista<-names(df)
lista[1]<- 'Stock'
lista[2]<- 'Date'
names(df)<-lista
Definicion de constantes y funciones.
num_min_days <- 30
stop_Profit <- 0.03
stop_Loss <- 0.1
Capital<-30000
coste<-0.0003
##### FUNCION DE LIMIPIEZA
func_Clean<-function(df){
dfClean <- df %>% select(Stock) %>% group_by(Stock) %>% summarize(n())
cond <- (dfClean$`n()` < num_min_days)
stock_to_drop <-dfClean[cond,"Stock"]
#print(stock_to_drop)
condClean <- df$Stock %in% stock_to_drop
df<-df[!condClean,]
#print('*************')
#print(' DATAFRAME LIMPIO: ')
#print(dim(df))
#print('*************')
return(df)
}
#### FUNCION DE CALCULO DE PRECIO DE VENTA, BENEFICIO
func_CalcBeneficios<-function(df,stop_Loss,stop_Profit,Capital,coste){
df$Var_Loss <- df$open - df$low
df$Var_Profit <- df$high - df$open
df$cond_Loss <- ifelse(df$Var_Loss >= stop_Loss,TRUE,FALSE)
df$cond_Profit <- ifelse(df$Var_Profit >= stop_Profit,TRUE,FALSE)
# OJO SE CALCULA RESTO DE LA COMPRA #############
df$Num_Acc <- (Capital*(1-coste)) %/% df$open ### DIVISION ENTERAS
df$Resto <- Capital - df$Num_Acc*df$open*(1+coste)
cond1 <- !((df$cond_Loss) | (df$cond_Profit)) ### NO TOCA NINGUNA DE LAS BARRERAS
cond2 <- ((df$cond_Loss) & (df$cond_Profit)) ### TOCA LAS DOS BARRERAS
cond3 <- ((df$cond_Loss) & (!df$cond_Profit)) ### SOLO TOCA PERDIDAS
cond4 <- ((df$cond_Profit) & (!df$cond_Loss)) ### SOLO TOCA BENEFICIOS
df$price_Sell <-0
df[cond1,'price_Sell'] = df[cond1,'close']
df[cond2,'price_Sell'] = df[cond2,'open'] - stop_Loss
df[cond3,'price_Sell'] = df[cond3,'open'] - stop_Loss
df[cond4,'price_Sell'] = df[cond4,'open'] + stop_Profit
df$Sell <- df$Num_Acc * df$price_Sell*(1-coste)
df$Beneficio <- df$Resto + df$Sell - Capital
df$dayPositiv <- df$Beneficio > 0
#print('*************************')
#print('DATA FRAME CALCULADO:')
#print(dim(df))
#print('*************************')
return(df)
}
##### CALCULAR FUNCION DE OUTPUT AGREGADOS #########
func_CalcOutput <-function(df){
Beneficio_Acumulado <- df %>% group_by(Stock) %>% summarise(sum(Beneficio),
mean(Beneficio),
n(),
mean(Var_Profit),
mean(Var_Loss),
100*sum(dayPositiv)/n(),
100*(1- sum(dayPositiv)/n())
)
names(Beneficio_Acumulado) <- c('Stock','Beneficio Total','Beneficio Promedio','Número de Operaciones','Promedio Horquilla Superior','Promedio Horquilla Inferior',
'Porcentaje Días Postivos','Porcentaje Días Negativos')
return(Beneficio_Acumulado)
}
func_CalcOutput_2 <-function(df){
Beneficio_Acumulado <- df %>% group_by(Stock) %>% summarise(sum(Beneficio),
mean(Beneficio),
n(),
mean(Var_Profit),
mean(Var_Loss),
100*sum(dayPositiv)/n(),
100*(1- sum(dayPositiv)/n()),
mean(Beneficio_por_Euro)
)
names(Beneficio_Acumulado) <- c('Stock','Beneficio Total','Beneficio Promedio','Número de Operaciones','Promedio Horquilla Superior','Promedio Horquilla Inferior',
'Porcentaje Días Postivos','Porcentaje Días Negativos','Beneficio Por euro invertido medio')
return(Beneficio_Acumulado)
}
Realizamos los cálculos:
df_1 <- func_Clean(df)
df_1 <- func_CalcBeneficios(df_1,stop_Loss,stop_Profit,Capital,coste)
df_Total <- func_CalcOutput(df_1)
datatable(df_Total)
Representamos a uno de los activos como ejemplo: ZEL
dg <- df_1[df_1$Stock == 'ZEL',]
dg$Beneficios_Acumulados <-cumsum(dg$Beneficio)
hchart(dg,"line",hcaes(x=Date,y=Beneficios_Acumulados))
Leemos un nuevo fichero que aportará una nueva señal al problema. Solo se realizarán compras y ventas los días que el valor de esta señal sea > 0,75. Debemos pivotar el fichero para hacer un merge con nuestro bote anterior, eliminando previamente los missing values. A continuación limnpiamos el fichero con el mismo criterio anterior, se calculan los beneficios y agregados de la misma manera pero se añade la condición de compra / venta para solo aquellos días en los que la nueva señal es > 0.75
price_apertura <- read.csv('price_departures.csv',sep=',')
price_apertura <- melt(price_apertura,id.vars =names(price_apertura)[1],measure.vars = names(price_apertura)[2:length(price_apertura)])
price_apertura <- price_apertura[!is.na(price_apertura$value),]
names(price_apertura) <- c('Date','Stock','Price')
df_merge <- merge(df,price_apertura)
df_merge <- func_Clean(df_merge)
df_2 <- df_merge
df_merge <- func_CalcBeneficios(df_merge,stop_Loss,stop_Profit,Capital,coste)
cond_drop <- df_merge$Price >= 0.75
df_merge <- df_merge[cond_drop,]
df_Total2 <- func_CalcOutput(df_merge)
datatable(df_Total2)
Cómo en el caso anterior representamos el valor ‘ZEL’
dg <- df_merge[df_merge$Stock == 'ZEL',]
dg$Beneficios_Acumulados <-cumsum(dg$Beneficio)
hchart(dg,"line",hcaes(x=Date,y=Beneficios_Acumulados))
Interpretamos que el capital cada día se calcula con el valor medio histórico de cada stock por el volumen diario y multiplicado por 0.005.
df_2['Var_Loss_2'] <- df_2['open'] - df_2['low']
df_2['Var_Profit_2'] <- df_2['high'] - df_2['open']
df_2_gr <- df_2 %>% group_by(Stock) %>% summarise(quantile(Var_Profit_2,0.3),quantile(Var_Loss_2,0.8),mean(close))
names(df_2_gr) <- c('Stock','stop_Loss_Per','stop_Profit_Per','close_mean')
df_2 <- merge(df_2,df_2_gr)
df_2$Cap_Per <- 0.0005 * df_2$vol * df_2$close_mean
df_2$cond_Loss <- ifelse(df_2$Var_Loss_2 >= df_2$stop_Loss_Per,TRUE,FALSE)
df_2$cond_Profit <- ifelse(df_2$Var_Profit_2 >= df_2$stop_Profit_Per,TRUE,FALSE)
df_2$Num_Acc <- (df_2$Cap_Per*(1-coste)) %/% df_2$open ### DIVISION ENTERAS
df_2$Resto <- df_2$Cap_Per - df_2$Num_Acc*df_2$open*(1+coste)
cond1 <- !((df_2$cond_Loss) | (df_2$cond_Profit)) ### NO TOCA NINGUNA DE LAS BARRERAS
cond2 <- ((df_2$cond_Loss) & (df_2$cond_Profit)) ### TOCA LAS DOS BARRERAS
cond3 <- ((df_2$cond_Loss) & (!df_2$cond_Profit)) ### SOLO TOCA PERDIDAS
cond4 <- ((df_2$cond_Profit) & (!df_2$cond_Loss)) ### SOLO TOCA BENEFICIOS
df_2$price_Sell <-0
df_2[cond1,'price_Sell'] = df_2[cond1,'close']
df_2[cond2,'price_Sell'] = df_2[cond2,'open'] - df_2[cond2,'stop_Loss_Per']
df_2[cond3,'price_Sell'] = df_2[cond3,'open'] - df_2[cond3,'stop_Loss_Per']
df_2[cond4,'price_Sell'] = df_2[cond4,'open'] + df_2[cond4,'stop_Profit_Per']
df_2$Sell <- df_2$Num_Acc * df_2$price_Sell*(1-coste)
df_2$Beneficio <- df_2$Resto + df_2$Sell - df_2$Cap_Per
df_2$dayPositiv <- df_2$Beneficio > 0
df_2$Beneficio_por_Euro <- df_2$Beneficio / df_2$Cap_Per
cond_drop <- df_2$Price >= 0.75
df_2 <- df_2[cond_drop,]
df_2['Var_Loss'] <- df_2['open'] - df_2['low']
df_2['Var_Profit'] <- df_2['high'] - df_2['open']
df_2 <- func_CalcOutput_2(df_2)
datatable(df_Total2)