Python Pandas for Financial Stuff

In [39]:
import datetime

import pandas as pd
import pandas.io.data
from pandas import Series, DataFrame
pd.__version__

import matplotlib.pyplot as plt
import numpy as np

%pylab inline
Populating the interactive namespace from numpy and matplotlib

Stoxx-Europe-600-Index

In [40]:
sc='FXXP.EX'
stoxx = pd.io.data.get_data_yahoo(sc, 
                                 start=datetime.datetime(2013, 1, 1))
stoxx.head(10)
Out[40]:
Open High Low Close Volume Adj Close
Date
2013-01-02 285.33 285.33 285.33 285.33 0 285.33
2013-01-03 286.83 286.83 286.83 286.83 0 286.83
2013-01-04 287.83 287.83 287.83 287.83 0 287.83
2013-01-07 286.63 286.63 286.63 286.63 0 286.63
2013-01-08 286.25 286.25 286.25 286.25 0 286.25
2013-01-09 288.22 288.22 288.22 288.22 0 288.22
2013-01-10 287.44 287.44 287.44 287.44 0 287.44
2013-01-11 287.08 287.08 287.08 287.08 0 287.08
2013-01-14 286.01 286.01 286.01 286.01 0 286.01
2013-01-15 285.97 285.97 285.97 285.97 0 285.97

Schlusspreis

In [41]:
plt.figure(figsize=(9,3))
stoxx['Close'].plot();
plt.ylabel('\$')
plt.title('Closing Price %s' % sc);
plt.savefig('Closing-Price-FXXP.png',bbox_inches='tight', dpi=150)

Financial Stuff

Moving Average

In [42]:
close_px = stoxx['Adj Close']
mad = 10
mavg = pd.ewma(close_px, mad)
plt.figure(figsize=(16,4))
mavg.plot();
plt.ylabel('\$')
plt.title('Exponentially Weighted Moving Average (%i Days) %s' % (mad, sc));

Returns

In [43]:
stoxx['rets'] = close_px.pct_change()
plt.figure(figsize=(16,4))
stoxx.rets.plot();
plt.title('Returns %s' % sc);
plt.ylabel('\$');

Relative Strength Index

Source: http://stackoverflow.com/a/20527056 (with Error!!)

The RSI is not calcualted with the rolling_mean but with the exponentially weighted moving average ewma!

In [44]:
# Get daily up or down
delta = stoxx['Close'].diff()

dUp, dDown = delta.copy( ), delta.copy( )
dUp[ dUp < 0 ] = 0
dDown[ dDown > 0 ] = 0

n=14
RolUp = pd.ewma( dUp, n)
RolDown = pd.ewma( dDown, n).abs()

RS = RolUp / RolDown
RSI = 100. - 100./(1.+RS)

plt.figure(figsize=(9,3))
RSI.plot();
plt.axhline(20, color='k', alpha=0.2)
plt.annotate('oversold',xy=(0.5, 0.3), xycoords='figure fraction', fontsize=20, alpha=0.4, ha='center')
plt.axhline(80, color='k', alpha=0.2)
plt.annotate('overbought',xy=(0.5, 0.8), xycoords='figure fraction', fontsize=20, alpha=0.4,ha='center')
plt.title('RSI %s (%i days)' % (sc, n));
plt.ylim([0,100]);
plt.ylabel('%');
plt.savefig('RSI-FXXP.png',bbox_inches='tight', dpi=150)

Monte Carlo Simulation

In [45]:
SO=stoxx['Close'][-1] # letzter Preis
vol=np.std(stoxx['rets'])*np.sqrt(252) # Historical Volatility
r=0.025 # Constant Short Rate

K = SO*1.1 # 10% OTM Call Option
T = 1.0 # Maturity 1 Year

M=364
dt=T/M # Time Steps
I = 100 # Simulation Paths
In [46]:
S=np.zeros((M+1,I))
S[0,:]=SO
for t in range(1, M+1):
    ran = np.random.standard_normal(I)
    S[t,:]=S[t-1,:] * np.exp((r-vol**2/2)*dt + vol*np.sqrt(dt)*ran)


MC=pd.DataFrame(data=S, index=pd.date_range(start=stoxx.index[-1], periods=M+1))

ax=MC.plot(alpha=0.2, color='k');
stoxx['Close'].plot(ax=ax);
plt.legend(['Monte Carlo Simulation']);
plt.ylabel('\$');
plt.savefig('Monte-Carlo-Simulation-FXXP.png',bbox_inches='tight', dpi=150)

Option Valuation

In [47]:
VO=np.exp(-r*T)*np.sum(np.max(S[-1]-K,0))/I
print('Call Value %8.3f' % VO)
Call Value    1.109

Vergleich

In [48]:
df = pd.io.data.get_data_yahoo(['AAPL', 'FXXP.EX', 'GOOG', 'FDAX.EX', 'TSLA'], 
                               start=datetime.datetime(2013, 1, 1))['Adj Close']
df.head()
Out[48]:
AAPL FDAX.EX FXXP.EX GOOG TSLA
Date
2013-01-02 532.39 7778.78 285.33 NaN 35.36
2013-01-03 525.67 7756.44 286.83 NaN 34.77
2013-01-04 511.03 7776.37 287.83 NaN 34.40
2013-01-07 508.02 7732.66 286.63 NaN 34.34
2013-01-08 509.39 7695.83 286.25 NaN 33.68

Returns

In [49]:
rets = df.pct_change()
In [50]:
fig=plt.figure(figsize=(6,6));
pd.scatter_matrix(rets, diagonal='kde', figsize=(10, 10));
plt.savefig('Return-Correlation-FXXP.png',bbox_inches='tight', dpi=150)
<matplotlib.figure.Figure at 0x1087e87d0>

Korrelation der Returns

In [51]:
corr = rets.corr()
corr
Out[51]:
AAPL FDAX.EX FXXP.EX GOOG TSLA
AAPL 1.000000 0.145395 0.135896 0.673684 0.047999
FDAX.EX 0.145395 1.000000 0.915619 0.027554 0.115146
FXXP.EX 0.135896 0.915619 1.000000 NaN 0.162412
GOOG 0.673684 0.027554 NaN 1.000000 0.727874
TSLA 0.047999 0.115146 0.162412 0.727874 1.000000
In [52]:
plt.imshow(corr, cmap='YlGn', interpolation='none')
plt.colorbar()
plt.xticks(range(len(corr)), corr.columns)
plt.yticks(range(len(corr)), corr.columns);
In [53]:
fig=plt.figure(figsize=(6,6))
plt.scatter(rets.mean(), rets.std(), s=50)
plt.xlabel('Expected returns')
plt.ylabel('Risk')
for label, x, y in zip(rets.columns, rets.mean(), rets.std()):
    plt.annotate(
        label, 
        xy = (x, y), xytext = (20, -20),
        textcoords = 'offset points', ha = 'right', va = 'bottom',
        bbox = dict(boxstyle = 'round,pad=0.5', fc = 'w', alpha = 0.5),
        arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))
    
plt.savefig('Risk-Return-FXXP.png',bbox_inches='tight', dpi=150)
In [54]:
print('Done.')
Done.