2011-01-10 11 views
1

Ich versuche eine benutzerdefinierte Funktion zu erstellen, die die drawdown-Funktion aus dem tseries-Paket verwendet. Ich möchte diese Funktion auf den richtigen Wertebereich in der Funktion anwenden, aber obwohl dies eine ziemlich neue Frage ist, kann ich keine mögliche Lösung sehen.Auswählen des richtigen Wertebereichs innerhalb einer Funktion

Hier ist, was meine Datenrahmen wie folgt aussieht:

> subSetTrades 
    Instrument EntryTime ExitTime AccountValue 
1   JPM 2007-03-01 2007-04-10   6997 
2   JPM 2007-04-10 2007-05-29   7261 
3   JPM 2007-05-29 2007-07-18   7545 
4   JPM 2007-07-18 2007-07-19   7614 
5   JPM 2007-07-19 2007-08-22   7897 
6   JPM 2007-08-22 2007-08-28   7678 
7   JPM 2007-08-28 2007-09-17   7587 
8   JPM 2007-09-17 2007-10-17   7752 
9   JPM 2007-10-17 2007-10-29   7717 
10  JPM 2007-10-29 2007-11-02   7423 
11  KFT 2007-04-13 2007-05-14   6992 
12  KFT 2007-05-14 2007-05-21   6944 
13  KFT 2007-05-21 2007-07-09   7069 
14  KFT 2007-07-09 2007-07-16   6919 
15  KFT 2007-07-16 2007-07-27   6713 
16  KFT 2007-07-27 2007-09-07   6820 
17  KFT 2007-09-07 2007-10-12   6927 
18  KFT 2007-10-12 2007-11-28   6983 
19  KFT 2007-11-28 2007-12-18   6957 
20  KFT 2007-12-18 2008-02-20   7146 

Wenn ich die Werte manuell berechne ich meine Funktion ausgegeben werden soll, die Ergebnisse richtig sind:

# Apply the function to the dataframe 
with(subSetTrades, tapply(AccountValue, Instrument, MDD_Duration)) 
JPM KFT 
106 85 
> # Check the function for JPM 
> maxdrawdown(subSetTrades[1:10,4])$from 
[1] 5 
> maxdrawdown(subSetTrades[1:10,4])$to 
[1] 10 
> # Get the entry time for JPM on row 5 
> # Get the exit time for JPM on row 10 
> # Calculate the time difference 
> difftime(subSetTrades[10,3], subSetTrades[5,2], units='days') 
Time difference of 106 days 
# Check the calculations for the other Instrument 
> maxdrawdown(subSetTrades[11:20,4])$from 
[1] 3 
> maxdrawdown(subSetTrades[11:20,4])$to 
[1] 5 
> # Get the exittime on row 5 for KFT, get the entrytime for KFT on row 3, 
# and calculate the time difference 
> difftime(subSetTrades[15,3], subSetTrades[13,2]) 
Time difference of 67 days 

Wie Sie in der oben sehen können Beispiel: Meine benutzerdefinierte Funktion (MDD_Duration) gibt die richtigen Werte für JPM an, gibt aber die falschen Werte für KFT an: anstelle von 85 sollte das Ergebnis 67 sein. Die Funktion MDD_Duration ist die folgende:

Das manuelle Zurückverfolgen der Schritte dieser benutzerdefinierten Funktion zeigt, dass ein Problem bei der Berechnung mit den Zeilennummern "from" und "to" besteht (d. H. R muss die Werte von KFT für die Länge des Instruments anpassen, das ihm vorausging, in diesem Fall JPM). Für die mögliche Lösung muss R tun so etwas wie:

den ‚von‘ Wert der maxdrawdown Funktion, wenn dieses Instrument der ersten (das heißt in oben auf der Liste) ist. Wenn das aktuelle Instrument jedoch das zweite (oder dritte usw.) ist, dann berücksichtigen Sie die Länge des vorherigen Instruments. Wenn also das Instrument JPM eine Länge von 10 hat, sollte die Suche nach den Werten von KFT bei +10 beginnen. Und die Suche nach den from und to Werten für Instrument 3 sollte am Länge des Instruments 1 + die Länge des Instruments startet 2.

Ich versuchte nrow in die Funktion (die die offensichtliche Lösung für diese Antwort scheint), was zu Fehlern bezüglich des Arguments der Länge 0 führte, obwohl nrow korrekt verwendet wurde (dh die gleiche Anweisung außerhalb der Funktion hat funktioniert). Ich habe auch versucht, die Daten innerhalb der Funktion zu unterteilen, was ebenfalls nicht funktionierte. Irgendwelche Ideen sind sehr willkommen. :)

Antwort

2

split ist dein Freund hier. Wenn ich Ihre Funktion ändern, damit es einen Datenrahmen mit den drei Variablen von Interesse erwartet (AccountValue, EntryTime, Exittime) wie folgt aus:

MDD_Duration <- function(x){ 
    # require(tseries) 
    # Get starting point 
    mdd_Start <- maxdrawdown(x$AccountValue)$from 
    mdd_StartDate <- x$EntryTime[mdd_Start] 
    # Get the endpoint 
    mdd_End <- maxdrawdown(x$AccountValue)$to 
    mdd_EndDate <- x$ExitTime[mdd_End] 
    return(difftime(mdd_EndDate, mdd_StartDate, units='days')) 
} 

Das können wir es auf die gespaltet Version Ihrer Daten anwenden:

> sapply(split(subSetTrades[,-1], subSetTrades[,1]), MDD_Duration) 
JPM KFT 
106 67 

Es könnte hilfreich sein, um zu sehen, was split auf Ihre Daten tun:

> split(subSetTrades[,-1], subSetTrades[,1]) 
$JPM 
    EntryTime ExitTime AccountValue 
1 2007-03-01 2007-04-10   6997 
2 2007-04-10 2007-05-29   7261 
3 2007-05-29 2007-07-18   7545 
4 2007-07-18 2007-07-19   7614 
5 2007-07-19 2007-08-22   7897 
6 2007-08-22 2007-08-28   7678 
7 2007-08-28 2007-09-17   7587 
8 2007-09-17 2007-10-17   7752 
9 2007-10-17 2007-10-29   7717 
10 2007-10-29 2007-11-02   7423 

$KFT 
    EntryTime ExitTime AccountValue 
11 2007-04-13 2007-05-14   6992 
12 2007-05-14 2007-05-21   6944 
13 2007-05-21 2007-07-09   7069 
14 2007-07-09 2007-07-16   6919 
15 2007-07-16 2007-07-27   6713 
16 2007-07-27 2007-09-07   6820 
17 2007-09-07 2007-10-12   6927 
18 2007-10-12 2007-11-28   6983 
19 2007-11-28 2007-12-18   6957 
20 2007-12-18 2008-02-20   7146 

Also, solange Sie eine Funktion haben, die mit einem Datum fra akzeptieren und arbeiten Ich/Teilmenge Ihres Datensatzes können wir split verwenden, um die Teilmengen und lapply oder sapply zu bilden, um unsere Funktion auf diese Teilmengen anzuwenden.

Vielleicht möchten Sie diese MDD_Duration() in Ihrer Funktion zu übernehmen:

MDD_Duration2 <- function(x){ 
    FUN <- function(x) { 
     # Get starting point 
     mdd_Start <- maxdrawdown(x$AccountValue)$from 
     mdd_StartDate <- x$EntryTime[mdd_Start] 
     # Get the endpoint 
     mdd_End <- maxdrawdown(x$AccountValue)$to 
     mdd_EndDate <- x$ExitTime[mdd_End] 
     return(difftime(mdd_EndDate, mdd_StartDate, units='days')) 
    } 
    sapply(split(x, droplevels(x[, "Instrument"])), FUN) 
} 

Wo wir die neue 2,12 (in R verwenden.x) Funktion droplevels auf x[, "Instrument"]) der Funktion zu ermöglichen, zu arbeiten, auch wenn wir eine einzige Ebene von Daten oder arbeitet auf einer Teilmenge der Daten:

> MDD_Duration2(subSetTrades) 
JPM KFT 
106 67 
> MDD_Duration2(subSetTrades[1:10,]) 
JPM 
106 
+1

Die Diskrepanz zwischen meinen ursprünglichen Ergebnissen und den von @ Jura25 zurückzuführen auf Ich habe vergessen, 'EntryTime' und' ExitTime' in Objekte der Klasse '' Date' 'zu konvertieren, wenn die Daten aus dem Post gelesen werden. Ich habe meine Antwort auf die korrigierten Daten erneut ausgeführt und repliziert nun die Ergebnisse von @ Jura25. –

+0

Danke Gavin, das funktioniert wie ein Zauber! Danke auch für die klare Veranschaulichung der Verwendung von "Split", die es gut zu verstehen machte. Ich mag Ihre 'Droplevel'-Anweisung in der MDD_Duration-Funktion und habe diese in mein Skript integriert. Vielen Dank! :) – Jura25

Verwandte Themen