Simple algorithm mainly based on Value (and Millenial) approach. (To be imporved)

This algorithm is roughly based on 2 books: Benjamin Graham's "The Intelligent Investor" and Patrick O'Shaughnessy's "Millenial Money". I am hoping to improve it in the nearest future by telling it to sell only in the case if the Sell - Buy of any given stock is positive, by allocating a different weight to each stock based on the market cap and by hopefully including: some of the more complicated HFT strategies and sentiment analysis.

86
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
"""
This Algorithm takes ideas from Benjamin Graham's Book ("The Intelligent Investor" and from Patrick O'Shaughnessy's book ("Millennial Money"). Although their ideas are similar there are some changes to the screening process.

"""

import pandas as pd
import numpy as np

def initialize(context):
### This instructions are here, because I am using Robinhood (famous for 0 fees and no shorting ability)
set_long_only()

### For Fundamentals Screening
context.max_num_stocks = 50

### Start the countdown (in days)
context.days = 0
### How long is the period (in days), for buy/sell frequency, !!!SUBJECT TO CHANGE!!!
context.periods_in_days = 100

schedule_function(compute_and_rebalance,
date_rules.every_day(),
time_rules.market_open(minutes=30))

def period_passed(context):
### This will tell if the period has passed and if it is time to buy/sell
return context.days % context.periods_in_days == 0

context.days += 1

if not period_passed(context):
return

screening(context)
context.security_list = list(context.fundamental_df.columns.values)

def screening(context):
### This is where screening (the most important part takes place)
fundamental_df = get_fundamentals(
query(
fundamentals.share_class_reference.is_primary_share,
fundamentals.cash_flow_statement.financing_cash_flow,

fundamentals.valuation.market_cap,
fundamentals.valuation_ratios.pe_ratio,
fundamentals.valuation_ratios.pb_ratio,
fundamentals.valuation_ratios.dividend_yield,
fundamentals.income_statement.research_and_development,

fundamentals.income_statement.operating_income,
fundamentals.income_statement.net_income,
fundamentals.balance_sheet.cash_and_cash_equivalents,

)

.filter(fundamentals.share_class_reference.is_primary_share == True)

.filter(fundamentals.valuation.market_cap > 10000000)
.filter(fundamentals.valuation_ratios.pe_ratio < 11)
.filter(fundamentals.valuation_ratios.pb_ratio < 1.6)
.filter(fundamentals.income_statement.research_and_development > 0)
.filter(fundamentals.valuation_ratios.dividend_yield > 0.015)

.filter(fundamentals.valuation.shares_outstanding > 0)
.filter(fundamentals.balance_sheet.cash_and_cash_equivalents > 0)
.filter( fundamentals.income_statement.net_income > 0)

.limit(context.max_num_stocks)
)

### Updating context
context.stocks = [stock for stock in fundamental_df]
context.fundamental_df = fundamental_df

def rebalance(context, data):
### Sell all shares before buying new ones
for stock in context.portfolio.positions:
if stock in context.fundamental_df:
### Add an instruction which only allows to sell if you sell higher then you bought
order_target_percent(stock, 0)

### Leave a 2% cash reserve.
weight = 0.98/len(context.stocks)

### buy all stocks equally, (To change in the future)
for stock in context.stocks:
order_target_percent(stock, weight)

def compute_and_rebalance(context, data):
if not period_passed(context):
return

rebalance(context, data)

There was a runtime error.
3 responses

Nice looking code! I ran a few backtests, and my biggest question is are you planning on implementing any sort of logic to protect against drawdown?

Delman Woodrum, although Drawdown does somewhat worries me my main focus is on improving the buying/selling functions. I am currently trying to allow my algorithm to buy more than 10 stocks and I also want to make my algorithm to sell stocks ONLY if it has positive return. And so on. In other words, as of right now Drawdown is not my strongest concern. But thanks for the response, I didn't expect to hear from anyone that quickly.

Hi Rasul! Great Algo, do you have a version of it that currently works on pipeline instead of Get_Fundamentals?