Cryptrality / backtester

3 stars 2 forks source link

Convert some Trality examples to Cryptrality #6

Open c0indev3l opened 1 year ago

c0indev3l commented 1 year ago

Here is for example macd_cross.py

import talib

SYMBOL = "BTCUSDT"

def initialize(state):
    state.number_offset_trades = 0

@schedule(interval="1h", symbols=SYMBOL)
def handler(state, dataMap):
    data = dataMap[SYMBOL]

    """
    1) Compute indicators from data
    """
    _macd, _macdsignal, _macdhist = talib.MACD(
        data["close"], fastperiod=12, slowperiod=26, signalperiod=9
    )

    signal = _macdsignal[-1]
    macd = _macd[-1]

    current_price = data["close"][-1]

    """
    2) Fetch portfolio
        > check liquidity (in quoted currency)
        > resolve buy value
    """
    # ToFix #portfolio = query_portfolio()
    # ToFix #balance_quoted = portfolio.excess_liquidity_quoted
    # we invest only 80% of available liquidity
    # buy_value = float(balance_quoted) * 0.80

    buy_value = 1000.0 * 0.80

    """
    3) Fetch position for symbol
        > has open position
        > check exposure (in base currency)
    """

    position = get_open_position(SYMBOL, side="LONG")
    has_position = position is not None

    """
    4) Resolve buy or sell signals
        > create orders using the order api
        > print position information
    """
    if macd > signal and not has_position:
        logger.info("-------")
        logger.info(f"Buy Signal: creating market order for {SYMBOL}")
        logger.info(f"Buy value: {buy_value} at current market price: {current_price}")
        order_market_value(symbol=SYMBOL, value=buy_value)  # creating market order

    elif macd < signal and has_position:
        logger.info("-------")
        logger.info(
            f"Sell Signal: closing {SYMBOL} position with exposure {0} at current market price {current_price}"
        )
        # ToFix: position.exposure
        close_position(SYMBOL)  # closing position

    """
    5) Check strategy profitability
        > print information profitability on every offsetting trade
    """
    """ToDo

    if state.number_offset_trades < portfolio.number_of_offsetting_trades:
        pnl = query_portfolio_pnl()
        print("-------")
        print("Accumulated Pnl of Strategy: {}".format(pnl))

        offset_trades = portfolio.number_of_offsetting_trades
        number_winners = portfolio.number_of_winning_trades
        print("Number of winning trades {}/{}.".format(number_winners, offset_trades))
        print("Best trade Return : {:.2%}".format(portfolio.best_trade_return))
        print("Worst trade Return : {:.2%}".format(portfolio.worst_trade_return))
        print(
            "Average Profit per Winning Trade : {:.2f}".format(
                portfolio.average_profit_per_winning_trade
            )
        )
        print(
            "Average Loss per Losing Trade : {:.2f}".format(
                portfolio.average_loss_per_losing_trade
            )
        )
        # reset number offset trades
        state.number_offset_trades = portfolio.number_of_offsetting_trades
    """

More examples can be found at https://gist.github.com/c0indev3l/855381f07865dfca079e8252e736ae35

c0indev3l commented 1 year ago
current_price = data["close"][-1]

is not very simple...

current_price = data.close[-1]

would be better

Maybe a dataclass could be used https://docs.python.org/3/library/dataclasses.html