Back to Community
EMA 50 vs 100

More or less, if the 50 day EMA drops below the 100 day EMA, sell. If it goes above, buy.
Uses a mix of 14 stocks that's a bit tech heavy so it uses QQQ as a benchmark.
For a better benchmark I'm going to re-run it with just buying the stock and holding the whole time.

Seems to miss out on sudden surges quite often.

Clone Algorithm
147
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
import talib

def initialize(context):
    set_symbol_lookup_date('2003-01-01')
    context.stocks = symbols('atvi','csco','cvx','ea','ebay','hpq','ibm','intc','msft','nvda','cog', 'bp', 'ste', 'xom')
    set_benchmark(symbol('qqq'))
    context.dayCount = 0
    context.date = None
    context.shorts = 0
    context.cancelCounter=0
    
def handle_data(context, data):  
    
    todays_date = get_datetime().date()
    
    if todays_date==context.date:
        return
    
    if todays_date!=context.date:
        context.dayCount+=1
        context.cancelCounter+=1
        context.date = todays_date
        
    if context.cancelCounter==5:
        end_of_day(context, data)
        context.cancelCounter=0
        
    if has_orders(context,data) and context.dayCount>1:
        print('has open orders - doing nothing!')
        return
    
    if context.dayCount == 1:
        buyAll(context,data)
    
    for stock in context.stocks:
        
        hist100 = history(bar_count=100, frequency='1d', field='price')
        series100 = hist100[stock]
        ema_result100 = talib.EMA(series100, timeperiod=100)
        ema_result50 = talib.EMA(series100, timeperiod=50)
        ema100 = ema_result100[-1]
        ema50 = ema_result50[-1]        
            
        getCash(context,data)
            
        if ema100 > ema50 and context.portfolio.positions[stock].amount > 0 and context.dayCount>2:
            log.info('{0}:  Selling {1} shares, EMA50:  {2}, EMA100:  {3}'.format(stock.symbol,context.portfolio.positions[stock].amount,ema50,ema100))
            order_target(stock, 0, style=LimitOrder(ema50))            
        
        if has_orders(context,data) and context.dayCount>7:
            print('has open orders - doing nothing!')
            return
            
        elif ema100 < ema50 and context.portfolio.positions[stock].amount == 0 and context.dayCount>2 and data[stock].price<context.freeCash:
            getCash(context,data)
            shares = round((context.freeCash*0.95)/data[stock].price,0)
            log.info('{0}:  Buying {1} shares, EMA50:  {2}, EMA100:  {3}'.format(stock.symbol,shares,ema50,ema100))
            order_target(stock, shares, style=LimitOrder(ema50))
            
        getCash(context,data)
            
        if context.portfolio.positions[stock].amount < 0:
            context.shorts+=1
    
    getCash(context,data)        
    record(Cash=context.freeCash)
    record(Shorts=context.shorts)
    context.shorts=0   
        
def has_orders(context,data):
    # Return true if there are pending orders.
    has_orders = False
    for sec in data:
        orders = get_open_orders(sec)
        if orders:
            for oo in orders:                  
                message = 'Open order for {amount} shares in {stock}'  
                message = message.format(amount=oo.amount, stock=sec)  
                log.info(message)

            has_orders = True
    return has_orders
    
def getCash(context,data):
    if context.portfolio.cash < (context.portfolio.portfolio_value-context.portfolio.positions_value):
        context.freeCash = context.portfolio.cash
    else:
        context.freeCash = (context.portfolio.portfolio_value-context.portfolio.positions_value)
    
def end_of_day(context, data):
    #cancle any order at the end of day. Do it ourselves so we can see slow moving stocks.
    open_orders = get_open_orders()
    
    if open_orders:
        
        log.info("")
        log.info("* EOD: Stoping Orders *")
        log.info("")
    
    if open_orders:  
        
        for security, orders in open_orders.iteritems():
            for oo in orders:
                log.info("X CANCLED {0:s} with {1:,d} / {2:,d} filled"\
                                     .format(security.symbol,
                                             oo.filled,
                                             oo.amount))
                cancel_order(oo)

def buyAll(context,data):
    for stock in context.stocks:
        order_value(stock, 1000)
        log.info('{0}:  Buying {1}shares'.format(stock.symbol,round(1000/data[stock].price,0)))
There was a runtime error.
6 responses

Here's the real benchmark. Performs initial purchase then sits on it.

Clone Algorithm
147
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
import talib

def initialize(context):
    set_symbol_lookup_date('2003-01-01')
    context.stocks = symbols('atvi','csco','cvx','ea','ebay','hpq','ibm','intc','msft','nvda','cog', 'bp', 'ste', 'xom')
    set_benchmark(symbol('qqq'))
    context.dayCount = 0
    context.date = None
    context.shorts = 0
    context.cancelCounter=0
    
def handle_data(context, data):  
    
    todays_date = get_datetime().date()
    
    if todays_date==context.date:
        return
    
    if todays_date!=context.date:
        context.dayCount+=1
        context.cancelCounter+=1
        context.date = todays_date
        
    if context.cancelCounter==5:
        end_of_day(context, data)
        context.cancelCounter=0
        
    if has_orders(context,data) and context.dayCount>1:
        print('has open orders - doing nothing!')
        return
    
    if context.dayCount == 1:
        buyAll(context,data)
    
#    for stock in context.stocks:
#        
#        hist100 = history(bar_count=100, frequency='1d', field='price')
#        series100 = hist100[stock]
#        ema_result100 = talib.EMA(series100, timeperiod=100)
#        ema_result50 = talib.EMA(series100, timeperiod=50)
#        ema100 = ema_result100[-1]
#        ema50 = ema_result50[-1]        
#            
#        getCash(context,data)
#            
#        if ema100 > ema50 and context.portfolio.positions[stock].amount > 0 and #context.dayCount>2:
#            log.info('{0}:  Selling {1} shares, EMA50:  {2}, EMA100:  {3}'.format(stock.symbol,context.portfolio.positions[stock].amount,ema50,ema100))
#            order_target(stock, 0, style=LimitOrder(ema50))            
#        
#        if has_orders(context,data) and context.dayCount>7:
#            print('has open orders - doing nothing!')
#            return
#            
#        elif ema100 < ema50 and context.portfolio.positions[stock].amount == 0 and context.dayCount>2 and data[stock].price<context.freeCash:
#            getCash(context,data)
#            shares = round((context.freeCash*0.95)/data[stock].price,0)
#            log.info('{0}:  Buying {1} shares, EMA50:  {2}, EMA100:  {3}'.format(stock.symbol,shares,ema50,ema100))
#            order_target(stock, shares, style=LimitOrder(ema50))
#            
#        getCash(context,data)
#            
#        if context.portfolio.positions[stock].amount < 0:
#            context.shorts+=1
#    
#    getCash(context,data)        
#    record(Cash=context.freeCash)
#    record(Shorts=context.shorts)
#    context.shorts=0   
        
def has_orders(context,data):
    # Return true if there are pending orders.
    has_orders = False
    for sec in data:
        orders = get_open_orders(sec)
        if orders:
            for oo in orders:                  
                message = 'Open order for {amount} shares in {stock}'  
                message = message.format(amount=oo.amount, stock=sec)  
                log.info(message)

            has_orders = True
    return has_orders
    
def getCash(context,data):
    if context.portfolio.cash < (context.portfolio.portfolio_value-context.portfolio.positions_value):
        context.freeCash = context.portfolio.cash
    else:
        context.freeCash = (context.portfolio.portfolio_value-context.portfolio.positions_value)
    
def end_of_day(context, data):
    #cancle any order at the end of day. Do it ourselves so we can see slow moving stocks.
    open_orders = get_open_orders()
    
    if open_orders:
        
        log.info("")
        log.info("* EOD: Stoping Orders *")
        log.info("")
    
    if open_orders:  
        
        for security, orders in open_orders.iteritems():
            for oo in orders:
                log.info("X CANCLED {0:s} with {1:,d} / {2:,d} filled"\
                                     .format(security.symbol,
                                             oo.filled,
                                             oo.amount))
                cancel_order(oo)

def buyAll(context,data):
    for stock in context.stocks:
        order_value(stock, 1000)
        log.info('{0}:  Buying {1}shares'.format(stock.symbol,round(1000/data[stock].price,0)))
There was a runtime error.

Nice! Comparing those 2 is not accurate though, as I don't see that you've accounted for broking fees. At a guess, the first script will have more buy/sells than the second, which is buy and hold only. I think there are other examples of how to add in fees and costs to the mix. Well done! Looking forward to seeing your next one :-)

I believe since I didn't set a custom commission it uses $0.03/share as a default rate.So the first one definitely got hit with more since its the only one with any activity. I'll try it again with commission set to $4.75/trade.

How did your algo perform after setting the the commission to the higher commission of $4.75/trade?

Not much change.

Clone Algorithm
147
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
import talib

def initialize(context):
    set_symbol_lookup_date('2003-01-01')
    context.stocks = symbols('atvi','csco','cvx','ea','ebay','hpq','ibm','intc','msft','nvda','cog', 'bp', 'ste', 'xom')
    set_benchmark(symbol('qqq'))
    set_commission(commission.PerTrade(cost=4.75))
    context.dayCount = 0
    context.date = None
    context.shorts = 0
    context.cancelCounter=0
    
def handle_data(context, data):  
    
    todays_date = get_datetime().date()
    
    if todays_date==context.date:
        return
    
    if todays_date!=context.date:
        context.dayCount+=1
        context.cancelCounter+=1
        context.date = todays_date
        
    if context.cancelCounter==5:
        end_of_day(context, data)
        context.cancelCounter=0
        
    if has_orders(context,data) and context.dayCount>1:
        print('has open orders - doing nothing!')
        return
    
    if context.dayCount == 1:
        buyAll(context,data)
    
    for stock in context.stocks:
        
        hist100 = history(bar_count=100, frequency='1d', field='price')
        series100 = hist100[stock]
        ema_result100 = talib.EMA(series100, timeperiod=100)
        ema_result50 = talib.EMA(series100, timeperiod=50)
        ema100 = ema_result100[-1]
        ema50 = ema_result50[-1]        
            
        getCash(context,data)
            
        if ema100 > ema50 and context.portfolio.positions[stock].amount > 0 and context.dayCount>2:
            log.info('{0}:  Selling {1} shares, EMA50:  {2}, EMA100:  {3}'.format(stock.symbol,context.portfolio.positions[stock].amount,ema50,ema100))
            order_target(stock, 0, style=LimitOrder(ema50))            
        
        if has_orders(context,data) and context.dayCount>7:
            print('has open orders - doing nothing!')
            return
            
        elif ema100 < ema50 and context.portfolio.positions[stock].amount == 0 and context.dayCount>2 and data[stock].price<context.freeCash:
            getCash(context,data)
            shares = round((context.freeCash*0.95)/data[stock].price,0)
            log.info('{0}:  Buying {1} shares, EMA50:  {2}, EMA100:  {3}'.format(stock.symbol,shares,ema50,ema100))
            order_target(stock, shares, style=LimitOrder(ema50))
            
        getCash(context,data)
            
        if context.portfolio.positions[stock].amount < 0:
            context.shorts+=1
    
    getCash(context,data)        
    record(Cash=context.freeCash)
    record(Shorts=context.shorts)
    context.shorts=0   
        
def has_orders(context,data):
    # Return true if there are pending orders.
    has_orders = False
    for sec in data:
        orders = get_open_orders(sec)
        if orders:
            for oo in orders:                  
                message = 'Open order for {amount} shares in {stock}'  
                message = message.format(amount=oo.amount, stock=sec)  
                log.info(message)

            has_orders = True
    return has_orders
    
def getCash(context,data):
    if context.portfolio.cash < (context.portfolio.portfolio_value-context.portfolio.positions_value):
        context.freeCash = context.portfolio.cash-5
    else:
        context.freeCash = (context.portfolio.portfolio_value-context.portfolio.positions_value)-5
    
def end_of_day(context, data):
    #cancle any order at the end of day. Do it ourselves so we can see slow moving stocks.
    open_orders = get_open_orders()
    
    if open_orders:
        
        log.info("")
        log.info("* EOD: Stoping Orders *")
        log.info("")
    
    if open_orders:  
        
        for security, orders in open_orders.iteritems():
            for oo in orders:
                log.info("X CANCLED {0:s} with {1:,d} / {2:,d} filled"\
                                     .format(security.symbol,
                                             oo.filled,
                                             oo.amount))
                cancel_order(oo)

def buyAll(context,data):
    for stock in context.stocks:
        order_value(stock, 1000)
        log.info('{0}:  Buying {1}shares'.format(stock.symbol,round(1000/data[stock].price,0)))
There was a runtime error.

it doesnt work......