Back to Community
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.

Clone Algorithm
71
Loading...
Backtest from to with initial capital
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()    
    set_commission(commission.PerTrade(cost=0))
    
### 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

def before_trading_start(context, data): 
    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:
            if data.can_trade(stock):
### 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:
        if data.can_trade(stock):
            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?