🏗️Examples

Adding more examples periodically

Below is a simple MACD Crossover strategy script:

# ===========================================
# BEGIN USER DEFINED SECTION
# This section is intended for user customization.
# ===========================================
  • Purpose: This section is specifically designed for users to define and customize their trading strategy. It is separated from the critical initialization and result-handling sections to allow for easy modification of the strategy logic without affecting the overall structure.


try:
  • Purpose: This line starts a try block, which is used to catch and handle exceptions that may occur during the execution of the strategy. If an error occurs, it will be caught by the corresponding except block, allowing for graceful error handling and logging.


    # Specify the interval you want to use
    interval = "1h"  # You can change this to "1m", "1d", etc.
  • Purpose: The interval variable defines the time frame for the data that will be used in the strategy. In this case, it is set to "1h", meaning the strategy will use hourly data. This can be adjusted to other intervals like "1m" (minute), "1d" (daily), etc., depending on the user's needs.


    # Executing the MACD command
    macd_command = context['modules']['application.DSL.commands.technical_indicators'].MACDCommand(
        start=context['data_provider'].start_date,
        end=context['data_provider'].end_date
    )
    macd_data = macd_command.execute(context['data_provider'])
  • Purpose: This block executes the MACD command to calculate the MACD, signal, and histogram values over the specified date range:

    • macd_command Initialization: A MACDCommand object is created using the start and end dates retrieved from the context.

    • execute() Method: The execute method of the MACDCommand is called, which calculates and returns the MACD data (a DataFrame containing the MACD line, signal line, and histogram).

    • macd_data: The resulting MACD data is stored in macd_data, which will be used later to determine trading signals.


    # Fetching OHLC data for the strategy with the specified interval
    ohlc_data = context['data_provider'].get_data(context['data_provider'].start_date, context['data_provider'].end_date, interval)
    if ohlc_data is None or 'Close' not in ohlc_data.columns:
        context['modules']['logging'].error("Original data does not contain 'Close' prices. Exiting strategy.")
        raise ValueError("Original data does not contain 'Close' prices.")
  • Purpose: This block retrieves the OHLC (Open, High, Low, Close) data for the specified time interval and date range:

    • ohlc_data Retrieval: The get_data method of the data_provider is called, retrieving OHLC data for the given date range and interval.

    • Data Validation: A check is performed to ensure that ohlc_data is not None and that the 'Close' column exists. If the data is missing or incomplete, an error is logged, and a ValueError is raised to halt the strategy execution.


    # Initializing the TradeSimulation class
    simulation = context['modules']['application.DSL.trading_simulation.trading_simulation'].TradeSimulation()
    position_open = False
  • Purpose: This block initializes the TradeSimulation class and sets a flag to track open positions:

    • simulation Initialization: A TradeSimulation object is created, which will be used to simulate buying and selling actions within the strategy.

    • position_open Flag: This boolean flag is set to False, indicating that no position is currently open at the start of the strategy execution.


    # Looping through MACD data to simulate trades
    for i in range(1, len(macd_data)):
        macd_value = macd_data.iloc[i]['macd']
        signal_value = macd_data.iloc[i]['signal']
        previous_macd_value = macd_data.iloc[i-1]['macd']
        previous_signal_value = macd_data.iloc[i-1]['signal']

        close_price = ohlc_data.iloc[i]['Close']
        trade_date = ohlc_data.index[i]  # Extract the correct date from the OHLC data
  • Purpose: This block iterates over the MACD data to simulate trades based on the MACD crossover strategy:

    • Looping Over MACD Data: The loop starts from index 1 and iterates through the MACD data.

    • Extracting Values: For each iteration:

      • macd_value and signal_value are the current MACD and signal line values.

      • previous_macd_value and previous_signal_value are the MACD and signal line values from the previous period.

      • close_price is the closing price from the OHLC data at the current period.

      • trade_date is the corresponding date for the current period.


        # Checks for MACD cross above signal line (Buy Signal)
        if macd_value > signal_value and previous_macd_value <= previous_signal_value and not position_open:
            simulation.buy(context['ticker'], 10, close_price, trade_date=trade_date, long=True)
            position_open = True
  • Purpose: This block checks for a buy signal based on the MACD crossover:

    • Buy Condition: The strategy looks for the MACD line to cross above the signal line (i.e., macd_value > signal_value and previous_macd_value <= previous_signal_value) and ensures no position is currently open (not position_open).

    • Executing Buy Order: If the condition is met, a buy order is placed using the TradeSimulation object, buying 10 units of the ticker at the current closing price and date.

    • Update Position Flag: The position_open flag is set to True, indicating that a position has been opened.


        # Checks for MACD cross below signal line (Sell Signal)
        elif macd_value < signal_value and previous_macd_value >= previous_signal_value and position_open:
            simulation.sell(context['ticker'], 10, close_price, trade_date=trade_date, long=True)
            position_open = False
  • Purpose: This block checks for a sell signal based on the MACD crossover:

    • Sell Condition: The strategy looks for the MACD line to cross below the signal line (i.e., macd_value < signal_value and previous_macd_value >= previous_signal_value) and ensures a position is currently open (position_open).

    • Executing Sell Order: If the condition is met, a sell order is placed using the TradeSimulation object, selling 10 units of the ticker at the current closing price and date.

    • Update Position Flag: The position_open flag is set to False, indicating that the position has been closed.


    # Calculating final P/L
    current_prices = {context['ticker']: context['data_provider'].get_current_price()}
    
    if current_prices[context['ticker']] is None:
        context['modules']['logging'].error(f"Failed to retrieve current price for {context['ticker']}. Exiting strategy.")
        raise ValueError(f"Current price for {context['ticker']} is None.")
    
    pl = simulation.calculate_pl(current_prices)
    context['modules']['logging'].info(f"Final P/L: {pl}")
  • Purpose: This block calculates the final profit/loss (P/L) for the strategy:

    • Retrieve Current Price: The current price of the ticker is fetched using the get_current_price method of the data_provider.

    • Price Validation: A check ensures that the current price is not None. If it is, an error is logged, and a ValueError is raised to halt the strategy.

    • Calculate P/L: The calculate_pl method of the TradeSimulation object is called to calculate the final P/L based on the current prices.

    • Log P/L: The final P/L is logged for the user’s reference.


except Exception as e:
    context['modules']['logging'].error(f"Error in MACDCommand execution: {e}")
  • Purpose: This block handles any exceptions that occur during the strategy execution:

    • Error Logging: If an exception is raised within the try block, it is caught here, and the error message is logged, specifying the error that occurred.


# ===========================================
# END USER DEFINED SECTION
# ===========================================
  • Purpose: Marks the end of the user-defined section, indicating that all strategy-specific code should be placed between the start and end markers of this section.


Last updated