예제 #1
0
def gap(f):
    r"""Calculate the gap percentage between the current open and
    the previous close.

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe with columns ``open`` and ``close``.

    Returns
    -------
    new_column : pandas.Series (float)
        The array containing the new feature.

    References
    ----------
    *A gap is a break between prices on a chart that occurs when the
    price of a stock makes a sharp move up or down with no trading
    occurring in between* [IP_GAP]_.

    .. [IP_GAP] http://www.investopedia.com/terms/g/gap.asp

    """
    c1 = 'open'
    c2 = 'close[1]'
    vexec(f, c2)
    new_column = 100 * pchange2(f, c1, c2)
    return new_column
예제 #2
0
def diminus(f, p=14):
    r"""Calculate the Minus Directional Indicator (-DI).

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe with columns ``high`` and ``low``.
    p : int
        The period over which to calculate the -DI.

    Returns
    -------
    new_column : pandas.Series (float)
        The array containing the new feature.

    References
    ----------
    *A component of the average directional index (ADX) that is used to
    measure the presence of a downtrend. When the -DI is sloping downward,
    it is a signal that the downtrend is getting stronger* [IP_NDI]_.

    .. [IP_NDI] http://www.investopedia.com/terms/n/negativedirectionalindicator.asp

    """
    tr = 'truerange'
    vexec(f, tr)
    atr = USEP.join(['atr', str(p)])
    vexec(f, atr)
    dmm = 'dmminus'
    f[dmm] = dminus(f)
    new_column = 100 * dminus(f).ewm(span=p).mean() / f[atr]
    return new_column
예제 #3
0
def truehigh(f):
    r"""Calculate the *True High* value.

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe with columns ``high`` and ``low``.

    Returns
    -------
    new_column : pandas.Series (float)
        The array containing the new feature.

    References
    ----------
    *Today's high, or the previous close, whichever is higher* [TS_TR]_.

    .. [TS_TR] http://help.tradestation.com/09_01/tradestationhelp/charting_definitions/true_range.htm

    """
    c1 = 'low[1]'
    vexec(f, c1)
    c2 = 'high'
    new_column = f.apply(c2max, axis=1, args=[c1, c2])
    return new_column
예제 #4
0
def rsi(f, c, p=14):
    r"""Calculate the Relative Strength Index (RSI).

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe containing the column ``net``.
    c : str
        Name of the column in the dataframe ``f``.
    p : int
        The period over which to calculate the RSI.

    Returns
    -------
    new_column : pandas.Series (float)
        The array containing the new feature.

    References
    ----------
    *Developed by J. Welles Wilder, the Relative Strength Index (RSI) is a momentum
    oscillator that measures the speed and change of price movements* [SC_RSI]_.

    .. [SC_RSI] http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:relative_strength_index_rsi

    """
    cdiff = 'net'
    vexec(f, cdiff)
    f['pval'] = upc(f, cdiff)
    f['mval'] = dpc(f, cdiff)
    upcs = ma(f, 'pval', p)
    dpcs = ma(f, 'mval', p)
    new_column = 100 - (100 / (1 + (upcs / dpcs)))
    return new_column
예제 #5
0
def truelow(f):
    r"""Calculate the *True Low* value.

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe with columns ``high`` and ``low``.

    Returns
    -------
    new_column : pandas.Series (float)
        The array containing the new feature.

    References
    ----------
    *Today's low, or the previous close, whichever is lower* [TS_TR]_.

    """
    c1 = 'high[1]'
    vexec(f, c1)
    c2 = 'low'
    new_column = f.apply(c2min, axis=1, args=[c1, c2])
    return new_column
예제 #6
0
def adx(f, p=14):
    r"""Calculate the Average Directional Index (ADX).

    Parameters
    ----------
    f : pandas.DataFrame
        Dataframe with all columns required for calculation. If you
        are applying ADX through ``vapply``, then these columns are
        calculated automatically.
    p : int
        The period over which to calculate the ADX.

    Returns
    -------
    new_column : pandas.Series (float)
        The array containing the new feature.

    References
    ----------
    The Average Directional Movement Index (ADX) was invented by J. Welles
    Wilder in 1978 [WIKI_ADX]_.  Its value reflects the strength of trend in any
    given instrument.

    .. [WIKI_ADX] https://en.wikipedia.org/wiki/Average_directional_movement_index

    """
    c1 = 'diplus'
    vexec(f, c1)
    c2 = 'diminus'
    vexec(f, c2)
    # calculations
    dip = f[c1]
    dim = f[c2]
    didiff = abs(dip - dim)
    disum = dip + dim
    new_column = 100 * didiff.ewm(span=p).mean() / disum
    return new_column
예제 #7
0
def trade_system(model, system, space, intraday, name, quantity):
    r"""Trade the given system.

    Parameters
    ----------
    model : alphapy.Model
        The model object with specifications.
    system : alphapy.System
        The long/short system to run.
    space : alphapy.Space
        Namespace of instrument prices.
    intraday : bool
        If True, then run an intraday system.
    name : str
        The symbol to trade.
    quantity : float
        The amount of the ``name`` to trade, e.g., number of shares

    Returns
    -------
    tradelist : list
        List of trade entries and exits.

    Other Parameters
    ----------------
    Frame.frames : dict
        All of the data frames containing price data.

    """

    # Unpack the model data.

    directory = model.specs['directory']
    extension = model.specs['extension']
    separator = model.specs['separator']

    # Unpack the system parameters.

    longentry = system.longentry
    shortentry = system.shortentry
    longexit = system.longexit
    shortexit = system.shortexit
    holdperiod = system.holdperiod
    scale = system.scale

    # Determine whether or not this is a model-driven system.

    entries_and_exits = [longentry, shortentry, longexit, shortexit]
    active_signals = [x for x in entries_and_exits if x is not None]
    use_model = False
    for signal in active_signals:
        if any(x in signal for x in ['phigh', 'plow']):
            use_model = True

    # Read in the price frame
    pf = Frame.frames[frame_name(name, space)].df

    # Use model output probabilities as input to the system

    if use_model:
        # get latest probabilities file
        probs_dir = SSEP.join([directory, 'output'])
        file_path = most_recent_file(probs_dir, 'probabilities*')
        file_name = file_path.split(SSEP)[-1].split('.')[0]
        # read the probabilities frame and trim the price frame
        probs_frame = read_frame(probs_dir, file_name, extension, separator)
        pf = pf[-probs_frame.shape[0]:]
        probs_frame.index = pf.index
        probs_frame.columns = ['probability']
        # add probability column to price frame
        pf = pd.concat([pf, probs_frame], axis=1)

    # Evaluate the long and short events in the price frame

    for signal in active_signals:
        vexec(pf, signal)

    # Initialize trading state variables

    inlong = False
    inshort = False
    h = 0
    p = 0
    q = quantity
    tradelist = []

    # Loop through prices and generate trades

    for dt, row in pf.iterrows():
        # get closing price
        c = row['close']
        if intraday:
            bar_number = row['bar_number']
            end_of_day = row['end_of_day']
        # evaluate entry and exit conditions
        lerow = row[longentry] if longentry else None
        serow = row[shortentry] if shortentry else None
        lxrow = row[longexit] if longexit else None
        sxrow = row[shortexit] if shortexit else None
        # process the long and short events
        if lerow:
            if p < 0:
                # short active, so exit short
                tradelist.append((dt, [name, Orders.sx, -p, c]))
                inshort = False
                h = 0
                p = 0
            if p == 0 or scale:
                # go long (again)
                tradelist.append((dt, [name, Orders.le, q, c]))
                inlong = True
                p = p + q
        elif serow:
            if p > 0:
                # long active, so exit long
                tradelist.append((dt, [name, Orders.lx, -p, c]))
                inlong = False
                h = 0
                p = 0
            if p == 0 or scale:
                # go short (again)
                tradelist.append((dt, [name, Orders.se, -q, c]))
                inshort = True
                p = p - q
        # check exit conditions
        if inlong and h > 0 and lxrow:
            # long active, so exit long
            tradelist.append((dt, [name, Orders.lx, -p, c]))
            inlong = False
            h = 0
            p = 0
        if inshort and h > 0 and sxrow:
            # short active, so exit short
            tradelist.append((dt, [name, Orders.sx, -p, c]))
            inshort = False
            h = 0
            p = 0
        # if a holding period was given, then check for exit
        if holdperiod and h >= holdperiod:
            if inlong:
                tradelist.append((dt, [name, Orders.lh, -p, c]))
                inlong = False
            if inshort:
                tradelist.append((dt, [name, Orders.sh, -p, c]))
                inshort = False
            h = 0
            p = 0
        # increment the hold counter
        if inlong or inshort:
            h += 1
            if intraday and end_of_day:
                if inlong:
                    # long active, so exit long
                    tradelist.append((dt, [name, Orders.lx, -p, c]))
                    inlong = False
                if inshort:
                    # short active, so exit short
                    tradelist.append((dt, [name, Orders.sx, -p, c]))
                    inshort = False
                h = 0
                p = 0
    return tradelist