In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from pandas import DataFrame, Series

In [2]:
import random; random.seed(0)
import string

N = 1000
def rands(n):
    choices = string.ascii_uppercase
    return ''.join([random.choice(choices) for _ in xrange(n)])

tickers = np.array([rands(5) for _ in xrange(N)])
tickers


Out[2]:
array(['VTKGN', 'KUHMP', 'XNHTQ', 'GXZVX', 'ISXRM', 'CLPXZ', 'MWGUO',
       'ASKVR', 'AMWGI', 'WEOGZ', 'ULCIN', 'YCOSO', 'VOZPP', 'LPKOH',
       'EEPRM', 'CTWYV', 'XYOKS', 'HVWXP', 'YPLRZ', 'XUCPM', 'QVGTD',
       'FUIVC', 'DSBOX', 'NRAQP', 'OKJZA', 'AYEDF', 'UYALC', 'GFQJE',
       'NBCZF', 'JTVXE', 'RZBRV', 'IGPLE', 'MKONI', 'JVGOA', 'TIBHG',
       'YJHJY', 'QQSKK', 'QAFIG', 'QJWOK', 'KSKRB', 'LGENM', 'OTWMI',
       'MVWVE', 'ZQCSZ', 'KRIFS', 'AVNCD', 'QWHZC', 'WKCHL', 'UWDNQ',
       'JWHAB', 'ROYYX', 'BTSRS', 'XQJNF', 'PADIU', 'SIQBE', 'ZHKOH',
       'MGBEN', 'BKIKC', 'XMVZI', 'MSLHT', 'XXQJZ', 'QBCTB', 'AKNLM',
       'PRKJZ', 'GULJB', 'WSXLR', 'DKFBY', 'FDFJO', 'DZZDK', 'RWMXI',
       'MMRFP', 'FIZXV', 'ADGUV', 'PSUBC', 'WBFBA', 'VIEDR', 'ZNXNO',
       'RUTZT', 'XFNPV', 'MUKPW', 'URAEN', 'GBWYH', 'KVBQD', 'HVBAK',
       'MWSRD', 'ZKPKB', 'MDAQQ', 'COJJU', 'MWPMQ', 'IDRQU', 'DXUXW',
       'RVNUE', 'ULTLU', 'BBYMX', 'YROFC', 'VXUSK', 'HCLOX', 'YKCUT',
       'ALRAX', 'ZSCBJ', 'AJAZV', 'BXFFR', 'YDAJA', 'PWECI', 'YDZJM',
       'HYYQE', 'ZCPEX', 'YUIGT', 'HKBDA', 'CBKOT', 'DKQCL', 'JYBKK',
       'SIFHM', 'YUHOR', 'ULKTL', 'GLYDM', 'QMFAS', 'QAHTQ', 'OESMR',
       'TGTHZ', 'DWBGN', 'PKCGH', 'TXPAU', 'HINGX', 'EKHNO', 'QNKQK',
       'UUHJQ', 'ESJPD', 'RJMKM', 'SIQBH', 'TBQAM', 'XANBW', 'RTRAB',
       'QZWSS', 'FTHCL', 'IEKXL', 'LSNDX', 'LUKUK', 'FFYPB', 'KGCEB',
       'QEPPS', 'NHWJL', 'QNYYY', 'YPMSF', 'GBEAR', 'DURZK', 'XLICW',
       'UILIA', 'BJFNE', 'FRTIW', 'GISBY', 'BLSBV', 'ZLDCC', 'TKXLC',
       'LTVBE', 'MDWYI', 'LOHOF', 'HLPNG', 'GDUCT', 'GHTRT', 'NWDQD',
       'TJRSR', 'FVGNR', 'GQHEV', 'OIPAD', 'KZNBT', 'UUOSF', 'TVTJP',
       'QXCVN', 'JLAFQ', 'RMYMI', 'WGPSV', 'UJBAS', 'ZILSR', 'GRHJO',
       'TDAQA', 'BFRBB', 'ZKXFL', 'JEIZT', 'JKGNT', 'RMBXK', 'KADWN',
       'TDIVV', 'GAUEU', 'RECYP', 'QLDPG', 'UTAYA', 'CHDGJ', 'TKHMK',
       'IXOZU', 'OGRLS', 'KMATA', 'RPUHR', 'FNIZZ', 'FOIZY', 'PSRJX',
       'XITAV', 'OYJQI', 'UPZAD', 'BDYYM', 'YVUTE', 'OLYEE', 'RECNU',
       'PTGHL', 'ZSYNO', 'ZEUUV', 'TERYO', 'JYOKP', 'UFANY', 'RQQMT',
       'GXHYY', 'CLTLN', 'USYEY', 'YQYGW', 'UPCAA', 'GTKUQ', 'KWAMV',
       'DSIAM', 'NBOJA', 'ECOBY', 'VYIXZ', 'THRPK', 'HBDDM', 'QTBVB',
       'OTQYI', 'PCOVF', 'GSGGY', 'ZEXOB', 'PQATV', 'BQLGL', 'EIRMO',
       'OVIVC', 'LJLVN', 'ZWDIA', 'TAXFK', 'BIKBT', 'SJVCB', 'JXTRO',
       'UKAUE', 'KJDJE', 'QQALO', 'WMCBW', 'UWGQC', 'VIYMA', 'XQHAJ',
       'EODEX', 'QGWQY', 'MXRBG', 'HEGFW', 'MWDOA', 'YAKUZ', 'AVNAU',
       'CPURJ', 'ALXIG', 'DNNBK', 'RZLLM', 'FKQKP', 'VZXJA', 'PMGBI',
       'UZCWB', 'SAKWK', 'YSPEI', 'KPZHN', 'YIQTQ', 'TFYEP', 'HQHLR',
       'GSJDP', 'ELKBS', 'RUOOE', 'FFNVJ', 'WTSID', 'ZWKWX', 'INISX',
       'ZTHWZ', 'JYNZZ', 'VREAP', 'SYNSQ', 'FQZCR', 'PJUAX', 'VMCLP',
       'GMUXO', 'VCWXE', 'VWWNP', 'FSKAD', 'KXOXY', 'CPINL', 'MCVMQ',
       'MEOEW', 'VDBBK', 'YOGFC', 'DVDWV', 'DOAWO', 'TMRYO', 'WICAF',
       'VIFMY', 'NICOF', 'JJTGY', 'TMWJJ', 'DUKNM', 'RJXLJ', 'KTZWM',
       'HLIGE', 'YMCJK', 'NZZOQ', 'RNMIR', 'CIXFZ', 'ZOBCF', 'ICUJG',
       'BJADP', 'YFTFA', 'XVBEG', 'YJULJ', 'TQHPS', 'VRQPC', 'YSHSQ',
       'RJORF', 'NDCXD', 'XMLIK', 'JOIVG', 'GMYAS', 'AKTLL', 'GMFHQ',
       'PYZNC', 'HNRYE', 'AWUTM', 'RKEKU', 'UYXRN', 'SEYSP', 'LQQXO',
       'FLGXV', 'OFBDL', 'RFRWT', 'LQZXI', 'REOJL', 'LRVMD', 'TTYKM',
       'OXSAF', 'WPWKF', 'AZDQM', 'JNCZM', 'AKTIT', 'TGZAW', 'NDGPH',
       'VFJNI', 'VGCEQ', 'OBZMI', 'SALRZ', 'TXDLA', 'HJIJU', 'EVOIO',
       'EMAWI', 'IZPKU', 'BONWP', 'MNUJO', 'SZSZK', 'PTJGZ', 'JZWFV',
       'ZHRUC', 'VISYA', 'PHCSZ', 'NJLKN', 'KCZZE', 'GLSAV', 'QHWRI',
       'OZBSW', 'SDPUK', 'PGIVM', 'LDJNG', 'VJGIV', 'XYATN', 'DGHKM',
       'YBSWJ', 'GFHDO', 'GAGVK', 'WYGOW', 'PEGZH', 'WUTSU', 'WBENF',
       'NMDCA', 'VCZZT', 'LHKIK', 'SXEGF', 'BWNBL', 'LUTDQ', 'NADRJ',
       'ZNRDM', 'TVFKM', 'LMHVX', 'JQJPS', 'NRTVE', 'FNNVN', 'XUNVM',
       'ILLQB', 'SZLBF', 'CGUAW', 'YEEZJ', 'VAZAP', 'YVIVK', 'MJJPU',
       'STANJ', 'FXFEE', 'RPNPY', 'WXBXA', 'QYNKI', 'XYQSI', 'DZRHZ',
       'PIXCU', 'ECGSP', 'KEYTR', 'VUCUV', 'TMRCT', 'GUQNN', 'BBAUD',
       'DKZXI', 'VCKPZ', 'BKXAP', 'KOSKX', 'YZBVW', 'DYDFY', 'VOHGK',
       'AQBUB', 'AHUVN', 'YCITI', 'DPBJG', 'IMNCI', 'JKMLB', 'FQVND',
       'BEJOR', 'NOJRS', 'KVTXM', 'IUAJZ', 'INGCC', 'LQONC', 'BJYEH',
       'MXYAQ', 'GRTXR', 'WUEBT', 'NZEKH', 'WMXSZ', 'PZELP', 'ZOWQN',
       'KJHFZ', 'NWXYG', 'IQIDT', 'ONSCX', 'MRPPS', 'CMFKN', 'JKTBY',
       'PEOCN', 'RKIRY', 'WKWCB', 'ZTPOI', 'XWMFR', 'SZUCZ', 'WPITP',
       'COAUV', 'SCPKD', 'XYXNW', 'FHXPF', 'DFMHT', 'HCXRZ', 'EWANM',
       'DVHXS', 'WWUTA', 'DFPAD', 'MBIFE', 'IWGQT', 'REJHO', 'ZFOBJ',
       'YXCWS', 'XLKXN', 'TEBLI', 'NIWTJ', 'DSODA', 'QNOKM', 'KCNDR',
       'TEFGP', 'KXONF', 'CYCDF', 'OQLKQ', 'GUQPA', 'ITFQZ', 'LNFAG',
       'MPVHI', 'SRSWC', 'DMPRF', 'DXGAH', 'NQTDN', 'ISJVE', 'ZNLSJ',
       'ALHRN', 'VMEDO', 'GFYDX', 'NYVHM', 'CJYCG', 'BWRPM', 'GPSUE',
       'QRPSN', 'YQQAD', 'PTDQE', 'TVQBH', 'HMUPZ', 'SDZBI', 'QKAHG',
       'UPDWF', 'IWTKN', 'ZSSRZ', 'YHLQG', 'QXHJL', 'KQBUH', 'QLPON',
       'EACKG', 'MMNDM', 'YEAIS', 'WCAIQ', 'XIUDQ', 'GTXLR', 'JWKPZ',
       'OLCYN', 'SRGQC', 'BVPHN', 'ORADC', 'TLFJR', 'LOYKC', 'CSICU',
       'XCQTG', 'VRLEG', 'VESOO', 'ADIQJ', 'GJMPO', 'JLUPZ', 'PHNMW',
       'TWSGH', 'EWXIA', 'MUSRA', 'CSVEV', 'YPOAK', 'MYLAO', 'BZRSS',
       'YKHCA', 'MTTAQ', 'VWUKS', 'SBBIQ', 'JQTUH', 'ZOQQR', 'ERLZS',
       'ZZVPP', 'MJKXQ', 'EALLB', 'FIJQE', 'VMBCY', 'AQERZ', 'XLLHL',
       'YAMXC', 'DVHUH', 'AVILB', 'QVFYQ', 'OFWLB', 'YJHBA', 'BWWMC',
       'DYOUB', 'BUDVY', 'LCSLN', 'XODJW', 'NCNAW', 'GSZXN', 'ISOXG',
       'SDKUJ', 'HJJAD', 'TSQDD', 'MMDZV', 'WERVI', 'ZCUDG', 'EDRGU',
       'UYUZO', 'AIKZK', 'HUXBZ', 'SZQAR', 'FZYWS', 'GYVQE', 'FOPKV',
       'RGAPI', 'XGOFZ', 'QTXLO', 'LQIVJ', 'UAJMX', 'STQXS', 'QXTAW',
       'ETKKE', 'LZVTQ', 'FBYXA', 'XTCEE', 'GXKOL', 'MGIGH', 'PAYNN',
       'KTTSZ', 'KCUSA', 'MVYJM', 'LTSME', 'PAJIB', 'CULDY', 'ILSEU',
       'VMSSZ', 'UJNKN', 'XCXND', 'YFAMO', 'BQOOC', 'JDMJI', 'WQCRZ',
       'JURMK', 'FKGMR', 'XDVTQ', 'EBDIH', 'VIEZS', 'UMCPL', 'ICIHJ',
       'SDJTI', 'WWEQQ', 'EOMGS', 'XXCJC', 'MRSBC', 'QVPCC', 'PFTHV',
       'XNSTQ', 'QKXEE', 'SFNXJ', 'TWRCN', 'UZLBJ', 'MYBXL', 'CTDDG',
       'ORWPQ', 'MNRHH', 'QQEFO', 'VIEBN', 'NPORW', 'IUFIM', 'NTATU',
       'AOADW', 'BXRTR', 'TTXJJ', 'QNRJK', 'KBTOX', 'TKUBQ', 'YXIHH',
       'XIKIG', 'WLNKI', 'KXHSF', 'XMHLT', 'WVDZM', 'YEYFW', 'HVEWR',
       'DYLEV', 'BATCT', 'CYDOQ', 'JCMIX', 'FFPLH', 'DVCXY', 'DYGUI',
       'LSOTK', 'BIXUY', 'PIMMG', 'WBIZO', 'YAVQW', 'TZITV', 'SUVHH',
       'KAXVD', 'VIPML', 'PXKAW', 'YUEKT', 'WWYQD', 'KYDYJ', 'PVCCM',
       'XZREU', 'JGPLN', 'ZAWLV', 'WTMNP', 'KSWIY', 'OHESH', 'VYJJH',
       'GZVWA', 'YVVYK', 'BONFT', 'ZSUUV', 'EPPWL', 'GNMAB', 'EMRNO',
       'ZCJOU', 'WQRXU', 'PAKBZ', 'VICOJ', 'SVPVA', 'GLMVE', 'ONQAB',
       'CKPTQ', 'CWKVE', 'JRQNY', 'VPRKN', 'QVFLE', 'FADTI', 'HDOKB',
       'JUTZW', 'MUUKK', 'OLQVX', 'QNFKF', 'SODEA', 'CQQNU', 'OGTJB',
       'FLPUW', 'UTPFR', 'SGJHZ', 'SJFIG', 'VEJNG', 'EYXAN', 'BLCUF',
       'HCZNK', 'OEUHW', 'THMHY', 'WORCU', 'JGIXC', 'ZMQNB', 'TKMVI',
       'DBRBP', 'BCKHC', 'YYZZX', 'OKTNF', 'UEQYN', 'DJNLD', 'PWZER',
       'ADNPG', 'TXZCR', 'NSYHW', 'CBYGS', 'FPIST', 'XULDR', 'LSZIL',
       'IIGJJ', 'JYJAZ', 'PIUAW', 'DADVB', 'XHFRG', 'OTRIQ', 'QALQJ',
       'EXAWE', 'ZXCTR', 'WMIUT', 'NZUMY', 'NVBDF', 'GDBOP', 'SPLLA',
       'QQQZS', 'FPORP', 'TLOYG', 'RTVOZ', 'ZNLCP', 'IRSWT', 'VVZIP',
       'OORYA', 'IMNXM', 'GWNUG', 'YKLMI', 'TOPPH', 'ICKGJ', 'QRTFE',
       'ZMMCR', 'EBGZI', 'BREHM', 'OHYTQ', 'BVVVV', 'EXHGA', 'EJGWB',
       'LJWVI', 'RLGSM', 'STOGD', 'ALRVH', 'BMIIB', 'NLSRJ', 'BZFTO',
       'ATZDS', 'OOLLE', 'JRWTQ', 'FAWTY', 'DZIOA', 'UYYED', 'OKAHU',
       'TGXJU', 'IZRJB', 'EYOUF', 'NPYNY', 'IPQCE', 'GGEKC', 'DWELC',
       'UGRVK', 'FELPR', 'PGADL', 'ZOZVZ', 'HRLWP', 'KYVML', 'KKIEV',
       'DQEWF', 'DAXUI', 'WNFOA', 'SHJWQ', 'YFAWP', 'DGYPO', 'UXKVW',
       'YMXVM', 'SDTKV', 'IUHMK', 'ZGVVY', 'SMYAX', 'TFHWC', 'HDFDJ',
       'WPECZ', 'GHEHY', 'JKIPN', 'GCOOB', 'ILMIR', 'UDKRP', 'WWOXU',
       'DAKJA', 'VNZVV', 'KYSCO', 'FQKBX', 'XQFKS', 'DFCYT', 'DGRZF',
       'WLWAN', 'KUYCT', 'JWWZN', 'MFBXC', 'LCAIC', 'HZGUU', 'BKDID',
       'DSBMO', 'LGQCE', 'HLFQG', 'MURPV', 'KLKDP', 'MUPIW', 'HHWZF',
       'FPAVL', 'TAUOA', 'BKQLQ', 'XJKUB', 'IBQRR', 'QTAQQ', 'VTAPK',
       'HCDEG', 'MPGFN', 'MBFKY', 'LGWZE', 'WMGVO', 'OSKST', 'VBHPR',
       'PUIQN', 'VHNGY', 'ZHWLH', 'JTZVV', 'HFGYE', 'FUWGN', 'JWPMR',
       'ZQVVG', 'KFPUK', 'ILSBY', 'ROACD', 'QOEWI', 'DHTMQ', 'HQGAS',
       'LHNJU', 'ZQBRA', 'KCWAR', 'MNGJL', 'LMVQW', 'NNQST', 'OKHTB',
       'YZXXY', 'PVELA', 'JLESE', 'ETXYW', 'FPNBF', 'OWTVL', 'YPHIJ',
       'DQNVC', 'DIFGJ', 'JNTNX', 'BRRYO', 'SLBCL', 'QJEWY', 'IHDZO',
       'OIUER', 'RYVLS', 'NDOSY', 'OGNSH', 'DFHFH', 'BLRAE', 'CKWGK',
       'JECFB', 'KTHZN', 'TOOUU', 'FEEGC', 'GKQAP', 'SXROH', 'JPUJR',
       'JQBCR', 'WITUB', 'RLFFV', 'RKMEZ', 'NBKWI', 'TCTPL', 'FMUBG',
       'HHRYP', 'RMMSR', 'JMBIT', 'ZMLDR', 'XBQFD', 'RHCSW', 'PTRNL',
       'OHAQX', 'JLSAG', 'UQBJP', 'DYEPB', 'GDTZX', 'FQXRB', 'LIQBR',
       'BBFWT', 'GAGYO', 'CSQWZ', 'WRWQF', 'NHGEB', 'HWNNC', 'YDZEB',
       'YAHRO', 'TITBA', 'GVCTY', 'ZCGBT', 'LGXPZ', 'RCDDJ', 'UXBKY',
       'UHXDI', 'FLNBE', 'QVCYN', 'UBJMO', 'ZNXZX', 'JWISS', 'PXUVL',
       'XSIKG', 'WJJKO', 'HVRUB', 'JFFIW', 'JBWUO', 'BDJKH', 'TZLEL',
       'DMKZJ', 'DYSSI', 'FSHPC', 'LQOQF', 'LBBFQ', 'UPJAS', 'WAQIK',
       'TLOSR', 'MNQAA', 'MSYNR', 'XCDMO', 'HKWNO', 'YPMEE', 'NBNWK',
       'VTVIP', 'QCERS', 'BMMLT', 'ZAYTJ', 'GPNYZ', 'UWRUN', 'SLXXZ',
       'GFQJK', 'URWVM', 'CKUJV', 'KVTRA', 'YJCAW', 'KPZYQ', 'TQKDF',
       'HFYFG', 'SZQHV', 'EQMTM', 'QAVSF', 'YZQVZ', 'HEIZH', 'LWELG',
       'KYLBX', 'WIBMQ', 'LBCTN', 'QHLIR', 'LCRZK', 'AOQJX', 'YMNLR',
       'BHUFN', 'FCKOG', 'ILSDP', 'PZPKM', 'PNRHG', 'ZYTZZ'], 
      dtype='|S5')

In [3]:
from numpy.random import rand
fac1, fac2, fac3 = np.random.rand(3, 1000)

ticker_subset = tickers.take(np.random.permutation(N)[:1000])

# 因子加权和以及噪声
port = Series(0.7 * fac1 - 1.2 * fac2 + 0.3 * fac3 + rand(1000),
             index=ticker_subset)
factors = DataFrame({'f1': fac1, 'f2': fac2, 'f3': fac3},
                   index=ticker_subset)
factors.corrwith(port)


Out[3]:
f1    0.416251
f2   -0.675152
f3    0.172357
dtype: float64

In [4]:
pd.ols(y=port, x=factors).beta


d:\Anaconda2\lib\site-packages\IPython\core\interactiveshell.py:2885: FutureWarning: The pandas.stats.ols module is deprecated and will be removed in a future version. We refer to external packages like statsmodels, see some examples here: http://statsmodels.sourceforge.net/stable/regression.html
  exec(code_obj, self.user_global_ns, self.user_ns)
Out[4]:
f1           0.708864
f2          -1.126909
f3           0.293945
intercept    0.468473
dtype: float64

In [6]:
ind_names = np.array(['FINANCIAL', 'TECH'])
sampler = np.random.randint(0, len(ind_names), N)
industries = Series(ind_names[sampler], index=tickers,
                   name='industry')

In [5]:
def beta_exposure(chunk, factors=None):
    return pd.ols(y=chunk, x=factors).beta

In [7]:
by_ind = port.groupby(industries)
exposures = by_ind.apply(beta_exposure, factors=factors)
exposures.unstack()


d:\Anaconda2\lib\site-packages\pandas\core\groupby.py:647: FutureWarning: The pandas.stats.ols module is deprecated and will be removed in a future version. We refer to external packages like statsmodels, see some examples here: http://statsmodels.sourceforge.net/stable/regression.html
  return func(g, *args, **kwargs)
Out[7]:
f1 f2 f3 intercept
industry
FINANCIAL 0.698325 -1.126663 0.301673 0.473768
TECH 0.719532 -1.127088 0.285383 0.463413

In [8]:
import pandas.io.data as web
data = web.get_data_yahoo('SPY', '2006-01-01', '2012-07-27')
data


d:\Anaconda2\lib\site-packages\pandas\io\data.py:35: FutureWarning: 
The pandas.io.data module is moved to a separate package (pandas-datareader) and will be removed from pandas in a future version.
After installing the pandas-datareader package (https://github.com/pydata/pandas-datareader), you can change the import ``from pandas.io import data, wb`` to ``from pandas_datareader import data, wb``.
  FutureWarning)
Out[8]:
Open High Low Close Volume Adj Close
Date
2006-01-03 125.190002 127.000000 124.389999 126.699997 73256700 102.136154
2006-01-04 126.860001 127.489998 126.699997 127.300003 51899600 102.619834
2006-01-05 127.150002 127.589996 126.879997 127.379997 47307500 102.684320
2006-01-06 128.020004 128.580002 127.360001 128.440002 62885900 103.538818
2006-01-09 128.419998 129.059998 128.380005 128.770004 43527400 103.804841
2006-01-10 128.389999 128.979996 128.259995 128.899994 44960800 103.909629
2006-01-11 129.020004 129.440002 128.729996 129.309998 49598900 104.240143
2006-01-12 129.080002 129.279999 128.440002 128.800003 40509200 103.829023
2006-01-13 128.570007 128.899994 128.199997 128.679993 44856700 103.732280
2006-01-17 128.199997 128.419998 127.809998 128.330002 52066600 103.450143
2006-01-18 127.580002 128.899994 127.160004 127.820000 75067600 103.039017
2006-01-19 128.130005 128.770004 127.809998 128.309998 81530400 103.434017
2006-01-20 128.279999 128.309998 125.970001 125.970001 114957800 101.547686
2006-01-23 126.209999 126.820000 126.129997 126.419998 67017400 101.910440
2006-01-24 126.629997 127.150002 126.419998 126.550003 53008800 102.015240
2006-01-25 127.040001 127.180000 125.839996 126.660004 87747700 102.103914
2006-01-26 127.250000 127.669998 126.760002 127.360001 71294000 102.668200
2006-01-27 127.660004 128.660004 127.449997 128.539993 65771200 103.619423
2006-01-30 128.440002 128.809998 128.350006 128.440002 33709600 103.538818
2006-01-31 128.320007 128.539993 127.489998 127.500000 72937000 102.781057
2006-02-01 127.820000 128.429993 127.720001 128.389999 63561000 103.498509
2006-02-02 128.100006 128.139999 126.800003 126.900002 83626900 102.297383
2006-02-03 126.580002 128.389999 126.139999 126.269997 86040400 101.789520
2006-02-06 126.440002 126.800003 126.169998 126.599998 45511900 102.055543
2006-02-07 126.379997 126.660004 125.400002 125.480003 71208100 101.152686
2006-02-08 125.849998 128.100006 125.599998 126.620003 59422200 102.071669
2006-02-09 126.919998 127.599998 126.370003 126.410004 62023300 101.902383
2006-02-10 126.430000 127.129997 125.449997 126.639999 64508700 102.087788
2006-02-13 126.599998 126.790001 125.949997 126.410004 52308700 101.902383
2006-02-14 126.459999 128.029999 126.209999 127.750000 90964400 102.982589
... ... ... ... ... ... ...
2012-06-15 133.380005 134.259995 133.100006 134.139999 169444500 123.518650
2012-06-18 133.580002 134.729996 133.279999 134.399994 131360900 123.758058
2012-06-19 135.080002 136.250000 134.369995 135.699997 137382600 124.955125
2012-06-20 135.710007 136.100006 134.270004 135.479996 206451800 124.752544
2012-06-21 135.639999 135.779999 132.330002 132.440002 205272200 121.953261
2012-06-22 133.130005 133.710007 132.619995 133.460007 130029200 122.892500
2012-06-25 132.050003 132.100006 130.850006 131.320007 146375700 120.921948
2012-06-26 131.699997 132.380005 130.929993 131.979996 141634000 121.529678
2012-06-27 132.419998 133.429993 131.970001 133.169998 108088000 122.625455
2012-06-28 132.289993 132.990005 131.279999 132.789993 169242100 122.275539
2012-06-29 135.199997 136.270004 134.850006 136.100006 212250900 125.323461
2012-07-02 136.479996 136.649994 135.520004 136.509995 129524500 125.700986
2012-07-03 136.479996 137.509995 136.339996 137.410004 80450000 126.529732
2012-07-05 136.899994 137.800003 136.289993 136.789993 126177500 125.958815
2012-07-06 135.470001 135.770004 134.850006 135.490005 151192100 124.761761
2012-07-09 135.380005 135.570007 134.699997 135.320007 103780500 124.605224
2012-07-10 136.009995 136.229996 133.679993 134.139999 167884800 123.518650
2012-07-11 134.210007 134.600006 133.380005 134.160004 141733400 123.537070
2012-07-12 133.380005 134.229996 132.600006 133.509995 143583200 122.938530
2012-07-13 133.860001 135.889999 133.839996 135.750000 129642600 125.001169
2012-07-16 135.440002 135.830002 134.899994 135.429993 97525200 124.706500
2012-07-17 135.970001 136.639999 134.550003 136.360001 138860300 125.562869
2012-07-18 136.039993 137.639999 135.960007 137.369995 113349700 126.492891
2012-07-19 137.649994 138.179993 137.210007 137.729996 129847300 126.824387
2012-07-20 136.949997 137.160004 136.320007 136.470001 142904500 125.664160
2012-07-23 134.470001 136.380005 133.839996 135.089996 145210900 124.393425
2012-07-24 135.190002 135.250000 133.029999 133.929993 173301200 123.325272
2012-07-25 134.210007 134.559998 133.250000 133.960007 129122300 123.352909
2012-07-26 135.889999 136.460007 135.259995 136.169998 156526500 125.387911
2012-07-27 136.889999 139.070007 136.139999 138.679993 236768900 127.699162

1655 rows × 6 columns


In [16]:
px = data['Adj Close']
returns = px.pct_change()

def to_index(rets):
    index = (1 + rets).cumprod()
    #first_loc = max(index.notnull().argmax() - 1, 0)
    #index.values[first_loc] = 1
    return index

def trend_signal(rets, lookback, lag):
    signal = pd.rolling_sum(rets, lookback, min_periods=lookback - 5)
    return signal.shift(lag)

In [14]:
signal = trend_signal(returns, 100, 3)
trade_friday = signal.resample('W-FRI').resample('B').ffill()
trade_rets = trade_friday.shift(1) * returns
trade_rets


d:\Anaconda2\lib\site-packages\ipykernel\__main__.py:11: FutureWarning: pd.rolling_sum is deprecated for Series and will be removed in a future version, replace with 
	Series.rolling(min_periods=95,window=100,center=False).sum()
d:\Anaconda2\lib\site-packages\ipykernel\__main__.py:2: FutureWarning: .resample() is now a deferred operation
use .resample(...).mean() instead of .resample(...)
  from ipykernel import kernelapp as app
Out[14]:
Date
2006-01-03             NaN
2006-01-04             NaN
2006-01-05             NaN
2006-01-06             NaN
2006-01-09             NaN
2006-01-10             NaN
2006-01-11             NaN
2006-01-12             NaN
2006-01-13             NaN
2006-01-16             NaN
2006-01-17             NaN
2006-01-18             NaN
2006-01-19             NaN
2006-01-20             NaN
2006-01-23             NaN
2006-01-24             NaN
2006-01-25             NaN
2006-01-26             NaN
2006-01-27             NaN
2006-01-30             NaN
2006-01-31             NaN
2006-02-01             NaN
2006-02-02             NaN
2006-02-03             NaN
2006-02-06             NaN
2006-02-07             NaN
2006-02-08             NaN
2006-02-09             NaN
2006-02-10             NaN
2006-02-13             NaN
                  ...     
2012-06-18    4.884083e-05
2012-06-19    2.437373e-04
2012-06-20   -4.085278e-05
2012-06-21   -5.654241e-04
2012-06-22    1.940706e-04
2012-06-25   -4.222074e-04
2012-06-26    1.323332e-04
2012-06-27    2.374123e-04
2012-06-28   -7.513573e-05
2012-06-29    6.563381e-04
2012-07-02    6.245238e-05
2012-07-03    1.366842e-04
2012-07-04             NaN
2012-07-05   -9.354402e-05
2012-07-06   -1.970248e-04
2012-07-09   -1.581715e-05
2012-07-10   -1.099299e-04
2012-07-11    1.879965e-06
2012-07-12   -6.107852e-05
2012-07-13    2.115085e-04
2012-07-16   -4.702764e-05
2012-07-17    1.369950e-04
2012-07-18    1.477627e-04
2012-07-19    5.228113e-05
2012-07-20   -1.825043e-04
2012-07-23   -4.270095e-05
2012-07-24   -3.626019e-05
2012-07-25    9.463087e-07
2012-07-26    6.966417e-05
2012-07-27    7.783688e-05
Name: Adj Close, dtype: float64

In [17]:
to_index(trade_rets).plot()


Out[17]:
<matplotlib.axes._subplots.AxesSubplot at 0xcf52ac8>

In [43]:
vol = returns.rolling(250, min_periods=200).std() * np.sqrt(250)

def sharpe(rets, ann=250):
    return rets.mean() / rets.std() * np.sqrt(ann)

trade_rets = trade_rets.reindex(vol.index, method='ffill')
len(vol) - len(trade_rets)


Out[43]:
0

In [44]:
trade_rets.groupby(pd.qcut(vol, 4)).agg(sharpe)


Out[44]:
Adj Close
[0.0954, 0.16]   -0.012380
(0.16, 0.188]     0.278561
(0.188, 0.231]   -0.325216
(0.231, 0.457]    0.525923
Name: Adj Close, dtype: float64

In [ ]: