avatarThornexdaniel

Summary

This article discusses a Python code that implements a 15-minute candle reversal pattern on Nasdaq futures, with the goal of detecting selling exhaustion in the market and increasing the probability of price moving in the other direction.

Abstract

The article presents a Python code for executing a 15-minute candle reversal pattern on Nasdaq futures, aiming to detect selling exhaustion in the market. The pattern requires a bearish candle to precede a bullish candle, with specific criteria for the bullish candle, such as a lower low, a lower high, and a close within the body of the bear candle. The code runs a simulation that enters a trade one tick above the high of the signal candle, with a 35-tick profit/loss and no time limit. The author also provides plots to show the time of day when this strategy works best and worst, as well as the daily win/loss percentage. The dataset used for testing is over 20000 periods long, spanning 10 months from 2023-05-01 00:00:00 to 2024-03-13 20:15:00.

Bullet points

  • The article presents a Python code for implementing a 1

70%+ Automated Returns-15M Bull Reversal-NQ Futures

This article will present the code to execute a simple 15m candle reversal patten on Nasdaq futures using Python. The pattern essentially detects selling exhaustion in the market, leaving a higher probability of price moving in the other direction. The criteria for the reversal pattern is as follows: a bearish candle must precede a bullish candle with a lower low, a lower high and a close within the body of the bear candle. Then, the code runs a simulation that enters a trade one tick above the high of the signal candle with a 35-tick profit/loss; i.e. a 1:1 Risk Reward Ratio with no time limit. This means whenever the signal is generated, the trade order will remain open until price reaches this level.

Plot indicating signals from strategy on TradingView
// Pine Script for implementing in TradingView
//@version=4
study("Candlestick Patterns", shorttitle="CP", overlay=true)

// Identify Bear Candle
bearCandle = close[1] < open[1]

// Check for Bull Candle with specific criteria
bullCandleCriteria = close > open and close > close[1] and close < open[1] and low < low[1] and high < high[1]

// Combine conditions to detect the specified pattern for bear followed by bull
bearBullPattern = bearCandle and bullCandleCriteria

// Plot yellow triangle on the second candle of the bear followed by bull pattern as a signal indicator
plotshape(bearBullPattern, style=shape.triangleup, location=location.belowbar, color=color.red, size=size.small)

I have also generated plots to show which time of day this strategy works best and worst, as well as the daily win/loss percentage. Lastly, I wanted to test if there was a significant success rate for this setup with respect to an 8-period Exponential Moving Average.

I coded all of this into Google Colab using Python and collected data from TradingView. The dataset is over 20000 periods long, spanning 10 months 2023–05–01 00:00:00 to 2024–03–13 20:15:00.

!pip install yfinance pandas matplotlib mplfinance

# Mounting T Data Sets from Google Drive

from google.colab import drive
drive.mount('/content/drive')

# Path to your file, e.g., "My Drive" is the root directory of your Google Drive
file_path = '/content/drive/My Drive/Historical_T_Data/NQ_15M_ETH.csv'

import pandas as pd
df = pd.read_csv(file_path, header = None)

# Define the conditions for the original signal pattern
def detect_signal_pattern(df):
    # Identify Bear Candle
    df['bearCandle'] = df[4] < df[1]

    # Check for Bull Candle with specific criteria
    bull_candle_condition = (
        (df[3] < df[3].shift(1)) &
        (df[2] < df[2].shift(1)) &
        (df[4] < df[1].shift(1)) &
        (df[4] > df[4].shift(1))
    )
    df['bullCandle'] = bull_candle_condition

    # Combine conditions to detect the original signal pattern
    df['signalPattern'] = df['bearCandle'].shift(1) & df['bullCandle']

    return df

# Define the conditions for the opposite signal pattern
def detect_opposite_signal_pattern(df):
    # Identify Bull Candle
    df['bullCandleOpposite'] = df[4] > df[1]

    # Check for Bear Candle with specific criteria
    bear_candle_condition = (
        (df[3] > df[3].shift(1)) &
        (df[2] > df[2].shift(1)) &
        (df[4] > df[1].shift(1)) &
        (df[4] < df[4].shift(1))
    )
    df['bearCandleOpposite'] = bear_candle_condition

    # Combine conditions to detect the opposite signal pattern
    df['oppositeSignalPattern'] = df['bullCandleOpposite'].shift(1) & df['bearCandleOpposite']

    return df

# Load your dataset into a DataFrame (replace this with your actual dataset)
# Assuming your dataset is already loaded into df

# Apply the indicator functions to your dataset
df = detect_signal_pattern(df)
df = detect_opposite_signal_pattern(df)

# Print the modified DataFrame with signal pattern columns
print(df)
import pandas as pd

# Function to apply the strategy and calculate performance metrics
def apply_strategy(df):
    # Initialize variables for performance metrics
    total_trades = 0
    total_winning_trades = 0
    total_losing_trades = 0

    # Iterate over rows in the DataFrame
    for index, row in df.iterrows():
        # Check if there is a bull signal
        if row['bullCandle']:
            # Convert values to numeric
            high = pd.to_numeric(row[2])

            # Take long position one tick above the high of the bull signal candle
            entry_price = high + 0.01

            # Increment total trades count
            total_trades += 1

            # Initialize variables to track price movement
            max_high = entry_price
            min_low = entry_price

            # Iterate over subsequent rows to track price movement
            for next_index, next_row in df.iloc[index+1:].iterrows():
                # Convert values to numeric
                next_high = pd.to_numeric(next_row[2])
                next_low = pd.to_numeric(next_row[3])

                # Update max_high and min_low
                max_high = max(max_high, next_high)
                min_low = min(min_low, next_low)

                # Check if price rises by 35 ticks first
                if max_high - entry_price >= 35 * 0.01:
                    total_winning_trades += 1
                    break
                # Check if price drops by 35 ticks first
                elif entry_price - min_low >= 35 * 0.01:
                    total_losing_trades += 1
                    break

    # Calculate win rate percentage
    win_rate_percentage = (total_winning_trades / total_trades) * 100 if total_trades != 0 else 0

    # Print performance metrics
    print("Total Trades Taken:", total_trades)
    print("Number of Winners:", total_winning_trades)
    print("Number of Losers:", total_losing_trades)
    print("Win Rate Percentage:", win_rate_percentage)

# Load your dataset into a DataFrame (replace this with your actual dataset)
# Assuming your dataset is already loaded into df

# Apply the strategy and calculate performance metrics
apply_strategy(df)

Total Trades Taken: 1080 Number of Winners: 758 Number of Losers: 322 Win Rate Percentage: 70.185%

import pandas as pd

# Function to apply the strategy and return winning and losing trades
def get_trades(df):
    winning_trades = []
    losing_trades = []

    # Iterate over rows in the DataFrame
    for index, row in df.iterrows():
        # Check if there is a bull signal
        if row['bullCandle']:
            # Convert values to numeric
            high = pd.to_numeric(row[2])

            # Take long position one tick above the high of the bull signal candle
            entry_price = high + 0.01

            # Initialize variables to track price movement
            max_high = entry_price
            min_low = entry_price

            # Iterate over subsequent rows to track price movement
            for next_index, next_row in df.iloc[index+1:].iterrows():
                # Convert values to numeric
                next_high = pd.to_numeric(next_row[2])
                next_low = pd.to_numeric(next_row[3])

                # Update max_high and min_low
                max_high = max(max_high, next_high)
                min_low = min(min_low, next_low)

                # Check if price rises by 35 ticks first
                if max_high - entry_price >= 35 * 0.01:
                    winning_trade_data = {'EntryPrice': entry_price, 'ExitPrice': max_high}
                    winning_trade_data.update(row)  # Add original row data
                    winning_trades.append(winning_trade_data)
                    break
                # Check if price drops by 35 ticks first
                elif entry_price - min_low >= 35 * 0.01:
                    losing_trade_data = {'EntryPrice': entry_price, 'ExitPrice': min_low}
                    losing_trade_data.update(row)  # Add original row data
                    losing_trades.append(losing_trade_data)
                    break

    # Create DataFrames for winning and losing trades
    winning_trades_df = pd.DataFrame(winning_trades)
    losing_trades_df = pd.DataFrame(losing_trades)

    return winning_trades_df, losing_trades_df

# Load your dataset into a DataFrame (replace this with your actual dataset)
# Assuming your dataset is already loaded into df

# Get winning and losing trades
winning_trades_df, losing_trades_df = get_trades(df)

# Print winning trades DataFrame
print("Winning Trades:")
print(winning_trades_df)

# Print losing trades DataFrame
print("\nLosing Trades:")
print(losing_trades_df)


import pandas as pd

# Function to tally winning trades in each hour
def tally_winning_trades_by_hour(winning_trades_df):
    # Convert the 'date' column to datetime with timezone awareness
    winning_trades_df['date'] = pd.to_datetime(winning_trades_df[0], utc=True)

    # Convert to local timezone (adjust as per your data)
    winning_trades_df['date'] = winning_trades_df['date'].dt.tz_convert('Europe/London')

    # Extract hour from the timestamp
    winning_trades_df['hour'] = winning_trades_df['date'].dt.hour

    # Group the trades by hour and count the number of winning trades in each hour
    hourly_counts = winning_trades_df.groupby('hour').size()

    return hourly_counts

# Assuming winning trades DataFrame is already loaded and named winning_trades_df

# Tally winning trades in each hour
hourly_counts = tally_winning_trades_by_hour(winning_trades_df)

# Print the hourly counts
print("Winning Trades Tally by Hour:")
print(hourly_counts)

#########

import pandas as pd
import matplotlib.pyplot as plt

# Function to tally winning trades in each hour
def tally_winning_trades_by_hour(winning_trades_df):
    # Convert the 'date' column to datetime with timezone awareness
    winning_trades_df['date'] = pd.to_datetime(winning_trades_df['date'], utc=True)

    # Convert to local timezone (adjust as per your data)
    winning_trades_df['date'] = winning_trades_df['date'].dt.tz_convert('Europe/London')

    # Extract hour from the timestamp
    winning_trades_df['hour'] = winning_trades_df['date'].dt.hour

    # Group the trades by hour and count the number of winning trades in each hour
    hourly_counts = winning_trades_df.groupby('hour').size()

    return hourly_counts

# Assuming winning trades DataFrame is already loaded and named winning_trades_df

# Tally winning trades in each hour
hourly_counts = tally_winning_trades_by_hour(winning_trades_df)

# Plot a bar chart
hourly_counts.plot(kind='bar', figsize=(10, 6))
plt.title('Tally of Winning Trades by Hour')
plt.xlabel('Hour')
plt.ylabel('Number of Winning Trades')
plt.xticks(rotation=45)
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.show()
import pandas as pd

# Function to tally losing trades in each hour
def tally_losing_trades_by_hour(losing_trades_df):
    # Convert the 'date' column to datetime with timezone awareness
    losing_trades_df['date'] = pd.to_datetime(losing_trades_df[0], utc=True)

    # Convert to local timezone (adjust as per your data)
    losing_trades_df['date'] = losing_trades_df['date'].dt.tz_convert('Europe/London')

    # Extract hour from the timestamp
    losing_trades_df['hour'] = losing_trades_df['date'].dt.hour

    # Group the trades by hour and count the number of losing trades in each hour
    hourly_counts = losing_trades_df.groupby('hour').size()

    return hourly_counts

# Assuming losing trades DataFrame is already loaded and named losing_trades_df

# Tally losing trades in each hour
hourly_counts_losing = tally_losing_trades_by_hour(losing_trades_df)

# Print the hourly counts
print("Losing Trades Tally by Hour:")
print(hourly_counts_losing)

import matplotlib.pyplot as plt

# Plot a bar chart for losing trades by hour
hourly_counts_losing.plot(kind='bar', figsize=(10, 6), color='red')
plt.title('Tally of Losing Trades by Hour')
plt.xlabel('Hour')
plt.ylabel('Number of Losing Trades')
plt.xticks(rotation=45)
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.show()
import pandas as pd

# Function to tally winning trades by day of the week
def tally_winning_trades_by_day(winning_trades_df):
    # Convert the 'date' column to datetime with timezone awareness
    winning_trades_df['date'] = pd.to_datetime(winning_trades_df['date'], utc=True)

    # Convert to local timezone (adjust as per your data)
    winning_trades_df['date'] = winning_trades_df['date'].dt.tz_convert('Europe/London')

    # Extract day of the week from the timestamp
    winning_trades_df['day_of_week'] = winning_trades_df['date'].dt.day_name()

    # Group the trades by day of the week and count the number of winning trades for each day
    daily_counts = winning_trades_df.groupby('day_of_week').size()

    return daily_counts

# Function to tally losing trades by day of the week
def tally_losing_trades_by_day(losing_trades_df):
    # Convert the 'date' column to datetime with timezone awareness
    losing_trades_df['date'] = pd.to_datetime(losing_trades_df['date'], utc=True)

    # Convert to local timezone (adjust as per your data)
    losing_trades_df['date'] = losing_trades_df['date'].dt.tz_convert('Europe/London')

    # Extract day of the week from the timestamp
    losing_trades_df['day_of_week'] = losing_trades_df['date'].dt.day_name()

    # Group the trades by day of the week and count the number of losing trades for each day
    daily_counts = losing_trades_df.groupby('day_of_week').size()

    return daily_counts

# Assuming winning trades and losing trades DataFrames are already loaded and named winning_trades_df and losing_trades_df respectively

# Tally winning trades by day of the week
daily_counts_winning = tally_winning_trades_by_day(winning_trades_df)

# Tally losing trades by day of the week
daily_counts_losing = tally_losing_trades_by_day(losing_trades_df)

# Print the daily counts for winning trades
print("Winning Trades Tally by Day of the Week:")
print(daily_counts_winning)
print()

# Print the daily counts for losing trades
print("Losing Trades Tally by Day of the Week:")
print(daily_counts_losing)

import matplotlib.pyplot as plt

# Plot a bar chart for winning trades by day of the week
plt.figure(figsize=(10, 6))
daily_counts_winning.plot(kind='bar', color='green', alpha=0.7, label='Winning Trades')

# Plot a bar chart for losing trades by day of the week
daily_counts_losing.plot(kind='bar', color='red', alpha=0.7, label='Losing Trades')

# Customize the plot
plt.title('Tally of Trades by Day of the Week')
plt.xlabel('Day of the Week')
plt.ylabel('Number of Trades')
plt.legend()
plt.xticks(rotation=45)
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()

# Show the plot
plt.show()
# Convert the 'EMA' column to numerical values
df['EMA'] = pd.to_numeric(df[6], errors='coerce')

# Check if the buy price is above or below the EMA for each trade
df['buy_price_above_EMA'] = df['entry_price'] > df['EMA']

# Now calculate the percentage of winners where the price is above and below the EMA
winners_above_EMA = df[df['signalPattern'] & df['buy_price_above_EMA']]
winners_below_EMA = df[df['signalPattern'] & ~df['buy_price_above_EMA']]

percentage_winners_above_EMA = (len(winners_above_EMA) / len(df[df['signalPattern']])) * 100
percentage_winners_below_EMA = (len(winners_below_EMA) / len(df[df['signalPattern']])) * 100

# Print the percentages
print("Percentage of winners where the price is above EMA:", percentage_winners_above_EMA)
print("Percentage of winners where the price is below EMA:", percentage_winners_below_EMA)

Percentage of winners where the price is above EMA: 51.67 Percentage of winners where the price is below EMA: 48.33

Finance
Algorithmic Trading
Futures Trading
Trading
Money
Recommended from ReadMedium