Konvertieren Sie täglich Pandas-Bestandsdaten zu monatlichen Daten mit dem ersten Handelstag des Monats

Ich habe einen Satz von berechneten OHLCVA täglichen Wertpapierdaten in einem pandas dataframe wie folgt:

>>> type(data_dy) <class 'pandas.core.frame.DataFrame'> >>> data_dy Open High Low Close Volume Adj Close Date 2012-12-28 140.64 141.42 139.87 140.03 148806700 134.63 2012-12-31 139.66 142.56 139.54 142.41 243935200 136.92 2013-01-02 145.11 146.15 144.73 146.06 192059000 140.43 2013-01-03 145.99 146.37 145.34 145.73 144761800 140.11 2013-01-04 145.97 146.61 145.67 146.37 116817700 140.72 [5 rows x 6 columns] 

Ich verwende das folgende Wörterbuch und die Pandas-Resample-Funktion, um das Dataframe in monatliche Daten zu konvertieren:

 >>> ohlc_dict = {'Open':'first','High':'max','Low':'min','Close': 'last','Volume': 'sum','Adj Close': 'last'} >>> data_dy.resample('M', how=ohlc_dict, closed='right', label='right') Volume Adj Close High Low Close Open Date 2012-12-31 392741900 136.92 142.56 139.54 142.41 140.64 2013-01-31 453638500 140.72 146.61 144.73 146.37 145.11 [2 rows x 6 columns] 

Das macht die Berechnungen richtig, aber ich würde gerne die Yahoo! Datum Konvention für monatliche Daten der Verwendung des ersten Handelstages der Periode statt der letzten Kalendertag der Periode, die Pandas verwendet.

So würde ich gerne die Antwort sein:

  Volume Adj Close High Low Close Open Date 2012-12-28 392741900 136.92 142.56 139.54 142.41 140.64 2013-01-02 453638500 140.72 146.61 144.73 146.37 145.11 

Ich könnte dies tun, indem ich die täglichen Daten in eine Python-Liste umwandle, die Daten verarbeitet und die Daten an ein Dataframe zurückgibst, aber wie kann man das mit Pandas machen?

  • Ändern einer Teilmenge von Zeilen in einem Pandas-Dataframe
  • Setzen Sie den Wert für eine ausgewählte Zelle in pandas DataFrame
  • Es können keine Methoden für Zeitstempel mit Hilfe von Series-Einbauten angewendet werden
  • Pandas groupby und Multiindex
  • Wie man Werte in einer bestimmten Zeile in einem Python Pandas DataFrame aktualisiert?
  • Handhabungs-Nullen in Pandas DataFrames Spaltenabteilungen in Python
  • 4 Solutions collect form web for “Konvertieren Sie täglich Pandas-Bestandsdaten zu monatlichen Daten mit dem ersten Handelstag des Monats”

    Statt M Sie MS als Resample-Regel übergeben:

     df =pd.DataFrame( range(72), index = pd.date_range('1/1/2011', periods=72, freq='D')) #df.resample('MS', how = 'mean') # pandas <0.18 df.resample('MS').mean() # pandas >= 0.18 

    Aktualisiert, um den ersten Geschäftstag des Monats in Bezug auf US Federal Holidays zu verwenden:

     df =pd.DataFrame( range(200), index = pd.date_range('12/1/2012', periods=200, freq='D')) from pandas.tseries.offsets import CustomBusinessMonthBegin from pandas.tseries.holiday import USFederalHolidayCalendar bmth_us = CustomBusinessMonthBegin(calendar=USFederalHolidayCalendar()) df.resample(bmth_us).mean() 

    Wenn Sie möchten, dass benutzerdefinierte Starts des Monats mit dem Min-Monat in den Daten versucht dies zu versuchen. (Es ist nicht schön, aber es sollte funktionieren).

     month_index =df.index.to_period('M') min_day_in_month_index = pd.to_datetime(df.set_index(new_index, append=True).reset_index(level=0).groupby(level=0)['level_0'].min()) custom_month_starts =CustomBusinessMonthBegin(calendar = min_day_in_month_index) 

    custom_start_months an den ersten Parameter von resample

    Danke J Bradley, deine Lösung hat perfekt geklappt. Ich musste meine Version von Pandas von ihrer offiziellen Website aktualisieren, obwohl die Version, die über Pip installiert wurde, keine CustomBusinessMonthBegin in pandas.tseries.offsets hatte. Mein letzter Code war:

     #----- imports ----- import pandas as pd from pandas.tseries.offsets import CustomBusinessMonthBegin import pandas.io.data as web #----- get sample data ----- df = web.get_data_yahoo('SPY', '2012-12-01', '2013-12-31') #----- build custom calendar ----- month_index =df.index.to_period('M') min_day_in_month_index = pd.to_datetime(df.set_index(month_index, append=True).reset_index(level=0).groupby(level=0)['Open'].min()) custom_month_starts = CustomBusinessMonthBegin(calendar = min_day_in_month_index) #----- convert daily data to monthly data ----- ohlc_dict = {'Open':'first','High':'max','Low':'min','Close': 'last','Volume': 'sum','Adj Close': 'last'} mthly_ohlcva = df.resample(custom_month_starts, how=ohlc_dict) 

    Dies ergab folgendes:

     >>> mthly_ohlcva Volume Adj Close High Low Close Open Date 2012-12-03 2889875900 136.92 145.58 139.54 142.41 142.80 2013-01-01 2587140200 143.92 150.94 144.73 149.70 145.11 2013-02-01 2581459300 145.76 153.28 148.73 151.61 150.65 2013-03-01 2330972300 151.30 156.85 150.41 156.67 151.09 2013-04-01 2907035000 154.20 159.72 153.55 159.68 156.59 2013-05-01 2781596000 157.84 169.07 158.10 163.45 159.33 2013-06-03 3533321800 155.74 165.99 155.73 160.42 163.83 2013-07-01 2330904500 163.78 169.86 160.22 168.71 161.26 2013-08-01 2283131700 158.87 170.97 163.05 163.65 169.99 2013-09-02 2226749600 163.90 173.60 163.70 168.01 165.23 2013-10-01 2901739000 171.49 177.51 164.53 175.79 168.14 2013-11-01 1930952900 176.57 181.75 174.76 181.00 176.02 2013-12-02 2232775900 181.15 184.69 177.32 184.69 181.09 

    Die Mindestdaten in den Daten, die in der Antwort von user2766344 zurückgegeben werden, stimmen nicht mit den von Yahoo! Die Daten von Yahoo! Ist wie folgt (sortiert nach der Antwort):

      Date Volume Adj Close High Low Close Open 2012-12-03 156690500 134.15 145.58 139.54 142.41 142.80 2013-01-02 128386400 141.01 150.94 144.73 149.70 145.11 2013-02-01 142543400 142.81 153.28 148.73 151.61 150.65 2013-03-01 121695200 148.24 156.85 150.41 156.67 151.09 2013-04-01 137411100 151.08 159.72 153.55 159.68 156.59 2013-05-01 134474800 154.65 169.07 158.10 163.45 159.33 2013-06-03 184686200 152.59 165.99 155.73 160.42 163.83 2013-07-01 112422400 160.47 169.86 160.22 168.71 161.26 2013-08-01 109911800 155.66 170.97 163.05 163.65 169.99 2013-09-03 118534300 160.59 173.60 163.70 168.01 165.23 2013-10-01 131979700 168.02 177.51 164.53 175.79 168.14 2013-11-01 99341100 173.00 181.75 174.76 181.00 176.02 2013-12-02 110423600 177.49 184.69 177.32 184.69 181.09 

    Beachten Sie, dass Adj Close aufgrund von Dividenden unterschiedlich ist, da die Antwort gebucht wurde und die Volumina auch unterschiedlich sind.

    Am wichtigsten ist, das Datum 2013-01-01 in der Antwort zurückgegeben wird als 2013-01-02 von Yahoo! zurückgegeben

    Warum wäre das so?

    Auch wäre es möglich, diese Lösung zu generieren, um auch für Wochen-, Viertel- und Jahr-Re-Sampling zu sorgen?

    Ich habe in der letzten Version von Pandas gesehen, die du den Zeitversatzalias 'BMS' verwenden kannst, der für "Geschäftsmonat Startfrequenz" oder "BM" steht, der für "Geschäftsmonat Endfrequenz" steht.

    Der Code im ersten Fall würde aussehen

     data_dy.resample('BMS', closed='right', label='right').apply(ohlc_dict) 

    Oder im zweiten Fall,

     data_dy.resample('BM', closed='right', label='right').apply(ohlc_dict) 
    Python ist die beste Programmiersprache der Welt.