or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-retrieval.mddata-utilities.mdindex.mdpandas-extensions.mdperformance-analysis.mdportfolio-optimization.mdreturn-calculations.mdrisk-metrics.mdstatistical-analysis.md

pandas-extensions.mddocs/

0

# Pandas Extensions

1

2

FFN automatically extends pandas Series and DataFrame objects with financial analysis methods, enabling seamless method chaining and functional composition. All FFN functions become available as methods on pandas objects when FFN is imported.

3

4

## Capabilities

5

6

### Extension System

7

8

Core functionality that adds FFN methods to pandas objects automatically.

9

10

```python { .api }

11

def extend_pandas():

12

"""

13

Extend pandas Series and DataFrame with all FFN functions as methods.

14

15

Called automatically when FFN is imported. Enables method chaining like:

16

prices.to_returns().calc_sharpe()

17

18

Returns:

19

None (modifies pandas classes in-place)

20

"""

21

```

22

23

### Available Extension Methods

24

25

When FFN is imported, all the following methods become available on pandas Series and DataFrame objects:

26

27

#### Return and Price Calculations

28

```python { .api }

29

# Convert between prices and returns

30

Series.to_returns() # Convert prices to simple returns

31

Series.to_log_returns() # Convert prices to log returns

32

Series.to_price_index(start=100) # Convert returns to price index

33

Series.rebase(value=100) # Rebase series to specified value

34

DataFrame.rebase(value=100) # Rebase all columns to specified value

35

```

36

37

#### Performance Analysis Methods

38

```python { .api }

39

# Performance statistics and analysis

40

Series.calc_perf_stats(rf=0.0, annualization_factor=252) # Create PerformanceStats object

41

DataFrame.calc_stats() # Create GroupStats object for multiple series

42

Series.calc_cagr() # Calculate Compound Annual Growth Rate

43

Series.calc_total_return() # Calculate total return

44

```

45

46

#### Risk Analysis Methods

47

```python { .api }

48

# Risk and drawdown analysis

49

Series.calc_max_drawdown() # Calculate maximum drawdown

50

Series.to_drawdown_series() # Convert to drawdown series

51

DataFrame.to_drawdown_series() # Calculate drawdowns for all columns

52

Series.calc_sharpe(rf=0.0, nperiods=None, annualize=True) # Sharpe ratio

53

DataFrame.calc_sharpe(rf=0.0, nperiods=None, annualize=True) # Sharpe for all columns

54

Series.calc_sortino_ratio(rf=0.0, nperiods=None, annualize=True) # Sortino ratio

55

Series.calc_calmar_ratio() # Calmar ratio

56

Series.to_ulcer_index() # Ulcer Index calculation

57

Series.to_ulcer_performance_index(rf=0.0, nperiods=None) # Ulcer Performance Index

58

```

59

60

#### Portfolio Optimization Methods

61

```python { .api }

62

# Portfolio weight calculation methods

63

DataFrame.calc_inv_vol_weights() # Inverse volatility weights

64

DataFrame.calc_mean_var_weights(weight_bounds=(0.0, 1.0), rf=0.0, covar_method="ledoit-wolf", options=None) # Mean-variance weights

65

DataFrame.calc_erc_weights(initial_weights=None, risk_weights=None, covar_method="ledoit-wolf", risk_parity_method="ccd", maximum_iterations=100, tolerance=1e-8) # Equal risk contribution weights

66

```

67

68

#### Statistical Analysis Methods

69

```python { .api }

70

# Advanced statistical methods

71

DataFrame.calc_clusters(n=None, plot=False) # K-means clustering

72

DataFrame.calc_ftca(threshold=0.5) # Fast Threshold Clustering Algorithm

73

Series.calc_prob_mom(other_returns) # Probabilistic momentum

74

DataFrame.resample_returns(func, seed=0, num_trials=100) # Bootstrap resampling

75

```

76

77

#### Data Processing Methods

78

```python { .api }

79

# Data transformation and processing

80

Series.to_monthly(method="ffill", how="end") # Convert to monthly frequency

81

DataFrame.to_monthly(method="ffill", how="end") # Convert all columns to monthly

82

Series.asfreq_actual(freq, method="ffill", how="end", normalize=False) # Custom frequency conversion

83

DataFrame.drop_duplicate_cols() # Remove duplicate columns

84

Series.winsorize(axis=0, limits=0.01) # Winsorize outliers

85

DataFrame.winsorize(axis=0, limits=0.01) # Winsorize all columns

86

Series.rescale(min=0.0, max=1.0, axis=0) # Rescale to range

87

DataFrame.rescale(min=0.0, max=1.0, axis=0) # Rescale all columns

88

DataFrame.rollapply(window, fn) # Rolling function application

89

```

90

91

#### Excess Returns and Risk-Adjusted Methods

92

```python { .api }

93

# Risk-adjusted return calculations

94

Series.to_excess_returns(rf, nperiods=None) # Calculate excess returns

95

DataFrame.to_excess_returns(rf, nperiods=None) # Excess returns for all columns

96

Series.calc_information_ratio(benchmark_returns) # Information ratio vs benchmark

97

Series.calc_risk_return_ratio() # Return/risk ratio (Sharpe without rf)

98

```

99

100

#### Formatting and Display Methods

101

```python { .api }

102

# Data formatting methods

103

Series.as_percent(digits=2) # Format as percentage strings

104

DataFrame.as_percent(digits=2) # Format all values as percentages

105

Series.as_format(format_str=".2f") # Apply custom format string

106

DataFrame.as_format(format_str=".2f") # Format all values with custom string

107

```

108

109

#### Visualization Methods

110

```python { .api }

111

# Plotting and visualization

112

DataFrame.plot_heatmap(title="Heatmap", show_legend=True, show_labels=True, label_fmt=".2f", vmin=None, vmax=None, figsize=None, label_color="w", cmap="RdBu", **kwargs) # General heatmap

113

DataFrame.plot_corr_heatmap(**kwargs) # Correlation heatmap with sensible defaults

114

```

115

116

## Usage Examples

117

118

### Basic Method Chaining

119

120

```python

121

import ffn

122

import pandas as pd

123

124

# Download price data

125

prices = ffn.get('AAPL,MSFT,GOOGL', start='2020-01-01')

126

127

# Method chaining example - from prices to risk analysis

128

analysis = (prices

129

.rebase(100) # Normalize to 100

130

.to_returns() # Convert to returns

131

.dropna() # Remove NaN values

132

.calc_sharpe(rf=0.02) # Calculate Sharpe ratios

133

)

134

135

print("Sharpe ratios via method chaining:")

136

print(analysis)

137

```

138

139

### Performance Analysis Pipeline

140

141

```python

142

import ffn

143

144

# Create comprehensive performance pipeline

145

def analyze_asset(ticker, start_date, benchmark='SPY'):

146

"""Complete performance analysis using pandas extensions."""

147

148

# Get asset and benchmark data

149

asset_prices = ffn.get(ticker, start=start_date)

150

benchmark_prices = ffn.get(benchmark, start=start_date)

151

152

# Performance analysis using method chaining

153

asset_performance = (asset_prices

154

.iloc[:, 0] # Get first column as Series

155

.calc_perf_stats(rf=0.02) # Create PerformanceStats object

156

)

157

158

# Risk analysis

159

risk_metrics = {

160

'Max Drawdown': asset_prices.iloc[:, 0].calc_max_drawdown(),

161

'Sharpe Ratio': asset_prices.to_returns().dropna().iloc[:, 0].calc_sharpe(rf=0.02),

162

'Calmar Ratio': asset_prices.iloc[:, 0].calc_calmar_ratio()

163

}

164

165

# Comparative analysis

166

combined_returns = ffn.merge(

167

asset_prices.to_returns().dropna(),

168

benchmark_prices.to_returns().dropna()

169

)

170

171

correlations = combined_returns.corr()

172

173

return {

174

'performance': asset_performance,

175

'risk_metrics': risk_metrics,

176

'correlations': correlations,

177

'returns': combined_returns

178

}

179

180

# Run analysis

181

results = analyze_asset('AAPL', '2020-01-01')

182

print(f"AAPL CAGR: {results['performance'].cagr:.2%}")

183

print(f"AAPL Sharpe: {results['risk_metrics']['Sharpe Ratio']:.3f}")

184

```

185

186

### Portfolio Construction with Extensions

187

188

```python

189

import ffn

190

import numpy as np

191

192

# Multi-asset portfolio construction

193

assets = ['SPY', 'QQQ', 'IWM', 'EFA', 'EEM', 'BND']

194

prices = ffn.get(assets, start='2020-01-01')

195

returns = prices.to_returns().dropna()

196

197

# Different weighting schemes using pandas extensions

198

equal_weights = pd.Series(1/len(assets), index=returns.columns)

199

inv_vol_weights = returns.calc_inv_vol_weights()

200

erc_weights = returns.calc_erc_weights()

201

mean_var_weights = returns.calc_mean_var_weights(rf=0.02)

202

203

# Portfolio performance comparison

204

portfolios = {

205

'Equal Weight': equal_weights,

206

'Inverse Vol': inv_vol_weights,

207

'Risk Parity': erc_weights,

208

'Mean-Variance': mean_var_weights

209

}

210

211

# Calculate portfolio returns and statistics

212

portfolio_analysis = {}

213

for name, weights in portfolios.items():

214

# Portfolio returns using method chaining

215

portfolio_returns = (returns * weights).sum(axis=1)

216

portfolio_prices = portfolio_returns.to_price_index(start=100)

217

218

# Performance analysis via extensions

219

perf_stats = portfolio_prices.calc_perf_stats(rf=0.02)

220

221

portfolio_analysis[name] = {

222

'weights': weights,

223

'cagr': perf_stats.cagr,

224

'sharpe': perf_stats.daily_sharpe,

225

'max_dd': perf_stats.max_drawdown,

226

'calmar': perf_stats.calmar

227

}

228

229

# Display results

230

results_df = pd.DataFrame(portfolio_analysis).T

231

results_df[['cagr', 'sharpe', 'max_dd', 'calmar']].round(3)

232

```

233

234

### Data Processing Pipeline

235

236

```python

237

import ffn

238

239

# Complex data processing using method chaining

240

raw_data = ffn.get(['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA'], start='2020-01-01')

241

242

# Multi-step processing pipeline

243

processed_data = (raw_data

244

.drop_duplicate_cols() # Remove any duplicate columns

245

.dropna() # Remove NaN values

246

.rebase(100) # Normalize to 100

247

.to_monthly(method='last') # Convert to monthly

248

.to_returns() # Calculate returns

249

.winsorize(limits=0.02) # Winsorize extreme values

250

.dropna() # Clean again

251

)

252

253

print(f"Processed data shape: {processed_data.shape}")

254

print(f"Monthly return statistics:")

255

print(processed_data.describe().round(4))

256

257

# Risk analysis on processed data

258

risk_analysis = {

259

'Sharpe Ratios': processed_data.calc_sharpe(rf=0.02),

260

'Correlations': processed_data.corr(),

261

'Drawdowns': processed_data.to_price_index().to_drawdown_series()

262

}

263

264

# Visualization using extensions

265

processed_data.corr().plot_corr_heatmap(title='Tech Stock Correlations (Monthly)',

266

figsize=(8, 6))

267

268

# Advanced statistical analysis

269

clusters = processed_data.calc_clusters(n=2, plot=True)

270

print(f"Asset clusters: {clusters}")

271

```

272

273

### Format and Display Pipeline

274

275

```python

276

import ffn

277

278

# Get data and calculate statistics

279

prices = ffn.get(['SPY', 'QQQ', 'BND'], start='2020-01-01')

280

returns = prices.to_returns().dropna()

281

282

# Calculate key metrics using extensions

283

metrics = pd.DataFrame({

284

'CAGR': [prices[col].calc_cagr() for col in prices.columns],

285

'Volatility': returns.std() * np.sqrt(252),

286

'Sharpe': returns.calc_sharpe(rf=0.02),

287

'Max Drawdown': [prices[col].calc_max_drawdown() for col in prices.columns],

288

'Calmar': [prices[col].calc_calmar_ratio() for col in prices.columns]

289

}, index=prices.columns)

290

291

# Format for presentation using extensions

292

print("Formatted Performance Summary:")

293

print("CAGR and Max Drawdown (as percentages):")

294

print(metrics[['CAGR', 'Max Drawdown']].as_percent())

295

296

print("\nAll metrics (2 decimal places):")

297

print(metrics.as_format('.3f'))

298

299

# Create formatted correlation matrix

300

correlations = returns.corr()

301

print("\nCorrelation Matrix (as percentages):")

302

print(correlations.as_format('.1%'))

303

```

304

305

## Implementation Notes

306

307

### Automatic Extension

308

- Extensions are applied automatically when `import ffn` is executed

309

- No additional setup required - all methods immediately available on pandas objects

310

- Extensions work with both pandas Series and DataFrame objects where applicable

311

312

### Method Chaining Benefits

313

- Enables functional programming style for financial analysis

314

- Reduces intermediate variable creation

315

- Improves code readability and maintainability

316

- Supports complex multi-step analysis pipelines

317

318

### Performance Considerations

319

- Extensions maintain pandas performance characteristics

320

- No overhead beyond normal function calls

321

- Methods preserve pandas indexing and data alignment behavior

322

- Compatible with pandas operations and other libraries