R - questions

Paolo1956

LOREM IPSUM
Registrato
20/6/10
Messaggi
7.053
Punti reazioni
850
Visto che molti di noi usano R,

possiamo porre qui domande su problemi incontrati.

Inizio io col prossimo post.
 
Nomi brevi dei mesi

- Carico un dataset che contiene una colonna di date con i nomi brevi dei mesi: Jan, Feb, .....

- Il problema è che le funzioni per convertire in data non mi riconoscono i nomi in inglese. Es

as.Date("15-Jan-17", format = "%d-%b-%y")
[1] NA

mentre:

as.Date("15-Gen-17", format = "%d-%b-%y")
[1] "2017-01-15"

- Provvisoriamente ho risolto via blocco note cambiando i nomi dei mesi, ma è chiaramente una soluzione del cavolo.

- Mi pare di ricordare che questo dipende dai settaggi di Windows.

- Vorrei una soluzione versatile che mi permetta di accedere a dataset di varia provenienza, in varie lingue senza doverne fare una copia modificata.
 
- Carico un dataset che contiene una colonna di date con i nomi brevi dei mesi: Jan, Feb, .....

- Il problema è che le funzioni per convertire in data non mi riconoscono i nomi in inglese. Es

as.Date("15-Jan-17", format = "%d-%b-%y")
[1] NA

mentre:

as.Date("15-Gen-17", format = "%d-%b-%y")
[1] "2017-01-15"

- Provvisoriamente ho risolto via blocco note cambiando i nomi dei mesi, ma è chiaramente una soluzione del cavolo.

- Mi pare di ricordare che questo dipende dai settaggi di Windows.

- Vorrei una soluzione versatile che mi permetta di accedere a dataset di varia provenienza, in varie lingue senza doverne fare una copia modificata.

Immagino siano i nav/dati di etf di vari emittenti. Provato a giocare col comando gsub() e far sostituire a R anziche' farlo a mano ??O creare una funzione cosi' a partire da:
stock$V2=ifelse(stock$V2=="jan",1,stock$V2)
stock$V2=ifelse(stock$V2=="feb",2,stock$V2)
stock$V2=ifelse(stock$V2=="mar",3,stock$V2)
stock$V2=ifelse(stock$V2=="apr",4,stock$V2)
stock$V2=ifelse(stock$V2=="may",5,stock$V2)
stock$V2=ifelse(stock$V2=="jun",6,stock$V2)
stock$V2=ifelse(stock$V2=="jul",7,stock$V2)
stock$V2=ifelse(stock$V2=="aug",8,stock$V2)
stock$V2=ifelse(stock$V2=="sep",9,stock$V2)
stock$V2=ifelse(stock$V2=="oct",10,stock$V2)
stock$V2=ifelse(stock$V2=="nov",11,stock$V2)
stock$V2=ifelse(stock$V2=="dec",12,stock$V2)

E poi passi il tutto a as.Date ..

:bye::bye:
 
Sì, dunque,
in realtà si tratta di dati economici, ma la sostanza non cambia.

Quello che pensavo io, invece di fare la sostituzione, è se era possibile avvertire la funzione di conversione che i nomi sono in inglese, o in francese, o in turco o quello che è, dato che si tratta di nomi standard. Mi ricordo che in VB.Net si poteva fare...
 
Allora, risolto con la libreria <readr>:

myData_1 <- read_csv("myFile.csv",
+ locale = locale(date_names = "en", date_format = "%d-%b-%y"))

che riconosce automaticamente la colonna delle date e le importa nel formato YYYY-MM-DD

per cambiare lingua basta cambiare il campo date_names
 
- Vorrei una soluzione versatile che mi permetta di accedere a dataset di varia provenienza, in varie lingue senza doverne fare una copia modificata.
Codice:
Sys.setlocale(category = "LC_TIME", locale = "C")
 
Colgo l'occasione per chiedere aiuto su un problema, temo, più complesso di quello di Paolo.
Come simulare in backtesting un'operatività At-LIMIT?
Lo script sottostante carica un paio di mesi di dati SPY da yahoo togliendo Volume e Adjusted e aggiungendo un segnale di buy/sell (nell'esempio, random):
Codice:
library(quantmod)
price <- getSymbols("SPY", from = "2019-01-01", to = "2019-03-1", auto.assign = FALSE)
spy   <- price[,1:5]
spy[,5] <- rbinom(length(spy[,1]), 1, 0.5)
colnames(spy) <- c("Open","High","Low","Close","SIGNAL")
head(spy)

             Open   High    Low  Close SIGNAL
# 2019-01-02 245.98 251.21 245.95 250.18      0
# 2019-01-03 248.23 248.57 243.67 244.21      1
# 2019-01-04 247.59 253.11 247.17 252.39      1
# 2019-01-07 252.69 255.95 251.69 254.38      1
# 2019-01-08 256.82 257.31 254.00 256.77      0
# 2019-01-09 257.56 258.91 256.19 257.97      1

Ora come simulare un'operatività di questo tipo?

Se SIGNAL ieri = 0 e SIGNAL oggi = 1 compera DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Se SIGNAL ieri = 1 e SIGNAL oggi = 0 vendi DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Ho trascurato per ora i costi di transazione perché possono essere di tipo diverso (%, fissi, un tanto a titolo etc.)
Ovviamente l'output della funzione dovrebbe essere un vettore (sempre xts, per comodità) con i rendimenti aritmetici generati dalla strategia.
Grazie in anticipo
 
Codice:
Sys.setlocale(category = "LC_TIME", locale = "C")

OK!

(Caffè pagato se passi da queste parti)

Ovviamente penso sia il caso di fare qualcosa del genere:
Codice:
oldLoc <- Sys.getLocale("LC_TIME")
Sys.setlocale(category = "LC_TIME", locale = "C")
mio codice
......
Sys.setlocale(category = "LC_TIME", locale = oldLoc)

per non avere casini poi durante la sessione
 
Colgo l'occasione per chiedere aiuto su un problema, temo, più complesso di quello di Paolo.
Come simulare in backtesting un'operatività At-LIMIT?
Lo script sottostante carica un paio di mesi di dati SPY da yahoo togliendo Volume e Adjusted e aggiungendo un segnale di buy/sell (nell'esempio, random):
Codice:
library(quantmod)
price <- getSymbols("SPY", from = "2019-01-01", to = "2019-03-1", auto.assign = FALSE)
spy   <- price[,1:5]
spy[,5] <- rbinom(length(spy[,1]), 1, 0.5)
colnames(spy) <- c("Open","High","Low","Close","SIGNAL")
head(spy)

             Open   High    Low  Close SIGNAL
# 2019-01-02 245.98 251.21 245.95 250.18      0
# 2019-01-03 248.23 248.57 243.67 244.21      1
# 2019-01-04 247.59 253.11 247.17 252.39      1
# 2019-01-07 252.69 255.95 251.69 254.38      1
# 2019-01-08 256.82 257.31 254.00 256.77      0
# 2019-01-09 257.56 258.91 256.19 257.97      1

Ora come simulare un'operatività di questo tipo?

Se SIGNAL ieri = 0 e SIGNAL oggi = 1 compera DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Se SIGNAL ieri = 1 e SIGNAL oggi = 0 vendi DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Ho trascurato per ora i costi di transazione perché possono essere di tipo diverso (%, fissi, un tanto a titolo etc.)
Ovviamente l'output della funzione dovrebbe essere un vettore (sempre xts, per comodità) con i rendimenti aritmetici generati dalla strategia.
Grazie in anticipo

la tua strategia mi pare sotto - specificata.
che cosa succede se per es. oggi arriva un segnale di vendita e domani i prezzi sono costantemente sotto la chiusura di oggi? A quello che capisco non vendi mai...
 
la tua strategia mi pare sotto - specificata.
Paolo, non è una strategia è solo un esempio.
Chiaramente l'operatività at-limit (comunissima nei mercati azionari e molto diffusa nella borsa Italiana) sarà inserita in una strategia che dovrà tener conto di altre mille cose...
Nell'esempio ho scelto, per comodità, il Close precedente come prezzo Limit, ma potrebbe essere qualsiasi altro prezzo.

Il mio interesse è solo sullo script: è abbastanza facile simulare un'operatività at-limit chiudendo la posizione al Close della medesima giornata, ma ho difficoltà nel considerare il caso 'reale' dove uno può restare sul titolo per parecchi giorni.
 
Colgo l'occasione per chiedere aiuto su un problema, temo, più complesso di quello di Paolo.
Come simulare in backtesting un'operatività At-LIMIT?
Lo script sottostante carica un paio di mesi di dati SPY da yahoo togliendo Volume e Adjusted e aggiungendo un segnale di buy/sell (nell'esempio, random):
Codice:
library(quantmod)
price <- getSymbols("SPY", from = "2019-01-01", to = "2019-03-1", auto.assign = FALSE)
spy   <- price[,1:5]
spy[,5] <- rbinom(length(spy[,1]), 1, 0.5)
colnames(spy) <- c("Open","High","Low","Close","SIGNAL")
head(spy)

             Open   High    Low  Close SIGNAL
# 2019-01-02 245.98 251.21 245.95 250.18      0
# 2019-01-03 248.23 248.57 243.67 244.21      1
# 2019-01-04 247.59 253.11 247.17 252.39      1
# 2019-01-07 252.69 255.95 251.69 254.38      1
# 2019-01-08 256.82 257.31 254.00 256.77      0
# 2019-01-09 257.56 258.91 256.19 257.97      1

Ora come simulare un'operatività di questo tipo?

Se SIGNAL ieri = 0 e SIGNAL oggi = 1 compera DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Se SIGNAL ieri = 1 e SIGNAL oggi = 0 vendi DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Ho trascurato per ora i costi di transazione perché possono essere di tipo diverso (%, fissi, un tanto a titolo etc.)
Ovviamente l'output della funzione dovrebbe essere un vettore (sempre xts, per comodità) con i rendimenti aritmetici generati dalla strategia.
Grazie in anticipo

Non è difficile o non ho capito bene la domanda. La cosa la puoi fare anche con excel. Se invece utilizzi linguaggi di programmazione devi dapprima caricare il vettore dei prezzi "x" nel DB quindi richiamarlo nello script (Puoi fare due colonne la prima la chiami ID dove ci saranno 1,2,3,4....., la seconda SPY dove ci saranno i prezzi al CLOSE time, in tal caso più che un vettore avrai una matrice). Poi ti crei un programma in cui espliciti tutte le clausole del tuo modello. Per calcolare il vettore dei guadagni e delle perdite ti consiglio di procedere nel seguente modo ti misuri inizialmente il size della matrice (così lo script diventa indipendente dal tempo, quindi significa dal numero di righe, e lo puoi riutilizzare in altri programmi) e quindi fai partire un ciclo for. che esamina per ogni giorno se l'evento descritto nelle clausole si è verificato o meno. Nel caso si verifichi l'evento non vi è neanche bisogno di far apparire 1 o 0 ma direttamente prendi il vettore dei prezzi (x(i)/x(i-1)-1) supponendo che vai Long. Infine suppongo dovrai calcolare la equity line. In tal caso ti conviene creare un altro script chiamato per esempio Capitalizzazione a cui dai impasto il vettore dei guadagni/perdite. Consiglio sempre di impostare ogni script con il calcolo immediato delle dimensioni della matrice che gli dai in pasto così che ogni script è sempre indipendente dal tempo o meglio non devi più reimpostare l'inizio e la fine del ciclo for ma si calcola questi estremi automaticamente. Ulteriormente se vuoi testare la tua strategia su più asset class allora puoi creare gli script con un doppio ciclo for in modo tale che dopo SPY per esempio valuti quel modello per QLD o campio Euro/Dollaro. In tal caso non ti resta che scaricarti i prezzi di più asset class per il periodo che vuoi caricarli nel DB e premere Enter.

PS
Se riesci già a fare questo allora possiamo migliorare ulteriormente il codice e velocizzarlo.
 
Ultima modifica:
Colgo l'occasione per chiedere aiuto su un problema, temo, più complesso di quello di Paolo.
Come simulare in backtesting un'operatività At-LIMIT?
Lo script sottostante carica un paio di mesi di dati SPY da yahoo togliendo Volume e Adjusted e aggiungendo un segnale di buy/sell (nell'esempio, random):
Codice:
library(quantmod)
price <- getSymbols("SPY", from = "2019-01-01", to = "2019-03-1", auto.assign = FALSE)
spy   <- price[,1:5]
spy[,5] <- rbinom(length(spy[,1]), 1, 0.5)
colnames(spy) <- c("Open","High","Low","Close","SIGNAL")
head(spy)

             Open   High    Low  Close SIGNAL
# 2019-01-02 245.98 251.21 245.95 250.18      0
# 2019-01-03 248.23 248.57 243.67 244.21      1
# 2019-01-04 247.59 253.11 247.17 252.39      1
# 2019-01-07 252.69 255.95 251.69 254.38      1
# 2019-01-08 256.82 257.31 254.00 256.77      0
# 2019-01-09 257.56 258.91 256.19 257.97      1

Ora come simulare un'operatività di questo tipo?

Se SIGNAL ieri = 0 e SIGNAL oggi = 1 compera DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Se SIGNAL ieri = 1 e SIGNAL oggi = 0 vendi DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Ho trascurato per ora i costi di transazione perché possono essere di tipo diverso (%, fissi, un tanto a titolo etc.)
Ovviamente l'output della funzione dovrebbe essere un vettore (sempre xts, per comodità) con i rendimenti aritmetici generati dalla strategia.
Grazie in anticipo
Sconsiglio vivamente di fare queste cose "a mano" per evitare errori e altrettanto vivamente suggerisco di usare le opportune funzioni di quantstrat, ci pensano poi le librerie a valutare se hai eseguito, a che prezzo e senza sguardi al futuro.
 
Grazie per il contributo, Amartya. Ho però dimenticato di dire che per motivi vari non voglio/posso usare i cicli for/next. Devono essere presenti solo calcoli vettoriali.

Sconsiglio vivamente di fare queste cose "a mano" per evitare errori e altrettanto vivamente suggerisco di usare le opportune funzioni di quantstrat, ci pensano poi le librerie a valutare se hai eseguito, a che prezzo e senza sguardi al futuro.
Avevo scartato quantstrat perché ne ho sentito parlare male (dicevano troppo lento) e, onestamente, non avevo notato l'esistenza di 'limit' tra i vary ordertype
Molte grazie.
 
Devono essere presenti solo calcoli vettoriali.

non mi è chiaro cosa intendi. L'unica cosa che riesco ad immaginare è che tu voglia calcolare il vettore gain/loss non tramite un ciclo for ma utilizzando l'algebra tra vettori. Supponendo pure che si possa fare (anche se non l'ho mai fatto in tal senso) mi risulta difficile a come far lavorare questo calcolo vettoriale con le clausole che determinano l'entrata o l'uscita o il non entrare nel mercato.
Il limite di questo approccio è che tu devi controllare rispetto al time frame che ti sei imposto (1 min, 1h, 1 gg, 1 settimana, etc etc) se le condizioni del mercato sono quelle previste dal modello. Il modo più intuitivo per farlo è appunto il ciclo FOR ...quindi PER ogni time frame controlla che......quindi......
L'algebra vettoriale è certamente velocissima, e stai parlando con uno che vettorializza tutto vuoi per la velocità vuoi perchè vettorializzando tutto a quel punto i sorgenti sono indipendenti da qualsiasi variabile dimensionale, ma, credo, si possa utilizzare se e solo se la dimensione del vettore corrisponde al tuo time frame.

Per essere più chiaro supponendo che il vettore dei prezzi sia 100*1(una sola asset class) ed il tuo modello necessita di controllare le variazioni, immagino, ad ogni prezzo allora hai 100 controlli da fare e quindi non vedo come si possa utilizzare l'algebra vettoriale in un questa fattispecie.
Laddove esistono le parole "ad ogni" non puoi prescindere dal ciclo for...mi verrebbe da dire.

In ogni caso anche se tu stai usando il ciclo for sempre di calcolo vettoriale si parla (nel modo che ti ho suggerito), non stai solo utilizzando l'algebra vettoriale o matriciale che dir si voglia. Quella appunto la puoi utilizzare se e solo se prendi in considerazione il singolo vettore come elemento singolo per operare e non già la cella occupata, in tal caso, credo, che tu non possa prescindere dal ciclo for....

Infine per la validazione sia del modello sia dello script il mio consiglio è quello di replicare se è possibile staticamente il modello su un foglio di calcolo tipo excel quindi lo costruisci in linguaggio di programmazione a quel punto ti crei un punto fisso (cioè un set di variabili di default) per cui sia il foglio excel sia il programma devono restituirti lo stesso identico risultato.
 
Colgo l'occasione per chiedere aiuto su un problema, temo, più complesso di quello di Paolo.
Come simulare in backtesting un'operatività At-LIMIT?
Lo script sottostante carica un paio di mesi di dati SPY da yahoo togliendo Volume e Adjusted e aggiungendo un segnale di buy/sell (nell'esempio, random):
Codice:
library(quantmod)
price <- getSymbols("SPY", from = "2019-01-01", to = "2019-03-1", auto.assign = FALSE)
spy   <- price[,1:5]
spy[,5] <- rbinom(length(spy[,1]), 1, 0.5)
colnames(spy) <- c("Open","High","Low","Close","SIGNAL")
head(spy)

             Open   High    Low  Close SIGNAL
# 2019-01-02 245.98 251.21 245.95 250.18      0
# 2019-01-03 248.23 248.57 243.67 244.21      1
# 2019-01-04 247.59 253.11 247.17 252.39      1
# 2019-01-07 252.69 255.95 251.69 254.38      1
# 2019-01-08 256.82 257.31 254.00 256.77      0
# 2019-01-09 257.56 258.91 256.19 257.97      1

Ora come simulare un'operatività di questo tipo?

Se SIGNAL ieri = 0 e SIGNAL oggi = 1 compera DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Se SIGNAL ieri = 1 e SIGNAL oggi = 0 vendi DOMANI X titoli con prezzo AT-LIMIT pari al CLOSE di oggi

Ho trascurato per ora i costi di transazione perché possono essere di tipo diverso (%, fissi, un tanto a titolo etc.)
Ovviamente l'output della funzione dovrebbe essere un vettore (sempre xts, per comodità) con i rendimenti aritmetici generati dalla strategia.
Grazie in anticipo
Il modo più rapido per fare quello che dici senza usare cicli penso sia questo:
Codice:
spy$limit_price_buy <- ifelse(lag(spy$SIGNAL, 2) == 0 & lag(spy$SIGNAL) == 1, lag(spy$Close), NA)
spy$limit_price_sell <- ifelse(lag(spy$SIGNAL, 2) == 1 & lag(spy$SIGNAL) == 0, lag(spy$Close), NA)
spy$order_buy <- ifelse(spy$Low <= spy$limit_price_buy, 1, NA)
spy$order_sell <- ifelse(spy$Low <= spy$limit_price_buy, 1, NA)
A parte il solito ifelse() vettorizzato, per muoversi avanti e indietro nel tempo di un oggetto di classe xts lag.xts può fare al caso tuo.
Avevo scartato quantstrat perché ne ho sentito parlare male (dicevano troppo lento) e, onestamente, non avevo notato l'esistenza di 'limit' tra i vary ordertype
Molte grazie.
quantstrat non è veloce, è vero.

Questo accade perchè per il calcolo delle transazioni alimenta un oggetto chiamato blotter, che in pratica ricalcola tutta la vostra posizione contabile ogni volta che si fa una transazione.

Questo richiede necessariamente di sapere quali erano le condizioni del portafoglio e del conto nell'istante prima, e quindi non si può vettorizzare: bisogna passare per forza di cose per la mannaia di un ciclo.
non mi è chiaro cosa intendi. L'unica cosa che riesco ad immaginare è che tu voglia calcolare il vettore gain/loss non tramite un ciclo for ma utilizzando l'algebra tra vettori.
Lui non parla di "vettorizzare" nel senso di algebra di matrici: si riferisce al fatto che in linguaggi come R e Python i cicli sono computazionalmente dispendiosi a differenza di quanto accade ad es. nel C++, quindi dove è possibile (ovvero dove il risultato dell'iterazione successiva non deve dipendere strettamente dal risultato dell'iterazione precedente) è meglio usare le funzioni base del linguaggio che fanno la chiamata direttamente a codice compilato in C/C++.

Comunque in R si possono usare senza problemi cicli purché si preallochi in memoria la dimensione del vettore o della matrice prima di partire: in questo caso le performance non sono così male; il vero problema è nel classico ciclo che "appende" roba in un contenitore.

Ad esempio questo in C++ è praticamente senza sforzo alcuno:
Codice:
std::vector< int > my_vector;

for (unsigned int i = 0; i < n; ++i)
{
  my_vector.push_back(i * 2);
}
La stessa cosa in R è pesantissima e da evitare come la peste:
Codice:
my_vector <- array()

for (i in 1:n)
{
  my_vector <- append(my_vector, i * 2)
}
La versione vettorizzata fa una velocissima chiamata C e non pesa nulla:
Codice:
my_vector <- 1:n * 2
Si usa direttamente il vettore 1:n e il ciclo in C che fa il calcolo è nascosto sotto.
 
Ultima modifica:
Grazie Amartya, Cren ti ha risposto meglio di quanto potessi fare io.

Il modo più rapido per fare quello che dici senza usare cicli penso sia questo:
Codice:
spy$limit_price_buy <- ifelse(lag(spy$SIGNAL, 2) == 0 & lag(spy$SIGNAL) == 1, lag(spy$Close), NA)
spy$limit_price_sell <- ifelse(lag(spy$SIGNAL, 2) == 1 & lag(spy$SIGNAL) == 0, lag(spy$Close), NA)
spy$order_buy <- ifelse(spy$Low <= spy$limit_price_buy, 1, NA)
spy$order_sell <- ifelse(spy$Low <= spy$limit_price_buy, 1, NA)
A parte il solito ifelse() vettorizzato, per muoversi avanti e indietro nel tempo di un oggetto di classe xts lag.xts può fare al caso tuo.

quantstrat non è veloce, è vero.

Il problema che vedo è che quando entra un ordine limit al prezzo X (supponiamo BUY), possono accadere 3 cose il giorno dopo:

1. l'ordine viene eseguito a prezzo X se Low <= X <= High and Open > X, per cui il return del giorno sarà Close/X-1
2. L'ordine viene eseguito al prezzo Open se X <= Open, per cui il return sarà Close/Open-1
3 l'ordine non viene eseguito se X < Low

Negli altri giorni (quando spy$SIGNAL == lag(spy$SIGNAL) )i return sono calcolati nel solito modo (Close/lag(Close)-1) se spySignal ==1, altrimenti sarà 0 (zero)

Nel caso del sell (parlo di operatività Buy/exit, senza short per ora) le cose cambiano ma non troppo: il prezzo 'pivot' per il calcolo del return sarà il Close del giorno e i riferimenti possibili saranno X, oppure l'Open del giorno dopo, oppure il Close del giorno dopo se X > High (caso in cui l'ordine non viene eseguito)

Ma forse mi sto perdendo in bicchiere d'acqua :-)
 
Ultima modifica:
Indietro