<jupyter_start><jupyter_text>"backtesting crypto with exit signal"> "How to fetch and backtest crypto data using fastquant"- toc: true- branch: master- badges: true- comments: true- author: <NAME>- categories: [crypto, backtest]<jupyter_code># uncomment to install in colab
# !pip3 install fastquant --update
# or pip install git+https://www.github.com/enzoampil/fastquant.git@history<jupyter_output><empty_output><jupyter_text>fetch data from binance  If a timestamp is given, it will return upto that timestamp<jupyter_code>from fastquant import get_crypto_data
crypto = get_crypto_data("ADA/USDT", 
                         "2022-01-01 00:00:00", 
                         "2022-03-03 00:00:00",
                         time_resolution='1h'
                        )
crypto.tail()<jupyter_output><empty_output><jupyter_text>EMA Crossover Example<jupyter_code>from fastquant import backtest
# Import modules
import backtrader as bt

# Import from package
from fastquant.strategies.base import BaseStrategy


class EMACStrategy(BaseStrategy):
    """
    Exponential moving average crossover strategy

    Parameters
    ----------
    fast_period : int
        The period used for the fast exponential moving average line (should be smaller than `slow_upper`)
    slow_period : int
        The period used for the slow exponential moving average line (should be larger than `fast_upper`)

    """

    params = (
        ("fast_period", 10),  # period for the fast moving average
        ("slow_period", 30),
    )

    def __init__(self):
        # Initialize global variables
        super().__init__()
        # Strategy level variables
        self.fast_period = self.params.fast_period
        self.slow_period = self.params.slow_period
        self.short_max = 1

        if self.strategy_logging:
            print("===Strategy level arguments===")
            print("fast_period :", self.fast_period)
            print("slow_period :", self.slow_period)
            print("allow_short :", self.allow_short)
        ema_fast = bt.ind.EMA(period=self.fast_period)  # fast moving average
        ema_slow = bt.ind.EMA(period=self.slow_period)  # slow moving average
        self.crossover = bt.ind.CrossOver(
            ema_fast, ema_slow
        )  # crossover signal

    def buy_signal(self):
        return self.crossover > 0

    def sell_signal(self):
        return self.crossover < 0<jupyter_output><empty_output><jupyter_text>Long only<jupyter_code>results, history = backtest(EMACStrategy, 
                               crypto, 
                            fast_period = 20,
                            slow_period = 50,
                               plot=False,
                               verbose=False,
                               return_history=True,
                            # allow_short=True,
                              )
orders = history['orders']
orders<jupyter_output><empty_output><jupyter_text>The final value in `results` can be calculated from the `commission` and `pnl` (profit & loss) of all the closed (bought and sold) transactions in history:<jupyter_code>r = results.squeeze()
r.final_value
profit = (r.final_value - 100000)/100000*100
print("Strategy")
print(f"Profit of asset: {profit}")
print("Buy and hold")
print(f"Start price of asset: {crypto.iloc[0, 3]}")
print(f"End price of asset: {crypto.iloc[-1, 3]}")
print(f"Profit of asset: {(crypto.iloc[-1, 3] - crypto.iloc[0, 3])/crypto.iloc[0, 3]*100}")<jupyter_output>Buy and hold
Start price of asset: 1.334
End price of asset: 0.94
Profit of asset: -29.5352323838081<jupyter_text>Long and Short<jupyter_code>results, history = backtest(EMACStrategy, 
                               crypto, 
                            fast_period = 20,
                            slow_period = 50,
                               plot=False,
                               verbose=False,
                               return_history=True,
                             allow_short=True,
                              )
orders = history['orders']
orders
periodic = history['periodic']
periodic.loc[periodic['dt']>='2022-01-30 19:00:00'].head(20)
periodic.loc[periodic['dt']>='2022-02-01 03:00:00'].head(20)<jupyter_output><empty_output><jupyter_text>The final value in `results` can be calculated from the `commission` and `pnl` (profit & loss) of all the closed (bought and sold) transactions in history:<jupyter_code>r = results.squeeze()
r.final_value
profit2 = (r.final_value - 100000)/100000*100
print("Strategy")
print(f"Profit of asset: {profit2}")
print("Buy and hold")
print(f"Start price of asset: {crypto.iloc[0, 3]}")
print(f"End price of asset: {crypto.iloc[-1, 3]}")
print(f"Profit of asset: {(crypto.iloc[-1, 3] - crypto.iloc[0, 3])/crypto.iloc[0, 3]*100}")<jupyter_output>Buy and hold
Start price of asset: 1.334
End price of asset: 0.94
Profit of asset: -29.5352323838081<jupyter_text>Final Results:<jupyter_code>print(f"Buy and hold profit %: {round((crypto.iloc[-1, 3] - crypto.iloc[0, 3])/crypto.iloc[0, 3]*100, 2)}%")
print(f"Long only profit %: {round(profit, 2)}%")
print(f"Long and Short profit %: {round(profit2, 2)}%")<jupyter_output>Buy and hold profit %: -29.54%
Long only profit %: 1.89%
Long and Short profit %: 33.24%
StarcoderdataJupyterStructuredCleanDedup