मैं अजगर 2.7 का उपयोग कर रहा हूँ। मैं दैनिक रिटर्न से चक्रवृद्धि रिटर्न की गणना करना चाहता हूं और मेरा वर्तमान कोड रिटर्न की गणना में बहुत धीमा है, इसलिए मैं उन क्षेत्रों की तलाश कर रहा था जहां मैं दक्षता हासिल कर सकूं।

मैं जो करना चाहता हूं वह दो तिथियों और एक सुरक्षा को मूल्य तालिका में पास करना है और सुरक्षा देने का उपयोग करके उन तिथियों के बीच कंपाउंडिंग रिटर्न की गणना करना है।

मेरे पास एक मूल्य तालिका है (prices_df):

security_id px_last    asof
    1       3.055   2015-01-05
    1       3.360   2015-01-06
    1       3.315   2015-01-07
    1       3.245   2015-01-08
    1       3.185   2015-01-09

मेरे पास दो तिथियों और सुरक्षा के साथ एक टेबल भी है (events_df):

asof            disclosed_on    security_ref_id
2015-01-05  2015-01-09 16:31:00     1
2018-03-22  2018-03-27 16:33:00     3616
2017-08-03  2018-03-27 12:13:00     2591
2018-03-22  2018-03-27 11:33:00     3615
2018-03-22  2018-03-27 10:51:00     3615

इस तालिका में दो तिथियों का उपयोग करके, मैं रिटर्न की गणना के लिए मूल्य तालिका का उपयोग करना चाहता हूं।

मैं जिन दो कार्यों का उपयोग कर रहा हूं:

import pandas as pd
# compounds returns
def cum_rtrn(df):
    df_out = df.add(1).cumprod()
    df_out['return'].iat[0] = 1
    return df_out

# calculates compound returns from prices between two dates
def calc_comp_returns(price_df, start_date=None, end_date=None, security=None):
    df = price_df[price_df.security_id == security]
    df = df.set_index(['asof'])
    df = df.loc[start_date:end_date]
    df['return'] = df.px_last.pct_change()
    df = df[['return']]
    df = cum_rtrn(df)
    return df.iloc[-1][0]

मैं फिर events_df पर .iterrows के साथ हर बार calc_comp_returns फ़ंक्शन पास करता हूं। हालाँकि, यह बहुत धीमी प्रक्रिया है क्योंकि मेरे पास 10K+ पुनरावृत्तियाँ हैं, इसलिए मैं सुधार की तलाश में हूँ। समाधान pandas पर आधारित होने की आवश्यकता नहीं है

# example of how function is called
start = datetime.datetime.strptime('2015-01-05', '%Y-%m-%d').date()
end = datetime.datetime.strptime('2015-01-09', '%Y-%m-%d').date()
calc_comp_returns(prices_df, start_date=start, end_date=end, security=1)
3
roarkz 29 मार्च 2018, 00:07

2 जवाब

हम prices_df से कीमतों को हथियाने के लिए pd.merge_asof का उपयोग करेंगे। हालांकि, जब हम ऐसा करते हैं, तो हमारे पास उपयोग किए जा रहे दिनांक कॉलम द्वारा क्रमबद्ध प्रासंगिक डेटाफ़्रेम की आवश्यकता होगी। साथ ही, सुविधा के लिए, मैं कुछ pd.merge_asof पैरामीटर को शब्दकोशों में कीवर्ड तर्क के रूप में उपयोग करने के लिए एकत्रित करूंगा।

prices_df = prices_df.sort_values(['asof'])

aed = events_df.sort_values('asof')
ded = events_df.sort_values('disclosed_on')

aokw = dict(
    left_on='asof', right_on='asof',
    left_by='security_ref_id', right_by='security_id'
)

start_price = pd.merge_asof(aed, prices_df, **aokw).px_last

dokw = dict(
    left_on='disclosed_on', right_on='asof',
    left_by='security_ref_id', right_by='security_id'
)

end_price = pd.merge_asof(ded, prices_df, **dokw).px_last

returns = end_price.div(start_price).sub(1).rename('return')
events_df.join(returns)

        asof        disclosed_on  security_ref_id    return
0 2015-01-05 2015-01-09 16:31:00                1  0.040816
1 2018-03-22 2018-03-27 16:33:00             3616       NaN
2 2017-08-03 2018-03-27 12:13:00             2591       NaN
3 2018-03-22 2018-03-27 11:33:00             3615       NaN
4 2018-03-22 2018-03-27 10:51:00             3615       NaN
0
piRSquared 28 मार्च 2018, 22:47

मैं पांडा से बहुत परिचित नहीं हूं, लेकिन मैं इसे एक शॉट दूंगा।

आपके समाधान के साथ समस्या

आपका समाधान वर्तमान में बड़ी मात्रा में अनावश्यक गणना करता है। यह ज्यादातर लाइन के कारण होता है:

    df['return'] = df.px_last.pct_change()

यह पंक्ति वास्तव में प्रारंभ और समाप्ति के बीच हर दिनांक के लिए प्रतिशत परिवर्तन की गणना कर रही है। बस इस समस्या को ठीक करने से आपको एक बड़ी गति मिलनी चाहिए। आपको बस शुरुआती कीमत और अंतिम कीमत मिलनी चाहिए और दोनों की तुलना करनी चाहिए। इन दो कीमतों के बीच की कीमतें आपकी गणना के लिए पूरी तरह से अप्रासंगिक हैं। फिर से, पंडों के साथ मेरी परिचितता शून्य है, लेकिन आपको इसके बजाय कुछ ऐसा करना चाहिए:

def calc_comp_returns(price_df, start_date=None, end_date=None, security=None):
    df = price_df[price_df.security_id == security]
    df = df.set_index(['asof'])
    df = df.loc[start_date:end_date]
    return 1 + (df['px_last'].iloc(-1) - df['px_last'].iloc(0)

याद रखें कि यह कोड इस तथ्य पर निर्भर करता है कि price_df को दिनांक के अनुसार क्रमबद्ध किया गया है, इसलिए यह सुनिश्चित करने के लिए सावधान रहें कि आप केवल calc_comp_returns दिनांक-क्रमबद्ध price_df पास करते हैं।

0
Community 20 जून 2020, 09:12