Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
How to calculate Volume Moving Average

Hello everyone,

I've been reading and playing around with Quantopian tools for a few weeks and now I'm trying to implement an algorith to learn the ropes.

Basically I am taking a simple MACD strategy and now I want to add a volume signal. I can use the day's volume with data[stock].volume but I would now like to try using a MA.

I know that mavg gives the price's moving average so I figured I would use talib's MA function. My problem is that I haven't been able to find the documentation that explains what parameters I need to pass. For example, to select SMA I can pass matype=0 apparently, then I pass timeperiod=5 to get the MA of the last 5 days, but it's not working for some reason.

After this I would like to try KAMA but again, I have no idea what the funciton signature is.

Any help is greatly appreciated.

import talib  
import numpy as np  
import pandas as pd  
# Put any initialization logic here.  The context object will be passed to  
# the other methods in your algorithm.  
def initialize(context):  
    set_symbol_lookup_date('2006-05-01')  
    context.stocks = symbols('JNJ', 'KO', 'MMM', 'DVY', 'VIG')  
    context.pct_per_stock = 1.0 / len(context.stocks)  
    # Create a variable to track the date change  
    context.date = None  


# Will be called on every trade event for the securities you specify.  
def handle_data(context, data):  
    todays_date = get_datetime().date()  
    # Do nothing unless the date has changed and its a new day.  
    if todays_date == context.date:  
        return  
    # Set the new date  
    context.date = todays_date  
    # Load historical data for the stocks  
    prices = history(40, '1d', 'price')  
    volumes = history(40, '1d', 'volume')  
    # Create the MACD signal and pass in the three parameters: fast period, slow period, and the signal.  
    # This is a series that is indexed by sids.  
    macd = prices.apply(MACD, fastperiod=12, slowperiod=26, signalperiod=9)  
    #NOT WORKING  
    volume_ma = volumes.apply(talib.MA, matype=0, timeperiod=5)  
    # Iterate over the list of stocks  
    for stock in context.stocks:  
        current_position = context.portfolio.positions[stock].amount  
        #log.info("VOLUME IS " + str(data[stock].volume)))  
        # Close position for the stock when the MACD signal is negative and we own shares.  
        if macd[stock] < 0 and current_position > 0 :  
            order_target(stock, 0)  
        # Enter the position for the stock when the MACD signal is positive and  
        # our portfolio shares are 0.  
        elif macd[stock] > 0 and current_position == 0:  
            order_target_percent(stock, context.pct_per_stock)  

    record(jnj=macd[symbol('JNJ')],  
           ko=macd[symbol('KO')],  
           dvy=macd[symbol('DVY')],  
           vig=macd[symbol('VIG')],  
           mmm=macd[symbol('MMM')])  

# Define the MACD function  
def MACD(prices, fastperiod=12, slowperiod=26, signalperiod=9):  
    '''  
    Function to return the difference between the most recent  
    MACD value and MACD signal. Positive values are long  
    position entry signals 

    optional args:  
        fastperiod = 12  
        slowperiod = 26  
        signalperiod = 9

    Returns: macd - signal  
    '''  
    macd, signal, hist = talib.MACD(prices,  
                                    fastperiod=fastperiod,  
                                    slowperiod=slowperiod,  
                                    signalperiod=signalperiod)  
    return macd[-1] - signal[-1]  
6 responses

Hello Akram,

You might just use the Pandas rolling stats methods found here:

http://pandas.pydata.org/pandas-docs/dev/computation.html

The method 'rolling_mean' should do the trick to compute the rolling mean of the volumes.

Grant

Thanks!

That would be for the equivalent of an SMA right? is there no way to apply ta-lib's KAMA for example, to volume? or do they only work for price?

Will check this out and see what happens. Thanks again.

import talib  
import numpy as np

def initialize(context):  
    context.stocks = symbols('TSLA')

def handle_data(context, data):  
    closes = history(50, '1d', 'close_price').ffill().bfill()  
    for sec in data:  
        C = closes[sec].values.tolist()

        print talib.KAMA(np.array(C), timeperiod=12)[-1]  

Thanks for that snippet.

Could you explain it a bit more please?

I see that you do ffill() and bfill() over closes (which for my example would be volumes). What does ffill and bfill do?

And finally, you iterate over all securities in data, you convert the array into a list, and then convert back to an array? and you take the first element ( [-1] ) of the list to print it.

Is this correct?

Thanks again!

Uhmm, it seems that the snippet is not working or I'm doing something wrong, but I Can't see why.

talib.KAMA is giving me all NaN's :/

I tried doing the [-1] at the end of talib.KAMA to get the current element I think, but it gave me the same issue (1 NaN instead of 12 though).

EDIT:

Ok, it seems to be working!

EDIT2:

It seems to work if I use talib.MA but not KAMA. Any ideas?

Thanks!

import talib  
import numpy as np  
import pandas as pd  
# Put any initialization logic here.  The context object will be passed to  
# the other methods in your algorithm.  
def initialize(context):  
    set_symbol_lookup_date('2006-05-01')  
    context.stocks = symbols('JNJ', 'KO', 'MMM')  
    context.pct_per_stock = 1.0 / len(context.stocks)  
    # Create a variable to track the date change  
    context.date = None  


# Will be called on every trade event for the securities you specify.  
def handle_data(context, data):  
    todays_date = get_datetime().date()  
    # Do nothing unless the date has changed and its a new day.  
    if todays_date == context.date:  
        return  
    # Set the new date  
    context.date = todays_date  
    # Load historical data for the stocks  
    prices = history(40, '1d', 'price')  
    volumes = history(12, '1d', 'volume').ffill().bfill()  
    #log.info("VOLUMES " + str(volumes))  
    # Create the MACD signal and pass in the three parameters: fast period, slow period, and the signal.  
    # This is a series that is indexed by sids.  
    macd = prices.apply(MACD, fastperiod=12, slowperiod=26, signalperiod=9)  
    #NOT WORKING  
    #volume_ma = volumes.apply(talib.MA, matype=0, timeperiod=5)  
    # Iterate over the list of stocks  
    for stock in context.stocks:  
        current_position = context.portfolio.positions[stock].amount  
        stock_volumes = volumes[stock].values.tolist()  
        vol_KAMA = talib.KAMA(np.array(stock_volumes), timeperiod=12)  
        log.info("VOL KAMA" + str(vol_KAMA))  
        #log.info("VOLUME IS " + str(data[stock].volume)))  
        # Close position for the stock when the MACD signal is negative and we own shares.  
        if macd[stock] < 0 and current_position > 0 :  
            order_target(stock, 0)  
        # Enter the position for the stock when the MACD signal is positive and  
        # our portfolio shares are 0.  
        elif macd[stock] > 0 and current_position == 0:  
            order_target_percent(stock, context.pct_per_stock)  

    record(jnj=macd[symbol('JNJ')],  
           ko=macd[symbol('KO')],  
           mmm=macd[symbol('MMM')])  
# Define the MACD function  
def MACD(prices, fastperiod=12, slowperiod=26, signalperiod=9):  
    '''  
    Function to return the difference between the most recent  
    MACD value and MACD signal. Positive values are long  
    position entry signals 

    optional args:  
        fastperiod = 12  
        slowperiod = 26  
        signalperiod = 9

    Returns: macd - signal  
    '''  
    macd, signal, hist = talib.MACD(prices,  
                                    fastperiod=fastperiod,  
                                    slowperiod=slowperiod,  
                                    signalperiod=signalperiod)  
    return macd[-1] - signal[-1]  

You were the first to mention KAMA() on this site.
Your time periods for KAMA and history are both 12, try larger for history and/or shorter for KAMA().
ffill() would forward fill an NaN value (not a number) with a previous value. bfill() does backward fill of NaN with current value like in the case of an IPO being born.
Now, someone can correct me if I'm wrong, history() returns a "time series" as it is called, a structure with a bit of complexity to it and like in your example above, for all securities all at the same time, then volumes[stock].values.tolist() turns into a plain list, then talib wants a numpy arrray, so np.array(stock_volumes). There might be a simpler way.
-1 (minus one) is the last element in the list, -2 second-to-last etc.
If you want the first element, that index starts at 0.
To do something with the last three values for example, this returns a list: [-3:]
Try clicking in the margin to set a breakpoint after your volumes history line, and when it breaks in, type volumes[-2:] and str(volumes[-2:]), maybe that'll be a minor useful tool example going forward.
I imagine talib's authors set out to achieve two goals: (1) World's coolest financial library (2) World's worst-ever documentation.