Notebook
In [71]:
#Custom factor for Sector PE
from quantopian.pipeline import CustomFactor
class SectorPE(CustomFactor):
    # Default inputs
    inputs = [Fundamentals.pe_ratio, morningstar.asset_classification.morningstar_sector_code]
    window_length = 252 #anual ratio
    # dataframe of the latest pe_ratio and sector name the [-1] specifies how many days from current day you
    # are getting values for. -1 being most recent.
    def compute(self, today, assets, out, pe, sectors):
        df = pd.DataFrame(index=assets, data={"pe_ratio": pe[-1],  
                                             "sector_code": sectors[-1]})  
        out[:] = df.groupby("sector_code").transform(np.mean).values.flatten() 
        
In [75]:
from quantopian.pipeline import Pipeline, CustomFactor
from quantopian.pipeline.data import morningstar
from quantopian.pipeline.data.morningstar import Fundamentals
from quantopian.pipeline.domain import US_EQUITIES
from quantopian.pipeline.filters import Q500US
from quantopian.research import run_pipeline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt




# Select a time range to inspect
period_start = '2002-11-17'
period_end = '2019-11-18'


# Pipeline definition
def make_pipeline():
    base_universe = Q500US()
    tradable_filter_notNull_PE = (Fundamentals.pe_ratio.latest.notnull() & Q500US())
    sector = morningstar.asset_classification.morningstar_sector_code.latest
    #https://www.quantopian.com/posts/morningstar-pe-ratio
    #Adjusted Close Price/ EPS. If the result is negative, zero, >10,000 or <0.001, then null.
    pe_ratio = Fundamentals.pe_ratio.latest 
    sector_pe = pe_ratio - pe_ratio.demean(groupby=sector) # simple way to get a sector average pe
    #.rank(groupby=sector)  
    
    return Pipeline(
        columns={
            'pe_ratio': pe_ratio,
            'custom_factor_sector_pe' : SectorPE(),
            'demean sector_pe' : sector_pe,
            'sector' : sector
        },
        screen=tradable_filter_notNull_PE
    )

# Pipeline execution
#panda_dataFrame
data = run_pipeline(
    make_pipeline(),
    start_date=period_start,
    end_date=period_end
)

data.tail(50)

Pipeline Execution Time: 2 Minutes, 37.61 Seconds
Out[75]:
custom_factor_sector_pe deman sector_pe pe_ratio sector
2019-11-18 00:00:00+00:00 Equity(45852 [TNDM]) 86.987513 86.987513 0.075293 206
Equity(45971 [AAL]) 74.698368 74.698368 8.152542 310
Equity(45992 [ARMK]) 64.302207 64.302207 20.594340 102
Equity(45993 [HLT]) 64.302207 64.302207 31.547468 102
Equity(46015 [ALLY]) 34.820332 34.820332 7.622222 103
Equity(46693 [GRUB]) 90.432737 90.432737 994.750000 308
Equity(46744 [PAYC]) 149.348163 149.348163 81.666667 311
Equity(46989 [PE]) 67.147838 67.147838 17.210526 309
Equity(47063 [ANET]) 149.348163 149.348163 20.297155 311
Equity(47163 [INFO]) 74.698368 74.698368 76.752688 310
Equity(47415 [SYF]) 34.820332 34.820332 6.760949 103
Equity(47777 [CFG]) 34.820332 34.820332 10.052910 103
Equity(47779 [CYBR]) 149.348163 149.348163 64.913793 311
Equity(47912 [ZAYO]) 149.348163 149.348163 56.213115 311
Equity(47921 [KEYS]) 149.348163 149.348163 66.920245 311
Equity(48863 [GDDY]) 149.348163 149.348163 103.181818 311
Equity(48934 [ETSY]) 64.302207 64.302207 50.602410 102
Equity(49229 [KHC]) 81.173594 81.173594 5.701775 205
Equity(49242 [PYPL]) 34.820332 34.820332 48.920188 103
Equity(49506 [HPE]) 149.348163 149.348163 47.888889 311
Equity(49608 [MTCH]) 90.432737 90.432737 40.045714 308
Equity(49655 [TEAM]) 149.348163 149.348163 1343.000000 311
Equity(50049 [FTV]) 149.348163 149.348163 33.787736 311
Equity(50288 [TTD]) 149.348163 149.348163 111.780488 311
Equity(50350 [COUP]) 149.348163 149.348163 81.690909 311
Equity(50392 [YUMC]) 64.302207 64.302207 23.772222 102
Equity(50428 [AA]) 79.517758 79.517758 22.216667 101
Equity(50642 [INVH]) 108.912718 108.912718 130.391304 104
Equity(50716 [DXC]) 149.348163 149.348163 8.433014 311
Equity(50735 [AYX]) 149.348163 149.348163 512.736842 311
Equity(50807 [CVNA]) 64.302207 64.302207 717.892392 102
Equity(50860 [VST]) 40.037890 40.037890 24.952381 207
Equity(50970 [ATUS]) 90.432737 90.432737 53.760000 308
Equity(51012 [BKR]) 67.147838 67.147838 50.422222 309
Equity(51157 [DD]) 79.517758 79.517758 17.846942 101
Equity(51231 [ROKU]) 90.432737 90.432737 4.400000 308
Equity(51689 [PAGS]) 149.348163 149.348163 42.836742 311
Equity(51854 [DBX]) 149.348163 149.348163 232.888889 311
Equity(51895 [SPOT]) 90.432737 90.432737 82.709661 308
Equity(51937 [DOCU]) 149.348163 149.348163 11.476427 311
Equity(52064 [EVRG]) 40.037890 40.037890 27.205882 207
Equity(52424 [ELAN]) 86.987513 86.987513 104.440000 206
Equity(52537 [STNE]) 149.348163 149.348163 73.536577 311
Equity(52592 [LIN]) 79.517758 79.517758 18.995471 101
Equity(52747 [DELL]) 149.348163 149.348163 16.278878 311
Equity(52968 [FOXA]) 90.432737 90.432737 14.274926 308
Equity(52991 [DOW]) 79.517758 79.517758 15.229675 101
Equity(53095 [ZM]) 90.432737 90.432737 1601.839564 308
Equity(53158 [UBER]) 149.348163 149.348163 2583.204334 311
Equity(53196 [CTVA]) 79.517758 79.517758 38.137946 101
In [76]:
from quantopian.pipeline.data.morningstar import Fundamentals
from quantopian.pipeline.domain import US_EQUITIES
from quantopian.pipeline.filters import Q500US
from quantopian.research import run_pipeline
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import cm
#https://www.quantopian.com/posts/sector-performance-notebook
# Select a time range to inspect
period_start = '2002-11-17'
period_end = '2019-11-18'
sector_codes = {
    # Cyclical
            '101': 'Basic Materials',
             '102': 'Consumer Cyclical',
             '103': 'Finacial Services',
             '104': 'Real Estate',
    #Defensive
             '205': 'Consumer Defensive',
             '206': 'Healthcare',
             '207': 'Utilities',
    #Sensitive
             '308': 'Communication Services',
             '309': 'Energy',
             '310': 'Industrials',
             '311': 'Technology'}
sector = morningstar.asset_classification.morningstar_sector_code.latest
pe_ratio = Fundamentals.pe_ratio.latest 
base_universe = Q500US()
tradable_filter_notNull_PE = (Fundamentals.pe_ratio.latest.notnull() & Q500US())

pipe = Pipeline(
        columns={
            'pe_ratio': pe_ratio,
            'sector' : sector
        },
        screen=tradable_filter_notNull_PE
    )

# Pipeline execution
#panda_dataFrame
data = run_pipeline(
    pipe,
    start_date=period_start,
    end_date=period_end
)
data = data.reset_index()
#data.head()
#Redefine index
data.set_index(['level_0', 'sector'])
#group by date/sector
data = data.groupby(['level_0', 'sector']).mean()
data = data.unstack().dropna()
#https://www.analyticsvidhya.com/blog/2016/01/python-tutorial-list-comprehension-examples/
data = data.rename(columns = {i: sector_codes[str(int(i))] for i in [x[1] for x in data.columns]})
data.tail(50)
#data.plot(colormap=cm.Set1)
#plt.show()

Pipeline Execution Time: 1 Minute, 16.49 Seconds
Out[76]:
pe_ratio
sector Basic Materials Consumer Cyclical Finacial Services Real Estate Consumer Defensive Healthcare Utilities Communication Services Energy Industrials Technology
level_0
2019-09-10 00:00:00+00:00 24.168626 73.593077 37.683851 62.022820 28.016342 39.811390 26.742589 191.176545 25.049520 25.356342 110.290325
2019-09-11 00:00:00+00:00 24.468865 72.159841 37.580846 60.875540 27.846630 40.125515 26.782791 194.597653 25.236765 25.423605 109.851798
2019-09-12 00:00:00+00:00 24.697554 73.168509 37.670602 60.854958 27.912658 40.626029 27.052381 195.376565 25.125359 25.542108 110.457040
2019-09-13 00:00:00+00:00 24.780927 74.010540 37.812160 61.075947 27.974062 40.469876 27.073485 197.225232 25.027896 25.657822 110.494500
2019-09-16 00:00:00+00:00 25.023704 73.633630 37.878390 60.414099 27.907314 40.295349 26.978771 191.692802 25.218243 25.704119 110.286224
2019-09-17 00:00:00+00:00 24.741033 72.630018 37.847938 61.119825 27.769949 40.324698 27.061045 184.860477 25.876237 25.669464 110.453709
2019-09-18 00:00:00+00:00 24.749374 72.466142 37.936991 62.198662 27.919427 40.246788 27.215038 192.553489 25.537673 25.703679 110.772034
2019-09-19 00:00:00+00:00 24.798785 71.841510 37.927923 61.948832 27.920182 40.182460 27.315182 192.474988 25.481106 25.662457 111.246407
2019-09-20 00:00:00+00:00 24.794479 72.139818 37.900176 61.859943 27.888179 40.180801 27.371959 192.765168 25.396931 25.586952 111.259694
2019-09-23 00:00:00+00:00 24.679055 71.757662 37.755745 62.149519 27.874411 40.393995 27.460641 188.744056 25.467813 25.406416 110.962293
2019-09-24 00:00:00+00:00 24.666602 71.285483 37.796634 62.370202 27.909304 40.181197 27.491802 188.664715 25.433256 25.347926 110.816893
2019-09-25 00:00:00+00:00 24.438429 70.785004 37.666356 62.672411 27.986656 39.582563 27.684048 194.101226 25.122972 25.186140 109.821670
2019-09-26 00:00:00+00:00 24.613934 71.875327 37.772108 62.179271 27.983932 39.573596 27.996632 193.297553 25.123178 25.580709 110.013502
2019-09-27 00:00:00+00:00 24.566954 71.608022 37.723564 62.507267 28.110307 39.204243 27.761849 193.355995 24.895705 25.574113 110.086923
2019-09-30 00:00:00+00:00 24.536196 71.006066 37.609407 61.766566 28.133834 38.787199 27.691409 185.462958 24.908611 25.379362 109.177928
2019-10-01 00:00:00+00:00 24.714864 74.236572 37.601948 70.315001 28.207499 38.849512 27.685494 185.961743 25.186622 25.369248 109.654245
2019-10-02 00:00:00+00:00 24.394430 73.980033 37.224066 69.800842 28.114656 38.216159 27.615255 184.897025 24.878803 24.861427 109.141014
2019-10-03 00:00:00+00:00 23.974616 73.051757 36.880534 69.535307 27.719555 37.680220 27.263983 180.773993 24.570447 24.443169 108.255046
2019-10-04 00:00:00+00:00 24.036025 74.213591 35.489887 70.297827 27.811239 38.178601 27.330647 187.199335 24.811716 24.595571 109.011393
2019-10-07 00:00:00+00:00 24.159878 74.483244 35.765766 70.582287 29.069365 38.525178 27.675829 186.843564 24.817457 24.866897 109.590873
2019-10-08 00:00:00+00:00 24.076967 73.651722 35.694274 70.240242 28.885940 38.345181 27.562372 187.929817 24.617083 24.727614 109.662172
2019-10-09 00:00:00+00:00 23.740801 71.640629 35.384073 70.089622 28.668198 37.638887 27.342871 180.690314 24.299333 24.382467 108.419538
2019-10-10 00:00:00+00:00 23.919341 72.311728 35.551583 70.504997 28.806897 37.936166 27.427083 179.181075 24.476358 24.629813 108.979386
2019-10-11 00:00:00+00:00 24.106298 73.330683 35.687263 70.786070 28.849733 38.084223 27.424666 175.213619 24.617155 24.843435 108.801382
2019-10-14 00:00:00+00:00 24.492085 74.605584 35.887399 70.403897 28.854239 38.474894 27.417797 175.931356 24.882609 25.319598 109.856565
2019-10-15 00:00:00+00:00 24.300672 74.637638 35.886741 70.439250 28.750383 38.382240 27.282975 174.778406 24.799556 25.293683 109.942996
2019-10-16 00:00:00+00:00 24.430078 75.601861 36.076462 70.396705 28.670298 38.855041 27.256018 175.765321 24.853977 25.520888 110.451423
2019-10-17 00:00:00+00:00 24.460541 74.342839 36.019745 70.082580 28.694113 38.760686 27.316802 168.889933 24.688345 25.491945 109.566797
2019-10-18 00:00:00+00:00 24.439311 74.253313 36.048000 70.153570 28.766553 38.834476 27.381553 167.724164 24.755260 25.568924 109.711989
2019-10-21 00:00:00+00:00 24.379754 73.096637 36.059425 70.960021 28.777709 38.642812 27.457810 165.632028 23.634967 25.453543 108.729346
2019-10-22 00:00:00+00:00 24.336047 73.864446 36.208014 71.225172 28.764531 38.519384 27.560662 164.961409 24.863952 25.582342 109.206094
2019-10-23 00:00:00+00:00 24.336058 73.122059 36.014304 70.833878 28.699052 42.321486 27.671374 157.040603 25.121599 25.593418 108.539752
2019-10-24 00:00:00+00:00 24.192032 73.237884 36.091142 71.084558 28.480149 38.708096 27.822019 157.131220 25.252778 25.570438 108.730439
2019-10-25 00:00:00+00:00 25.694191 73.966605 36.221984 70.894337 28.500626 38.697828 27.889239 162.127114 25.210843 25.817536 123.792515
2019-10-28 00:00:00+00:00 25.947904 74.050593 36.305017 70.119170 28.322671 38.879739 27.520201 160.510239 25.359299 25.968988 124.540717
2019-10-29 00:00:00+00:00 26.054736 73.516857 36.404372 69.755903 28.256478 39.570904 27.247770 167.573146 25.202008 26.019701 125.369769
2019-10-30 00:00:00+00:00 26.188260 73.474955 36.446789 68.741770 28.366579 40.172608 27.305060 165.367187 25.274024 26.075813 132.114577
2019-10-31 00:00:00+00:00 25.937239 74.173471 36.497772 65.099560 28.569024 39.725750 27.497850 174.934215 24.964367 26.018059 134.094309
2019-11-01 00:00:00+00:00 25.535114 110.130443 37.376885 63.348137 30.188796 40.027632 27.801676 174.743557 24.024118 35.121825 132.654551
2019-11-04 00:00:00+00:00 26.408605 110.710799 37.520103 62.116575 31.149317 40.504397 27.776528 176.048440 24.333134 36.522458 129.845405
2019-11-05 00:00:00+00:00 27.059620 122.173831 16.715531 61.173531 31.538142 40.923464 27.647383 112.229016 24.814185 36.463436 137.360414
2019-11-06 00:00:00+00:00 27.265783 122.850212 16.704350 62.267592 31.651707 39.962330 27.332829 110.267408 25.693836 36.485459 136.716792
2019-11-07 00:00:00+00:00 23.573697 123.140785 16.770415 60.497778 31.777621 37.558572 27.631534 109.744350 25.324044 36.652241 136.777266
2019-11-08 00:00:00+00:00 24.469252 123.667700 16.861991 59.655014 31.685852 37.960864 27.108740 108.736912 25.512513 37.394296 135.402529
2019-11-11 00:00:00+00:00 24.524990 124.497071 16.883988 59.592138 31.656404 38.253971 26.695769 112.481214 25.640959 37.664727 135.595475
2019-11-12 00:00:00+00:00 24.398219 124.491838 16.746390 59.708601 31.554703 38.421631 26.518124 112.091354 25.514687 37.512672 135.469276
2019-11-13 00:00:00+00:00 24.429088 123.705562 17.352055 59.396123 31.594456 38.695479 26.579228 111.843251 25.473325 37.316309 136.328679
2019-11-14 00:00:00+00:00 24.329920 123.721851 17.304850 60.033589 31.798964 38.706738 26.852040 111.291160 25.361502 37.105882 136.510626
2019-11-15 00:00:00+00:00 24.457628 123.911230 17.375589 60.467641 31.775987 38.676798 26.874535 112.773568 25.335218 37.474191 136.580098
2019-11-18 00:00:00+00:00 24.481610 124.212213 17.434703 60.864319 31.753668 39.335964 26.899026 115.634121 25.511504 37.843463 137.792852
In [ ]:
 
In [ ]:
#Testing graphing
# Slice dataframe to get values for each stock
idx = pd.IndexSlice
T_data = data.loc[idx[:, symbols('T')], :]
VZ_data = data.loc[idx[:, symbols('VZ')], :]

dates = data.index.levels[0] # x-coordinates

plt.plot(dates, T_data['pe_ratio'], label ='T PE Ratio')
plt.plot(dates, VZ_data['pe_ratio'], label='VZ PE Ratio')

# Add labels
plt.legend()
plt.title('PE Ratios')
plt.show()