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

PROBLEMA 6

Definicion de constantes y funciones.

Creamos 3 funciones:
  1. func_Clean : Función que elimina los activos con menos de 30 observaciones.
  2. func_CalcBeneficios : Función que cálcula los beneficios al final del día.
  3. func_CalcOutput : Función que cálcula los output del problema, agregaciones: totales, promedios, etc.
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))

PROBLEMA 7

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))

PROBLEMA 8

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)