Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Did i build a stop loss and trailing stop loss correctly? #377

Open
brettelliot opened this issue Jul 26, 2022 · 2 comments
Open

Did i build a stop loss and trailing stop loss correctly? #377

brettelliot opened this issue Jul 26, 2022 · 2 comments
Labels

Comments

@brettelliot
Copy link

brettelliot commented Jul 26, 2022

Hi all,

I didn't see stop loss or trailing stop loss functionality anywhere so I tried implementing it myself. The stop loss was easy but the trailing stop loss took a little work. I figured I'd post here so that other people might benefit.. or maybe other people can tell me where I messed up!

Would love feedback on these.

Thanks,
Brett

import pandas as pd 
import numpy as np
%matplotlib inline

pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)
pd.set_option('display.width', None)
pd.set_option('display.max_colwidth', None)

# Set trading fees
def trading_fees(q, p):
    return abs(q)*p*0.003

# Simple moving average backtest
def sma_strat(tickers, sma_per=50, start='2018-01-01', name='sma', initial_capital=1000.0, stop_pct=None, trailing=None):
    """
    Long securities that are above their n period.
    
    """
    # download data
    data = bt.get(tickers, start=start)
    
    # calc sma
    sma = data.rolling(sma_per).mean()
    
    signals = sma.copy()
    signals[data > sma] = True
    signals[data <= sma] = False
    signals[sma.isnull()] = False
    
    if stop_pct is not None:
        if trailing:
            # Use a trailing stop loss
            for ticker in data:
                df = pd.DataFrame()
                df['price'] = data[ticker]
                df['signal_change'] = signals[ticker].ne(signals[ticker].shift())
                df['trade_id'] = df['signal_change'].cumsum()
                df['trailing_stop_loss'] = df.groupby('trade_id')['price'].cummax() * (1 - stop_pct)
                signals.loc[df['price'] <= df['trailing_stop_loss'], ticker] = False
        else:
            # Use a stop loss
            stop_loss = (data*(1-stop_pct)).where((signals.shift(1) == False) & (signals == True), np.nan)
            stop_loss = stop_loss.ffill()
            signals[data <= stop_loss] = False

    tw = signals.copy()
    tw[signals == True] = 1.0 / len(tickers)
    tw[signals == False] = 0.0  

    # create strategy
    s = bt.Strategy(name, [bt.algos.WeighTarget(tw),
                                    bt.algos.Rebalance()])

    # now we create the backtest
    return bt.Backtest(s, data, integer_positions=False, initial_capital=initial_capital, commissions=trading_fees)

# Params
start = '2018-01-01'
initial_capital=1000.0
tickers = ['BTC-USD', 'ETH-USD']

sma = sma_strat(tickers, sma_per=50, start=start, name='sma', initial_capital=initial_capital)
sma_stop = sma_strat(tickers, sma_per=50, start=start, name='sma_stop', initial_capital=initial_capital, stop_pct=0.05)
sma_trailing_stop = sma_strat(tickers, sma_per=50, start=start, name='sma_trailing_stop', initial_capital=initial_capital, stop_pct=0.05, trailing=True)

# run all the backtests!
results = bt.run(sma, sma_stop, sma_trailing_stop)
results.plot(freq='m', logy=True);
results.display()



@brettelliot
Copy link
Author

Ive spent more time on this and the trailing stop loss is definitely busted. I've managed to build one using a loop but the one above has issues.

@posidonius
Copy link

Ive spent more time on this and the trailing stop loss is definitely busted. I've managed to build one using a loop but the one above has issues.

You should avoid using a for loop and try to find a vector-based solution since you're working in Pandas. Looping through each ticker in the universe is going to be extremely inefficient.

Let me know if you ever made any progress on this btw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants