🏗️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
tryblock, 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 correspondingexceptblock, 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
intervalvariable 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_commandInitialization: AMACDCommandobject is created using the start and end dates retrieved from thecontext.execute()Method: Theexecutemethod of theMACDCommandis 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 inmacd_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_dataRetrieval: Theget_datamethod of thedata_provideris called, retrieving OHLC data for the given date range and interval.Data Validation: A check is performed to ensure that
ohlc_datais notNoneand that the 'Close' column exists. If the data is missing or incomplete, an error is logged, and aValueErroris raised to halt the strategy execution.
# Initializing the TradeSimulation class
simulation = context['modules']['application.DSL.trading_simulation.trading_simulation'].TradeSimulation()
position_open = FalsePurpose: This block initializes the
TradeSimulationclass and sets a flag to track open positions:simulationInitialization: ATradeSimulationobject is created, which will be used to simulate buying and selling actions within the strategy.position_openFlag: This boolean flag is set toFalse, 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 dataPurpose: 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_valueandsignal_valueare the current MACD and signal line values.previous_macd_valueandprevious_signal_valueare the MACD and signal line values from the previous period.close_priceis the closing price from the OHLC data at the current period.trade_dateis 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 = TruePurpose: 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_valueandprevious_macd_value <= previous_signal_value) and ensures no position is currently open (not position_open).Executing Buy Order: If the condition is met, a
buyorder is placed using theTradeSimulationobject, buying 10 units of the ticker at the current closing price and date.Update Position Flag: The
position_openflag is set toTrue, 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 = FalsePurpose: 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_valueandprevious_macd_value >= previous_signal_value) and ensures a position is currently open (position_open).Executing Sell Order: If the condition is met, a
sellorder is placed using theTradeSimulationobject, selling 10 units of the ticker at the current closing price and date.Update Position Flag: The
position_openflag is set toFalse, 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_pricemethod of thedata_provider.Price Validation: A check ensures that the current price is not
None. If it is, an error is logged, and aValueErroris raised to halt the strategy.Calculate P/L: The
calculate_plmethod of theTradeSimulationobject 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
tryblock, 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