Earlier than implementing any buying and selling technique, getting ready clear, structured knowledge is essential. Beneath is the Python script for managing this very important step:
import pandas as pd
import pandas_ta as ta
from tqdm import tqdm
import os
import numpy as np
import plotly.graph_objects as gotqdm.pandas()
def read_csv_to_dataframe(file_path):
df = pd.read_csv(file_path)
df["Gmt time"] = df["Gmt time"].str.change(".000", "")
df['Gmt time'] = pd.to_datetime(df['Gmt time'], format='%d.%m.%Y %H:%M:%S')
df = df[df.High != df.Low] # Take away invalid rows
df.set_index("Gmt time", inplace=True)
return df
def read_data_folder(folder_path="./knowledge"):
dataframes = []
file_names = []
for file_name in tqdm(os.listdir(folder_path)):
if file_name.endswith('.csv'):
file_path = os.path.be a part of(folder_path, file_name)
df = read_csv_to_dataframe(file_path)
dataframes.append(df)
file_names.append(file_name)
return dataframes, file_names
Step Breakdown:
- Library Importation: Libraries reminiscent of
pandas
streamline knowledge manipulation,pandas_ta
calculates technical indicators,tqdm
screens progress, andplotly
is used for visualization. - File Preprocessing: Information are learn individually, and irrelevant rows are filtered out (e.g., rows the place
Excessive
equalsLow
are thought-about anomalies). - Timestamp Conversion: The datetime format is standardized to make sure constant time-series indexing.
- Effectivity for Bulk Knowledge: The
read_data_folder
operate allows processing a number of datasets, accommodating situations like multi-asset evaluation.
The technique depends on particular circumstances met by sequential candlestick formations. Right here is the operate that evaluates the sample:
def total_signal(df, current_candle):
current_pos = df.index.get_loc(current_candle)
c1 = df['High'].iloc[current_pos] > df['Close'].iloc[current_pos]
c2 = df['Close'].iloc[current_pos] > df['High'].iloc[current_pos-2]
c3 = df['High'].iloc[current_pos-2] > df['High'].iloc[current_pos-1]
c4 = df['High'].iloc[current_pos-1] > df['Low'].iloc[current_pos]
c5 = df['Low'].iloc[current_pos] > df['Low'].iloc[current_pos-2]
c6 = df['Low'].iloc[current_pos-2] > df['Low'].iloc[current_pos-1]
if c1 and c2 and c3 and c4 and c5 and c6:
return 2 # Sign to purchase (lengthy)
# Symmetrical circumstances for brief indicators
c1 = df['Low'].iloc[current_pos] < df['Open'].iloc[current_pos]
c2 = df['Open'].iloc[current_pos] < df['Low'].iloc[current_pos-2]
c3 = df['Low'].iloc[current_pos-2] < df['Low'].iloc[current_pos-1]
c4 = df['Low'].iloc[current_pos-1] < df['High'].iloc[current_pos]
c5 = df['High'].iloc[current_pos] < df['High'].iloc[current_pos-2]
c6 = df['High'].iloc[current_pos-2] < df['High'].iloc[current_pos-1]
if c1 and c2 and c3 and c4 and c5 and c6:
return 1 # Sign to promote (brief)
return 0
Step Breakdown:
- Logic Clarification: Six circumstances guarantee exact detection of a selected candlestick sequence, defining entry factors for each purchase and promote indicators.
- Sign Output: The operate returns a numerical sign (
2
for lengthy,1
for brief,0
for no sign), which can be later interpreted throughout backtesting. - Error Minimization: Through the use of strict logical circumstances, false indicators are minimized, guaranteeing the technique operates on high-probability setups.
Visualizing entry and exit factors is important for verifying a method. Beneath are the capabilities for marking patterns and plotting them on candlestick charts:
def add_total_signal(df):
df['TotalSignal'] = df.progress_apply(lambda row: total_signal(df, row.title), axis=1)
return dfdef add_pointpos_column(df, signal_column):
def pointpos(row):
if row[signal_column] == 2:
return row['Low'] - 1e-4
elif row[signal_column] == 1:
return row['High'] + 1e-4
return np.nan
df['pointpos'] = df.apply(lambda row: pointpos(row), axis=1)
return df
def plot_candlestick_with_signals(df, start_index, num_rows):
df_subset = df[start_index:start_index + num_rows]
fig = make_subplots(rows=1, cols=1)
fig.add_trace(go.Candlestick(
x=df_subset.index,
open=df_subset['Open'],
excessive=df_subset['High'],
low=df_subset['Low'],
shut=df_subset['Close'],
title='Candlesticks'), row=1, col=1)
fig.add_trace(go.Scatter(
x=df_subset.index, y=df_subset['pointpos'], mode="markers",
marker=dict(measurement=10, shade="MediumPurple", image='circle'),
title="Entry Factors"), row=1, col=1)
fig.present()
Step Breakdown:
- Integration with Alerts: The
add_total_signal
operate augments the dataset with generated commerce indicators. - Chart Enhancements: Entry factors are marked as purple circles under or above candles, aligning visible suggestions with technique logic.
- Customizability: The script accommodates customizations reminiscent of time ranges, making it adaptable for numerous datasets.
With the logic in place, it’s time to backtest. Right here’s how one can consider efficiency throughout varied property:
from backtesting import Technique, Backtestdef SIGNAL():
return df.TotalSignal
class MyStrat(Technique):
mysize = 0.1 # Commerce measurement
slperc = 0.04 # Cease loss proportion
tpperc = 0.02 # Take revenue proportion
def init(self):
self.signal1 = self.I(SIGNAL)
def subsequent(self):
if self.signal1 == 2 and never self.place:
self.purchase(measurement=self.mysize, sl=self.knowledge.Shut[-1] * (1 - self.slperc), tp=self.knowledge.Shut[-1] * (1 + self.tpperc))
elif self.signal1 == 1 and never self.place:
self.promote(measurement=self.mysize, sl=self.knowledge.Shut[-1] * (1 + self.slperc), tp=self.knowledge.Shut[-1] * (1 - self.tpperc))
Step Breakdown:
- Cease Loss & Take Revenue Ranges: Adjustable percentages guarantee strong threat administration.
- Sign Integration: The backtest dynamically interprets generated indicators and executes trades accordingly.
- Flexibility for Optimization: Parameters like
mysize
,slperc
, andtpperc
may be fine-tuned to maximise profitability.
Backtesting outcomes on the S&P 500 index provided the next takeaways:
- 65% Win Price: Demonstrates constant success below varied market circumstances.
- Aggregated Return: Yielded a notable 71% return throughout the testing interval.
- Commerce-Particular Insights: The most effective commerce delivered a revenue of 10.3%, whereas the worst drawdown was restricted to 4.8%.
Whereas this technique excelled with equities, its efficiency on foreign exchange was much less constant, indicating potential for asset-specific refinement.
This candlestick sample technique demonstrates the facility of mixing conventional buying and selling knowledge with cutting-edge automation. Whereas its simplicity is a bonus, combining it with further patterns or refining it for particular asset lessons could unlock better potential.
For step-by-step tutorials and Python code, go to our e-newsletter, the place we dive even deeper into algorithmic methods and buying and selling applied sciences. Subscribe to remain up to date with the most recent developments in automated buying and selling!