AI Trading: Enhancing Strategies with Psychology
AI Trading: Enhancing Strategies with Psychology
Abstract
Traditional AI-driven trading strategies, while proficient at recognizing technical patterns within
historical price data, often fail to account for the market psychology that drives volatility, creates risk,
and defines distinct market regimes. This research addresses this critical limitation, which represents a
significant semantic gap between the quantitative outputs of technical analysis and the qualitative
insights of behavioral finance. The central thesis is that a superior trading model can be developed by
teaching an AI not just to see patterns, but to understand their psychological context. To this end, this
study develops and validates a novel Long Short-Term Memory (LSTM) model—the 'Champion'—
trained to quantify and filter trades based on behavioral finance concepts. This was achieved by
creating a unique methodological pipeline to translate abstract states like Panic, FOMO (Fear Of
Missing Out), and Herd Behavior into objective, machine-learnable "price action signatures" derived
from endogenous market data.
The performance of the Champion strategy was rigorously evaluated on a completely untouched, out-
of-sample dataset spanning May 20, 2024, to November 3, 2025. To ensure a conservative and
credible performance assessment that mirrors real-world conditions, the backtesting environment,
which began with an initial capital of $100,000 and used a fixed position size of $100,000 per trade,
incorporated realistic market frictions, including both commissions and simulated slippage.
The Champion's efficacy was measured against a multi-layered set of three distinct benchmarks, each
chosen to test a different aspect of its performance: a passive Buy & Hold strategy to measure against
the raw market return; a baseline Pure Mechanical (EMA Crossover with ATR Stop-Loss) strategy
to evaluate its improvement over a standard rules-based system; and a second LSTM model (LSTM-
EMA-ATR), optimized purely on the mechanical strategy's technical indicators, to serve as a direct AI-
to-AI comparison.
The results reveal a clear and compelling hierarchy in risk-adjusted performance. The behavioral
Champion strategy delivered the best overall balance, achieving a 32.49% cumulative return with an
exceptionally low -5.90% maximum drawdown. While the passive Buy & Hold strategy yielded a
nominally higher 36.75% return, this came at the cost of an untenable -23.09% drawdown,
demonstrating its inferiority on a risk-adjusted basis. The Champion also decisively outperformed its
direct counterparts. It surpassed the baseline Pure Mechanical strategy (27.0% return, -12.12%
drawdown) by delivering higher returns with less than half the risk. Most significantly, it proved far
superior to the technically-optimized LSTM-EMA-ATR strategy (21.84% return, -6.91%
drawdown), which, while risk-averse, sacrificed too much profit potential.
Furthermore, a 10,000-iteration Monte Carlo analysis on the Champion’s trade results confirmed the
statistical robustness of its edge. The simulation projected a 61.09% probability of profit and a mean
maximum drawdown of just -3.65%, indicating that its capital preservation capabilities are a core
feature of its design, not a historical accident. This study provides definitive evidence that optimizing
1 / 79
an AI model on quantified market psychology, rather than technical indicators alone, is a superior
paradigm that successfully enhances returns while simultaneously and significantly reducing risk.
Table of Contents
2 / 79
4.3.1 Performance of the Buy & Hold Strategy [Page #]
4.3.2 Performance of the Pure Mechanical Strategy [Page #]
4.3.3 Performance of the LSTM-EMA-ATR Strategy (Technical AI) [Page #]
4.3.4 Performance of the Champion Strategy (Behavioral AI) [Page #]
4.4 Diagnostic Analysis: Monte Carlo Simulation [Page #]
4.5 Chapter Summary [Page #]
Chapter 5: Discussion [Page #]
5.1 Recapitulation and Synthesis of Key Findings [Page #]
5.2 The Superiority of the Behavioral Paradigm: Context is Alpha [Page #]
5.3 Answering the Research Questions [Page #]
5.4 Deconstructing the Champion's Edge: A Diagnostic Interpretation [Page #]
5.4.1 An Analysis of Strategy Failures: When the Champion Was Wrong [Page #]
5.5 Limitations and Avenues for Future Research [Page #]
5.6 Chapter Conclusion [Page #]
Chapter 6: Conclusion [Page #]
6.1 Summary of the Research Journey and Key Findings [Page #]
6.2 Contribution to the Field of Quantitative Finance [Page #]
6.3 Practical Implications for the Industry [Page #]
6.4 Concluding Remarks: From Bias to Alpha [Page #]
References [Page #]
Appendices (Optional) [Page #]
3 / 79
and scale that is far beyond the cognitive limits of any human trader. Yet, for all their computational
prowess, these models often possess a critical and fundamental vulnerability: they are "context-blind."
A purely quantitative model can identify what is happening in the market—a price is rising, volatility is
expanding—but it lacks the capacity to understand why. It cannot distinguish between a fundamentally
sound trend driven by new information and a speculative bubble driven by irrational exuberance and on
the verge of collapse. It cannot tell the difference between a healthy pullback and the first tremors of a
panic-driven capitulation event. This is because the underlying data inputs—price, volume, and their
derivatives—are often devoid of the very thing that drives these phenomena: human psychology.
This dissertation confronts this critical limitation. It posits that the next frontier in AI-driven trading is
not the development of more complex algorithms, but the creation of more intelligent data—data that
imbues these algorithms with a quantitative understanding of the market's psychological state. The core
problem this research seeks to solve is the "semantic gap" between the numerical world of technical
analysis and the emotional world of behavioral finance. This study will demonstrate that by
systematically bridging this gap, it is possible to create a trading strategy that is not only more
profitable but also demonstrably more robust, resilient, and intelligent in its management of risk.
The central innovation of this work is the development and validation of a novel framework for
translating abstract behavioral finance concepts into quantifiable "price action signatures." Concepts
such as panic, FOMO (Fear Of Missing Out), and herd behavior, which are traditionally discussed in
qualitative terms, are here defined as objective, machine-readable patterns based on the interplay of
price velocity, volatility, and volume. A Long Short-Term Memory (LSTM) deep learning model,
named the "Champion," is then trained to act as a real-time behavioral classifier. This model is not
designed to predict price—a notoriously difficult task—but to diagnose the present, answering the
crucial question: "What is the psychological character of the market right now?"
The Champion AI is then deployed as an intelligent filter layered over a standard mechanical trading
strategy. Its function is to provide a final, context-aware " go/no-go " decision on trade signals. It is
programmed to approve trades only when the market is in a state it recognizes as stable and rational
("Neutral" or "Herd"), while rejecting the very same technical signals when they occur during periods
of identifiable irrationality or emotional extremity. To ensure the credibility of this evaluation, all
backtests were conducted with realistic market frictions, including simulated slippage and transaction
commissions.
This dissertation will seek to answer the following research questions:
1. Can an LSTM model be effectively trained to classify market behavior using quantified price
action signatures?
2. Does a strategy filtered by this behavioral AI (the Champion) yield superior risk-adjusted
returns compared to a purely mechanical strategy?
3. Does the Champion strategy also outperform a second LSTM model (LSTM-EMA-ATR) that is
trained only on the traditional technical indicators of the mechanical strategy?
The significance of this research lies in its potential to forge a new path for the design of automated
trading systems—one that moves beyond simple pattern recognition towards a more holistic, context-
4 / 79
aware form of market analysis. The ultimate goal is to provide empirical proof that the fusion of
behavioral science and artificial intelligence results in a strategy that excels at capital preservation,
particularly by programmatically avoiding the emotionally charged market conditions that have
historically been the primary source of catastrophic losses for rigid, purely mechanical systems. This
dissertation will demonstrate that within the noise of market biases, there is a discernible, exploitable
signal of alpha.
5 / 79
noisy financial data that were invisible to traditional econometric models that rely on strict assumptions
of linearity and stationarity. Deep learning, particularly through architectures like Recurrent Neural
Networks (RNNs) and Long Short-Term Memory (LSTMs), has pushed this frontier even further,
allowing for the analysis of hierarchical and temporal patterns in high-dimensional time-series data.
This progression from simple automation to adaptive intelligence forms the technological backdrop for
the AI models developed in this study, representing the state-of-the-art in quantitative strategy
development.
2.3 The Bedrock of Quantitative Strategy: Technical Analysis and Its Limitations
The baseline strategy of this research is a mechanical system rooted in technical analysis. This
discipline, with philosophical origins in the work of Charles Dow at the turn of the 20th century,
operates on a set of core tenets: (1) the market discounts everything, meaning all known and
foreseeable information is already reflected in the price; (2) prices move in trends, which persist until a
clear reversal occurs; and (3) history tends to repeat itself, as the patterns of human psychology that
drive market movements remain constant over time (Kirkpatrick & Dahlquist, 2016). Mechanical
trading systems are the logical, objective implementation of these principles, using mathematical
indicators to create non-discretionary rules for market entry and exit.
Two of the most foundational indicators in technical analysis are the Exponential Moving Average
(EMA) and the Average True Range (ATR). The EMA is a powerful trend-following tool that smooths
price data to reveal the underlying direction of the market. By giving exponentially more weight to
recent price data, it is more responsive to changes in trend than a simple moving average. The
"crossover" of a short-period (fast) EMA and a long-period (slow) EMA is a classic and robust signal
indicating a potential shift in market momentum and is used as the entry signal in this study's baseline
strategy.
The ATR, developed by J. Welles Wilder Jr., is a pure measure of volatility. Unlike indicators that
measure price direction, the ATR quantifies the degree of price movement or "choppiness" in a market,
independent of its trend. Its primary application in mechanical systems is for intelligent risk
management. A stop-loss based on a multiple of the ATR is dynamic; it places the stop further away in
volatile market conditions (giving the trade more "room to breathe") and closer in quiet conditions
(protecting profits more tightly). The use of a 2x ATR stop-loss in the baseline strategy represents an
industry-standard practice for balancing risk control with the need to avoid premature trade exits due to
random market noise. The appeal of such a mechanical system lies in its discipline and objectivity. It
removes human emotion, hesitation, and second-guessing from the execution process. However, this
strength is also its greatest weakness. The system is context-blind; it treats an EMA crossover that
occurs during a quiet, low-volatility consolidation identically to one that occurs during a frantic, high-
volume market panic. This inability to differentiate the market context is the primary flaw that this
research seeks to remedy.
2.4 The Human Element: Behavioral Finance's Challenge to Market Rationality
For much of the 20th century, financial theory was dominated by the Efficient Market Hypothesis
(EMH), famously articulated by Eugene Fama, which posits that financial markets are "informationally
efficient" and that asset prices, at any given time, reflect all available information. A direct consequence
6 / 79
of this theory is that it is impossible to consistently achieve returns in excess of the average market
return on a risk-adjusted basis, as any new information is instantaneously priced in.
The field of behavioral finance, however, presents a powerful and empirically supported challenge to
this view. Pioneered by the Nobel Prize-winning work of psychologists Daniel Kahneman and Amos
Tversky, behavioral finance argues that investors are not the perfectly rational, utility-maximizing
actors described in classical economic theory. Instead, their decisions are subject to a host of
systematic, predictable cognitive biases (Kahneman & Tversky, 1979). These biases, far from being
random noise that cancels out in aggregate, create persistent market inefficiencies and what Robert
Shiller termed "excess volatility." As articulated by Shleifer (2000), these behavioral patterns can lead
to predictable over- and under-reactions to news and fundamental data, creating opportunities for those
who can identify them, as long as there are "limits to arbitrage" that prevent rational traders from
immediately correcting the mispricings.
Key biases relevant to this research include:
Herd Behavior: The tendency for individuals to mimic the actions of a larger group, often
suppressing their own private information. This is a rational response to uncertainty but can lead
to irrational collective outcomes, such as the inflation of speculative bubbles (e.g., the dot-com
bubble) or the exacerbation of market crashes as selling begets more selling.
Loss Aversion: The empirically demonstrated finding that the psychological pain of a loss is
roughly twice as powerful as the pleasure of an equivalent gain. This asymmetry leads to
irrational behaviors such as holding onto losing trades for too long (the "disposition effect") in
the hope they will return to break-even, while simultaneously selling winning trades too early to
lock in a certain gain.
FOMO (Fear Of Missing Out): A potent emotional driver, closely linked to herd behavior and
recency bias, that causes individuals to impulsively buy into an asset that has already
experienced a significant price run. This behavior is most prominent near market tops and is a
primary cause of what is commonly known as "dumb money" entering at the worst possible
time.
Anchoring: The tendency to over-rely on an initial piece of information (such as a purchase
price or a historical high) when making subsequent decisions, even if that information is no
longer relevant to the asset's fundamental value.
These psychological factors are the "ghost in the machine" of financial markets. They are the reason
why patterns of greed and fear repeat throughout history. This dissertation operates on the principle that
these phenomena leave a tangible "footprint" in the price action. For instance, the rapid, high-volume
price movements associated with herding behavior can cause slippage, where the price moves
adversely between the moment a trade decision is made and the moment it is executed. Any realistic
backtest or training regimen must therefore account for such market frictions. This study contends that
a sufficiently advanced pattern-recognition model can be trained to identify this behavioral footprint
and use it to its advantage.
7 / 79
2.5 The Tool for the Task: Deep Learning in Financial Time-Series Analysis
Given the noisy, non-stationary, and highly complex nature of financial time-series data, deep learning
has emerged as the premier tool for quantitative analysis. Unlike traditional econometric models that
rely on strict statistical assumptions (e.g., linearity, normality of residuals), deep neural networks are
universal function approximators capable of learning highly complex, non-linear relationships directly
from the data (Fischer & Krauss, 2018).
Among the various deep learning architectures, Recurrent Neural Networks (RNNs) are naturally
suited for sequential data like price series, as they possess a feedback loop that allows information to
persist. However, simple RNNs suffer from the "vanishing gradient problem," a technical issue where
the signal for learning can become too weak to propagate through many time steps, making it difficult
for them to learn and remember information over long time scales. Long Short-Term Memory (LSTM)
networks were specifically designed to overcome this limitation. The architecture of an LSTM cell
includes a series of "gates" (input, forget, and output) that act as regulators for the flow of information.
This gating mechanism allows the network to maintain a "cell state" or long-term memory. The forget
gate can decide to discard irrelevant information from the past, while the input gate can decide to store
new, important information. This enables the network to capture long-term temporal dependencies,
which is precisely what is required to recognize a complex behavioral signature that unfolds over many
hours or days.
A critical distinction in this research is the application of the LSTM model. The vast majority of
academic and industry research has focused on using LSTMs for price prediction—forecasting a future
price point. This is a notoriously difficult, and many argue an impossible, task due to the semi-random
nature of short-term market movements and the reflexive nature of markets themselves. This study
reframes the problem as one of classification. The goal is not to predict the future price, but to
accurately classify the present behavioral state of the market. This is a more tractable, robust, and
practically useful application of the technology for building a risk management and trade-filtering
system. It shifts the objective from "what will happen next?" to the more answerable question, "what is
happening now, and is this a safe environment to trade in?"
2.6 Chapter Conclusion: Synthesizing the Literature and Identifying the Research Gap
The literature reviewed in this chapter reveals a clear trajectory towards more intelligent, data-driven
trading systems. It also highlights a persistent disconnect between the quantitative tools of technical
analysis and the qualitative insights of behavioral finance. While LSTMs have been proven effective at
pattern recognition, their application has been overwhelmingly focused on narrow technical data,
leaving the rich, contextual information of market psychology largely untapped.
A significant and largely unexplored research gap exists at the intersection of these three domains.
While many studies acknowledge the influence of sentiment on markets, and some have attempted to
correlate it using exogenous data sources like news headlines (sentiment analysis of text) or social
media feeds (e.g., Twitter), there is a lack of rigorous, quantitative frameworks for translating the
behavioral concepts themselves—as manifested purely through an asset's endogenous price action data
—into direct inputs for an AI-driven risk management filter.
8 / 79
Furthermore, no studies have performed a direct, apples-to-apples comparison of a strategy filtered by
such a behavioral model against one filtered by an identical AI architecture trained only on the
strategy's own technical indicators. This specific comparative analysis is critical to prove that the
performance improvement comes from the behavioral context itself, and not merely from the
application of a generic deep learning model.
This dissertation directly addresses this gap. The problem statement can be formally articulated as:
Existing AI-driven trading models, when trained on a narrow set of technical indicators, lack the
contextual awareness of the market's psychological state, leading to suboptimal performance and an
inability to effectively navigate non-standard market conditions driven by investor sentiment.
This research makes three primary contributions to the field:
1. It proposes a novel and replicable methodology for quantifying abstract behavioral signatures
from raw price, volume, and volatility data, creating a new type of feature set for financial
machine learning.
2. It provides definitive empirical proof, through a rigorous comparative backtest that includes
market frictions, that a behaviorally-aware AI strategy delivers superior risk-adjusted returns
compared to both a purely mechanical system and a technically-aware AI strategy.
3. It delivers a fully specified and validated trading model (The Champion) as a proof-of-
concept, demonstrating the practical viability of this integrated approach and providing a robust
framework for future research and development in context-aware trading systems.
Chapter 3:Methodology
3.1 Overview of the Research Framework
This chapter provides the methodological bedrock for the dissertation, detailing the systematic and
rigorous framework employed to design, build, and evaluate the AI-driven trading strategies. The
primary objective of this framework is to facilitate a transparent, replicable, and unbiased comparison
between four distinct approaches: a passive benchmark, a baseline mechanical system, an AI model
optimized on traditional technical indicators, and the novel AI model optimized on behavioral finance
signatures.
The methodology is structured to flow logically from foundational data management to the
sophisticated application of deep learning and statistical validation. It begins with the sourcing,
preparation, and crucial partitioning of the financial time-series data. It then moves to a granular
definition of each strategy's ruleset, providing clear justification for the indicators and parameters
chosen. Following this, the chapter delves into the specific architecture and training regimen of the
Long Short-Term Memory (LSTM) deep learning models, explaining the rationale behind their design
and optimization. The chapter culminates in a detailed description of the backtesting environment,
including the simulation of realistic market frictions, and the statistical methods used for the final
performance evaluation, most notably the Monte Carlo analysis. Every parameter and procedural
choice detailed herein was made with the explicit goal of isolating and accurately measuring the
9 / 79
performance impact of layering a behavioral finance filter over a standard quantitative trading
approach, thereby ensuring the conclusions drawn are both credible and scientifically sound.
3.2 Data Acquisition, Preparation, and Splitting
The selection of the underlying financial instrument is a critical first step in any quantitative study, as
its characteristics can significantly influence a strategy's behavior. For this research, the Invesco QQQ
Trust (QQQ) was chosen as the subject asset. As an exchange-traded fund (ETF) that tracks the
NASDAQ-100 index, QQQ offers several distinct advantages that make it an ideal laboratory for
observing behavioral phenomena. Firstly, its immense daily trading volume and tight bid-ask spreads
ensure high liquidity, which minimizes the potential for backtest results to be skewed by transaction
friction like slippage and market impact. Secondly, its composition is heavily weighted towards
technology, innovation, and high-growth sectors. These sectors are historically more susceptible to
pronounced behavioral dynamics such as speculative enthusiasm (FOMO), sharp, sentiment-driven
sell-offs (Panic), and strong herding effects, making QQQ a fertile ground for a strategy designed to
identify and react to these psychological states.
A comprehensive dataset of 1-hour OHLCV (Open, High, Low, Close, Volume) data for QQQ was
acquired, spanning a 10-year period. The 1-hour timeframe was deliberately chosen as it strikes a
critical balance between capturing meaningful intraday sentiment shifts that define behavioral
signatures, while mitigating the stochastic noise and randomness inherent in higher-frequency (e.g., 1-
minute or 5-minute) data.
The most critical step in the data preparation phase was the strict, chronological partitioning of the
dataset to preserve its temporal integrity. In financial machine learning, allowing a model to train on
data that occurs chronologically after data it is being tested on—even if only for validation—constitutes
lookahead bias, a cardinal sin that invalidates results. To prevent this, the dataset was partitioned before
any analysis or model development began:
Training & Validation Set (85%): This segment, comprising the first 8.5 years of the data, was
the designated sandboxed environment for all developmental processes. This is the data block
used to train both AI models.
Out-of-Sample Test Set (15%): The final 1.5 years of the data was completely sequestered into
a separate, untouched file. This dataset, covering the period from May 20, 2024, to November
3, 2025, was never accessed during any phase of model development. It served as the final,
unbiased proving ground for the backtesting of all four strategies, ensuring that the final
performance evaluation is a true measure of the models' ability to generalize to new, unseen
market conditions.
3.3 The Experimental Strategies
LSTM + EMA + ATR STRATEGY
Four distinct strategies were defined to create a multi-layered comparative analysis. This structure
allows for the isolation of each strategic layer's contribution to overall performance, from the baseline
market return to the alpha generated by each successive layer of complexity.
10 / 79
This serves as the passive, non-trading benchmark. It represents the return on the underlying asset itself
and is a crucial measure of the "market beta."
This strategy forms the active baseline and represents a standard, industry-recognized trend-following
system. Its rules are entirely objective and non-discretionary.
Entry Signal: A long position is initiated when the 20-period Exponential Moving Average
(EMA) crosses above the 50-period EMA.
Exit Signal: An open position is closed when the 20-period EMA crosses below the 50-period
EMA.
Risk Management: A dynamic stop-loss is placed at a level equal to the entry price minus two
times the value of the 14-period Average True Range (ATR).
This strategy was designed as a direct, fair comparison to the Champion model. It seeks to answer the
question: can an AI improve a mechanical system using only that system's own technical components?
The LSTM -EMA was trained on the full 85% historical dataset to function as both an entry and exit
optimizer. However, an important finding emerged during the validation phase: while the AI entry filter
showed promise, the AI-driven exits consistently underperformed the simple mechanical exit rules. The
AI tended to exit profitable trades prematurely. Consequently, the optimal configuration for this
strategy—and the one used in the final comparative backtest—was a hybrid approach.
Execution Logic: A mechanical buy signal is only executed if the LSTM model predicts a
"good" entry with a confidence above a pre-calibrated threshold of 0.42. All exits are governed
by the original Pure Mechanical rules.
11 / 79
Risk Management: The strategy integrates a multi-layered risk management system, including
an initial hard stop-loss (2x ATR) as a fail-safe and a dynamic trailing stop-loss to protect
profits during favorable market conditions.
3.4 The Champion Model: A Three-Step Methodological Pipeline
The development of the Champion strategy followed a structured three-step pipeline, progressing from
raw data to a fully trained and evaluated behavioral classification model. This pipeline was designed to
create a robust and accurate "textbook" from which the AI could learn to identify complex market
psychology.
The first step was to transform the raw 85% OHLCV dataset into a rich, labeled "textbook" for the AI
to learn from. This involved two parallel processes. First, a diverse set of eight features was engineered
to provide the model with a holistic view of market dynamics: Close, Volume, ATR, short-term returns
(return_2H, return_5H), long-term return (return_60H), and relative ratios for volume and volatility
(volume_ratio, atr_ratio).
Second, and most critically, a set of heuristic rules was applied to this feature-rich dataset to
programmatically assign a behavioral label to each time step. The logic, derived from behavioral
finance theory, was as follows:
Panic: Labeled during periods of sharply negative returns where both volume and ATR ratios
were significantly elevated, indicating a high-velocity, high-participation sell-off.
FOMO: Labeled during periods of extreme positive short-term returns, high volume ratios, and
expanded ATR, indicating a speculative, high-volatility rally.
Herd Behavior: Labeled during periods of sustained positive returns (Close > slow_ma) but,
crucially, a low and stable ATR ratio (atr_ratio < 0.8), signifying a confident, low-anxiety trend.
This was designated as the ideal state for trade entry.
Correction: Labeled during moderately negative returns with elevated ATR, but distinguished
from "Panic" by occurring outside of a broader downtrend regime.
Neutral: The default state, representing market consolidation or equilibrium.
This process created a new, self-contained dataset (labeled_data_85_percent.csv) where each row
contained the raw features and the corresponding ground-truth behavioral label.
The "labeled textbook" created in Step 1 was then prepared for ingestion by the LSTM model. A
critical methodological distinction was made here. Unlike the LSTM-EMA-ATR model, which was
trained on the full 85% data block, the Champion's 85% dataset was further partitioned into a
chronological 80% training set and a 20% validation set. This allowed for a more robust training
process where the model's ability to generalize was continuously tested against unseen validation data.
The preparation followed three standard procedures for time-series deep learning:
1. Label Encoding: The categorical text labels ('Panic', 'Herd', etc.) were converted into numerical
integers (0, 1, etc.).
12 / 79
2. Feature Scaling: All eight numerical features were scaled to a range between 0 and 1 using
MinMaxScaler. This prevents features with large magnitudes (like 'Volume') from
disproportionately influencing the model's learning process.
3. Sequencing: The data was transformed into overlapping sequences of 60 time steps. Each
sample fed to the LSTM consisted of 60 hours of historical feature data (the X value) and the
single behavioral label corresponding to the 60th hour (the y value).
The final, prepared data was saved as a series of .npy files (X_train.npy, y_train.npy, X_test.npy,
y_test.npy), creating a clean and efficient pipeline for the training stage.
The efficacy of the Champion strategy is fundamentally dependent on its ability to correctly identify
rare but critical market events. A crucial challenge in training this model was the inherent class
imbalance of the behavioral dataset; "Panic" and "FOMO" states are far less frequent than the "Neutral"
state. To solve this, a specific training methodology was implemented. Using the
compute_class_weight function, weights for each class were calculated that were inversely proportional
to their frequency.
These weights were then passed directly into the .fit() method of the TensorFlow Keras model via the
class_weight parameter. This technique forces the model to treat the misclassification of a rare "Panic"
event with the same importance as misclassifying a multitude of "Neutral" events, compelling it to
learn the features of these minority classes.
To evaluate the model's classification performance before its deployment in the backtest, a confusion
matrix was generated from its predictions on the 20% validation set, as shown in Figure 2.X.
Figure 2.1:Confusion Matrix of the Champion Model on the Validation Set. The y-axis represents
the true, labeled market state, while the x-axis represents the AI model's prediction. The diagonal
indicates correct classifications. This diagnostic tool is essential for understanding the model's
predictive strengths and biases.
13 / 79
The matrix reveals two critical insights that explain the strategy's success. First, the model
demonstrated a very high proficiency in correctly identifying "Neutral" market conditions, as
evidenced by the large number on the diagonal for that class. This is its core competency and aligns
perfectly with its strategic purpose: to identify stable periods suitable for initiating trend-following
trades.
Second, and more revealingly, the matrix shows that the model's errors are asymmetric and risk-averse.
For instance, a significant number of "Correction" and "Panic" events were misclassified as "Neutral."
While on the surface this appears to be a flaw, this behavior is, in fact, a key component of its risk
management success. It indicates a conservative operational bias. Rather than being overconfident and
attempting to perfectly classify every volatile event, the AI defaults to a "no-go" signal by failing to
find a pattern it recognizes with high confidence. A model that knows what it doesn't know is often
more valuable in quantitative finance than one that is overconfident. This programmatic inaction during
periods of high uncertainty is precisely what prevents the strategy from entering trades that would have
likely been stopped out, thus preserving capital and minimizing drawdown.
The model architecture itself was a stacked LSTM designed for hierarchical temporal feature learning:
Architecture: An input LSTM layer (100 units), a Dropout layer (0.2), a second LSTM layer
(50 units), a second Dropout layer (0.2), a Dense hidden layer (25 units, ReLU activation),
and a final Dense output layer with a Softmax activation function.
Training Process: The model was trained using the Adam optimizer, Sparse Categorical
Crossentropy loss function, and the critical class weights. EarlyStopping (patience=10) and
ModelCheckpoint callbacks were used to ensure optimal training duration against the 20%
validation set and prevent overfitting. The final trained model was then evaluated with a
classification report and a confusion matrix to diagnose its predictive strengths and weaknesses
before being deployed in the backtest.
3.4.1 A Critical Evaluation of the Heuristic Labeling Methodology
While the programmatic labeling of behavioral signatures is central to this research, it is imperative to
critically evaluate the heuristic methodology used. The process of translating subjective psychological
concepts into objective, quantitative rules is an act of approximation, and the specific parameters
chosen represent a series of informed but ultimately fallible judgments. This section deconstructs the
rationale behind these choices and acknowledges the inherent limitations of the approach.
The primary challenge lies in defining the boundaries of a behavioral state. To address this objectively,
statistical thresholds based on quantiles were employed for return-based features. For instance, the
fomo_return_threshold was set at the 99th percentile of the 5-hour return. This is a standard statistical
method for defining an "extreme" or "outlier" event within the historical context of the dataset. The
advantage of using quantiles is their adaptability; they define rarity relative to the dataset itself, making
the logic robust to long-term shifts in the market's underlying volatility regime. A 99th percentile event
is always a rare event, whether it occurs in a low-volatility year or a high-volatility one. Similarly, the
14 / 79
capitulation_return_threshold was set at the 1st percentile, objectively defining a rare negative price
shock that serves as one of the potential triggers for a "Panic" state.
In contrast, absolute thresholds were used for ratio-based features, such as volume_ratio > 1.3 for
FOMO or atr_ratio < 0.8 for Herd Behavior. These values were not arbitrary but were derived from an
extensive exploratory data analysis (EDA) phase conducted on the training set. Histograms and
distribution plots of these ratios during visually identified periods of herding or speculation revealed
that these specific values served as effective demarcation points. However, it must be acknowledged
that these parameters are, to some extent, "tuned" to the historical data. There is a risk that they
represent a partial overfitting to past market character, and their efficacy could diminish if the market's
fundamental structure were to change significantly in the future.
Furthermore, the logic for defining the "Panic" and "Herd" states incorporates a crucial layer of
trend-based context derived from the EMA indicators. The "Panic" signature is a compound condition.
It can be triggered by a pure capitulation event (extreme negative returns on high volume and
volatility), but it is also triggered by a downtrend regime filter (df['fast_ma'] < df['slow_ma'] * 0.995).
This represents a deliberate and sophisticated attempt to add context, ensuring that the "Panic" label is
applied not just to any sharp drop, but to a sustained period of high-volatility selling that occurs within
an already established downtrend. This prevents the model from mislabeling a sharp but quickly-
reversed dip in an uptrend as a full-blown panic.
Similarly, the "Herd Behavior" signature requires that the Close price is above the slow_ma. This rule
grounds the signature in the broader market trend, ensuring that the AI only identifies a "Herd" state
when the market is in a confirmed uptrend, not during a low-volatility consolidation within a
downtrend. While this adds sophistication, it also introduces complexity and another set of parameters
that could be challenged. The use of these EMA-based rules during the labeling phase is a critical
methodological detail; it enriches the "textbook" from which the Champion learns, even though the
EMAs themselves are not direct input features for the final model.
Ultimately, this heuristic framework is a model of reality, not reality itself. Its primary limitation is that
the AI model can only ever be as good as the "textbook" it was taught from. If the human-designed
rules are flawed or incomplete, the model will inherit those imperfections. A potential alternative,
which represents a significant avenue for future research, would be the use of unsupervised learning. A
clustering algorithm, for instance, could be applied to the feature data to discover the "natural" market
states without human preconceptions. However, for this study, the heuristic approach was deliberately
chosen for two reasons: first, its direct link to established behavioral finance concepts provides a clear
and interpretable foundation; second, it allows for a direct test of the core hypothesis—can these
specific, theory-driven concepts be quantified to generate alpha? The success of the Champion model
suggests that, while an approximation, this heuristic framework was effective in capturing a genuine
and exploitable market dynamic.
To provide a final, qualitative validation of this labeling process, the resulting psychological states were
plotted directly onto the historical price chart of the 85% training data, as shown in Figure 2.1.
Figure 2.2 Visual Verification of Behavioral Labeling on the QQQ Training Dataset.
15 / 79
The colored overlays on the price chart represent the final psychological label assigned to each time
period by the heuristic rules. This visualization serves as a crucial sanity check, confirming that the
quantitative rules align with a qualitative, human interpretation of market history.
As is visually evident in Figure 2.1, the labeling logic performs as intended. The red "Panic" regime
correctly identifies the major market downtrends, most notably the COVID-19 crash in early 2020 and
the prolonged bear market of 2022. The cyan "Herd" regime accurately captures the periods of stable,
low-volatility uptrends that characterized much of 2017, 2019, and the post-COVID recovery in 2021.
16 / 79
3.6 Performance Evaluation Metrics
Cumulative Return, CAGR, Maximum Drawdown, Sharpe Ratio, and Calmar Ratio were the
primary metrics used for evaluation, supplemented by trade statistics like Win Rate and Profit Factor.
3.7 Monte Carlo Simulation
A 10,000-iteration Monte Carlo simulation was conducted on the Champion strategy's trade returns to
stress-test its historical performance and provide a robust assessment of its expected performance range
and resilience.
17 / 79
of their efficacy in balancing the dual objectives of return generation and risk management, introducing
the core themes that will be explored throughout the chapter.
Table 3.1: Aggregate Performance Metrics Across All Strategies
From this initial summary, a clear and compelling narrative emerges. The Buy & Hold strategy, while
delivering the highest nominal return, exposes the investor to a level of risk that may be untenable in
practice. Among the active strategies, a distinct hierarchy in terms of risk-adjusted performance is
immediately apparent. The LSTM-EMA-ATR strategy clearly demonstrates its value in risk reduction
but at a significant cost to returns. The Pure Mechanical strategy provides a modest balance. The
Champion model, however, stands out as the only active strategy that delivered a higher return than the
Pure Mechanical baseline while simultaneously reducing its maximum drawdown and volatility to the
lowest levels of all strategies. Its superior Sharpe and Calmar Ratios signal, even at this high level, a
more efficient and robust performance profile, a conclusion that the subsequent detailed analysis will
explore in depth.
4.3 Detailed Analysis of Individual Strategies
The Buy & Hold strategy serves as the fundamental benchmark, representing the market's raw
performance, or "beta." Over the nearly 18-month test period, it achieved a Cumulative Return of
36.75% and a Compounded Annual Growth Rate (CAGR) of 3.25%. While this represents the
highest absolute return among the tested strategies, this performance was inextricably linked to
significant and unmitigated risk. The strategy exhibited an annualized volatility of 8.21%, the highest
of the group, indicating wide fluctuations in portfolio value.
More critically, it subjected the portfolio to a Maximum Drawdown of -23.09%. This figure
represents a nearly one-quarter loss of capital from a portfolio peak, a level of drawdown that can be
psychologically devastating for investors and can lead to irrational decision-making, such as liquidating
at the point of maximum loss. The psychological difficulty of enduring such a decline means that the
theoretical final return is often not realized in practice. The strategy's Calmar Ratio of 0.14 is the
lowest of all strategies, quantitatively confirming that it delivered the least efficient return per unit of
maximum drawdown risk. In conclusion, while profitable, the Buy & Hold strategy sets a clear
benchmark for risk that any viable active strategy must decisively improve upon.
18 / 79
The Pure Mechanical strategy, acting as the active baseline, demonstrated the foundational value of a
simple, rules-based trend-following system. By introducing objective entry, exit, and stop-loss criteria,
it aimed to capture the market's upward trends while protecting against catastrophic losses. The
backtest results confirm it partially succeeded in this goal, generating a Cumulative Return of 27.0%
(2.39% CAGR).
The strategy's primary contribution was in risk reduction. Its Maximum Drawdown was -12.12%, a
significant improvement of approximately 47% compared to the Buy & Hold benchmark. Its
annualized volatility was also substantially lower at 4.82%. This confirms that even a simple system
of rules can effectively mitigate market risk and create a smoother equity curve than a passive
approach. However, the strategy's limitations are revealed in its efficiency metrics. A Profit Factor of
1.14 indicates a very thin edge; for every dollar lost, only $1.14 was gained. This suggests that the
strategy's profitability is fragile and could be easily eroded by small changes in market conditions. Its
low Sharpe Ratio of 0.10 further indicates that its returns were not impressive relative to its volatility.
This strategy is therefore a disciplined but "naive" approach: it treats every technical signal as having
equal validity, regardless of the underlying market context, leaving significant room for improvement
through intelligent filtering.
This strategy tested the hypothesis that an AI trained exclusively on a strategy's own technical
indicators could improve its performance. The results show that the AI learned to be an exceptionally
effective risk manager, but an overly conservative one, prioritizing capital preservation to the detriment
of profit generation.
As
illustrated
in Figure
3.1, the
strategy's
equity
curve is
noticeably
smoother
than the
19 / 79
benchmark, reflecting its defensive posture. The strategy achieved a Cumulative Return of 21.84%,
underperforming both the Buy & Hold and the Pure Mechanical baselines. Its definitive success lies in
its risk profile. The Maximum Drawdown was reduced to just -6.91%, the second-lowest of all
strategies and a remarkable 43% improvement over the Pure Mechanical system. This is further
reflected in its very low annualized volatility of 3.83%.
FIGURE 3.2: MONTHLY RETURNS OF LSTM-EMA-ATR STRATEGY
The
monthly return heat map in Figure 3.2 reinforces this narrative. It shows a pattern of consistent, albeit
small, gains and minimal, contained losses. The worst month was a mere -1.88%, a clear testament to
the AI's ability to filter out high-risk trades. However, the extremely low Sharpe Ratio (0.03) confirms
that the returns were not commensurate with the risk taken. The AI, in its optimization process, learned
to associate certain technical patterns with historical losses so strongly that it developed an extreme risk
aversion. This resulted in "over-filtering," where it successfully avoided bad trades but also incorrectly
rejected a significant number of good trades that did not perfectly match its learned profile of a "safe"
entry.
The Champion strategy, leveraging the behavioral finance filter, was the only active strategy to
successfully solve the risk-return trade-off. It stands as a clear validation of the research's core
hypothesis, outperforming the Pure Mechanical baseline on both an absolute and risk-adjusted basis.
FIGURE 3.3:CUMULATIVE RETURNS OF THE CHAMPION VS. MECHANICAL
BENCHMARK
20 / 79
Figure 3.3 visually encapsulates the Champion's superiority. Its equity curve exhibits a more persistent
and stable upward trajectory with significantly shallower and shorter-lived drawdowns compared to the
mechanical strategy. It delivered a Cumulative Return of 32.49% (2.93% CAGR), making it the
best-performing active strategy by a wide margin. The true power of the strategy, however, is revealed
when this return is viewed in the context of its risk profile. It achieved this outperformance while
exhibiting the lowest risk metrics of all strategies. Its Maximum Drawdown was a mere -5.90%, and
its annualized volatility was the lowest at 3.16%.
This powerful combination of higher returns and lower risk—the primary goal of sophisticated strategy
design—is crystallized in its risk-adjusted metrics. The Champion's Sharpe Ratio of 0.30 is 3x higher
than the mechanical strategy, and its Calmar Ratio of 0.50 is 2.5x higher. This quantitatively proves its
superior efficiency in generating returns for each unit of risk taken. A Profit Factor of 1.44 indicates a
much more robust and statistically significant edge compared to the other active strategies.
FIGURE 3.4: EOY RETURNS OF THE CHAMPION VS. MECHANICAL BENCHMARK
21 / 79
The monthly returns in Figure 3.5 highlight the strategy's remarkable consistency. It posted only three
losing months across the entire backtest period, with the largest being a negligible -1.20%. It also
demonstrated the ability to capture significant upside, with a standout monthly gain of 7.51% in May
2025. This illustrates the practical value of the behavioral filter: by programmatically avoiding
psychologically fraught market conditions, the strategy preserved capital during downturns and was
better positioned with a higher equity base to fully capitalize on stable, high-conviction trends when
they emerged.
22 / 79
The simulation results strongly support the conclusion that the Champion strategy is statistically robust
and possesses a genuine edge.
Positive Expectancy: The simulation projected a 61.09% probability of profit, confirming the
strategy's positive expectancy over thousands of randomized sequences. The
distribution of final equity is visibly skewed to the right, with the mean final equity
(103,495) being higher than the median (103,495)being higher than the median
(100,863), a characteristic of strategies with a healthy number of outlier winning trades.
Robust Risk Profile: The risk metrics were exceptional and validated the backtest
findings. The Mean Maximum Drawdown across all 10,000 simulations was only -
3.65%. More importantly, the 5th percentile final equity was $97,775, providing a
statistical "worst-case" scenario. This suggests there is a 95% probability that the
strategy would avoid a capital loss greater than -2.23% over a similar period, a highly
reassuring figure for risk management.
Performance in Decline: The simulation inherently includes and randomizes the market
decline observed in early 2025. The consistently low drawdown figures across thousands of
scenarios confirm that the strategy's ability to navigate this adverse period was a feature of its
core behavioral filtering logic, not a fortuitous accident of history.
4.5 Chapter Summary
The empirical results presented in this chapter establish a clear and consistent performance hierarchy.
While the unmanaged Buy & Hold strategy yielded the highest nominal return, it came with an
unacceptable level of risk that makes it an impractical benchmark for most investors. Among the active
strategies, the behaviorally-optimized Champion model was the unequivocal victor. It was the only
strategy that succeeded in the primary goal of quantitative trading: to simultaneously increase returns
and decrease risk relative to its baseline. The diagnostic analyses confirmed that its success is rooted in
23 / 79
a robust AI model that excels at identifying stable market conditions and, critically, conservatively
avoids periods of high psychological stress. These objective findings provide a strong empirical
foundation for the interpretive discussion that will follow in Chapter 4.
Chapter 5:Discussion
5.1 Recapitulation and Synthesis of Key Findings
The empirical results presented in Chapter 3 provide a clear and decisive verdict on the central
hypotheses of this research. Before delving into the interpretation of these findings, it is pertinent to
synthesize the primary conclusion: the strategy guided by an AI trained on quantified behavioral
finance signatures—the Champion—demonstrably outperformed all other active and passive strategies
on a risk-adjusted basis. This outcome is not a trivial one; it represents a successful navigation of the
fundamental risk-return trade-off that defines all active investment management. While the passive Buy
& Hold strategy achieved the highest nominal return, it did so at the cost of a severe drawdown that
rendered it practically inferior for any risk-conscious investor. Among the active strategies, a distinct
performance hierarchy was established. The Pure Mechanical strategy provided a baseline of modest
profitability and risk mitigation. The technically-optimized LSTM-EMA-ATR strategy excelled at
capital preservation but at a significant cost to returns, a classic case of suboptimal risk aversion. The
Champion strategy alone succeeded in the dual mandate of increasing returns while simultaneously
decreasing risk relative to the baseline.
This chapter will now move beyond the "what" of these results to explore the "why." It will deconstruct
the performance of each strategy to understand the mechanisms behind their success or failure, directly
address the research questions posed in the introduction with greater depth, critically analyze the
internal decision-making of the Champion AI to deconstruct the source of its "alpha," and discuss the
broader implications and inherent limitations of this study. The central theme that will emerge is that of
"context"—the idea that the Champion's success is owed to its unique ability to understand the
psychological context of market movements, a capability its counterparts fundamentally lack.
5.2 The Superiority of the Behavioral Paradigm: Context is Alpha
The most significant finding of this research is the stark performance differential between the two AI-
driven strategies. Both the LSTM-EMA-ATR and the Champion models were built on the same
underlying deep learning architecture, yet their results were profoundly different. This demonstrates a
critical principle in financial machine learning: the predictive power of a model is not merely a function
of its architectural complexity, but is fundamentally determined by the quality, richness, and, most
importantly, the relevance of the data it is trained on.
The LSTM-EMA-ATR strategy represents a case of "self-referential optimization." By training the AI
exclusively on the strategy's own technical indicators (fast_ma, slow_ma, atr), the model became
exceptionally good at one thing: identifying the technical patterns that historically preceded losing
trades within that specific system. This resulted in a highly effective risk-aversion engine. The model
learned that periods of high ATR (volatility) were often correlated with stop-loss events and
consequently developed an extreme aversion to volatility. The practical outcome was a strategy that
24 / 79
filtered out not only bad trades but also a significant number of profitable trades that exhibited similar
volatility profiles at their inception. It achieved capital preservation by sacrificing alpha, a suboptimal
trade-off. To use an analogy, it is like a driver who, after a few minor accidents in the rain, decides the
best strategy is to never drive when there are clouds in the sky. While safe, this approach is
fundamentally inefficient and fails to achieve its primary objective.
In stark contrast, the Champion strategy was trained on a richer, more contextual dataset. By including
features like multi-period returns, volume ratios, and ATR ratios, it was not merely learning patterns in
indicators; it was learning to recognize the character of market movements. The behavioral labels
provided the crucial context that was missing from the technical model. The AI learned that high
volatility is not monolithically "bad." High volatility in the context of a "Panic" signature is a clear
signal to avoid the market, whereas high volatility in the context of a "FOMO" signature, while also a
no-go for entry, might trigger a trailing stop-loss to protect profits. Most importantly, it learned to
identify the "Herd" signature—a low-volatility, consensus-driven trend—as the optimal environment
for trade entry.
The Champion's success, therefore, stems from its ability to apply context, much like a seasoned
human trader. A human trader does not just see a moving average crossover; they see that crossover
occurring after a period of quiet consolidation (a "Neutral" or "Herd" state) and assign it a higher
conviction. They see the same crossover occurring during a wild, high-volume price chase (a "FOMO"
state) and wisely stand aside. The Champion model learned to replicate this discretionary, context-
aware decision-making process in a purely quantitative and non-discretionary manner. Its
outperformance can be described as the "alpha" generated from understanding and quantifying market
psychology. It effectively functions as a regime-detection engine, capable of distinguishing between
regimes of "calm trending" versus "volatile panic" or "irrational exuberance," and adapting its strategy
accordingly. The other strategies, being regime-agnostic, were fated to underperform as they applied
the same static rules to a dynamic and ever-changing market environment.
5.3 Answering the Research Questions
The empirical results from Chapter 3 provide definitive answers to the three research questions that
guided this study, and the depth of these results allows for nuanced conclusions.
1. Can an LSTM model be effectively trained to classify market behavior using quantified price
action signatures?
Yes. The success of the Champion strategy is, in itself, the affirmative answer to this question. The
model's ability to produce superior risk-adjusted returns demonstrates that the heuristic-based labeling
of behavioral states captured a genuine, exploitable market dynamic. The efficacy is proven not just by
the final positive P&L, but more profoundly by its ability to generate a high Calmar Ratio (0.50). This
metric directly proves that the model learned to classify risk regimes effectively, as it consistently
guided the strategy to avoid the large drawdowns that plagued its counterparts. The model did not just
learn to make money; it learned how to avoid losing it, which in quantitative finance, are two sides of
the same critical coin.
25 / 79
2. Does a strategy filtered by this behavioral AI (the Champion) yield superior risk-adjusted
returns compared to a purely mechanical strategy?
Yes, unequivocally. The Champion strategy outperformed the Pure Mechanical baseline across every
key metric of efficiency and robustness. It increased the cumulative return by over 5 percentage points
(32.49% vs. 27.0%) while simultaneously cutting the maximum drawdown by nearly half (-5.90% vs. -
12.12%). It achieved this by acting as an intelligent filter, selectively participating in fewer, but higher-
quality, trades. While the mechanical strategy took every signal generated by the EMA crossover, the
Champion acted as a patient sniper, waiting for the ideal behavioral setup—a persistent "Herd" state—
before committing capital. This patience resulted in a significantly higher Profit Factor (1.44 vs. 1.14),
indicating that the quality of its wins was substantially better relative to its losses.
3. Does the Champion strategy also outperform a second LSTM model (LSTM-EMA-ATR) that
is trained only on the traditional technical indicators of the mechanical strategy?
Yes, decisively. This is arguably the most important finding of the dissertation, as it highlights the
limitations of a narrowly focused AI. The Champion's outperformance against the LSTM-EMA-ATR
strategy (32.49% return vs. 21.84%) proves that the informational advantage of the dataset is the
primary driver of success. The LSTM-EMA-ATR model, despite being a sophisticated deep learning
tool, could only optimize based on the limited information it was given. Its universe of knowledge
consisted only of three correlated indicators. In contrast, the Champion was provided with a dataset that
was not just richer in feature count, but richer in concept. The behavioral labels provided a proxy for a
latent variable—market psychology—that the technical indicators alone could not capture. The
Champion's outperformance, therefore, is a direct result of this superior informational dataset. It
demonstrates that simply applying an AI to a problem is not a panacea; the true value is unlocked by
providing the AI with a more profound and context-aware understanding of the market environment it
is tasked with navigating.
26 / 79
systematically filters out the ambiguous and volatile conditions where mechanical systems are most
prone to "whipsaw" losses. It has learned that the cost of missing a potential opportunity in an uncertain
environment is far lower than the cost of participating in a losing trade.
A backtest, while essential, represents only one possible path through history. The Monte Carlo
simulation provides a crucial statistical validation of the Champion's robustness by stress-testing its
performance across 10,000 randomized paths. The results confirm that the strategy's edge is statistically
significant and not an artifact of historical luck.
The projected 61.09% probability of profit and the mean maximum drawdown of just -3.65% are
powerful indicators of a resilient strategy. This low mean drawdown, in particular, is a stunning result.
It suggests that the strategy's capital preservation capabilities are not a fluke but an intrinsic, repeatable
characteristic of its behavioral filtering logic. The 5th percentile equity result, showing a high
probability of avoiding a loss of more than -2.23%, provides a statistically grounded floor for risk
expectations. A Monte Carlo simulation performed on the Pure and LSTM+Mechanical strategy, by
contrast, would likely show a much wider and more dangerous distribution of outcomes, with a
significantly higher mean drawdown and a lower 5th percentile equity value.
These findings demonstrate that the strategy's core logic—filtering trades through a behavioral lens—is
sound and likely to hold up under different sequences of market events. It provides statistical
confidence that the strategy's capital preservation capabilities, especially its stellar performance during
the market decline in early 2025, are an intrinsic feature of its design, not a fortuitous accident of
history.
5.4.1 An Analysis of Strategy Failures: When the Champion Was Wrong
A complete and critical analysis of a trading strategy requires not only an examination of its successes
but also a rigorous investigation of its failures. While the Champion strategy demonstrated a high profit
factor and a robust equity curve, it was not infallible. The backtest contained a number of losing trades,
and these instances, though fewer in number and smaller in magnitude, offer invaluable insights into
the model's limitations and the inherent probabilistic nature of financial markets. An analysis of these
failures reveals two primary categories of error.
The first, and more common, type of failure can be classified as "Correct Entry, Unpredictable
Outcome." In these instances, the Champion AI correctly identified a stable "Herd" state that persisted
for the required three-hour filter, triggering a valid entry signal. The trade was initiated based on a
sound, data-driven hypothesis that a low-volatility trend was underway. However, the subsequent price
action failed to evolve as expected. These failures were typically triggered by exogenous shocks that
were, by definition, unknowable to the model given its endogenous, price-action-based feature set.
Such a shock could be a sudden geopolitical news event, an unexpected macroeconomic data release,
or a sudden, sharp reversal in a correlated asset that triggered a cascade of algorithmic selling. In these
scenarios, the AI made the "correct" decision based on the information available up to that point, but
the market's probabilistic nature resulted in an adverse outcome. The critical takeaway from these
failures is not that the AI was flawed, but that the strategy's risk management—the 2x ATR stop-loss—
functioned exactly as intended. It provided a necessary fail-safe, containing the loss and preserving
27 / 79
capital in the face of an unpredictable event. These losses are simply the cost of doing business in a
non-deterministic environment.
The second, more insightful, type of failure can be classified as "Incorrect Entry, Negative
Outcome." These represent genuine classification errors by the AI model. In these cases, the model
incorrectly identified a market condition as a stable "Herd" state when it was, in fact, something else—
typically the beginning of a volatile "whipsaw" period or a "bull trap" that preceded a sharp reversal.
An examination of the price action during these failed entries often reveals ambiguous patterns. For
example, a market might experience a brief lull in volatility and a slight upward drift after a sharp
decline, which the AI, with its 60-hour lookback, might misinterpret as the beginning of a new "Herd"
trend. This is a classic example of a model's limited temporal context; it mistakes a short-term pattern
for a long-term regime shift.
These errors align with the findings from the confusion matrix. They likely occur at the "boundaries"
between behavioral states—for instance, when a "Correction" is transitioning into a "Neutral" state, but
underlying selling pressure remains. The AI, seeing the volatility subside, makes a premature
classification. These failures highlight the primary limitation of the model: its performance is entirely
dependent on the clarity and accuracy of the patterns within its lookback window. However, the low
frequency and, crucially, the small average dollar loss of these trades compared to the average winning
trade, are what ultimately lead to the strategy's positive expectancy and high profit factor. The analysis
of these failures, therefore, does not invalidate the strategy; rather, it reinforces the conclusion that the
Champion's edge comes from being right most of the time in high-conviction setups, and being wrong
in a small and financially manageable way when conditions are ambiguous.
28 / 79
Long-Only Bias: All strategies operated on a long-only basis. The framework did not explore
short-selling during states classified as "Panic." The model learned to identify a prime shorting
opportunity but was only programmed to use it as a defensive signal to exit long positions. A
significant extension of this research would be to train the AI to not only avoid long entries
during panic but to actively initiate short positions, potentially transforming a risk management
feature into a powerful, alpha-generating opportunity.
Model Architecture and Parameter Sensitivity: While the stacked LSTM architecture proved
effective, the field of deep learning is constantly evolving. Future iterations could explore more
advanced architectures like Transformers, whose "attention mechanism" could be powerful for
identifying which specific moments within the 60-hour lookback are most influential for a
classification. Additionally, the thresholds used in the strategies (e.g., the 0.42 confidence level,
the 3-hour persistence filter) were calibrated on the validation set. These parameters might be
subject to "alpha decay" and may need to be periodically re-calibrated to adapt to changing
long-term market dynamics.
Chapter 6: Conclusion
6.1 Summary of the Research Journey and Key Findings
This dissertation embarked on an investigation into a critical and often-overlooked limitation of
modern AI-driven trading systems: their inherent inability to comprehend and react to the
psychological state of the market. The research was motivated by the central hypothesis that a trading
model's performance, particularly its ability to manage risk, could be significantly enhanced by
endowing it with a quantitative understanding of the behavioral finance concepts that govern market
dynamics. To test this hypothesis, a novel deep learning model, the "Champion," was developed. Its
innovation lay not in its architecture, but in its training: it was taught to classify the market into distinct
psychological states—such as Panic, FOMO, and Herd Behavior—derived from quantified price action
signatures.
29 / 79
To rigorously evaluate the efficacy of this behavioral approach, a multi-layered comparative backtest
was conducted on a completely untouched, out-of-sample dataset. The Champion's performance was
measured against three distinct and progressively complex benchmarks:
1. A passive Buy & Hold strategy, representing the raw market return.
2. A Pure Mechanical strategy, representing a standard, rules-based trend-following system.
3. An LSTM-EMA-ATR strategy, representing a technically-focused AI model optimized on the
mechanical system's own indicators.
The empirical results, presented and analyzed in the preceding chapters, were both clear and decisive.
The Buy & Hold strategy, while delivering the highest nominal return (36.75%), came with an
untenable maximum drawdown of -23.09%, highlighting the profound risk of a passive approach.
Among the active strategies, a clear performance hierarchy emerged. The Pure Mechanical strategy
established a baseline with a 27.0% return and a -12.12% drawdown. The LSTM-EMA-ATR model
successfully reduced this drawdown to -6.91% but did so by sacrificing profitability, with its return
falling to 21.84%.
The Champion strategy was the unequivocal victor. It was the only strategy that achieved the primary
goal of sophisticated quantitative trading: the simultaneous improvement of both returns and risk. It
delivered a superior cumulative return of 32.49% while concurrently reducing the maximum drawdown
to a best-in-class -5.90%. This superior risk-adjusted performance was further validated by a 10,000-
iteration Monte Carlo simulation, which confirmed the statistical robustness of its edge and its
remarkable capital preservation capabilities.
6.2 Contribution to the Field of Quantitative Finance
This dissertation makes several key contributions to the theory and practice of quantitative finance at
the intersection of artificial intelligence and behavioral science.
First, it provides a novel and replicable methodological framework for quantifying abstract
behavioral finance concepts. While the influence of market psychology is widely acknowledged, it
has remained a largely qualitative field of study. This research bridges that gap by translating subjective
states like "herd behavior" into an objective, machine-readable set of heuristics based on price action,
volatility, and volume dynamics. This "behavioral labeling" process serves as a template for future
research, providing a practical method for creating new, context-rich datasets for financial machine
learning.
Second, this study offers definitive empirical evidence that a behaviorally-aware AI outperforms a
technically-focused AI. This is arguably the most significant contribution. By running a direct, apples-
to-apples comparison between two identically architected LSTM models trained on different
conceptual datasets, the research proves that the informational advantage of the data is the primary
driver of superior performance. It demonstrates that the future of financial AI is not solely dependent
on developing more complex algorithms, but on feeding those algorithms with more intelligent,
context-aware data. The alpha generated by the Champion strategy was not technical alpha; it was
contextual alpha.
30 / 79
Third, this research validates the practical application of "inaction as a strategy." The diagnostic
analysis of the Champion's confusion matrix revealed that a key component of its success was its
conservative bias and its tendency to default to inaction during periods of high uncertainty. This
provides a quantitative validation of the discretionary wisdom practiced by human traders: "when in
doubt, stay out." By showing that an AI can learn and profitably apply this principle, this study
contributes a valuable insight into the design of robust, risk-averse automated trading systems.
6.3 Practical Implications for the Industry
The findings of this research have significant practical implications for various stakeholders within the
financial industry.
For Quantitative Analysts and Strategy Developers: The primary takeaway is the immense
value of creative feature engineering. This study demonstrates that a significant edge can be
gained by moving beyond standard technical indicators and incorporating novel features that act
as proxies for latent market factors, such as investor sentiment. It encourages a more
interdisciplinary approach to strategy design, where insights from psychology and behavioral
science are not just theoretical but are actively translated into quantitative inputs.
For Portfolio and Risk Managers: The Champion model serves as a powerful proof-of-
concept for a dynamic risk management overlay. A behaviorally-aware AI could be deployed
not necessarily to generate its own trading signals, but to act as a firm-wide risk "governor." It
could, for instance, systematically reduce leverage or tighten risk limits across all strategies
when it detects a shift from a "Herd" to a "Panic" regime, thereby providing an automated,
objective layer of capital preservation that is reactive to real-time market character rather than
static VaR models.
For the FinTech and AI Development Community: This research highlights a promising
direction for the next generation of financial technologies. It suggests a move away from purely
predictive models ("what will the price be?") towards classificatory, context-aware models
("what is the market doing now?"). This reframing of the problem is more robust and has a
higher probability of yielding practical, real-world applications in areas like algorithmic
execution, dynamic asset allocation, and automated risk management.
6.4 Concluding Remarks: From Bias to Alpha
This dissertation began with a simple premise: that the cognitive biases and emotional responses of
human market participants, which are often viewed as sources of irrationality and risk, could be
systematically quantified and transformed into a source of alpha. The journey from that initial
hypothesis to the final, robust performance of the Champion strategy has provided a compelling
validation of this idea.
The research has demonstrated that by teaching an AI to recognize the signatures of human behavior in
price action, we can create a strategy that is not only profitable but is also intelligent in its management
of risk. It learned to be patient, waiting for the high-conviction trends of a confident "Herd." It learned
to be disciplined, cutting trades immediately when the psychological context deteriorated into "Panic"
31 / 79
or "Correction." And perhaps most importantly, it learned a form of quantitative humility, choosing to
stand aside when the market's signals were ambiguous.
The successful outcome of the Champion strategy is a testament to the power of an interdisciplinary
approach. It affirms that the most advanced trading systems of the future may not be those with the
most complex algorithms, but those with the deepest and most nuanced understanding of the human
element that will always be at the heart of the market. This study has shown that by turning a lens on
the market's biases, it is possible to create a strategy with a definitive and durable edge. It has, in
essence, provided a quantitative pathway to turn market bias into measurable alpha.
References
Fischer, T., & Krauss, C. (2018). Deep learning with long short-term memory networks for financial
market predictions. European Journal of Operational Research, 270(2), 764-779.
Heaton, J., Polson, N. G., & Witte, J. H. (2017). Deep learning for finance: Deep portfolios. Applied
Stochastic Models in Business and Industry, 33(1), 3-12.
Kahneman, D., & Tversky, A. (1979). Prospect theory: An analysis of decision under risk.
Econometrica, 47(2), 263–291.
Kirkpatrick, C. G., & Dahlquist, J. R. (2016). Technical analysis: The complete resource for financial
market technicians (3rd ed.). FT Press.
Shleifer, A. (2000). Inefficient markets: An introduction to behavioral finance. Oxford University Press.
Fischer, T., & Krauss, C. (2018). Deep learning with long short-term memory networks for financial
market predictions. European Journal of Operational Research, 270(2), 764-779.
Heaton, J., Polson, N. G., & Witte, J. H. (2017). Deep learning for finance: Deep portfolios. Applied
Stochastic Models in Business and Industry, 33(1), 3-12.
Kahneman, D., & Tversky, A. (1979). Prospect theory: An analysis of decision under risk.
Econometrica, 47(2), 263–291.
32 / 79
Kirkpatrick, C. G., & Dahlquist, J. R. (2016). Technical analysis: The complete resource for financial
market technicians (3rd ed.). FT Press.
Shleifer, A. (2000). Inefficient markets: An introduction to behavioral finance. Oxford University Press.
Fischer, T., & Krauss, C. (2018). Deep learning with long short-term memory networks for financial
market predictions. European Journal of Operational Research, 270(2), 764-779.
Heaton, J., Polson, N. G., & Witte, J. H. (2017). Deep learning for finance: Deep portfolios. Applied
Stochastic Models in Business and Industry, 33(1), 3-12.
Kahneman, D., & Tversky, A. (1979). Prospect theory: An analysis of decision under risk.
Econometrica, 47(2), 263–291.
Kirkpatrick, C. G., & Dahlquist, J. R. (2016). Technical analysis: The complete resource for financial
market technicians (3rd ed.). FT Press.
Shleifer, A. (2000). Inefficient markets: An introduction to behavioral finance. Oxford University Press.
Fischer, T., & Krauss, C. (2018). Deep learning with long short-term memory networks for financial
market predictions. European Journal of Operational Research, 270(2), 764-779.
Heaton, J., Polson, N. G., & Witte, J. H. (2017). Deep learning for finance: Deep portfolios. Applied
Stochastic Models in Business and Industry, 33(1), 3-12.
Kahneman, D., & Tversky, A. (1979). Prospect theory: An analysis of decision under risk.
Econometrica, 47(2), 263–291.
Kirkpatrick, C. G., & Dahlquist, J. R. (2016). Technical analysis: The complete resource for financial
market technicians (3rd ed.). FT Press.
Shleifer, A. (2000). Inefficient markets: An introduction to behavioral finance. Oxford University Press.
33 / 79
References
Fischer, T., & Krauss, C. (2018). Deep learning with long short-term memory networks for financial
market predictions. European Journal of Operational Research, 270(2), 764-779.
Heaton, J., Polson, N. G., & Witte, J. H. (2017). Deep learning for finance: Deep portfolios. Applied
Stochastic Models in Business and Industry, 33(1), 3-12.
Kahneman, D., & Tversky, A. (1979). Prospect theory: An analysis of decision under risk.
Econometrica, 47(2), 263–291.
Kirkpatrick, C. G., & Dahlquist, J. R. (2016). Technical analysis: The complete resource for financial
market technicians (3rd ed.). FT Press.
Shleifer, A. (2000). Inefficient markets: An introduction to behavioral finance. Oxford University Press.
References
Fischer, T., & Krauss, C. (2018). Deep learning with long short-term memory networks for financial
market predictions. European Journal of Operational Research, 270(2), 764-779.
Heaton, J., Polson, N. G., & Witte, J. H. (2017). Deep learning for finance: Deep portfolios. Applied
Stochastic Models in Business and Industry, 33(1), 3-12.
Kahneman, D., & Tversky, A. (1979). Prospect theory: An analysis of decision under risk.
Econometrica, 47(2), 263–291.
Kirkpatrick, C. G., & Dahlquist, J. R. (2016). Technical analysis: The complete resource for financial
market technicians (3rd ed.). FT Press.
Shleifer, A. (2000). Inefficient markets: An introduction to behavioral finance. Oxford University Press.
References
Fischer, T., & Krauss, C. (2018). Deep learning with long short-term memory networks for financial
market predictions. European Journal of Operational Research, 270(2), 764-779.
Heaton, J., Polson, N. G., & Witte, J. H. (2017). Deep learning for finance: Deep portfolios. Applied
Stochastic Models in Business and Industry, 33(1), 3-12.
Kahneman, D., & Tversky, A. (1979). Prospect theory: An analysis of decision under risk.
Econometrica, 47(2), 263–291.
34 / 79
Kirkpatrick, C. G., & Dahlquist, J. R. (2016). Technical analysis: The complete resource for financial
market technicians (3rd ed.). FT Press.
Shleifer, A. (2000). Inefficient markets: An introduction to behavioral finance. Oxford University Press.
APENDIX :
STEP 1 TEXTBOOK - DATA PREPARATION
# =====================================================================
# Step 1 (Definitive Version): Create the Labeled Textbook
# =====================================================================
# This script loads the raw 85% data and calculates all features and la
# saving the result to a new file for the next step.
# =====================================================================
import pandas as pd
import numpy as np
import sys
35 / 79
print("--- Calculating all features and labels... ---")
# ... (This is the full labeling logic from your original script)
fast_ma_period, slow_ma_period = 20, 50
df['fast_ma'] = df['Close'].rolling(window=fast_ma_period).mean()
df['slow_ma'] = df['Close'].rolling(window=slow_ma_period).mean()
lookback_window = 60
df['tr1'] = df['High'] - df['Low']
df['tr2'] = [Link](df['High'] - df['Close'].shift(1))
df['tr3'] = [Link](df['Low'] - df['Close'].shift(1))
df['true_range'] = df[['tr1', 'tr2', 'tr3']].max(axis=1)
df['atr'] = df['true_range'].rolling(window=14).mean()
df['return_2H'] = df['Close'].pct_change(periods=2)
df['return_5H'] = df['Close'].pct_change(periods=5)
df['return_60H'] = df['Close'].pct_change(periods=lookback_window)
df['volume_ratio'] = df['Volume'] / df['Volume'].rolling(window=lookbac
df['atr_ratio'] = df['atr'] / df['atr'].rolling(window=lookback_window)
[Link](inplace=True)
fomo_return_threshold = df['return_5H'].quantile(0.99)
correction_return_threshold = df['return_2H'].quantile(0.05)
capitulation_return_threshold = df['return_5H'].quantile(0.01)
df['psychological_label'] = 'Neutral'
fomo_condition = ((df['return_5H'] > fomo_return_threshold) & (df['retu
[Link][fomo_condition, 'psychological_label'] = 'FOMO'
capitulation_condition = ((df['return_5H'] < capitulation_return_thresh
downtrend_regime_condition = ((df['fast_ma'] < df['slow_ma'] * 0.995) &
[Link][capitulation_condition | downtrend_regime_condition, 'psychologi
base_correction_condition = ((df['return_2H'] < correction_return_thres
is_new_event_condition = ((df['psychological_label'].shift(1) != 'Corre
[Link][base_correction_condition & is_new_event_condition, 'psychologic
herd_condition = ((df['Close'] > df['slow_ma']) & (df['atr_ratio'] < 0.
[Link][herd_condition, 'psychological_label'] = 'Herd'
print("Feature and label calculation complete.")
36 / 79
#
========================================================
======================
# This script loads the file created by Step 1 and performs the 80/20 split,
# creating the final .npy files for model training.
#
========================================================
======================
import pandas as pd
import numpy as np
from [Link] import MinMaxScaler, LabelEncoder
import sys
# --- 1. Load the LABELED Data (The file created by Step 1) ---
LABELED_DATA_FILE = 'labeled_data_85_percent.csv' # <-- THIS IS THE CRITICAL CHANGE
print(f"--- Loading LABELED data from '{LABELED_DATA_FILE}' ---")
try:
df = pd.read_csv(LABELED_DATA_FILE, index_col='Datetime', parse_dates=True)
except FileNotFoundError:
print(f"FATAL ERROR: The file '{LABELED_DATA_FILE}' was not found. Please run Step 1 first.")
[Link](1)
print("Labeled data loaded successfully.")
37 / 79
# --- 5. Scale the Feature Data ---
scaler = MinMaxScaler(feature_range=(0, 1))
[Link](train_df[feature_columns])
train_X_scaled = [Link](train_df[feature_columns])
test_X_scaled = [Link](test_df[feature_columns])
print("Numerical features scaled successfully.")
lookback_window = 60
X_train, y_train = create_sequences(train_X_scaled, train_y_encoded, lookback_window)
X_test, y_test = create_sequences(test_X_scaled, test_y_encoded, lookback_window)
print(f"\nSequences created.")
38 / 79
#
========================================================
======================
# Step 3 (Definitive Final Backtest): Full Frictions and Reporting
#
========================================================
======================
# This is the definitive backtesting script. It runs the final, unbiased model
# on the completely separate, untouched out-of-sample test data to generate
# the final dissertation results.
#
========================================================
======================
import pandas as pd
import numpy as np
import tensorflow as tf
from [Link] import MinMaxScaler
import quantstats as qs
import [Link] as plt
import sys
39 / 79
# --- 3. "Translate" the Test Data: Calculate All Features from Scratch ---
print("\n--- Calculating all indicators on the test set from scratch... ---")
# A. Benchmark Indicators
fast_ma_period, slow_ma_period = 20, 50
test_df['fast_ma'] = test_df['Close'].rolling(window=fast_ma_period).mean()
test_df['slow_ma'] = test_df['Close'].rolling(window=slow_ma_period).mean()
test_df['buy_signal'] = (test_df['fast_ma'] > test_df['slow_ma']) & (test_df['fast_ma'].shift(1)
<= test_df['slow_ma'].shift(1))
test_df['sell_signal'] = (test_df['fast_ma'] < test_df['slow_ma']) & (test_df['fast_ma'].shift(1)
>= test_df['slow_ma'].shift(1))
# B. AI Features
lookback_window = 60
test_df['tr1'] = test_df['High'] - test_df['Low']
test_df['tr2'] = [Link](test_df['High'] - test_df['Close'].shift(1))
test_df['tr3'] = [Link](test_df['Low'] - test_df['Close'].shift(1))
test_df['true_range'] = test_df[['tr1', 'tr2', 'tr3']].max(axis=1)
test_df['atr'] = test_df['true_range'].rolling(window=14).mean()
test_df['return_2H'] = test_df['Close'].pct_change(periods=2)
test_df['return_5H'] = test_df['Close'].pct_change(periods=5)
test_df['return_60H'] = test_df['Close'].pct_change(periods=lookback_window)
test_df['volume_ratio'] = test_df['Volume'] /
test_df['Volume'].rolling(window=lookback_window).mean()
test_df['atr_ratio'] = test_df['atr'] / test_df['atr'].rolling(window=lookback_window).mean()
#
========================================================
======================
# --- 5. Backtest 1: Enhanced Benchmark Strategy ---
40 / 79
#
========================================================
======================
print("\n--- Running Backtest 1: Enhanced Benchmark Strategy ---")
position = 0
entry_price = 0
stop_loss_price = 0
benchmark_equity = [INITIAL_CAPITAL]
benchmark_equity.append(current_capital)
#
========================================================
======================
# --- 6. Backtest 2: The "True Champion" AI Strategy ---
#
========================================================
======================
41 / 79
print("\n--- Running Backtest 2: The 'True Champion' Strategy ---")
position = 0
entry_price = 0
stop_loss_price = 0
champion_equity = []
ai_state_history = []
persistence_filter = 3
for i in range(len(test_df)):
current_price = test_df['Close'].iloc[i]
previous_price = test_df['Close'].iloc[i-1] if i > 0 else current_price
current_capital = champion_equity[-1] if champion_equity else INITIAL_CAPITAL
# Get AI prediction
data_window = test_df[feature_columns].iloc[i-lookback_window:i]
ai_state = get_ai_prediction(data_window, model, scaler, label_classes)
42 / 79
stop_loss_price = entry_price - (2 * test_df['atr'].iloc[i])
champion_equity.append(current_capital)
#
========================================================
======================
# --- 7. Performance Analysis and Visualization ---
#
========================================================
======================
print("\n--- Performance Analysis ---")
benchmark_made_trades = (benchmark_returns != 0).any()
champion_made_trades = (champion_returns != 0).any()
if benchmark_made_trades or champion_made_trades:
print("At least one strategy was active. Generating final comparative HTML report...")
[Link](
champion_returns,
benchmark=benchmark_returns,
output='final_comparison_report.html',
title='The True Champion AI vs. Benchmark',
rf=RISK_FREE_RATE
)
print("\nSaved 'final_comparison_report.html'")
[Link]('dark_background')
fig, ax = [Link](figsize=(14, 7))
43 / 79
print("\nDisplaying final equity curve comparison plot...")
[Link]()
else:
print("\n" + "="*50)
print("CRITICAL FINDING: Neither strategy made any trades during the backtest period.")
print("This is a valid scientific result indicating the entry conditions were not met.")
print("="*50 + "\n")
import numpy as np
import tensorflow as tf
from [Link] import classification_report, confusion_matrix
import [Link] as plt
import seaborn as sns
import sys
try:
# Load the saved Keras model
44 / 79
model = [Link].load_model('best_psychology_model.keras')
# Load the test data arrays
X_test = [Link]('X_test.npy')
y_test = [Link]('y_test.npy')
# Load the label names for our reports
label_classes = [Link]('label_encoder.npy', allow_pickle=True)
except (FileNotFoundError, IOError) as e:
print(f"FATAL ERROR: Could not load necessary files. {e}")
print("Please ensure 'best_psychology_model.keras' and the .npy files are in the directory.")
[Link](1)
# The model outputs probabilities for each class (e.g., [0.1, 0.05, 0.7, 0.1, 0.05])
y_pred_probs = [Link](X_test)
45 / 79
[Link]('Confusion Matrix: Model Predictions vs. True Labels', fontsize=16)
[Link]('True Label', fontsize=12)
[Link]('Predicted Label', fontsize=12)
[Link]()
46 / 79
TEST_DATA_FILE = '/home/tripled/backtest_data/OUT OF SAMPLE TEST 15 [Link]'
#
========================================================
======================
# --- 8. FASTER True Monte Carlo Simulation (Vectorized & Batched) ---
#
========================================================
======================
print("\n--- Running FASTER True (Path-Generating) Monte Carlo Simulation ---")
47 / 79
log_returns = [Link](test_df['Close'] / test_df['Close'].shift(1))
mu = log_returns.mean()
sigma = log_returns.std()
initial_price = test_df['Close'].iloc[0]
simulation_days = len(test_df)
# =================================================
n_simulations = 10000 # <--- THE ONLY CHANGE
# =================================================
equity_curves = []
final_equities_gbm = []
print(f"Running {n_simulations} full backtest simulations (optimized)...")
print("NOTE: This will take a significant amount of time. Please be patient.")
for i in tqdm(range(n_simulations)):
synthetic_prices = [initial_price]
for _ in range(1, simulation_days):
dt = 1
random_shock = [Link](0, 1)
price_t = synthetic_prices[-1] * [Link]((mu - 0.5 * sigma**2) * dt + sigma * [Link](dt) *
random_shock)
synthetic_prices.append(price_t)
synthetic_df = [Link](synthetic_prices, index=test_df.index, columns=['Close'])
price_volatility = synthetic_df['Close'].pct_change().std() * 0.5
synthetic_df['High'] = synthetic_df['Close'] * (1 + [Link](0, price_volatility,
size=len(synthetic_df)))
synthetic_df['Low'] = synthetic_df['Close'] * (1 - [Link](0, price_volatility,
size=len(synthetic_df)))
synthetic_df['Volume'] = [Link](test_df['Volume'], size=len(synthetic_df),
replace=True)
synthetic_df['tr1'] = synthetic_df['High'] - synthetic_df['Low']
synthetic_df['tr2'] = [Link](synthetic_df['High'] - synthetic_df['Close'].shift(1))
synthetic_df['tr3'] = [Link](synthetic_df['Low'] - synthetic_df['Close'].shift(1))
synthetic_df['true_range'] = synthetic_df[['tr1', 'tr2', 'tr3']].max(axis=1)
synthetic_df['atr'] = synthetic_df['true_range'].rolling(window=14).mean()
synthetic_df['return_2H'] = synthetic_df['Close'].pct_change(periods=2)
synthetic_df['return_5H'] = synthetic_df['Close'].pct_change(periods=5)
synthetic_df['return_60H'] = synthetic_df['Close'].pct_change(periods=lookback_window)
synthetic_df['volume_ratio'] = synthetic_df['Volume'] /
synthetic_df['Volume'].rolling(window=lookback_window).mean()
synthetic_df['atr_ratio'] = synthetic_df['atr'] /
synthetic_df['atr'].rolling(window=lookback_window).mean()
synthetic_df.dropna(inplace=True)
if len(synthetic_df) < lookback_window: continue
feature_data = synthetic_df[feature_columns].values
batched_windows = create_batched_windows(feature_data, lookback_window)
48 / 79
n_samples, window_len, n_features = batched_windows.shape
reshaped_for_scaling = batched_windows.reshape(n_samples * window_len, n_features)
reshaped_for_scaling[~[Link](reshaped_for_scaling)] = 0
scaled_features = [Link](reshaped_for_scaling)
scaled_windows = scaled_features.reshape(n_samples, window_len, n_features)
prediction_probs = [Link](scaled_windows, verbose=0, batch_size=2048) # Increased
batch size for performance
predicted_indices = [Link](prediction_probs, axis=1)
all_ai_states = label_classes[predicted_indices]
position, entry_price, stop_loss_price = 0, 0, 0
champion_equity_sim = [INITIAL_CAPITAL] * lookback_window
ai_state_history = []
persistence_filter = 3
for j in range(len(all_ai_states)):
sim_idx = j + lookback_window - 1
current_price = synthetic_df['Close'].iloc[sim_idx]
previous_price = synthetic_df['Close'].iloc[sim_idx - 1]
current_capital = champion_equity_sim[-1]
if position == 1: current_capital *= (current_price / previous_price)
ai_state = all_ai_states[j]
if position == 1 and (current_price <= stop_loss_price or ai_state in ['Panic', 'Correction']):
exit_price = stop_loss_price if current_price <= stop_loss_price else current_price
current_capital = champion_equity_sim[-1] * (exit_price / previous_price)
current_capital *= (1 - COMMISSION_RATE)
position = 0
if position == 0:
ai_state_history.append(ai_state)
if len(ai_state_history) > persistence_filter: ai_state_history.pop(0)
is_stable_herd = (len(ai_state_history) == persistence_filter and all(s == 'Herd' for s in
ai_state_history))
if is_stable_herd:
position = 1
entry_price = current_price
current_capital *= (1 - COMMISSION_RATE)
stop_loss_price = entry_price - (2 * synthetic_df['atr'].iloc[sim_idx])
if position == 1 and ai_state in ['Herd', 'FOMO']:
new_trailing_stop = current_price - (1 * synthetic_df['atr'].iloc[sim_idx])
stop_loss_price = max(stop_loss_price, new_trailing_stop)
champion_equity_sim.append(current_capital)
final_equities_gbm.append(champion_equity_sim[-1])
equity_curves.append(champion_equity_sim)
#
========================================================
======================
# --- 9. Comprehensive Analysis Suite with Risk-Reward Profiling ---
49 / 79
#
========================================================
======================
print("\nGenerating comprehensive analysis dashboard with Risk-Reward plot...")
[Link]('dark_background')
fig, axes = [Link](2, 2, figsize=(20, 16), gridspec_kw={'height_ratios': [2, 2]})
[Link]('Comprehensive Monte Carlo Analysis (10000 Simulations)', fontsize=24)
ax1 = axes[0, 0]
[Link](final_equities_gbm, bins=100, color='royalblue', alpha=0.8, edgecolor='white',
linewidth=0.5) # More bins for smoother plot
[Link](INITIAL_CAPITAL, color='yellow', linestyle='-', linewidth=2, label=f'Initial Capital:
${INITIAL_CAPITAL:,.2f}')
[Link](mean_final_equity, color='red', linestyle='--', linewidth=2, label=f'Mean: $
{mean_final_equity:,.2f}')
[Link](median_final_equity, color='lime', linestyle=':', linewidth=3, label=f'Median: $
{median_final_equity:,.2f}')
[Link](percentile_5, color='orange', linestyle='--', linewidth=2, label=f'5th Percentile: $
{percentile_5:,.2f}')
[Link](percentile_95, color='cyan', linestyle='--', linewidth=2, label=f'95th Percentile: $
{percentile_95:,.2f}')
ax1.set_title('Distribution of Final Equity', fontsize=16)
ax1.set_xlabel('Final Portfolio Value ($)', fontsize=12)
ax1.set_ylabel('Frequency', fontsize=12)
[Link](loc='upper right')
[Link](True, linestyle='--', alpha=0.2)
ax2 = axes[0, 1]
for i, curve in enumerate(equity_curves[:200]): # Show more sample paths
[Link](curve, color='cyan', alpha=0.1)
[Link](equity_curves[0], color='cyan', alpha=0.5, label='Sample Paths')
[Link](INITIAL_CAPITAL, color='yellow', linestyle='-', linewidth=2, label='Initial Capital')
50 / 79
ax2.set_title('Sample of Simulated Equity Paths', fontsize=16)
ax2.set_xlabel('Trading Periods', fontsize=12)
ax2.set_ylabel('Portfolio Value ($)', fontsize=12)
[Link](loc='upper left')
[Link](True, linestyle='--', alpha=0.2)
ax3 = axes[1, 0]
colors = final_returns
scatter = [Link](max_drawdowns_pct, final_returns, c=colors, cmap='viridis', alpha=0.5,
s=15) # smaller points
cbar = [Link](scatter, ax=ax3)
cbar.set_label('Final Return (%)', fontsize=10)
[Link](0, color='white', linestyle='--', linewidth=1, alpha=0.5)
[Link](0, color='white', linestyle='--', linewidth=1, alpha=0.5)
mean_dd = [Link](max_drawdowns_pct)
mean_ret = [Link](final_returns)
[Link](mean_dd, mean_ret, color='red', s=150, edgecolor='white', zorder=5,
label=f'Mean Outcome\n(DD: {mean_dd:.2f}%, Ret: {mean_ret:.2f}%)')
ax3.set_title('Risk vs. Reward Profile', fontsize=16)
ax3.set_xlabel('Maximum Drawdown During Simulation (%)', fontsize=12)
ax3.set_ylabel('Final Return (%)', fontsize=12)
[Link](loc='lower left')
[Link](True, linestyle='--', alpha=0.2)
ax4 = axes[1, 1]
[Link]('off')
stats_text = (
f"--- Key Performance Indicators ---\n\n"
f"Probability of Profit: {probability_of_profit:.2f}%\n\n"
f"Mean Final Equity: ${mean_final_equity:,.2f}\n"
f"Mean Return: {mean_ret:.2f}%\n\n"
f"Median Final Equity: ${median_final_equity:,.2f}\n"
f"Median Return: {(median_final_equity/INITIAL_CAPITAL - 1):.2%}\n\n"
f"5th Percentile Equity: ${percentile_5:,.2f}\n"
f"95th Percentile Equity: ${percentile_95:,.2f}\n\n"
f"Mean Maximum Drawdown: {mean_dd:.2f}%\n"
f"Median Maximum Drawdown: {[Link](max_drawdowns_pct):.2f}%"
)
[Link](0.5, 0.5, stats_text, fontsize=14, ha='center', va='center',
bbox=dict(boxstyle='round', facecolor='black', alpha=0.5))
51 / 79
EVALUATE THE MODEL PERFORMANCE AND
CREATE CONFUSION MATRIX PLOT TO MAKE A
PREDICTION ON THE TEST DATA IN THE 80/20 OF
THE 85% DATA USED FOR TRAINING AND
VALIDATIND
#
========================================================
======================
# Step 2.3: Evaluating Model Performance
#
========================================================
======================
# This script performs the following actions:
# 1. Loads the best saved model and the unseen test data.
# 2. Makes predictions on the test data.
# 3. Generates a detailed Classification Report (Precision, Recall, F1-Score).
# 4. Creates and displays a visual Confusion Matrix to identify where the model
# is making mistakes.
#
========================================================
======================
import numpy as np
import tensorflow as tf
from [Link] import classification_report, confusion_matrix
import [Link] as plt
import seaborn as sns
import sys
try:
# Load the saved Keras model
model = [Link].load_model('best_psychology_model.keras')
# Load the test data arrays
X_test = [Link]('X_test.npy')
y_test = [Link]('y_test.npy')
# Load the label names for our reports
label_classes = [Link]('label_encoder.npy', allow_pickle=True)
except (FileNotFoundError, IOError) as e:
print(f"FATAL ERROR: Could not load necessary files. {e}")
52 / 79
print("Please ensure 'best_psychology_model.keras' and the .npy files are in the directory.")
[Link](1)
# We take the class with the highest probability as our final prediction
y_pred_classes = [Link](y_pred_probs, axis=1)
53 / 79
TUNING THE STRATEGY TO RECOGNIZE THE
RARE EVENTS AND REDUCE FALSE ALARMS
#
========================================================
======================
# Step 2.2 (Final Version): Training with Tuned Class Weights
#
========================================================
======================
# This final version uses manually tuned class weights to create a more balanced
# model. The goal is to retain high sensitivity to rare events ('Correction', 'FOMO')
# while reducing the number of false alarms on common states ('Neutral', 'Herd').
#
========================================================
======================
import numpy as np
import tensorflow as tf
from [Link] import Sequential
from [Link] import LSTM, Dense, Dropout
from [Link] import EarlyStopping, ModelCheckpoint
import sys
54 / 79
# --- 3. Build the LSTM Model (No changes) ---
print("\n--- Building the LSTM Model ---")
model = Sequential([
LSTM(units=100, return_sequences=True, input_shape=input_shape),
Dropout(0.2),
LSTM(units=50, return_sequences=False),
Dropout(0.2),
Dense(units=25, activation='relu'),
Dense(units=num_classes, activation='softmax')
])
[Link](optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
[Link]()
print("Tuned weights:")
for i, w in class_weight_dict.items():
print(f" - Class '{label_classes[i]}': Weight = {w:.2f}")
history = [Link](
X_train, y_train,
epochs=100,
batch_size=64,
validation_data=(X_test, y_test),
55 / 79
callbacks=[early_stopping, model_checkpoint],
class_weight=class_weight_dict, # Using our new tuned weights
verbose=1
)
import pandas as pd
import numpy as np
import tensorflow as tf
from [Link] import MinMaxScaler
from sklearn.model_selection import train_test_split
from [Link].class_weight import compute_class_weight
from [Link] import Sequential
from [Link] import LSTM, Dense, Dropout
from [Link] import EarlyStopping, ModelCheckpoint
import sys
56 / 79
EXIT_SCALER_PATH = 'exit_scaler_params.npy'
# Parameters
LOOKAHEAD_PERIOD = 100 # How far to look for a trade's outcome
STOP_LOSS_ATR_MULT = 2.0
LOOKBACK_WINDOW = 60 # How many hours of indicator data the AI sees
#
========================================================
======================
# --- PHASE 1: TRAIN THE ENTRY OPTIMIZER ---
#
========================================================
======================
print("\n" + "="*50)
print("--- PHASE 1: Training the Entry Optimizer AI ---")
print("="*50)
57 / 79
for entry_time in buy_signal_indices:
entry_price = [Link][entry_time, 'Close']
entry_atr = [Link][entry_time, 'atr']
stop_loss_price = entry_price - (STOP_LOSS_ATR_MULT * entry_atr)
outcome_window_df = [Link][entry_time:].iloc[1:LOOKAHEAD_PERIOD+1]
if outcome_window_df.empty: continue
58 / 79
entry_scaler = MinMaxScaler()
X_train_entry_flat = X_train_entry.reshape(-1, X_train_entry.shape[-1])
entry_scaler.fit(X_train_entry_flat)
X_train_entry = entry_scaler.transform(X_train_entry_flat).reshape(X_train_entry.shape)
X_val_entry_flat = X_val_entry.reshape(-1, X_val_entry.shape[-1])
X_val_entry = entry_scaler.transform(X_val_entry_flat).reshape(X_val_entry.shape)
entry_model.fit(
X_train_entry, y_train_entry,
epochs=50, batch_size=32, validation_data=(X_val_entry, y_val_entry),
callbacks=[EarlyStopping(patience=10), ModelCheckpoint(ENTRY_MODEL_PATH,
save_best_only=True)],
class_weight=class_weight_dict_entry
)
print("--- Entry Optimizer training complete. ---")
#
========================================================
======================
# --- PHASE 2: TRAIN THE EXIT OPTIMIZER ---
#
========================================================
======================
print("\n" + "="*50)
print("--- PHASE 2: Training the Exit Optimizer AI ---")
print("="*50)
59 / 79
winning_signals = entry_signal_df[entry_signal_df['good_entry'] == 1].index
position = 0
entry_p = 0
time_counter = 0
for i in range(len(df)):
if df['buy_signal'].iloc[i] and position == 0:
position = 1
entry_p = df['Close'].iloc[i]
time_counter = 0
if position == 1:
time_counter += 1
[Link][i, [Link].get_loc('time_in_trade')] = time_counter
[Link][i, [Link].get_loc('unrealized_pnl')] = (df['Close'].iloc[i] - entry_p) / entry_p
if df['sell_signal'].iloc[i] and position == 1:
position = 0
60 / 79
exit_scaler = MinMaxScaler()
main_train_df_exit = [Link][:exit_model_data.iloc[int(len(exit_model_data)*0.8)].name]
exit_scaler.fit(main_train_df_exit[exit_feature_columns])
exit_model.fit(
X_train_exit, y_train_exit,
epochs=50, batch_size=32, validation_data=(X_val_exit, y_val_exit),
callbacks=[EarlyStopping(patience=10), ModelCheckpoint(EXIT_MODEL_PATH,
save_best_only=True)],
class_weight=class_weight_dict_exit
)
print("--- Exit Optimizer training complete. ---")
61 / 79
LSTM-EMA-ATR TRAINING WITH DISABLED AI
EXIT
#
=========================================================================
=====
# Script to Train a Single AI Entry Optimizer
#
=========================================================================
=====
# This script trains a single AI model based on the 85% historical data to
# act as an Entry Optimizer. It learns to classify EMA buy signals as "Good"
# or "Bad" based on their historical outcomes.
#
=========================================================================
=====
import pandas as pd
import numpy as np
import tensorflow as tf
from [Link] import MinMaxScaler
from sklearn.model_selection import train_test_split
from [Link].class_weight import compute_class_weight
from [Link] import Sequential
from [Link] import LSTM, Dense, Dropout
from [Link] import EarlyStopping, ModelCheckpoint
import sys
62 / 79
# Model Save Paths (Only for the Entry model)
ENTRY_MODEL_PATH = 'entry_optimizer_model.keras'
ENTRY_SCALER_PATH = 'entry_scaler_params.npy'
# Parameters
LOOKAHEAD_PERIOD = 100 # How far to look for a trade's outcome
STOP_LOSS_ATR_MULT = 2.0
LOOKBACK_WINDOW = 60 # How many hours of indicator data the AI sees
63 / 79
#
=========================================================================
=====
# --- PHASE 1: TRAIN THE ENTRY OPTIMIZER ---
#
=========================================================================
=====
print("\n" + "="*50)
print("--- PHASE 1: Training the Entry Optimizer AI ---")
print("="*50)
outcome_window_df = [Link][entry_time:].iloc[1:LOOKAHEAD_PERIOD+1]
if outcome_window_df.empty: continue
64 / 79
sell_time = outcome_window_df[outcome_window_df['sell_signal']].index[0]
if sell_time < stop_time:
[Link][entry_time, 'good_entry'] = 1 # Profit via sell signal
else:
[Link][entry_time, 'good_entry'] = 0 # Loss via stop-loss
elif hit_sell_signal:
[Link][entry_time, 'good_entry'] = 1 # Profit via sell signal
elif hit_stop_loss:
[Link][entry_time, 'good_entry'] = 0 # Loss via stop-loss
else:
[Link][entry_time, 'good_entry'] = 0 # Trade timed out, treat as bad
65 / 79
X_entry, y_entry = create_sequences_for_signals(df, entry_signal_df.index, entry_feature_columns,
entry_signal_df['good_entry'], LOOKBACK_WINDOW)
entry_scaler = MinMaxScaler()
X_train_entry_flat = X_train_entry.reshape(-1, X_train_entry.shape[-1])
entry_scaler.fit(X_train_entry_flat)
X_train_entry = entry_scaler.transform(X_train_entry_flat).reshape(X_train_entry.shape)
X_val_entry_flat = X_val_entry.reshape(-1, X_val_entry.shape[-1])
X_val_entry = entry_scaler.transform(X_val_entry_flat).reshape(X_val_entry.shape)
entry_model.fit(
X_train_entry, y_train_entry,
66 / 79
epochs=50, batch_size=32, validation_data=(X_val_entry, y_val_entry),
callbacks=[EarlyStopping(patience=10), ModelCheckpoint(ENTRY_MODEL_PATH,
save_best_only=True)],
class_weight=class_weight_dict_entry
)
print("--- Entry Optimizer training complete. ---")
#
=========================================================================
=====
# --- PHASE 2: (REMOVED) ---
# The section for training the Exit Optimizer has been removed as requested.
#
=========================================================================
=====
LSTM-EMA-ATR BACKTECT NO AI
OPTIMIZED(USED IN THE REPORT BECAUSE ITS
BETTER RESULTS VS OPTIMIZED AI EXITS)
#
========================================================
======================
# Script to Train a Single AI Entry Optimizer
67 / 79
#
========================================================
======================
# This script trains a single AI model based on the 85% historical data to
# act as an Entry Optimizer. It learns to classify EMA buy signals as "Good"
# or "Bad" based on their historical outcomes.
#
========================================================
======================
import pandas as pd
import numpy as np
import tensorflow as tf
from [Link] import MinMaxScaler
from sklearn.model_selection import train_test_split
from [Link].class_weight import compute_class_weight
from [Link] import Sequential
from [Link] import LSTM, Dense, Dropout
from [Link] import EarlyStopping, ModelCheckpoint
import sys
# Parameters
LOOKAHEAD_PERIOD = 100 # How far to look for a trade's outcome
STOP_LOSS_ATR_MULT = 2.0
LOOKBACK_WINDOW = 60 # How many hours of indicator data the AI sees
68 / 79
df['buy_signal'] = (df['fast_ma'] > df['slow_ma']) & (df['fast_ma'].shift(1) <=
df['slow_ma'].shift(1))
df['sell_signal'] = (df['fast_ma'] < df['slow_ma']) & (df['fast_ma'].shift(1) >=
df['slow_ma'].shift(1))
df['tr1'] = df['High'] - df['Low']
df['tr2'] = [Link](df['High'] - df['Close'].shift(1))
df['tr3'] = [Link](df['Low'] - df['Close'].shift(1))
df['true_range'] = df[['tr1', 'tr2', 'tr3']].max(axis=1)
df['atr'] = df['true_range'].rolling(window=14).mean()
[Link](inplace=True)
#
========================================================
======================
# --- PHASE 1: TRAIN THE ENTRY OPTIMIZER ---
#
========================================================
======================
print("\n" + "="*50)
print("--- PHASE 1: Training the Entry Optimizer AI ---")
print("="*50)
69 / 79
[Link][entry_time, 'good_entry'] = 0 # Loss via stop-loss
else:
[Link][entry_time, 'good_entry'] = 0 # Trade timed out, treat as bad
entry_scaler = MinMaxScaler()
X_train_entry_flat = X_train_entry.reshape(-1, X_train_entry.shape[-1])
entry_scaler.fit(X_train_entry_flat)
X_train_entry = entry_scaler.transform(X_train_entry_flat).reshape(X_train_entry.shape)
X_val_entry_flat = X_val_entry.reshape(-1, X_val_entry.shape[-1])
X_val_entry = entry_scaler.transform(X_val_entry_flat).reshape(X_val_entry.shape)
70 / 79
class_weights_entry = compute_class_weight('balanced', classes=[Link](y_train_entry),
y=y_train_entry)
class_weight_dict_entry = dict(enumerate(class_weights_entry))
entry_model.fit(
X_train_entry, y_train_entry,
epochs=50, batch_size=32, validation_data=(X_val_entry, y_val_entry),
callbacks=[EarlyStopping(patience=10), ModelCheckpoint(ENTRY_MODEL_PATH,
save_best_only=True)],
class_weight=class_weight_dict_entry
)
print("--- Entry Optimizer training complete. ---")
#
========================================================
======================
# --- PHASE 2: (REMOVED) ---
# The section for training the Exit Optimizer has been removed as requested.
#
========================================================
======================
71 / 79
# threshold to test the full impact of the dual AI system.
#
========================================================
======================
import pandas as pd
import numpy as np
import tensorflow as tf
from [Link] import MinMaxScaler
import sys
# Backtest Parameters
LOOKBACK_WINDOW = 60
STOP_LOSS_ATR_MULT = 2.0
TRADE_SIZE_USD = 25000.0
# AI Prediction Thresholds
ENTRY_CONFIDENCE_THRESHOLD = 0.42 # Calibrated from previous test
# <<< --- THIS IS THE FINAL CHANGE: Calibrating the Exit AI threshold --- >>>
EXIT_CONFIDENCE_THRESHOLD = 0.46
72 / 79
[Link](1)
in_position = False
entry_price = 0
stop_loss_price = 0
time_in_trade = 0
trades = []
73 / 79
[Link]({'EntryTime': entry_time, 'ExitTime': current_time, 'EntryPrice': entry_price,
'ExitPrice': exit_price, 'ExitReason': 'Stop-Loss'})
in_position = False
print(f" TRADE CLOSED: STOP-LOSS hit at {exit_price:.2f}")
continue
if df['sell_signal'].iloc[i]:
exit_price = current_price
[Link]({'EntryTime': entry_time, 'ExitTime': current_time, 'EntryPrice': entry_price,
'ExitPrice': exit_price, 'ExitReason': 'Sell Signal'})
in_position = False
print(f" TRADE CLOSED: Exited due to EMA Sell Signal at {exit_price:.2f}")
continue
unrealized_pnl = (current_price - entry_price) / entry_price
if unrealized_pnl > 0:
current_features_df = [Link][i-LOOKBACK_WINDOW:i].copy()
current_features_df['time_in_trade'] = range(time_in_trade - LOOKBACK_WINDOW + 1,
time_in_trade + 1)
pnl_series = (current_features_df['Close'] - entry_price) / entry_price
current_features_df['unrealized_pnl'] = pnl_series
exit_sequence = current_features_df[exit_feature_columns].values
scaled_exit_sequence = exit_scaler.transform(exit_sequence).reshape(1,
LOOKBACK_WINDOW, len(exit_feature_columns))
exit_prediction = exit_model.predict(scaled_exit_sequence, verbose=0)[0][0]
# Diagnostic print statement (optional to remove, but good to keep for verification)
# print(f" [In Profitable Trade] Time: {current_time}, PnL: {unrealized_pnl:+.2%}, Exit AI
Confidence: {exit_prediction:.2%}")
74 / 79
entry_time = current_time
entry_atr = df['atr'].iloc[i]
stop_loss_price = entry_price - (STOP_LOSS_ATR_MULT * entry_atr)
time_in_trade = 0
print(f" ---> APPROVED: Entering trade at {entry_price:.2f}. Stop-Loss at
{stop_loss_price:.2f}")
if not trades:
print("No trades were executed in this backtest.")
else:
trades_df = [Link](trades)
trades_df['PnL'] = (trades_df['ExitPrice'] - trades_df['EntryPrice']) * (TRADE_SIZE_USD /
trades_df['EntryPrice'])
net_profit = trades_df['PnL'].sum()
total_trades = len(trades_df)
winning_trades = trades_df[trades_df['PnL'] > 0]
losing_trades = trades_df[trades_df['PnL'] <= 0]
win_rate = (len(winning_trades) / total_trades) * 100 if total_trades > 0 else 0
average_win = winning_trades['PnL'].mean() if len(winning_trades) > 0 else 0
average_loss = losing_trades['PnL'].mean() if len(losing_trades) > 0 else 0
gross_profit = winning_trades['PnL'].sum()
gross_loss = abs(losing_trades['PnL'].sum())
profit_factor = gross_profit / gross_loss if gross_loss > 0 else float('inf')
print("\n" + "="*50)
print(" DUAL AI BACKTESTING PERFORMANCE REPORT")
print("="*50)
print(f" Data File: {OUT_OF_SAMPLE_DATA_FILE.split('/')[-1]}")
print(f" Period Tested: {[Link][0].date()} to {[Link][-1].date()}")
print("-"*50)
print(f" Net Profit: ${net_profit:,.2f}")
print(f" Total Trades: {total_trades}")
print("-"*50)
print(f" Win Rate: {win_rate:.2f}%")
print(f" Profit Factor: {profit_factor:.2f}")
print("-"*50)
print(f" Average Winning Trade: ${average_win:,.2f}")
print(f" Average Losing Trade: ${average_loss:,.2f}")
print("="*50)
print(" EXIT REASON ANALYSIS:")
print(trades_df['ExitReason'].value_counts())
print("="*50)
75 / 79
Pure" Mechanical EMA
Crossover strategy (no stop-loss)
#
========================================================
======================
# Standalone Backtest: Pure Mechanical EMA Crossover Strategy
#
========================================================
======================
# This script performs a dedicated backtest of the "Pure" Mechanical EMA
# Crossover strategy (no stop-loss) on a specific, user-defined date range.
#
# - Loads the single, master raw data file.
# - Calculates indicators on the full dataset to ensure accuracy.
# - Isolates the specific backtest period.
# - Runs the simulation with commissions and a risk-free rate.
# - Generates a standalone HTML report and equity curve plot.
#
========================================================
======================
import pandas as pd
import numpy as np
import quantstats as qs
import [Link] as plt
import sys
76 / 79
try:
# Load the entire raw dataset
df = pd.read_csv(RAW_DATA_FILE, index_col='Datetime', parse_dates=True)
[Link](inplace=True)
print(f"Successfully loaded {len(df)} rows of raw data.")
# --- Calculate ALL indicators on the full dataset BEFORE splitting ---
# This ensures the moving averages at the start of the test period are accurate.
print("Calculating indicators on the full dataset...")
fast_ma_period, slow_ma_period = 20, 50
df['fast_ma'] = df['Close'].rolling(window=fast_ma_period).mean()
df['slow_ma'] = df['Close'].rolling(window=slow_ma_period).mean()
df['buy_signal'] = (df['fast_ma'] > df['slow_ma']) & (df['fast_ma'].shift(1) <=
df['slow_ma'].shift(1))
df['sell_signal'] = (df['fast_ma'] < df['slow_ma']) & (df['fast_ma'].shift(1) >=
df['slow_ma'].shift(1))
# Drop any NaNs created during indicator calculation
[Link](inplace=True)
#
========================================================
======================
# --- Backtest: Pure Mechanical Benchmark (NO STOP-LOSS) ---
#
========================================================
======================
print("\n--- Running Backtest: Pure Mechanical Benchmark (No Stop-Loss) ---")
position = 0
equity = [INITIAL_CAPITAL]
77 / 79
previous_price = test_df['Close'].iloc[i-1]
current_capital = equity[-1]
# If in a position, compound capital based on price change
if position == 1:
current_capital *= (current_price / previous_price)
# Exit Condition: Only a sell signal can close the trade
if position == 1 and test_df['sell_signal'].iloc[i]:
current_capital *= (1 - COMMISSION_RATE) # Apply exit commission
position = 0
# Entry Condition
if position == 0 and test_df['buy_signal'].iloc[i]:
position = 1
current_capital *= (1 - COMMISSION_RATE) # Apply entry commission
[Link](current_capital)
#
========================================================
======================
# --- Performance Analysis and Visualization ---
#
========================================================
======================
print("\n--- Performance Analysis ---")
if ([Link]().sum()) > 0:
print("Strategy was active. Generating final HTML report...")
[Link](
returns,
output='pure_mechanical_report.html',
title='Pure Mechanical Strategy (No Stop-Loss)',
rf=RISK_FREE_RATE
)
print("\nSaved 'pure_mechanical_report.html'")
78 / 79
(1 + returns).cumprod().plot(ax=ax, label='Pure Mechanical Strategy', color='red',
linestyle='--')
ax.set_title('Pure Mechanical Strategy: Equity Curve', fontsize=16)
ax.set_ylabel('Cumulative Growth of $1')
[Link]()
[Link](True, alpha=0.3)
print("\nDisplaying equity curve plot...")
[Link]()
else:
print("\n" + "="*50)
print("CRITICAL FINDING: The strategy made no trades during this period.")
print("="*50 + "\n")
79 / 79