Back to Community
[Feedback request] A newbie building his framework to start messing with algos

Hi!
I'm new at python, quantopian & stock exchange (perfect combo right?) so i wanted to build a framework that (hopefully) can be reused when coding any crazy algorithm idea.

What i expect from my framework:
- 0 leverage
- Prevent overlapped buy/sell orders
- Automatic stoploss

¿Could you guys give me ideas on how to improve the base/framework?

¡Any constructive criticism is welcome!

Clone Algorithm
4
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
# Some sources
# Difference between 2 numbers: http://www.calculatorsoup.com/calculators/algebra/percent-difference-calculator.php

import math

"""
    Called once at the start of the algorithm.
    """ 
def initialize(context):
    
    context.settings = {
        'maxPercentPerETF': 10, # % from initial investment
        'stopLossBenefits': 4, # % if currentPrice > buyPrice && has lost stopLossBenefits% the latest days
        'stopLoss': 6, # %
        'reserveBenefitsPercent': 0 # % if currentCash > initialCash, do not reinvest this percent
    };

    # http://etfdb.com/etfdb-categories/
    context.etfs = [
        symbol('XLK'), # tech
        symbol('USO'), #oil
        symbol('GLD'), #gold
        symbol('SPY'), #spy
        symbol('XLE'), #energy
        symbol('VNQ'), #realestate
        symbol('SLV'), #silver
        symbol('TAN'), #alt_energy
        symbol('AOR'), #diversified_portfolio
        symbol('DBA'), #agriculture
        symbol('XLF'), #financial
    ]
    context.latestSell = {};
    setupStopLossBenefitsCrons();
    
    
def setupStopLossBenefitsCrons():
    # For every minute available (max is 6 hours and 30 minutes)
  total_minutes = 6 * 60 + 30

  for i in range(1, total_minutes):
    # Every 10 minutes run schedule
    if i % 10 == 0:
      # This will start at 9:31AM and will run every 10 minutes
      schedule_function(lookForSpikeBenefits, date_rules.every_day(), time_rules.market_open(minutes=i), True)
    elif i % 30 == 0:

      # This will start at 9:31AM and will run every 30 minutes
      schedule_function(lookForSlowCollapses, date_rules.every_day(), time_rules.market_open(minutes=i), True)
        
# Automatically executed every minute
def handle_data(context, data):
    stopLosses(context, data)
    runAlgorithm(context, data)
    
def lookForSpikeBenefits(context, data):
    for stock in context.portfolio.positions:
        checkStopLossBenefits(context, data, stock, False)
    
def lookForSlowCollapses(context, data):
    for stock in context.portfolio.positions:
        checkStopLossBenefits(context, data, stock, True)
    
def runAlgorithm(context, data):
    priceHistory = data.history(context.etfs, "price", 2, "1d")
        
    # Look for any growing stock
    for stock in context.etfs:
        yesterdayPrice = priceHistory[stock][-2]
        currentPrice = priceHistory[stock][-1]
            
        if currentPrice > yesterdayPrice:
            buyStock(context, data, stock, context.settings['maxPercentPerETF'])
        
'''
    Check if any stock in portfolio is generating higher losses than what we allow
'''
def stopLosses(context, data):
    for stock in context.portfolio.positions:
        position = context.portfolio.positions[stock]
        priceHistory = data.history(stock, "price", 2, "1d")
        yesterdayPrice = priceHistory[-2]
        currentPrice = priceHistory[-1]
        diffPercent = ((currentPrice - position.cost_basis) / position.cost_basis) * 100
        
        
        if (diffPercent <= -context.settings['stopLoss']) and (currentPrice < yesterdayPrice):
            #print str(diffPercent) + " - " + str(context.settings['stopLoss'])
            print "SELLing "+ stock.symbol + " request " + str(diffPercent) + "% ("+ str(currentPrice) + "/" + str(position.cost_basis) +")"
            sellStock(context, stock)

"""
    Checks if the given stock has currentPrice > buyPrice and
    price has started dropping, to sell it before lossing any benefit
"""
def checkStopLossBenefits(context, data, stock, inAWeek):
    position = context.portfolio.positions[stock]
    if inAWeek:
        priceHistory = data.history(stock, "price", 7, "1d")
        yesterdayPrice = priceHistory[-7]
        currentPrice = priceHistory[-1]
    else:
        priceHistory = data.history(stock, "price", 2, "1d")
        yesterdayPrice = priceHistory[-2]
        currentPrice = priceHistory[-1]
    
    
    lossesPercent = ((currentPrice - position.cost_basis) / position.cost_basis) * 100; # bad if its negative
    diffPercent = ((yesterdayPrice - currentPrice) / currentPrice) * 100

    if (lossesPercent > 0 and diffPercent <= -context.settings['stopLossBenefits']):
        sellStock(context, stock)


def sellStock (context, stock):
    if (context.portfolio.positions[stock].amount > 0):
        print "SELLing " + stock.symbol
        closeAnyOpenOrders(stock)
        order_target(stock, 0)
        context.latestSell[stock.symbol] = todayDate();
    
                    
def buyStock (context, data, stock, percent):
    maxMoneyToSpend = (context.portfolio.starting_cash * percent) / 100
    percent = float(percent) / 100; # order_target_percent works with decimals not %
    
    if (str(percent) == "0.0"):
        raise Exception('Invalid percent set to buy stock from ' + stock.symbol)
    
    if (hasEnoughMoney(context, data, maxMoneyToSpend) and (not get_open_orders(stock)) and 
    ((context.portfolio.positions[stock] is None) or (context.portfolio.positions[stock].amount < 1)) and
    (stock.symbol not in context.latestSell or context.latestSell[stock.symbol] != todayDate())):
        #order_target_percent(stock, percent)
        currentPrice = data.history(stock, "price", 1, "1m")[-1]
        shares = math.floor(maxMoneyToSpend / currentPrice)
        order(stock, shares)
        print "BUYing " + stock.symbol + " - " + str(shares) + "s x " + str(currentPrice) + "$ (MAX " + str(maxMoneyToSpend) + "$)"


def closeAnyOpenOrders(stock):  
    orders = get_open_orders(stock)  
    if orders:  
        for order in orders:  
             cancel_order(order) 

def hasEnoughMoney(context, data, requiredMoney):
    return (getAvailableMoney(context, data) > requiredMoney)
        
def getAvailableMoney(context, data):
    availableMoney = context.account.available_funds - openOrdersCost(data);
    
    # Dont reinvest all benefits
    # @ToDo: this is not working as expected,
    # as we assign a %, the reserved $$ will be dynamically changing
    if (context.settings['reserveBenefitsPercent'] > 0 and availableMoney > context.portfolio.starting_cash):
        availableMoney -= ((availableMoney - context.portfolio.starting_cash) * context.settings['reserveBenefitsPercent']) / 100;
    
    return availableMoney
    

"""
    Returns the $ pending in open orders 
    From https://www.quantopian.com/help -> Earnings Announcement Risk Framework
"""
def openOrdersCost(data):  
    amount_ordered = 0 
    openOrders = get_open_orders()
    for order in openOrders:
        for oo in openOrders[order]:
            amount_ordered += oo.amount * data.current(oo.sid, 'price')
                
    return amount_ordered
        
"""
    Gets the current date in backtest
"""
def todayDate():
    return get_datetime().strftime("%d/%m/%Y");
There was a runtime error.
1 response

Is it that bad?