Bagaimana saya bisa secara efisien menerapkan versi vektor dari aturan pembayaran hari kerja "Dimodifikasi Mengikuti" di Pandas?

Latar Belakang

Di bidang keuangan, sering kali kupon pendapatan tetap dibayarkan berdasarkan "pengikut yang dimodifikasi", yaitu, jika tanggal kupon jatuh pada akhir pekan atau hari libur, maka kupon itu dibayarkan pada hari kerja berikutnya, kecuali jika disebutkan sebagai berikut hari kerja jatuh ke bulan kalender berikutnya, dalam hal ini kita mundur ke hari kerja sebelumnya terdekat.

     April 2017       
Su Mo Tu We Th Fr Sa  
                   1  
 2  3  4  5  6  7  8  
 9 10 11 12 13 14 15  
16 17 18 19 20 21 22  
23 24 25 26 27 28 29  
30 

April 2017 menawarkan contoh yang baik. Jika pembayaran jatuh pada hari Sabtu tanggal 15, maka akan dimajukan ke hari Senin tanggal 17. Namun jika jatuh pada hari Sabtu tanggal 29, dua minggu kemudian akan diundur menjadi hari Jumat tanggal 28 (karena hari Senin berikutnya jatuh pada bulan Mei).

Saya perlu melakukan ini untuk ribuan tanggal pada satu waktu, maka saya ingin itu menjadi vektor dan panda efisien jika memungkinkan (yaitu, saya ingin menghindari hanya menjalankan setiap tanggal melalui if-then-else). Jadi diberi vektor tanggal, itu akan memeriksa yang jatuh pada Sabtu/Minggu dan secara otomatis menerapkan aturan, mengeluarkan vektor tanggal "dimodifikasi berikut".

3
Thomas Browne 19 November 2017, 02:21

1 menjawab

Jawaban Terbaik

Jika Anda tertarik dengan solusi panda, ini adalah permulaan:

import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import CustomBusinessDay

BDayUS = CustomBusinessDay(calendar=USFederalHolidayCalendar())       

def is_weekday(dates):
    return ~dates.weekday_name.isin(['Saturday', 'Sunday'])

def in_next_month(dates1, dates2):
    return dates1.month == dates2.month - 1

def next_bus_day(dates):
    fwd = dates + BDayUS(1)
    return fwd.where(~in_next_month(dates, fwd), dates - BDayUS(1))

def payment_day(dates):
    return dates.where(is_weekday(dates), next_bus_day(dates))

Untuk April 2017:

dates = pd.date_range('4/1/2017', '4/30/2017')

payment_day(dates)
# DatetimeIndex(['2017-04-03', '2017-04-03', '2017-04-03', '2017-04-04',
#                '2017-04-05', '2017-04-06', '2017-04-07', '2017-04-10',
#                '2017-04-10', '2017-04-10', '2017-04-11', '2017-04-12',
#                '2017-04-13', '2017-04-14', '2017-04-17', '2017-04-17',
#                '2017-04-17', '2017-04-18', '2017-04-19', '2017-04-20',
#                '2017-04-21', '2017-04-24', '2017-04-24', '2017-04-24',
#                '2017-04-25', '2017-04-26', '2017-04-27', '2017-04-28',
#                '2017-04-28', '2017-04-28'],
#               dtype='datetime64[ns]', freq='D')

payment_day(dates).weekday_name
# Index(['Monday', 'Monday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
#        'Friday', 'Monday', 'Monday', 'Monday', 'Tuesday', 'Wednesday',
#        'Thursday', 'Friday', 'Monday', 'Monday', 'Monday', 'Tuesday',
#        'Wednesday', 'Thursday', 'Friday', 'Monday', 'Monday', 'Monday',
#        'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Friday', 'Friday'],
#       dtype='object')

Lihat juga: Hari Kerja Khusus dari dokumen. Silakan stress-test ini; Saya kebanyakan hanya bekerja dengan BDay default dan saya tidak yakin apakah Hari Libur Federal sejalan dengan penutupan pasar NYSE.

2
Brad Solomon 19 November 2017, 16:24