I am new to quant. finance and trying to calculate trend
, momentum
, correlation
and volatility
. Below are the functions I have created
import pandas as pd
def roll_correlation(first_df, second_df, rolling_period):
"""
Rolling correlation
"""
return first_df.rolling(rolling_period).corr(second_df)
def roll_volatility(df, rolling_period):
"""
Rolling volatility
"""
return df.pct_change().rolling(rolling_period).std(ddof=0)
# ASK: is rolling momentum calculation is correct
def roll_momentum(df, rolling_period):
"""
Rolling momentum
"""
return df.pct_change(rolling_period)
def roll_returns(df, rolling_period):
"""
Rolling returns
"""
return df.rolling(rolling_period).apply(lambda x: x.iloc[[0, -1]].pct_change()[-1])
def trend(df, rolling_period):
"""
Identify trend
"""
return df.apply(lambda x: x.autocorr(rolling_period))
if __name__ == '__main__':
df = pd.Dataframe({'A': [1,2,3,4]})
print (trend(df,2))
1 Answer 1
The functions broadly look fine, though without formal definitions it's impossible to say whether they're correct from a quantitative finance standpoint: You ask:
is rolling momentum calculation is correct
Who knows? Asset momentum is a broad concept, and to know whether this is correct again you have to offer formal definitions.
roll_returns
is definitely wrong, though. The last -1
needs to be in an iloc[]
.
Avoid using lambdas. For roll_returns
just write a separate function to improve clarity and eliminate the possibility of closure references, and for trend
provide a class method reference.
For these utility methods to be maximally useful, add PEP484 typehints.
Your docstrings are less helpful than having no documentation at all, since they just repeat the name of the function.
All together,
import pandas as pd
def roll_correlation(first_df: pd.DataFrame, second_df: pd.DataFrame, rolling_period: int):
return first_df.rolling(rolling_period).corr(second_df)
def roll_volatility(df: pd.DataFrame, rolling_period: int) -> pd.Series:
return df.pct_change().rolling(rolling_period).std(ddof=0)
def roll_momentum(df: pd.DataFrame, rolling_period: int) -> pd.Series:
return df.pct_change(rolling_period)
def return_inner(x: pd.Series) -> float:
return x.iloc[[0, -1]].pct_change().iloc[-1]
def roll_returns(df: pd.DataFrame, rolling_period: int) -> pd.Series:
return df.rolling(rolling_period).apply(return_inner)
def trend(df: pd.DataFrame, rolling_period: int) -> pd.Series:
return df.apply(pd.Series.autocorr, lag=rolling_period)
def demo() -> None:
df = pd.DataFrame({'A': range(1, 5)})
print('Sample data:')
print(df)
print()
for method in (roll_volatility, roll_momentum, roll_returns, trend):
print(f'{method.__name__}:')
stat = method(df, rolling_period=2)
print(stat)
print()
if __name__ == '__main__':
demo()
Sample data:
A
0 1
1 2
2 3
3 4
roll_volatility:
A
0 NaN
1 NaN
2 0.250000
3 0.083333
roll_momentum:
A
0 NaN
1 NaN
2 2.0
3 1.0
roll_returns:
A
0 NaN
1 1.000000
2 0.500000
3 0.333333
trend:
A 1.0
dtype: float64