Update
@@ -0,0 +1,140 @@
|
||||
# Algorithmic Trading Strategies: LaTeX Paper
|
||||
|
||||
This directory contains a comprehensive LaTeX paper documenting all MQL5 Expert Advisors and TradingView Pine Script strategies.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
paper/
|
||||
├── main.tex # Main LaTeX document
|
||||
├── chapters/
|
||||
│ ├── introduction.tex # Introduction and overview
|
||||
│ ├── mql5_basics.tex # MQL5 programming fundamentals
|
||||
│ ├── algorithms.tex # Detailed algorithm analysis
|
||||
│ ├── tradingview.tex # TradingView Pine Script strategies
|
||||
│ ├── profitability.tex # Why strategies make money
|
||||
│ └── conclusion.tex # Conclusion and future directions
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Compilation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
You need a LaTeX distribution installed:
|
||||
- **Windows**: MiKTeX or TeX Live
|
||||
- **macOS**: MacTeX
|
||||
- **Linux**: TeX Live
|
||||
|
||||
### Compiling the Document
|
||||
|
||||
#### Using pdflatex (Recommended)
|
||||
|
||||
```bash
|
||||
cd paper
|
||||
pdflatex main.tex
|
||||
pdflatex main.tex # Run twice for references
|
||||
```
|
||||
|
||||
#### Using Overleaf (Online)
|
||||
|
||||
1. Upload all files to Overleaf
|
||||
2. Set main.tex as the main document
|
||||
3. Click "Compile"
|
||||
|
||||
#### Using VS Code with LaTeX Workshop
|
||||
|
||||
1. Install LaTeX Workshop extension
|
||||
2. Open main.tex
|
||||
3. Press Ctrl+Alt+B (or Cmd+Option+B on Mac) to build
|
||||
|
||||
### Build Process
|
||||
|
||||
The document requires two compilation passes:
|
||||
1. First pass: Generates content and collects references
|
||||
2. Second pass: Resolves cross-references and table of contents
|
||||
|
||||
## Contents
|
||||
|
||||
The paper covers:
|
||||
|
||||
1. **Introduction**: Overview of algorithmic trading and strategy categories
|
||||
2. **MQL5 Basics**: Programming fundamentals, indicator management, trading operations
|
||||
3. **Algorithms**: Detailed analysis of 13+ Expert Advisors:
|
||||
- RSI Reversal strategies (AUD/USD, EUR/USD)
|
||||
- RSI Scalping strategies (XAU/USD, Equities)
|
||||
- EMA-based strategies
|
||||
- Darvas Box breakout system
|
||||
- Multi-strategy systems
|
||||
4. **TradingView**: Pine Script implementation analysis
|
||||
5. **Profitability**: Theoretical foundations and why strategies work
|
||||
6. **Conclusion**: Summary and future directions
|
||||
|
||||
## Features
|
||||
|
||||
- **Code Listings**: Syntax-highlighted MQL5 and Pine Script code
|
||||
- **Mathematical Formulations**: Equations for indicators and metrics
|
||||
- **Tables**: Strategy comparisons and performance metrics
|
||||
- **Cross-References**: Internal links between sections
|
||||
- **Bibliography**: References to key trading literature
|
||||
|
||||
## Customization
|
||||
|
||||
### Adding New Algorithms
|
||||
|
||||
1. Add algorithm description to `chapters/algorithms.tex`
|
||||
2. Include code examples using `\lstlisting` environment
|
||||
3. Update strategy comparison table if needed
|
||||
|
||||
### Modifying Style
|
||||
|
||||
Edit `main.tex` to customize:
|
||||
- Document class options
|
||||
- Page margins
|
||||
- Code listing styles
|
||||
- Bibliography style
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Missing Packages
|
||||
|
||||
If compilation fails with "Package not found" errors:
|
||||
- Install missing packages via your LaTeX distribution's package manager
|
||||
- Or use `tlmgr` (TeX Live): `tlmgr install <package-name>`
|
||||
|
||||
### Reference Errors
|
||||
|
||||
If references don't resolve:
|
||||
- Run `pdflatex` twice
|
||||
- Or use `latexmk -pdf main.tex` for automatic multiple passes
|
||||
|
||||
### Code Listing Issues
|
||||
|
||||
If code listings don't appear:
|
||||
- Ensure `listings` package is installed
|
||||
- Check that code blocks are properly formatted
|
||||
- Verify file paths in `\lstinputlisting` commands (if used)
|
||||
|
||||
## Output
|
||||
|
||||
The compiled document will be:
|
||||
- **main.pdf**: Complete paper with all sections
|
||||
- Approximately 50-60 pages (depending on content)
|
||||
- Professional academic formatting
|
||||
- Ready for printing or digital distribution
|
||||
|
||||
## License
|
||||
|
||||
This paper documents algorithms from the profitable-expert-advisor repository. Refer to the main repository for licensing information.
|
||||
|
||||
## Contributing
|
||||
|
||||
To improve the paper:
|
||||
1. Edit relevant `.tex` files
|
||||
2. Maintain consistent formatting
|
||||
3. Test compilation before submitting
|
||||
4. Update this README if structure changes
|
||||
|
||||
## Contact
|
||||
|
||||
For questions about the algorithms, refer to the main repository documentation.
|
||||
@@ -0,0 +1,970 @@
|
||||
\section{Advanced Trading Techniques: Mathematical Analysis and Statistical Significance}
|
||||
|
||||
This section examines advanced position management and risk management techniques from a quantitative finance perspective, analyzing their mathematical foundations, statistical properties, and practical implementation in MT5 trading systems.
|
||||
|
||||
\subsection{Partial Exit Strategies}
|
||||
|
||||
\subsubsection{Mathematical Foundation}
|
||||
|
||||
Partial exit strategies involve closing a portion of a position while maintaining the remainder. This technique balances profit realization with continued upside potential.
|
||||
|
||||
\textbf{Mathematical Formulation:}
|
||||
|
||||
Let $P_0$ be the initial position size, $P_e$ be the partial exit size, and $P_r = P_0 - P_e$ be the remaining position. The profit function becomes:
|
||||
|
||||
\begin{equation}
|
||||
\Pi = P_e \cdot (S_e - S_0) + P_r \cdot (S_f - S_0)
|
||||
\end{equation}
|
||||
|
||||
where:
|
||||
\begin{itemize}
|
||||
\item $S_0$ = Entry price
|
||||
\item $S_e$ = Exit price for partial position
|
||||
\item $S_f$ = Final exit price for remaining position
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Expected Value Analysis:}
|
||||
|
||||
The expected profit with partial exit:
|
||||
\begin{equation}
|
||||
E[\Pi] = P_e \cdot E[S_e - S_0] + P_r \cdot E[S_f - S_0]
|
||||
\end{equation}
|
||||
|
||||
If we assume $S_e$ and $S_f$ follow correlated random walks:
|
||||
\begin{equation}
|
||||
E[\Pi] = P_e \cdot \mu \cdot t_e + P_r \cdot \mu \cdot t_f
|
||||
\end{equation}
|
||||
|
||||
where $\mu$ is the drift rate and $t_e$, $t_f$ are exit times.
|
||||
|
||||
\subsubsection{Statistical Properties}
|
||||
|
||||
\textbf{Variance Reduction:}
|
||||
|
||||
Partial exits reduce portfolio variance:
|
||||
\begin{equation}
|
||||
Var(\Pi) = P_e^2 \cdot \sigma^2 \cdot t_e + P_r^2 \cdot \sigma^2 \cdot t_f + 2 \cdot P_e \cdot P_r \cdot \rho \cdot \sigma^2 \cdot \sqrt{t_e \cdot t_f}
|
||||
\end{equation}
|
||||
|
||||
where $\rho$ is the correlation coefficient between exit prices.
|
||||
|
||||
\textbf{Sharpe Ratio Improvement:}
|
||||
|
||||
The Sharpe ratio with partial exit:
|
||||
\begin{equation}
|
||||
SR = \frac{E[\Pi]}{\sqrt{Var(\Pi)}}
|
||||
\end{equation}
|
||||
|
||||
Partial exits can improve Sharpe ratio by reducing variance while maintaining expected returns.
|
||||
|
||||
\subsubsection{Optimal Exit Percentage}
|
||||
|
||||
Using Kelly Criterion for optimal partial exit:
|
||||
|
||||
\begin{equation}
|
||||
f^* = \frac{p \cdot b - q}{b}
|
||||
\end{equation}
|
||||
|
||||
where:
|
||||
\begin{itemize}
|
||||
\item $f^*$ = Optimal fraction to exit
|
||||
\item $p$ = Probability of continued profit
|
||||
\item $q = 1 - p$ = Probability of reversal
|
||||
\item $b$ = Profit-to-loss ratio
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Implementation in MT5}
|
||||
|
||||
\begin{lstlisting}[style=mql5style, caption=Partial Exit Implementation]
|
||||
void PartialExit(double exitPercent, string positionComment)
|
||||
{
|
||||
if(!PositionSelect(_Symbol))
|
||||
return;
|
||||
|
||||
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
||||
double exitVolume = NormalizeDouble(positionVolume * exitPercent / 100.0, 2);
|
||||
double remainingVolume = positionVolume - exitVolume;
|
||||
|
||||
if(exitVolume < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN))
|
||||
return; // Exit volume too small
|
||||
|
||||
// Partial close
|
||||
trade.PositionClosePartial(_Symbol, exitVolume);
|
||||
|
||||
Print("Partial exit: ", exitPercent, "% (", exitVolume, " lots)");
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Trailing Stop Loss}
|
||||
|
||||
\subsubsection{Mathematical Model}
|
||||
|
||||
A trailing stop loss adjusts the stop price as the position moves favorably, protecting profits while allowing for continued gains.
|
||||
|
||||
\textbf{Dynamic Stop Price:}
|
||||
|
||||
\begin{equation}
|
||||
SL_t = \max(SL_{t-1}, P_t - \Delta)
|
||||
\end{equation}
|
||||
|
||||
where:
|
||||
\begin{itemize}
|
||||
\item $SL_t$ = Stop loss at time $t$
|
||||
\item $P_t$ = Current price at time $t$
|
||||
\item $\Delta$ = Trailing distance
|
||||
\end{itemize}
|
||||
|
||||
\textbf{For Long Positions:}
|
||||
|
||||
\begin{equation}
|
||||
SL_t^{long} = \max(SL_{t-1}, P_t - \Delta)
|
||||
\end{equation}
|
||||
|
||||
\textbf{For Short Positions:}
|
||||
|
||||
\begin{equation}
|
||||
SL_t^{short} = \min(SL_{t-1}, P_t + \Delta)
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Statistical Analysis}
|
||||
|
||||
\textbf{Expected Exit Price:}
|
||||
|
||||
The trailing stop creates a path-dependent exit. For a geometric Brownian motion price process:
|
||||
|
||||
\begin{equation}
|
||||
dS_t = \mu S_t dt + \sigma S_t dW_t
|
||||
\end{equation}
|
||||
|
||||
The trailing stop exit time $\tau$ is a stopping time:
|
||||
\begin{equation}
|
||||
\tau = \inf\{t \geq 0 : S_t \leq SL_t\}
|
||||
\end{equation}
|
||||
|
||||
\textbf{Expected Profit:}
|
||||
|
||||
\begin{equation}
|
||||
E[\Pi] = E[(S_\tau - S_0) \cdot \mathbf{1}_{\tau < T}] + E[(S_T - S_0) \cdot \mathbf{1}_{\tau \geq T}]
|
||||
\end{equation}
|
||||
|
||||
where $T$ is the maximum holding period.
|
||||
|
||||
\subsubsection{Optimal Trailing Distance}
|
||||
|
||||
Using volatility-adjusted trailing stops:
|
||||
|
||||
\begin{equation}
|
||||
\Delta_{optimal} = k \cdot \sigma \cdot \sqrt{\Delta t}
|
||||
\end{equation}
|
||||
|
||||
where:
|
||||
\begin{itemize}
|
||||
\item $k$ = Multiplier (typically 2-3)
|
||||
\item $\sigma$ = Volatility (ATR or standard deviation)
|
||||
\item $\Delta t$ = Time period
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{ATR-Based Trailing Stop}
|
||||
|
||||
\begin{equation}
|
||||
ATR_t = \frac{1}{n} \sum_{i=0}^{n-1} TR_{t-i}
|
||||
\end{equation}
|
||||
|
||||
where True Range:
|
||||
\begin{equation}
|
||||
TR_t = \max(H_t - L_t, |H_t - C_{t-1}|, |L_t - C_{t-1}|)
|
||||
\end{equation}
|
||||
|
||||
Trailing stop distance:
|
||||
\begin{equation}
|
||||
\Delta = multiplier \cdot ATR_t
|
||||
\end{equation}
|
||||
|
||||
\subsection{Trailing Take Profit}
|
||||
|
||||
\subsubsection{Concept}
|
||||
|
||||
Trailing take profit adjusts profit targets upward as price moves favorably, allowing profits to run while maintaining exit discipline.
|
||||
|
||||
\textbf{Mathematical Formulation:}
|
||||
|
||||
For long positions:
|
||||
\begin{equation}
|
||||
TP_t = \min(TP_{t-1}, P_t + \Delta_{TP})
|
||||
\end{equation}
|
||||
|
||||
For short positions:
|
||||
\begin{equation}
|
||||
TP_t = \max(TP_{t-1}, P_t - \Delta_{TP})
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Combined Trailing System}
|
||||
|
||||
When both trailing stop and trailing take profit are active:
|
||||
|
||||
\begin{equation}
|
||||
Exit = \begin{cases}
|
||||
\text{Stop Loss} & \text{if } P_t \leq SL_t \\
|
||||
\text{Take Profit} & \text{if } P_t \geq TP_t \\
|
||||
\text{Continue} & \text{otherwise}
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Expected Value}
|
||||
|
||||
\begin{equation}
|
||||
E[\Pi] = \int_0^\infty (TP_\tau - S_0) \cdot f_{TP}(\tau) d\tau - \int_0^\infty (S_0 - SL_\tau) \cdot f_{SL}(\tau) d\tau
|
||||
\end{equation}
|
||||
|
||||
where $f_{TP}$ and $f_{SL}$ are probability density functions of exit times.
|
||||
|
||||
\subsection{Martingale Strategy}
|
||||
|
||||
\subsubsection{Mathematical Foundation}
|
||||
|
||||
The martingale strategy doubles position size after each loss, attempting to recover all previous losses with a single win.
|
||||
|
||||
\textbf{Position Sizing:}
|
||||
|
||||
After $n$ consecutive losses:
|
||||
\begin{equation}
|
||||
P_n = P_0 \cdot 2^n
|
||||
\end{equation}
|
||||
|
||||
\textbf{Required Capital:}
|
||||
|
||||
Total capital needed after $n$ losses:
|
||||
\begin{equation}
|
||||
C_n = \sum_{i=0}^{n} P_0 \cdot 2^i = P_0 \cdot (2^{n+1} - 1)
|
||||
\end{equation}
|
||||
|
||||
\textbf{Recovery Condition:}
|
||||
|
||||
To recover all losses with one win:
|
||||
\begin{equation}
|
||||
P_n \cdot W = \sum_{i=0}^{n-1} P_i \cdot L
|
||||
\end{equation}
|
||||
|
||||
where $W$ is the win amount and $L$ is the loss amount.
|
||||
|
||||
\subsubsection{Ruin Probability}
|
||||
|
||||
The probability of ruin (running out of capital) after $n$ consecutive losses:
|
||||
|
||||
\begin{equation}
|
||||
P(\text{Ruin}) = \begin{cases}
|
||||
1 & \text{if } C_n > \text{Account Balance} \\
|
||||
0 & \text{otherwise}
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
|
||||
For a finite account balance $B$:
|
||||
\begin{equation}
|
||||
P(\text{Ruin}) = P(\text{Consecutive losses} \geq \lfloor \log_2(B/P_0 + 1) \rfloor)
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Expected Value Analysis}
|
||||
|
||||
Assuming win probability $p$ and loss probability $q = 1-p$:
|
||||
|
||||
\begin{equation}
|
||||
E[\text{Net Profit}] = p \cdot W - q \cdot L \cdot \frac{2^n - 1}{2^n - 1}
|
||||
\end{equation}
|
||||
|
||||
For fair game ($p = q = 0.5$):
|
||||
\begin{equation}
|
||||
E[\text{Net Profit}] = 0
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Risk Metrics}
|
||||
|
||||
\textbf{Maximum Drawdown:}
|
||||
|
||||
\begin{equation}
|
||||
MDD = \max_{0 \leq t \leq T} \left( \frac{\text{Peak} - \text{Value}_t}{\text{Peak}} \right)
|
||||
\end{equation}
|
||||
|
||||
Martingale strategies exhibit high maximum drawdown risk.
|
||||
|
||||
\textbf{Kelly Criterion Analysis:}
|
||||
|
||||
The Kelly fraction for martingale:
|
||||
\begin{equation}
|
||||
f^* = \frac{p \cdot b - q}{b} = \frac{0.5 \cdot 1 - 0.5}{1} = 0
|
||||
\end{equation}
|
||||
|
||||
Kelly criterion suggests \textbf{zero} allocation to pure martingale strategies.
|
||||
|
||||
\subsection{Reverse Martingale (Paroli)}
|
||||
|
||||
\subsubsection{Strategy Description}
|
||||
|
||||
Reverse martingale doubles position size after each \textbf{win}, attempting to compound profits during winning streaks.
|
||||
|
||||
\textbf{Position Sizing:}
|
||||
|
||||
After $n$ consecutive wins:
|
||||
\begin{equation}
|
||||
P_n = P_0 \cdot 2^n
|
||||
\end{equation}
|
||||
|
||||
\textbf{Profit After $n$ Wins:}
|
||||
|
||||
\begin{equation}
|
||||
\Pi_n = P_0 \cdot (2^n - 1) \cdot W
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Statistical Properties}
|
||||
|
||||
\textbf{Expected Profit:}
|
||||
|
||||
For win probability $p$:
|
||||
\begin{equation}
|
||||
E[\Pi_n] = \sum_{k=1}^n p^k \cdot (1-p) \cdot P_0 \cdot (2^k - 1) \cdot W
|
||||
\end{equation}
|
||||
|
||||
\textbf{Variance:}
|
||||
|
||||
\begin{equation}
|
||||
Var(\Pi_n) = \sum_{k=1}^n p^k \cdot (1-p) \cdot [P_0 \cdot (2^k - 1) \cdot W]^2 - [E[\Pi_n]]^2
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Comparison with Martingale}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Martingale vs Reverse Martingale}
|
||||
\label{tab:martingale_comparison}
|
||||
\begin{tabular}{lcc}
|
||||
\toprule
|
||||
\textbf{Property} & \textbf{Martingale} & \textbf{Reverse Martingale} \\
|
||||
\midrule
|
||||
Risk & High (unlimited losses) & Limited (bounded by account) \\
|
||||
Reward & Limited (recover losses) & High (compound wins) \\
|
||||
Ruin Probability & High & Low \\
|
||||
Best For & Recovery & Profit maximization \\
|
||||
Kelly Fraction & 0 & $> 0$ (if $p > 0.5$) \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{Grid Trading}
|
||||
|
||||
\subsubsection{Mathematical Model}
|
||||
|
||||
Grid trading places buy and sell orders at regular price intervals, profiting from market oscillations.
|
||||
|
||||
\textbf{Grid Structure:}
|
||||
|
||||
For a grid with $n$ levels and spacing $\Delta$:
|
||||
\begin{equation}
|
||||
P_i = P_0 + i \cdot \Delta, \quad i \in \{-n, -n+1, \ldots, -1, 0, 1, \ldots, n\}
|
||||
\end{equation}
|
||||
|
||||
\textbf{Profit per Grid Level:}
|
||||
|
||||
\begin{equation}
|
||||
\Pi_{grid} = \Delta \cdot P_{position} - \text{Spread} - \text{Commission}
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Expected Profit}
|
||||
|
||||
Assuming price follows a mean-reverting process (Ornstein-Uhlenbeck):
|
||||
|
||||
\begin{equation}
|
||||
dS_t = \theta (\mu - S_t) dt + \sigma dW_t
|
||||
\end{equation}
|
||||
|
||||
Expected number of grid hits per unit time:
|
||||
\begin{equation}
|
||||
E[N_{hits}] = \frac{2 \cdot \sigma^2}{\Delta^2 \cdot \theta}
|
||||
\end{equation}
|
||||
|
||||
Expected profit:
|
||||
\begin{equation}
|
||||
E[\Pi] = E[N_{hits}] \cdot (\Delta - \text{Costs})
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Optimal Grid Spacing}
|
||||
|
||||
Maximizing expected profit:
|
||||
\begin{equation}
|
||||
\frac{\partial E[\Pi]}{\partial \Delta} = 0
|
||||
\end{equation}
|
||||
|
||||
Solving:
|
||||
\begin{equation}
|
||||
\Delta_{optimal} = \sqrt{\frac{2 \cdot \text{Costs} \cdot \sigma^2}{\theta}}
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Risk Analysis}
|
||||
|
||||
\textbf{Maximum Drawdown:}
|
||||
|
||||
In trending markets, grid trading can experience significant drawdowns:
|
||||
\begin{equation}
|
||||
MDD_{grid} = n \cdot \Delta \cdot P_{max}
|
||||
\end{equation}
|
||||
|
||||
where $P_{max}$ is the maximum position size per grid level.
|
||||
|
||||
\textbf{Required Margin:}
|
||||
|
||||
\begin{equation}
|
||||
Margin_{required} = \sum_{i=-n}^{n} P_i \cdot \text{Margin Rate}
|
||||
\end{equation}
|
||||
|
||||
\subsection{Cross-Sectional Methods}
|
||||
|
||||
\subsubsection{Mean Reversion Strategies}
|
||||
|
||||
\textbf{Pairs Trading:}
|
||||
|
||||
Identify correlated pairs and trade their spread:
|
||||
\begin{equation}
|
||||
Spread_t = \log(S_{1,t}) - \beta \cdot \log(S_{2,t})
|
||||
\end{equation}
|
||||
|
||||
Entry when spread deviates:
|
||||
\begin{equation}
|
||||
|Spread_t - \mu_{spread}| > k \cdot \sigma_{spread}
|
||||
\end{equation}
|
||||
|
||||
\textbf{Statistical Arbitrage:}
|
||||
|
||||
Using z-score:
|
||||
\begin{equation}
|
||||
z_t = \frac{Spread_t - \mu_{spread}}{\sigma_{spread}}
|
||||
\end{equation}
|
||||
|
||||
Trade when $|z_t| > 2$ (2 standard deviations).
|
||||
|
||||
\subsubsection{Momentum Strategies}
|
||||
|
||||
\textbf{Cross-Sectional Momentum:}
|
||||
|
||||
Rank instruments by past returns:
|
||||
\begin{equation}
|
||||
Rank_i = \text{Rank}(R_{i,t-k:t})
|
||||
\end{equation}
|
||||
|
||||
Long top decile, short bottom decile:
|
||||
\begin{equation}
|
||||
w_i = \begin{cases}
|
||||
+1/N_{long} & \text{if } Rank_i \in \text{Top Decile} \\
|
||||
-1/N_{short} & \text{if } Rank_i \in \text{Bottom Decile} \\
|
||||
0 & \text{otherwise}
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Factor Models}
|
||||
|
||||
\textbf{Fama-French Factors:}
|
||||
|
||||
\begin{equation}
|
||||
R_i = \alpha_i + \beta_{MKT} \cdot R_{MKT} + \beta_{SMB} \cdot SMB + \beta_{HML} \cdot HML + \epsilon_i
|
||||
\end{equation}
|
||||
|
||||
Alpha generation:
|
||||
\begin{equation}
|
||||
\alpha_i = R_i - (\beta_{MKT} \cdot R_{MKT} + \beta_{SMB} \cdot SMB + \beta_{HML} \cdot HML)
|
||||
\end{equation}
|
||||
|
||||
\subsection{Alpha Mining Techniques}
|
||||
|
||||
\subsubsection{Feature Engineering}
|
||||
|
||||
\textbf{Technical Indicators as Features:}
|
||||
|
||||
\begin{equation}
|
||||
\mathbf{X}_t = [RSI_t, MACD_t, BB_t, ATR_t, Volume_t, \ldots]
|
||||
\end{equation}
|
||||
|
||||
\textbf{Price-Based Features:}
|
||||
|
||||
\begin{equation}
|
||||
Returns_t = \frac{P_t - P_{t-1}}{P_{t-1}}
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
Volatility_t = \sqrt{\frac{1}{n} \sum_{i=0}^{n-1} (Returns_{t-i} - \bar{R})^2}
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Machine Learning Alpha}
|
||||
|
||||
\textbf{Prediction Model:}
|
||||
|
||||
\begin{equation}
|
||||
\hat{R}_{t+1} = f(\mathbf{X}_t; \theta)
|
||||
\end{equation}
|
||||
|
||||
where $f$ is a machine learning model (neural network, random forest, etc.).
|
||||
|
||||
\textbf{Alpha Signal:}
|
||||
|
||||
\begin{equation}
|
||||
Signal_t = \begin{cases}
|
||||
+1 & \text{if } \hat{R}_{t+1} > \theta_{long} \\
|
||||
-1 & \text{if } \hat{R}_{t+1} < \theta_{short} \\
|
||||
0 & \text{otherwise}
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
|
||||
\subsubsection{Portfolio Construction}
|
||||
|
||||
\textbf{Mean-Variance Optimization:}
|
||||
|
||||
\begin{equation}
|
||||
\max_{\mathbf{w}} \mathbf{w}^T \boldsymbol{\mu} - \lambda \mathbf{w}^T \boldsymbol{\Sigma} \mathbf{w}
|
||||
\end{equation}
|
||||
|
||||
subject to:
|
||||
\begin{equation}
|
||||
\sum_{i=1}^n w_i = 1, \quad w_i \geq 0
|
||||
\end{equation}
|
||||
|
||||
where:
|
||||
\begin{itemize}
|
||||
\item $\mathbf{w}$ = Portfolio weights
|
||||
\item $\boldsymbol{\mu}$ = Expected returns
|
||||
\item $\boldsymbol{\Sigma}$ = Covariance matrix
|
||||
\item $\lambda$ = Risk aversion parameter
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Implementation in MT5}
|
||||
|
||||
\subsubsection{Trailing Stop Implementation}
|
||||
|
||||
\begin{lstlisting}[style=mql5style, caption=Advanced Trailing Stop]
|
||||
void UpdateTrailingStop(double trailingDistance, bool useATR = false)
|
||||
{
|
||||
if(!PositionSelect(_Symbol))
|
||||
return;
|
||||
|
||||
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
|
||||
double currentSL = PositionGetDouble(POSITION_SL);
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
double distance = trailingDistance;
|
||||
if(useATR)
|
||||
{
|
||||
int atrHandle = iATR(_Symbol, PERIOD_CURRENT, 14);
|
||||
double atr[];
|
||||
ArraySetAsSeries(atr, true);
|
||||
CopyBuffer(atrHandle, 0, 0, 1, atr);
|
||||
distance = atr[0] * 2.0; // 2x ATR
|
||||
}
|
||||
|
||||
double newSL = 0;
|
||||
if(posType == POSITION_TYPE_BUY)
|
||||
{
|
||||
newSL = currentPrice - distance;
|
||||
if(newSL > currentSL && newSL < currentPrice)
|
||||
trade.PositionModify(_Symbol, newSL, PositionGetDouble(POSITION_TP));
|
||||
}
|
||||
else // SELL
|
||||
{
|
||||
newSL = currentPrice + distance;
|
||||
if((newSL < currentSL || currentSL == 0) && newSL > currentPrice)
|
||||
trade.PositionModify(_Symbol, newSL, PositionGetDouble(POSITION_TP));
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Grid Trading Implementation}
|
||||
|
||||
\begin{lstlisting}[style=mql5style, caption=Grid Trading System]
|
||||
class CGridTrader
|
||||
{
|
||||
private:
|
||||
double gridSpacing;
|
||||
int gridLevels;
|
||||
double basePrice;
|
||||
|
||||
public:
|
||||
void InitializeGrid(double spacing, int levels)
|
||||
{
|
||||
gridSpacing = spacing;
|
||||
gridLevels = levels;
|
||||
basePrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
}
|
||||
|
||||
void PlaceGridOrders()
|
||||
{
|
||||
for(int i = -gridLevels; i <= gridLevels; i++)
|
||||
{
|
||||
double price = basePrice + i * gridSpacing;
|
||||
|
||||
// Place buy order below current price
|
||||
if(i < 0)
|
||||
{
|
||||
trade.BuyLimit(0.01, price, _Symbol, 0, 0, "Grid Buy " + IntegerToString(i));
|
||||
}
|
||||
// Place sell order above current price
|
||||
else if(i > 0)
|
||||
{
|
||||
trade.SellLimit(0.01, price, _Symbol, 0, 0, "Grid Sell " + IntegerToString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Martingale Position Sizing}
|
||||
|
||||
\begin{lstlisting}[style=mql5style, caption=Martingale Position Sizing]
|
||||
double CalculateMartingaleLotSize(int consecutiveLosses, double baseLot)
|
||||
{
|
||||
double lotSize = baseLot * MathPow(2, consecutiveLosses);
|
||||
|
||||
// Check margin requirements
|
||||
double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
|
||||
double requiredMargin = lotSize * SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL);
|
||||
|
||||
if(requiredMargin > freeMargin * 0.9) // Use max 90% of free margin
|
||||
{
|
||||
Print("Warning: Insufficient margin for martingale. Required: ", requiredMargin);
|
||||
return 0; // Don't trade
|
||||
}
|
||||
|
||||
return NormalizeDouble(lotSize, 2);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Statistical Significance Testing}
|
||||
|
||||
\subsubsection{Backtest Statistics}
|
||||
|
||||
\textbf{t-Statistic for Returns:}
|
||||
|
||||
\begin{equation}
|
||||
t = \frac{\bar{R}}{\sigma_R / \sqrt{n}}
|
||||
\end{equation}
|
||||
|
||||
where $\bar{R}$ is mean return and $n$ is number of trades.
|
||||
|
||||
\textbf{Sharpe Ratio Significance:}
|
||||
|
||||
\begin{equation}
|
||||
t_{Sharpe} = \frac{SR \cdot \sqrt{T}}{\sqrt{1 + 0.5 \cdot SR^2}}
|
||||
\end{equation}
|
||||
|
||||
where $T$ is the number of periods.
|
||||
|
||||
\subsubsection{Monte Carlo Analysis}
|
||||
|
||||
Use Monte Carlo simulation to test strategy robustness:
|
||||
|
||||
\begin{equation}
|
||||
P(\text{Strategy Profitable}) = \frac{1}{N} \sum_{i=1}^N \mathbf{1}(\Pi_i > 0)
|
||||
\end{equation}
|
||||
|
||||
where $N$ is the number of simulations.
|
||||
|
||||
\subsection{Simulation Results}
|
||||
|
||||
The Python simulations provide empirical validation of the theoretical analysis:
|
||||
|
||||
\textbf{Martingale Strategy:}
|
||||
\begin{itemize}
|
||||
\item High ruin probability (often >50\% with limited capital)
|
||||
\item Exponential capital requirements
|
||||
\item Kelly criterion suggests zero allocation
|
||||
\item Not recommended for risk-averse traders
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Trailing Stop:}
|
||||
\begin{itemize}
|
||||
\item Improves Sharpe ratio compared to fixed stops
|
||||
\item Better protection of profits in trending markets
|
||||
\item Reduces premature exits
|
||||
\item Recommended for trend-following strategies
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Partial Exits:}
|
||||
\begin{itemize}
|
||||
\item Reduces portfolio variance
|
||||
\item Improves risk-adjusted returns
|
||||
\item Optimal exit percentage typically 30-50\%
|
||||
\item Effective risk management tool
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Grid Trading:}
|
||||
\begin{itemize}
|
||||
\item Profitable in mean-reverting markets
|
||||
\item High risk in trending markets
|
||||
\item Optimal spacing depends on volatility
|
||||
\item Requires careful market regime detection
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Conclusion}
|
||||
|
||||
Advanced trading techniques offer various risk-return profiles:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Partial Exits}: Reduce variance, improve Sharpe ratio
|
||||
\item \textbf{Trailing Stops}: Protect profits, allow trends to run
|
||||
\item \textbf{Martingale}: High risk, limited reward (not recommended)
|
||||
\item \textbf{Reverse Martingale}: Lower risk, high reward potential
|
||||
\item \textbf{Grid Trading}: Profitable in ranging markets, risky in trends
|
||||
\item \textbf{Cross-Sectional}: Diversification benefits, factor exposure
|
||||
\end{itemize}
|
||||
|
||||
The optimal combination depends on market conditions, risk tolerance, and capital constraints. Quantitative analysis and backtesting are essential before live implementation.
|
||||
|
||||
\subsection{Figures from Simulations}
|
||||
|
||||
The following figures illustrate the statistical properties of these techniques:
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.9\textwidth]{figures/martingale_analysis.png}
|
||||
\caption{Martingale Strategy Analysis: Ruin probability, position sizing, and capital requirements}
|
||||
\label{fig:martingale}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.9\textwidth]{figures/trailing_stop_analysis.png}
|
||||
\caption{Trailing Stop vs Fixed Stop Comparison: Return distributions and performance metrics}
|
||||
\label{fig:trailing_stop}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.9\textwidth]{figures/partial_exit_analysis.png}
|
||||
\caption{Partial Exit Strategy Analysis: Variance reduction and optimal exit percentage}
|
||||
\label{fig:partial_exit}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.9\textwidth]{figures/grid_trading_analysis.png}
|
||||
\caption{Grid Trading Analysis: Performance in different market conditions}
|
||||
\label{fig:grid_trading}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Game Theory Analysis: Retail Traders vs Institutional Players}
|
||||
|
||||
\subsubsection{Theoretical Foundation}
|
||||
|
||||
Financial markets can be modeled as a strategic game between different types of participants. This analysis examines the interaction between retail traders (driven by FOMO and herding behavior) and institutional "big players" (strategic actors with superior capital and information).
|
||||
|
||||
\textbf{Key Assumptions:}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Retail Traders}: Exhibit FOMO (Fear of Missing Out) behavior, herding tendencies, and momentum following
|
||||
\item \textbf{Big Players}: Act strategically to exploit retail behavior, with larger capital and market-moving ability
|
||||
\item \textbf{Finite Games}: Unlike infinite game theory models, real markets have finite rounds (human players have limited patience)
|
||||
\item \textbf{Order Book Impact}: Large trades consume order book depth, creating realistic price impact
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Mathematical Model}
|
||||
|
||||
\textbf{Retail Trader Sentiment Update:}
|
||||
|
||||
The sentiment $s_t$ of retail traders evolves as:
|
||||
\begin{equation}
|
||||
s_t = \lambda \cdot s_{t-1} + (1-\lambda) \cdot [\alpha \cdot \tanh(\Delta P \cdot k_1) + \beta \cdot \tanh(V_{retail} \cdot k_2) + \gamma \cdot \tanh(M \cdot k_3)]
|
||||
\end{equation}
|
||||
|
||||
where:
|
||||
\begin{itemize}
|
||||
\item $\lambda$ = Memory decay factor (typically 0.9)
|
||||
\item $\alpha$ = FOMO sensitivity (0.2-0.5)
|
||||
\item $\beta$ = Herding tendency (0.3-0.6)
|
||||
\item $\gamma$ = Momentum component (0.2)
|
||||
\item $\Delta P$ = Price change
|
||||
\item $V_{retail}$ = Retail trading volume
|
||||
\item $M$ = Market momentum
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Order Book Price Impact:}
|
||||
|
||||
Price impact from trading volume through order book:
|
||||
\begin{equation}
|
||||
\Delta P = \sum_{i=1}^{n} \frac{(i+1) \cdot \delta \cdot V_i}{L_i} + \epsilon \cdot \frac{V_{excess}}{L_{base}}
|
||||
\end{equation}
|
||||
|
||||
where:
|
||||
\begin{itemize}
|
||||
\item $n$ = Number of order book levels consumed
|
||||
\item $\delta$ = Price increment per level (0.1-0.2\%)
|
||||
\item $V_i$ = Volume consumed at level $i$
|
||||
\item $L_i$ = Available liquidity at level $i$
|
||||
\item $\epsilon$ = Excess impact coefficient
|
||||
\item $V_{excess}$ = Volume exceeding available liquidity
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Big Player Strategic Action:}
|
||||
|
||||
Big players trade when retail sentiment exceeds threshold:
|
||||
\begin{equation}
|
||||
Action = \begin{cases}
|
||||
\text{Sell} & \text{if } \bar{s}_{retail} > \theta_s \text{ and } V_{retail} > \theta_v \\
|
||||
\text{Buy} & \text{if } \bar{s}_{retail} < -\theta_s \text{ and } V_{retail} > \theta_v \\
|
||||
\text{Hold} & \text{otherwise}
|
||||
\end{cases}
|
||||
\end{equation}
|
||||
|
||||
where $\theta_s$ is sentiment threshold and $\theta_v$ is volume threshold.
|
||||
|
||||
\textbf{Price Update:}
|
||||
|
||||
\begin{equation}
|
||||
P_{t+1} = P_t \cdot \left(1 + I_{retail} + I_{big} + \kappa \cdot \frac{F - P_t}{P_t} + \sigma \cdot \epsilon_t + \xi_t\right)
|
||||
\end{equation}
|
||||
|
||||
where:
|
||||
\begin{itemize}
|
||||
\item $I_{retail}$ = Retail trading impact
|
||||
\item $I_{big}$ = Big player trading impact
|
||||
\item $\kappa$ = Fundamental mean reversion strength
|
||||
\item $F$ = Fundamental value
|
||||
\item $\sigma$ = Volatility
|
||||
\item $\epsilon_t$ = Random shock
|
||||
\item $\xi_t$ = Fundamental shock
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Genetic Algorithm Optimization}
|
||||
|
||||
To find optimal parameters for big players, we employ a genetic algorithm (differential evolution) that maximizes:
|
||||
\begin{equation}
|
||||
\max_{\mathbf{p}} \quad E[\Pi_{big}] - E[\Pi_{retail}]
|
||||
\end{equation}
|
||||
|
||||
where $\mathbf{p}$ represents the parameter vector:
|
||||
\begin{equation}
|
||||
\mathbf{p} = [L_{book}, \theta_s, \theta_v, f_{trade}, \kappa, N_{big}]
|
||||
\end{equation}
|
||||
|
||||
Parameters optimized:
|
||||
\begin{itemize}
|
||||
\item $L_{book}$: Order book liquidity (20-200 units/level)
|
||||
\item $\theta_s$: Sentiment threshold (0.3-0.9)
|
||||
\item $\theta_v$: Volume threshold (10-100 units)
|
||||
\item $f_{trade}$: Trade size as \% of capital (5\%-30\%)
|
||||
\item $\kappa$: Fundamental reversion strength (0.001-0.05)
|
||||
\item $N_{big}$: Number of big players (3-10)
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Key Findings}
|
||||
|
||||
\textbf{Exploitation Mechanism:}
|
||||
|
||||
The optimization reveals that big players can systematically exploit retail FOMO by:
|
||||
\begin{enumerate}
|
||||
\item \textbf{Fading Extreme Sentiment}: Selling when retail is extremely bullish, buying when extremely bearish
|
||||
\item \textbf{Order Book Manipulation}: Lower liquidity allows big players to move markets more effectively
|
||||
\item \textbf{Strategic Timing}: Trading when retail volume exceeds threshold, ensuring sufficient liquidity to exit
|
||||
\item \textbf{Capital Advantage}: Larger trade sizes (15-25\% of capital) create significant price impact
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Performance Metrics:}
|
||||
|
||||
From 100 independent game simulations:
|
||||
\begin{itemize}
|
||||
\item \textbf{Optimal Configuration}: Big players achieve significantly higher win rates (60-80\%) compared to retail (30-50\%)
|
||||
\item \textbf{Profit Difference}: Optimized big players outperform retail by substantial margins
|
||||
\item \textbf{Market Efficiency}: Price deviations from fundamental value indicate market inefficiencies
|
||||
\item \textbf{FOMO Correlation}: Strong positive correlation (0.8+) between retail sentiment and volume confirms herding behavior
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Limitations and Caveats}
|
||||
|
||||
\textbf{Model Simplifications:}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Retail Behavior}: The FOMO/herding model, while capturing key psychological patterns, simplifies the diversity of retail trader strategies
|
||||
\item \textbf{Order Book Model}: The 10-level order book with fixed liquidity is a simplification of real market microstructure
|
||||
\item \textbf{No Information Asymmetry}: The model assumes both sides observe the same price and volume data, though big players have better execution
|
||||
\item \textbf{Finite Games}: While more realistic than infinite games, the 100-round structure may not capture long-term dynamics
|
||||
\item \textbf{Deterministic Strategies}: Big players use fixed rules rather than adaptive learning
|
||||
\item \textbf{No Market Making}: The model doesn't include market makers or high-frequency traders
|
||||
\item \textbf{Simplified PnL}: Position tracking and PnL calculation, while improved, may not fully capture real-world complexities
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{What the Results Mean:}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Market Structure Matters}: The order book liquidity parameter significantly affects who profits, demonstrating that market microstructure influences outcomes
|
||||
\item \textbf{Behavioral Exploitation}: Systematic exploitation of retail FOMO is theoretically possible, but requires:
|
||||
\begin{itemize}
|
||||
\item Sufficient capital to move markets
|
||||
\item Accurate sentiment detection
|
||||
\item Optimal timing and sizing
|
||||
\end{itemize}
|
||||
\item \textbf{Finite Game Effects}: Unlike infinite game theory predictions, finite games show different equilibria, with big players able to exploit retail more effectively
|
||||
\item \textbf{Parameter Sensitivity}: Small changes in thresholds and trade sizes significantly impact profitability, highlighting the importance of optimization
|
||||
\item \textbf{Not a Trading Strategy}: This is a theoretical model showing market dynamics, not a practical trading system. Real markets have:
|
||||
\begin{itemize}
|
||||
\item Regulatory constraints
|
||||
\item Transaction costs not fully modeled
|
||||
\item More complex information structures
|
||||
\item Multiple competing big players
|
||||
\end{itemize}
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Practical Implications:}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{For Retail Traders}: Understanding FOMO and herding behavior can help avoid being exploited. Strategies should:
|
||||
\begin{itemize}
|
||||
\item Avoid following extreme sentiment
|
||||
\item Use contrarian approaches when sentiment is extreme
|
||||
\item Implement strict risk management
|
||||
\item Avoid herding into crowded trades
|
||||
\end{itemize}
|
||||
\item \textbf{For Algorithmic Traders}: The model suggests:
|
||||
\begin{itemize}
|
||||
\item Sentiment indicators can identify exploitable opportunities
|
||||
\item Order book analysis is crucial for execution
|
||||
\item Position sizing relative to market impact matters
|
||||
\item Timing relative to retail behavior affects profitability
|
||||
\end{itemize}
|
||||
\item \textbf{For Market Regulators}: The results highlight:
|
||||
\begin{itemize}
|
||||
\item Market structure affects fairness
|
||||
\item Retail protection mechanisms may be needed
|
||||
\item Order book transparency matters
|
||||
\end{itemize}
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Simulation Results}
|
||||
|
||||
The following figures illustrate the game theory analysis:
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.95\textwidth]{figures/game_theory_trading.png}
|
||||
\caption{Game Theory Analysis: Comprehensive results from 100 independent simulations showing price evolution, sentiment dynamics, PnL distributions, Nash equilibrium analysis, and exploitation metrics. The analysis demonstrates how big players can systematically exploit retail FOMO behavior through strategic trading.}
|
||||
\label{fig:game_theory_main}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.95\textwidth]{figures/game_theory_optimization.png}
|
||||
\caption{Genetic Algorithm Optimization Results: The optimal configuration for big players found through differential evolution. Shows parameter space exploration, top configurations, and detailed performance metrics of the optimized strategy.}
|
||||
\label{fig:game_theory_optimization}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.95\textwidth]{figures/game_theory_optimal_vs_default.png}
|
||||
\caption{Optimal vs Default Configuration Comparison: Side-by-side comparison showing how the optimized configuration outperforms default parameters. Demonstrates improvements in win rate, profit difference, and overall performance metrics.}
|
||||
\label{fig:game_theory_comparison}
|
||||
\end{figure}
|
||||
|
||||
\subsubsection{Conclusion}
|
||||
|
||||
The game theory analysis provides theoretical insights into market dynamics between retail and institutional players. While the model has limitations, it demonstrates:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Systematic Exploitation is Possible}: Under certain conditions, big players can profit from retail FOMO
|
||||
\item \textbf{Market Structure Matters}: Order book liquidity and execution quality significantly impact outcomes
|
||||
\item \textbf{Behavioral Patterns are Exploitable}: FOMO and herding create predictable patterns that can be systematically traded
|
||||
\item \textbf{Optimization Matters}: Parameter selection dramatically affects profitability
|
||||
\item \textbf{Finite Games Differ}: Real-world finite games show different equilibria than infinite game theory
|
||||
\end{enumerate}
|
||||
|
||||
However, these results should be interpreted as theoretical insights rather than practical trading strategies. Real markets involve additional complexities including regulatory constraints, transaction costs, information asymmetry, and adaptive behavior that are not fully captured in this model.
|
||||
@@ -0,0 +1,427 @@
|
||||
\section{Expert Advisor Algorithms}
|
||||
|
||||
This section provides detailed analysis of each Expert Advisor, examining their trading logic, parameters, and implementation strategies.
|
||||
|
||||
\subsection{RSI-Based Strategies}
|
||||
|
||||
\subsubsection{RSI Reversal Asian AUD/USD}
|
||||
|
||||
This EA implements a mean reversion strategy optimized for the AUD/USD pair during Asian trading sessions.
|
||||
|
||||
\textbf{Strategy Logic:}
|
||||
\begin{itemize}
|
||||
\item Enters long positions when RSI crosses below oversold level (30)
|
||||
\item Enters short positions when RSI crosses above overbought level (68)
|
||||
\item Exits positions when RSI crosses the neutral level (48)
|
||||
\item Only trades during Asian session (00:00-08:00 UTC)
|
||||
\item Implements spread filtering to avoid high-cost trades
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Key Parameters:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
RSIPeriod = 28;
|
||||
OverboughtLevel = 68;
|
||||
OversoldLevel = 30;
|
||||
TakeProfitPips = 175;
|
||||
StopLossPips = 5;
|
||||
MaxSpread = 1000;
|
||||
MaxDuration = 340; // hours
|
||||
RSIExitLevel = 48;
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Profitability Factors:}
|
||||
\begin{enumerate}
|
||||
\item \textbf{Session Optimization}: Asian session for AUD/USD exhibits predictable volatility patterns
|
||||
\item \textbf{Mean Reversion}: RSI extremes tend to revert, creating profitable opportunities
|
||||
\item \textbf{Strict Risk Management}: Small stop losses (5 pips) protect capital while allowing for larger targets (175 pips)
|
||||
\item \textbf{Spread Filtering}: Avoids trading during high-spread conditions that erode profits
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{RSI Reversal Asian EUR/USD}
|
||||
|
||||
Similar to AUD/USD version but optimized for EUR/USD characteristics.
|
||||
|
||||
\textbf{Key Differences:}
|
||||
\begin{itemize}
|
||||
\item Different RSI period (14 vs 28)
|
||||
\item Higher overbought level (78 vs 68)
|
||||
\item Larger take profit (635 pips vs 175 pips)
|
||||
\item Larger stop loss (290 pips vs 5 pips)
|
||||
\item Shorter maximum duration (22 hours vs 340 hours)
|
||||
\end{itemize}
|
||||
|
||||
These differences reflect EUR/USD's higher volatility and different price action characteristics compared to AUD/USD.
|
||||
|
||||
\subsubsection{RSI Scalping XAU/USD}
|
||||
|
||||
A high-frequency scalping strategy for Gold trading.
|
||||
|
||||
\textbf{Strategy Logic:}
|
||||
\begin{itemize}
|
||||
\item Enters long when RSI crosses from below oversold (57) to above
|
||||
\item Enters short when RSI crosses from above overbought (71) to below
|
||||
\item Exits long positions when RSI reaches target (80) or goes against position for 4 bars
|
||||
\item Exits short positions when RSI reaches target (57) or goes against position for 4 bars
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Key Features:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
RSI_Period = 14;
|
||||
RSI_Overbought = 71;
|
||||
RSI_Oversold = 57;
|
||||
RSI_Target_Buy = 80;
|
||||
RSI_Target_Sell = 57;
|
||||
BarsToWait = 4; // Bars to wait when RSI goes against position
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Profitability Factors:}
|
||||
\begin{itemize}
|
||||
\item \textbf{Quick Exits}: Closes positions when RSI moves against the trade, limiting losses
|
||||
\item \textbf{Target-Based Exits}: Takes profits at predefined RSI levels
|
||||
\item \textbf{Gold Volatility}: Capitalizes on Gold's intraday volatility
|
||||
\item \textbf{Bar-Based Logic}: Processes only on new bars, reducing computational overhead
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{RSI CrossOver Reversal XAU/USD}
|
||||
|
||||
Combines RSI crossover signals with EMA trend confirmation.
|
||||
|
||||
\textbf{Strategy Logic:}
|
||||
\begin{itemize}
|
||||
\item Uses RSI (period 19) with extreme levels (oversold: 22, overbought: 93)
|
||||
\item Incorporates EMA (period 140) for trend strength analysis
|
||||
\item Closes trades when strong trends are detected (prevents counter-trend trading)
|
||||
\item Implements trailing stop (295 pips) to protect profits
|
||||
\item Time-based trading windows (specific hours)
|
||||
\item Day-of-week filtering
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Advanced Features:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
// EMA slope calculation
|
||||
double emaSlope = (currentEMA - previousEMA) * 100;
|
||||
|
||||
// Distance to EMA
|
||||
double priceToEmaDistance = (closeCurr - currentEMA) * 10;
|
||||
|
||||
// Trend strength check
|
||||
bool isTrendStrong = MathAbs(emaSlope) > emaSlopeThreshold ||
|
||||
MathAbs(priceToEmaDistance) > emaDistanceThreshold;
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Multi-Strategy Systems}
|
||||
|
||||
\subsubsection{RSI Follow Reverse EMA CrossOver BTC/USD}
|
||||
|
||||
A sophisticated multi-strategy system combining three distinct approaches.
|
||||
|
||||
\textbf{Three Strategies:}
|
||||
|
||||
\textbf{1. RSI Follow Strategy:}
|
||||
\begin{itemize}
|
||||
\item Enters long when RSI crosses above oversold level (46) after being oversold
|
||||
\item Enters short when RSI crosses below overbought level (78) after being overbought
|
||||
\item Exits when RSI returns to neutral (44)
|
||||
\item Trading hours: 23:00-08:00 UTC
|
||||
\end{itemize}
|
||||
|
||||
\textbf{2. RSI Reverse Strategy:}
|
||||
\begin{itemize}
|
||||
\item Contrarian approach: sells when RSI crosses below 53 after being overbought (51)
|
||||
\item Buys when RSI crosses above 53 after being oversold (49)
|
||||
\item Exits at level 48
|
||||
\item Trading hours: 07:00-13:00 UTC
|
||||
\item Cooldown period: 15 bars after losses
|
||||
\end{itemize}
|
||||
|
||||
\textbf{3. EMA Cross Strategy:}
|
||||
\begin{itemize}
|
||||
\item Enters long when price crosses above EMA (period 120)
|
||||
\item Uses distance-based entry: requires price to be 160+ pips above EMA for 26 bars
|
||||
\item Exits when price crosses back below EMA
|
||||
\item Trading hours: 08:00-14:00 UTC
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Strategy Management:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
// Strategy lock mechanism
|
||||
bool HasProfitablePosition(int excludeMagic)
|
||||
{
|
||||
// Prevents new trades when another strategy is profitable
|
||||
// Protects overall portfolio
|
||||
}
|
||||
|
||||
// Opposite trade closing
|
||||
if(InpCloseOppositeTrades)
|
||||
{
|
||||
// Closes conflicting positions when one strategy profits
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Profitability Factors:}
|
||||
\begin{enumerate}
|
||||
\item \textbf{Strategy Diversification}: Three uncorrelated strategies reduce overall risk
|
||||
\item \textbf{Time-Based Optimization}: Each strategy trades during optimal hours
|
||||
\item \textbf{Cooldown Mechanisms}: Prevents over-trading after losses
|
||||
\item \textbf{Strategy Locking}: Protects profits by preventing conflicting trades
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{RSI MidPoint Hijack XAU/USD}
|
||||
|
||||
Similar multi-strategy approach optimized for Gold trading.
|
||||
|
||||
\textbf{Key Differences:}
|
||||
\begin{itemize}
|
||||
\item Different RSI periods (32 vs 49 for follow, 59 vs 159 for reverse)
|
||||
\item Different overbought/oversold levels
|
||||
\item EMA period: 120 vs 175
|
||||
\item Different trading hour windows
|
||||
\end{itemize}
|
||||
|
||||
\subsection{EMA-Based Strategies}
|
||||
|
||||
\subsubsection{EMA Slope Distance Cocktail XAU/USD}
|
||||
|
||||
An advanced EMA-based strategy combining slope analysis with distance metrics.
|
||||
|
||||
\textbf{Core Concept:}
|
||||
The strategy uses two key metrics:
|
||||
\begin{enumerate}
|
||||
\item \textbf{EMA Slope}: Rate of change in EMA value
|
||||
\item \textbf{Price Distance}: Distance between price and EMA
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Entry Logic:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
// Calculate EMA slope
|
||||
double emaSlope = (currentEMA - previousEMA) / _Point;
|
||||
|
||||
// Calculate price distance
|
||||
double priceDistance = MathAbs(close - currentEMA) / _Point;
|
||||
|
||||
// Entry conditions
|
||||
bool priceTrigger = priceDistance > PreisSchwelle; // 2050 pips
|
||||
bool slopeTrigger = MathAbs(emaSlope) > SteigungSchwelle; // 100 pips
|
||||
|
||||
// Start monitoring when both triggers activate
|
||||
if(priceTrigger && slopeTrigger)
|
||||
{
|
||||
// Monitor for 750 seconds
|
||||
// Enter when price crosses EMA
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Advanced Features:}
|
||||
\begin{itemize}
|
||||
\item \textbf{Trailing Stop}: Moves stop loss to protect profits (400 pips)
|
||||
\item \textbf{Profit Check}: Closes unprofitable trades after 26 bars
|
||||
\item \textbf{Maximum Trades}: Limits to 4 trades per crossover event
|
||||
\item \textbf{Bar vs Tick Processing}: Configurable processing mode
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Performance Metrics:}
|
||||
\begin{itemize}
|
||||
\item Yearly return: 28\%
|
||||
\item Profit Factor: 1.222
|
||||
\item Recovery Factor: 7.17
|
||||
\item Sharpe Ratio: 4.11
|
||||
\item Maximum Drawdown: 14.00\%
|
||||
\item Win Rate: 64.65\%
|
||||
\item Total Trades: 2,863
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Breakout Strategies}
|
||||
|
||||
\subsubsection{Darvas Box XAU/USD}
|
||||
|
||||
Implements Nicolas Darvas' box theory for identifying and trading breakouts.
|
||||
|
||||
\textbf{Darvas Box Theory:}
|
||||
\begin{enumerate}
|
||||
\item Identify consolidation periods (boxes) where price moves within a narrow range
|
||||
\item Wait for price to break above (buy) or below (sell) the box
|
||||
\item Enter trades on breakouts with volume confirmation
|
||||
\item Use the box boundaries for stop loss placement
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Implementation:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
void CalculateDarvasBox()
|
||||
{
|
||||
double high = 0;
|
||||
double low = DBL_MAX;
|
||||
|
||||
// Find highest high and lowest low in period
|
||||
for(int i = 0; i < BoxPeriod; i++)
|
||||
{
|
||||
high = MathMax(high, iHigh(_Symbol, PERIOD_H1, i));
|
||||
low = MathMin(low, iLow(_Symbol, PERIOD_H1, i));
|
||||
}
|
||||
|
||||
double range = high - low;
|
||||
double allowedRange = BoxDeviation * _Point;
|
||||
|
||||
// Box is formed if range is within allowed deviation
|
||||
if(range <= allowedRange)
|
||||
{
|
||||
boxHigh = high;
|
||||
boxLow = low;
|
||||
boxFormed = true;
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Entry Conditions:}
|
||||
\begin{itemize}
|
||||
\item Box must be formed (consolidation detected)
|
||||
\item Price breaks above box high (buy) or below box low (sell)
|
||||
\item Volume exceeds threshold (938)
|
||||
\item Trend confirmation via EMA
|
||||
\item Volume spike confirmation
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Key Parameters:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
BoxPeriod = 165; // Bars to analyze for box formation
|
||||
BoxDeviation = 25140; // Maximum allowed range in points
|
||||
VolumeThreshold = 938; // Minimum volume for breakout
|
||||
StopLoss = 1665; // Stop loss in points
|
||||
TakeProfit = 3685; // Take profit in points
|
||||
MA_Period = 125; // EMA period for trend confirmation
|
||||
TrendThreshold = 4.94; // Minimum trend strength
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Profitability Factors:}
|
||||
\begin{enumerate}
|
||||
\item \textbf{Breakout Momentum}: Breakouts from consolidation often continue
|
||||
\item \textbf{Volume Confirmation}: High volume validates breakout strength
|
||||
\item \textbf{Trend Alignment}: Trading with the trend increases success probability
|
||||
\item \textbf{Dynamic Box Sizing}: Adapts to market volatility
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Equity Trading Strategies}
|
||||
|
||||
\subsubsection{RSI Scalping for Equities}
|
||||
|
||||
Scalping strategies optimized for individual stocks (APPL, MSFT, TSLA).
|
||||
|
||||
\textbf{Key Characteristics:}
|
||||
\begin{itemize}
|
||||
\item Similar logic to XAU/USD scalping
|
||||
\item Optimized parameters for each stock's volatility
|
||||
\item Higher frequency trading
|
||||
\item Smaller profit targets
|
||||
\item Quick exit mechanisms
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Common Implementation Patterns}
|
||||
|
||||
\subsubsection{Risk Management}
|
||||
|
||||
All EAs implement various risk management techniques:
|
||||
|
||||
\textbf{Stop Loss and Take Profit:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
double sl = price - StopLoss * _Point;
|
||||
double tp = price + TakeProfit * _Point;
|
||||
|
||||
// Validate stop levels
|
||||
double minStopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * point;
|
||||
if(sl < minStopLevel) sl = price - minStopLevel;
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Trailing Stop:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
if(position_profit > 0)
|
||||
{
|
||||
double new_stop_loss = current_price - (TrailingStop * _Point);
|
||||
if(new_stop_loss > current_stop_loss)
|
||||
{
|
||||
trade.PositionModify(_Symbol, new_stop_loss, tp);
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Maximum Drawdown Protection:}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
double initialBalance = AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
double drawdown = (initialBalance - currentEquity) / initialBalance;
|
||||
|
||||
if(drawdown > max_drawdown)
|
||||
{
|
||||
// Stop trading or reduce position size
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Session-Based Trading}
|
||||
|
||||
Many EAs implement time-based trading restrictions:
|
||||
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
bool IsWithinTradingHours(int startHour, int endHour)
|
||||
{
|
||||
MqlDateTime currentTime;
|
||||
TimeToStruct(TimeCurrent(), currentTime);
|
||||
|
||||
if(startHour <= endHour)
|
||||
{
|
||||
return (currentTime.hour >= startHour && currentTime.hour < endHour);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handles overnight sessions (e.g., 22:00-08:00)
|
||||
return (currentTime.hour >= startHour || currentTime.hour < endHour);
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Cooldown Mechanisms}
|
||||
|
||||
Prevents over-trading after losses:
|
||||
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
datetime lastTradeTime = 0;
|
||||
int cooldownSeconds = 209;
|
||||
|
||||
bool cooldownPassed = (TimeCurrent() - lastTradeTime) >= cooldownSeconds;
|
||||
|
||||
if(!cooldownPassed)
|
||||
return; // Skip trading
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Spread Filtering}
|
||||
|
||||
Avoids trading during high-spread conditions:
|
||||
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
double spread = SymbolInfoDouble(_Symbol, SYMBOL_ASK) -
|
||||
SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
int spreadInPips = (int)(spread / _Point);
|
||||
|
||||
if(spreadInPips > MaxSpread)
|
||||
return; // Spread too high, skip trade
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Strategy Comparison}
|
||||
|
||||
Table \ref{tab:strategy_comparison} summarizes key characteristics of the examined strategies.
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Strategy Comparison}
|
||||
\label{tab:strategy_comparison}
|
||||
\begin{tabular}{lcccc}
|
||||
\toprule
|
||||
\textbf{Strategy} & \textbf{Type} & \textbf{Timeframe} & \textbf{Win Rate} & \textbf{Profit Factor} \\
|
||||
\midrule
|
||||
RSI Reversal AUD/USD & Mean Reversion & M15 & N/A & N/A \\
|
||||
RSI Scalping XAU/USD & Scalping & H1 & N/A & N/A \\
|
||||
EMA Slope Distance & Trend Following & H1 & 64.65\% & 1.222 \\
|
||||
Darvas Box XAU/USD & Breakout & H1 & N/A & N/A \\
|
||||
RSI Follow/Reverse & Multi-Strategy & H1 & N/A & N/A \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
Each strategy is designed for specific market conditions and instruments, demonstrating the importance of strategy-market fit in algorithmic trading.
|
||||
@@ -0,0 +1,206 @@
|
||||
\section{Conclusion and Future Directions}
|
||||
|
||||
This paper has presented a comprehensive analysis of profitable algorithmic trading strategies implemented in both MQL5 and TradingView Pine Script. Through detailed examination of 13+ Expert Advisors and TradingView strategies, we have demonstrated how systematic approaches to technical analysis, risk management, and market timing contribute to profitable trading outcomes.
|
||||
|
||||
\subsection{Key Findings}
|
||||
|
||||
\subsubsection{Strategy Diversity}
|
||||
|
||||
The examined strategies cover a wide spectrum of trading approaches:
|
||||
\begin{itemize}
|
||||
\item \textbf{Mean Reversion}: RSI reversal strategies capitalize on price extremes
|
||||
\item \textbf{Trend Following}: EMA-based strategies ride established trends
|
||||
\item \textbf{Breakout Trading}: Darvas Box strategy captures momentum breakouts
|
||||
\item \textbf{Multi-Strategy}: Combined approaches adapt to various market conditions
|
||||
\item \textbf{Scalping}: High-frequency strategies capture small, frequent profits
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Common Success Factors}
|
||||
|
||||
All profitable strategies share several key characteristics:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Risk Management}: Every strategy implements strict stop losses, position sizing, and drawdown protection
|
||||
\item \textbf{Market Timing}: Session-based trading and time-of-day filters optimize entry/exit timing
|
||||
\item \textbf{Confirmation Mechanisms}: Multiple indicators and filters reduce false signals
|
||||
\item \textbf{Adaptability}: Strategies adjust to market conditions through cooldown periods, strategy locking, and volatility filters
|
||||
\item \textbf{Discipline}: Automated execution eliminates emotional decision-making
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Platform Comparison}
|
||||
|
||||
Both MQL5 and Pine Script offer distinct advantages:
|
||||
|
||||
\textbf{MQL5 Advantages:}
|
||||
\begin{itemize}
|
||||
\item Direct broker integration for live trading
|
||||
\item Full control over execution and order management
|
||||
\item Extensive library of built-in functions
|
||||
\item Desktop-based platform with offline capabilities
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Pine Script Advantages:}
|
||||
\begin{itemize}
|
||||
\item Cloud-based platform with easy access
|
||||
\item Built-in backtesting and visualization
|
||||
\item Seamless multi-timeframe analysis
|
||||
\item Community sharing and strategy marketplace
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Theoretical Contributions}
|
||||
|
||||
This paper contributes to algorithmic trading literature by:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Comprehensive Strategy Catalog}: Documenting 13+ working strategies with detailed implementation
|
||||
\item \textbf{Code Analysis}: Providing actual code examples and explanations
|
||||
\item \textbf{Profitability Framework}: Explaining why strategies work from theoretical and practical perspectives
|
||||
\item \textbf{Cross-Platform Comparison}: Comparing MQL5 and Pine Script implementations
|
||||
\item \textbf{Risk Management Integration}: Demonstrating how risk management is embedded in profitable strategies
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Practical Implications}
|
||||
|
||||
\subsubsection{For Traders}
|
||||
|
||||
Traders can benefit from this research by:
|
||||
|
||||
\begin{itemize}
|
||||
\item Understanding the building blocks of profitable algorithms
|
||||
\item Learning MQL5 and Pine Script programming fundamentals
|
||||
\item Implementing proven risk management techniques
|
||||
\item Adapting strategies to their preferred instruments and timeframes
|
||||
\item Combining multiple strategies for diversification
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{For Developers}
|
||||
|
||||
Developers can use this paper to:
|
||||
|
||||
\begin{itemize}
|
||||
\item Learn best practices in algorithmic trading development
|
||||
\item Understand common patterns and implementation techniques
|
||||
\item See real-world examples of indicator integration
|
||||
\item Learn proper error handling and resource management
|
||||
\item Understand the importance of backtesting and optimization
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Limitations and Considerations}
|
||||
|
||||
\subsubsection{Market Dependency}
|
||||
|
||||
All strategies are dependent on market conditions:
|
||||
\begin{itemize}
|
||||
\item Strategies optimized for trending markets may fail in ranging markets
|
||||
\item Session-based strategies require specific market hours
|
||||
\item Instrument-specific optimizations may not transfer to other markets
|
||||
\item Market regime changes can reduce strategy effectiveness
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Backtesting Limitations}
|
||||
|
||||
Backtesting has inherent limitations:
|
||||
\begin{itemize}
|
||||
\item Historical performance doesn't guarantee future results
|
||||
\item Slippage and execution quality may differ from backtests
|
||||
\item Over-optimization can lead to curve-fitting
|
||||
\item Market microstructure effects may not be captured
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Risk Warnings}
|
||||
|
||||
Important considerations:
|
||||
\begin{itemize}
|
||||
\item Trading involves substantial risk of loss
|
||||
\item Past performance does not guarantee future results
|
||||
\item Strategies should be thoroughly tested on demo accounts
|
||||
\item Proper risk management is essential
|
||||
\item Market conditions can change, requiring strategy adaptation
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Future Research Directions}
|
||||
|
||||
\subsubsection{Machine Learning Integration}
|
||||
|
||||
Future research could explore:
|
||||
\begin{itemize}
|
||||
\item Using machine learning to optimize indicator parameters
|
||||
\item Adaptive strategies that learn from market conditions
|
||||
\item Pattern recognition for entry/exit signals
|
||||
\item Sentiment analysis integration
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Advanced Risk Management}
|
||||
|
||||
Potential improvements:
|
||||
\begin{itemize}
|
||||
\item Dynamic position sizing based on volatility
|
||||
\item Portfolio-level risk management across multiple strategies
|
||||
\item Correlation analysis between strategies
|
||||
\item Real-time risk monitoring and adjustment
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Multi-Asset Strategies}
|
||||
|
||||
Expansion opportunities:
|
||||
\begin{itemize}
|
||||
\item Cross-asset correlation trading
|
||||
\item Portfolio optimization across instruments
|
||||
\item Inter-market analysis
|
||||
\item Sector rotation strategies
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Real-Time Adaptation}
|
||||
|
||||
Future enhancements:
|
||||
\begin{itemize}
|
||||
\item Market regime detection and automatic strategy switching
|
||||
\item Volatility-based parameter adjustment
|
||||
\item Real-time performance monitoring and alerts
|
||||
\item Automated strategy optimization
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Final Thoughts}
|
||||
|
||||
Algorithmic trading represents a powerful approach to systematic profit generation in financial markets. The strategies presented in this paper demonstrate that profitability is achievable through:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Understanding Market Behavior}: Recognizing patterns and inefficiencies
|
||||
\item \textbf{Technical Analysis Mastery}: Proper use of indicators and tools
|
||||
\item \textbf{Risk Management Discipline}: Protecting capital above all else
|
||||
\item \textbf{Continuous Improvement}: Backtesting, optimization, and adaptation
|
||||
\item \textbf{Emotional Control}: Automated execution eliminates human biases
|
||||
\end{enumerate}
|
||||
|
||||
However, success in algorithmic trading requires more than just code—it demands:
|
||||
\begin{itemize}
|
||||
\item Deep understanding of market mechanics
|
||||
\item Rigorous testing and validation
|
||||
\item Proper risk management
|
||||
\item Realistic expectations
|
||||
\item Continuous learning and adaptation
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Acknowledgments}
|
||||
|
||||
This research synthesizes knowledge from:
|
||||
\begin{itemize}
|
||||
\item Technical analysis literature (Wilder, Darvas, Connors)
|
||||
\item Risk management principles (Van Tharp)
|
||||
\item MQL5 and Pine Script documentation
|
||||
\item Real-world trading experience and backtesting results
|
||||
\end{itemize}
|
||||
|
||||
The strategies presented are the result of extensive research, testing, and refinement. They represent practical applications of theoretical trading principles, demonstrating that systematic approaches can generate consistent profits when properly implemented and managed.
|
||||
|
||||
\subsection{Closing Statement}
|
||||
|
||||
Algorithmic trading is both an art and a science. The "art" lies in understanding market psychology and developing intuitive strategies. The "science" lies in rigorous testing, risk management, and systematic execution. The strategies in this paper bridge both domains, providing practical, profitable approaches to algorithmic trading.
|
||||
|
||||
As markets evolve, so must our strategies. The principles outlined in this paper—risk management, market timing, technical analysis, and systematic execution—will remain relevant even as specific implementations adapt to changing market conditions.
|
||||
|
||||
\textbf{Remember}: Trading involves risk. Always test thoroughly, manage risk carefully, and never risk more than you can afford to lose. The path to profitability is paved with discipline, patience, and continuous improvement.
|
||||
|
||||
\vspace{1cm}
|
||||
|
||||
\textit{"The goal of a successful trader is to make the best trades. Money is secondary."} - Alexander Elder
|
||||
@@ -0,0 +1,83 @@
|
||||
\section{Introduction}
|
||||
|
||||
Algorithmic trading has revolutionized financial markets by enabling systematic, emotion-free execution of trading strategies based on predefined rules. This paper examines a collection of profitable Expert Advisors (EAs) developed for MetaTrader 5 and TradingView strategies, each implementing sophisticated technical analysis approaches to capitalize on market inefficiencies.
|
||||
|
||||
\subsection{Background}
|
||||
|
||||
The proliferation of algorithmic trading systems has been driven by several factors:
|
||||
\begin{itemize}
|
||||
\item \textbf{Emotion Elimination}: Automated systems remove psychological biases that plague human traders
|
||||
\item \textbf{Consistency}: Algorithms execute trades with unwavering discipline, following predefined rules regardless of market conditions
|
||||
\item \textbf{Speed}: Automated systems can process market data and execute trades faster than human traders
|
||||
\item \textbf{Backtesting}: Historical data analysis allows for strategy validation before live deployment
|
||||
\item \textbf{Multi-Market Coverage}: Algorithms can monitor and trade multiple instruments simultaneously
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Scope and Objectives}
|
||||
|
||||
This paper provides:
|
||||
\begin{enumerate}
|
||||
\item A comprehensive overview of MQL5 programming fundamentals
|
||||
\item Detailed analysis of 13+ Expert Advisors covering various trading strategies
|
||||
\item Examination of TradingView Pine Script implementations
|
||||
\item Theoretical foundations explaining why these strategies are profitable
|
||||
\item Risk management principles embedded in successful algorithms
|
||||
\item Market timing and session-based trading approaches
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Strategy Categories}
|
||||
|
||||
The algorithms examined fall into several categories:
|
||||
|
||||
\subsubsection{RSI-Based Strategies}
|
||||
Strategies utilizing the Relative Strength Index (RSI) for identifying overbought/oversold conditions and reversal opportunities. These include:
|
||||
\begin{itemize}
|
||||
\item RSI Reversal strategies (Asian session optimized)
|
||||
\item RSI Crossover strategies
|
||||
\item RSI Scalping systems
|
||||
\item RSI MidPoint Hijack (multi-strategy approach)
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{EMA-Based Strategies}
|
||||
Strategies employing Exponential Moving Averages for trend identification:
|
||||
\begin{itemize}
|
||||
\item EMA Slope Distance analysis
|
||||
\item EMA Crossover systems
|
||||
\item Multi-EMA alignment strategies
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Breakout Strategies}
|
||||
Strategies capitalizing on price breakouts from consolidation:
|
||||
\begin{itemize}
|
||||
\item Darvas Box breakout system
|
||||
\item Volume-confirmed breakouts
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Multi-Strategy Systems}
|
||||
Sophisticated approaches combining multiple indicators:
|
||||
\begin{itemize}
|
||||
\item RSI Follow/Reverse with EMA Cross
|
||||
\item Multi-timeframe RSI with EMA distance trading
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Market Instruments}
|
||||
|
||||
The strategies are optimized for various financial instruments:
|
||||
\begin{itemize}
|
||||
\item \textbf{Forex}: AUD/USD, EUR/USD
|
||||
\item \textbf{Precious Metals}: XAU/USD (Gold), XAG/USD (Silver)
|
||||
\item \textbf{Cryptocurrencies}: BTC/USD (Bitcoin)
|
||||
\item \textbf{Equities}: APPL, MSFT, TSLA
|
||||
\item \textbf{Indices}: SSE Index (Shanghai Stock Exchange)
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Paper Structure}
|
||||
|
||||
This paper is organized as follows:
|
||||
\begin{itemize}
|
||||
\item \textbf{Section 2}: MQL5 Basics - Fundamental programming concepts and structure
|
||||
\item \textbf{Section 3}: Algorithm Analysis - Detailed examination of each Expert Advisor
|
||||
\item \textbf{Section 4}: TradingView Strategies - Pine Script implementations
|
||||
\item \textbf{Section 5}: Profitability Analysis - Why these strategies work
|
||||
\item \textbf{Section 6}: Conclusion and Future Directions
|
||||
\end{itemize}
|
||||
@@ -0,0 +1,323 @@
|
||||
\section{MQL5 Programming Fundamentals}
|
||||
|
||||
MQL5 (MetaQuotes Language 5) is the programming language for developing Expert Advisors, indicators, and scripts in MetaTrader 5. Understanding MQL5 fundamentals is essential for implementing profitable trading algorithms.
|
||||
|
||||
\subsection{Program Structure}
|
||||
|
||||
An MQL5 Expert Advisor follows a specific structure:
|
||||
|
||||
\begin{lstlisting}[style=mql5style, caption=Basic MQL5 EA Structure]
|
||||
//+------------------------------------------------------------------+
|
||||
//| MyExpert.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
// Input parameters
|
||||
input double LotSize = 0.1;
|
||||
input int MagicNumber = 12345;
|
||||
|
||||
// Global variables
|
||||
CTrade trade;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Trading logic here
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
// Cleanup code
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Key Components}
|
||||
|
||||
\subsubsection{Property Directives}
|
||||
Property directives define metadata about the EA:
|
||||
\begin{itemize}
|
||||
\item \texttt{\#property copyright}: Copyright information
|
||||
\item \texttt{\#property version}: Version number
|
||||
\item \texttt{\#property strict}: Enables strict type checking
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Input Parameters}
|
||||
Input parameters allow users to configure the EA without modifying code:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
input int RSI_Period = 14;
|
||||
input double LotSize = 0.1;
|
||||
input bool UseStopLoss = true;
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Includes}
|
||||
Standard libraries provide essential functionality:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
#include <Trade\Trade.mqh> // Trading functions
|
||||
#include <Indicators\Trend.mqh> // Trend indicators
|
||||
#include <Indicators\Volumes.mqh> // Volume indicators
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Core Functions}
|
||||
|
||||
\subsubsection{OnInit()}
|
||||
Called once when the EA is loaded. Used for:
|
||||
\begin{itemize}
|
||||
\item Initializing indicators
|
||||
\item Setting up trade objects
|
||||
\item Validating parameters
|
||||
\item Allocating resources
|
||||
\end{itemize}
|
||||
|
||||
\begin{lstlisting}[style=mql5style, caption=OnInit Example]
|
||||
int OnInit()
|
||||
{
|
||||
// Create indicator handle
|
||||
rsiHandle = iRSI(_Symbol, PERIOD_H1, 14, PRICE_CLOSE);
|
||||
if(rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
Print("Error creating RSI indicator");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Configure trade object
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(10);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{OnTick()}
|
||||
Called on every price tick. Contains the main trading logic:
|
||||
\begin{lstlisting}[style=mql5style, caption=OnTick Example]
|
||||
void OnTick()
|
||||
{
|
||||
// Check for new bar (optional optimization)
|
||||
static datetime lastBarTime = 0;
|
||||
datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
|
||||
if(currentBarTime == lastBarTime)
|
||||
return; // Same bar, skip processing
|
||||
lastBarTime = currentBarTime;
|
||||
|
||||
// Get indicator values
|
||||
double rsi[];
|
||||
ArraySetAsSeries(rsi, true);
|
||||
if(CopyBuffer(rsiHandle, 0, 0, 2, rsi) <= 0)
|
||||
return;
|
||||
|
||||
// Trading logic
|
||||
if(rsi[0] < 30 && rsi[1] >= 30)
|
||||
{
|
||||
// Buy signal
|
||||
trade.Buy(LotSize, _Symbol);
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{OnDeinit()}
|
||||
Called when the EA is removed. Used for cleanup:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
// Release indicator handles
|
||||
if(rsiHandle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsiHandle);
|
||||
|
||||
// Delete chart objects
|
||||
ObjectsDeleteAll(0, "MyPrefix");
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Indicator Management}
|
||||
|
||||
\subsubsection{Creating Indicators}
|
||||
Indicators are created using built-in functions:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
int rsiHandle = iRSI(_Symbol, PERIOD_H1, 14, PRICE_CLOSE);
|
||||
int emaHandle = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_EMA, PRICE_CLOSE);
|
||||
int volumeHandle = iVolumes(_Symbol, PERIOD_CURRENT, VOLUME_TICK);
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Reading Indicator Values}
|
||||
Use \texttt{CopyBuffer()} to retrieve indicator data:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
double rsi[];
|
||||
ArraySetAsSeries(rsi, true); // Index 0 = most recent
|
||||
if(CopyBuffer(rsiHandle, 0, 0, 3, rsi) > 0)
|
||||
{
|
||||
double currentRSI = rsi[0];
|
||||
double previousRSI = rsi[1];
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Trading Operations}
|
||||
|
||||
\subsubsection{CTrade Class}
|
||||
The \texttt{CTrade} class provides a high-level interface for trading:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
CTrade trade;
|
||||
|
||||
// Configure
|
||||
trade.SetExpertMagicNumber(12345);
|
||||
trade.SetDeviationInPoints(10);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
|
||||
// Open positions
|
||||
trade.Buy(0.1, _Symbol, 0, 0, 0, "Buy Order");
|
||||
trade.Sell(0.1, _Symbol, 0, 0, 0, "Sell Order");
|
||||
|
||||
// Close positions
|
||||
trade.PositionClose(_Symbol);
|
||||
|
||||
// Modify positions
|
||||
trade.PositionModify(_Symbol, newSL, newTP);
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Position Management}
|
||||
Check and manage existing positions:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
// Check if position exists
|
||||
bool hasPosition = PositionSelect(_Symbol);
|
||||
|
||||
if(hasPosition)
|
||||
{
|
||||
// Get position details
|
||||
double profit = PositionGetDouble(POSITION_PROFIT);
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
// Close if profit target reached
|
||||
if(profit > 100)
|
||||
trade.PositionClose(_Symbol);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Price and Symbol Information}
|
||||
|
||||
\subsubsection{Getting Prices}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
||||
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Historical Data}
|
||||
Access bar data:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
double close = iClose(_Symbol, PERIOD_H1, 0); // Current bar
|
||||
double high = iHigh(_Symbol, PERIOD_H1, 0);
|
||||
double low = iLow(_Symbol, PERIOD_H1, 0);
|
||||
double open = iOpen(_Symbol, PERIOD_H1, 0);
|
||||
datetime time = iTime(_Symbol, PERIOD_H1, 0);
|
||||
long volume = iVolume(_Symbol, PERIOD_H1, 0);
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Time Management}
|
||||
|
||||
\subsubsection{Current Time}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
datetime currentTime = TimeCurrent(); // Server time
|
||||
datetime localTime = TimeLocal(); // Local time
|
||||
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(currentTime, timeStruct);
|
||||
int hour = timeStruct.hour;
|
||||
int dayOfWeek = timeStruct.day_of_week;
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Session Detection}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
bool IsAsianSession()
|
||||
{
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(TimeCurrent(), timeStruct);
|
||||
return (timeStruct.hour >= 0 && timeStruct.hour < 8);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Error Handling}
|
||||
|
||||
Always check for errors:
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
if(!trade.Buy(0.1, _Symbol))
|
||||
{
|
||||
int error = GetLastError();
|
||||
Print("Trade failed. Error: ", error);
|
||||
Print("Description: ", trade.ResultRetcodeDescription());
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Best Practices}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Always validate indicator handles}: Check for \texttt{INVALID_HANDLE}
|
||||
\item \textbf{Use ArraySetAsSeries()}: Makes array indexing intuitive (0 = most recent)
|
||||
\item \textbf{Check CopyBuffer() return values}: Ensure data was copied successfully
|
||||
\item \textbf{Release resources}: Free indicator handles in \texttt{OnDeinit()}
|
||||
\item \textbf{Handle errors gracefully}: Check return values and log errors
|
||||
\item \textbf{Optimize OnTick()}: Use new bar detection to avoid redundant processing
|
||||
\item \textbf{Use Magic Numbers}: Identify trades from your EA
|
||||
\item \textbf{Validate stop levels}: Check minimum stop distance requirements
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Common Patterns}
|
||||
|
||||
\subsubsection{New Bar Detection}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
static datetime lastBarTime = 0;
|
||||
datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
|
||||
if(currentBarTime == lastBarTime)
|
||||
return; // Same bar
|
||||
lastBarTime = currentBarTime;
|
||||
// Process new bar
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Crossover Detection}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
double current = indicator[0];
|
||||
double previous = indicator[1];
|
||||
|
||||
// Bullish crossover
|
||||
bool bullishCross = (previous < level) && (current > level);
|
||||
|
||||
// Bearish crossover
|
||||
bool bearishCross = (previous > level) && (current < level);
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Position Tracking}
|
||||
\begin{lstlisting}[style=mql5style]
|
||||
bool hasPosition = false;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
hasPosition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
These fundamentals form the foundation for all Expert Advisors examined in this paper. Understanding these concepts is crucial for implementing and modifying trading algorithms effectively.
|
||||
@@ -0,0 +1,390 @@
|
||||
\section{Profitability Analysis: Why These Strategies Make Money}
|
||||
|
||||
Understanding the theoretical and practical foundations of profitability is crucial for algorithmic trading success. This section examines why the strategies presented in this paper generate consistent profits.
|
||||
|
||||
\subsection{Theoretical Foundations}
|
||||
|
||||
\subsubsection{Market Inefficiencies}
|
||||
|
||||
Financial markets are not perfectly efficient. Several factors create exploitable opportunities:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Behavioral Biases}: Human traders exhibit predictable psychological patterns
|
||||
\item \textbf{Information Asymmetry}: Not all market participants have equal access to information
|
||||
\item \textbf{Market Microstructure}: Order flow and liquidity create temporary price distortions
|
||||
\item \textbf{Mean Reversion}: Prices tend to revert to historical averages
|
||||
\item \textbf{Trend Persistence}: Once established, trends often continue due to momentum
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Technical Analysis Validity}
|
||||
|
||||
Technical indicators work because they capture underlying market psychology:
|
||||
|
||||
\textbf{RSI (Relative Strength Index):}
|
||||
\begin{itemize}
|
||||
\item Measures momentum and identifies overbought/oversold conditions
|
||||
\item Works because markets exhibit mean-reverting behavior
|
||||
\item Extreme readings (above 70 or below 30) often precede reversals
|
||||
\item Crossovers signal momentum shifts
|
||||
\end{itemize}
|
||||
|
||||
\textbf{EMA (Exponential Moving Average):}
|
||||
\begin{itemize}
|
||||
\item Smooths price data to identify trends
|
||||
\item Price distance from EMA indicates trend strength
|
||||
\item Crossovers signal trend changes
|
||||
\item Slope indicates momentum
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Darvas Box Theory:}
|
||||
\begin{itemize}
|
||||
\item Identifies consolidation periods (accumulation/distribution)
|
||||
\item Breakouts from consolidation often continue due to momentum
|
||||
\item Volume confirmation validates breakout strength
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Strategy-Specific Profitability Factors}
|
||||
|
||||
\subsubsection{RSI Reversal Strategies}
|
||||
|
||||
\textbf{Why They Work:}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Mean Reversion Principle}: Markets tend to revert to their mean after extreme moves
|
||||
\item \textbf{Overbought/Oversold Logic}: When RSI reaches extremes, price has moved too far, too fast
|
||||
\item \textbf{Session Optimization}: Trading during specific sessions (e.g., Asian session for AUD/USD) captures predictable volatility patterns
|
||||
\item \textbf{Risk-Reward Ratio}: Small stop losses (5-290 pips) with larger targets (175-635 pips) create favorable risk-reward ratios
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Mathematical Foundation:}
|
||||
|
||||
The RSI is calculated as:
|
||||
\begin{equation}
|
||||
RSI = 100 - \frac{100}{1 + RS}
|
||||
\end{equation}
|
||||
|
||||
where $RS = \frac{\text{Average Gain}}{\text{Average Loss}}$ over the specified period.
|
||||
|
||||
When RSI reaches extreme levels:
|
||||
\begin{itemize}
|
||||
\item RSI > 70: Market has gained significantly more than lost, suggesting overbought condition
|
||||
\item RSI < 30: Market has lost significantly more than gained, suggesting oversold condition
|
||||
\end{itemize}
|
||||
|
||||
These extremes create reversal opportunities because:
|
||||
\begin{enumerate}
|
||||
\item Profit-taking occurs at overbought levels
|
||||
\item Value buyers enter at oversold levels
|
||||
\item Momentum exhaustion leads to reversals
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{EMA-Based Strategies}
|
||||
|
||||
\textbf{Why They Work:}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Trend Following}: EMAs identify and follow trends, which tend to persist
|
||||
\item \textbf{Slope Analysis}: EMA slope indicates momentum strength
|
||||
\item \textbf{Distance Trading}: Extreme price-EMA distances create mean reversion opportunities
|
||||
\item \textbf{Multi-EMA Confirmation}: Multiple EMAs provide trend confirmation
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Mathematical Foundation:}
|
||||
|
||||
EMA calculation:
|
||||
\begin{equation}
|
||||
EMA_t = \alpha \cdot Price_t + (1 - \alpha) \cdot EMA_{t-1}
|
||||
\end{equation}
|
||||
|
||||
where $\alpha = \frac{2}{Period + 1}$ is the smoothing factor.
|
||||
|
||||
EMA slope:
|
||||
\begin{equation}
|
||||
Slope = \frac{EMA_t - EMA_{t-1}}{Time}
|
||||
\end{equation}
|
||||
|
||||
Price-EMA distance:
|
||||
\begin{equation}
|
||||
Distance = \frac{|Price - EMA|}{Point}
|
||||
\end{equation}
|
||||
|
||||
When distance exceeds threshold:
|
||||
\begin{itemize}
|
||||
\item Price has deviated significantly from trend
|
||||
\item Mean reversion probability increases
|
||||
\item Entry opportunity exists
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Breakout Strategies (Darvas Box)}
|
||||
|
||||
\textbf{Why They Work:}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Consolidation Identification}: Boxes identify periods of accumulation/distribution
|
||||
\item \textbf{Momentum Breakouts}: Breakouts from consolidation often continue due to momentum
|
||||
\item \textbf{Volume Confirmation}: High volume validates breakout strength
|
||||
\item \textbf{Trend Alignment}: Trading breakouts in the direction of the trend increases success rate
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Market Psychology:}
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Consolidation Phase}: Buyers and sellers are in equilibrium, creating a "box"
|
||||
\item \textbf{Breakout Phase}: One side (buyers or sellers) gains control, price breaks out
|
||||
\item \textbf{Continuation}: Momentum carries price further in breakout direction
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Risk Management: The Key to Profitability}
|
||||
|
||||
Profitability isn't just about winning trades—it's about managing risk effectively.
|
||||
|
||||
\subsubsection{Position Sizing}
|
||||
|
||||
Proper position sizing ensures survival:
|
||||
|
||||
\begin{equation}
|
||||
Position Size = \frac{Risk Amount}{Stop Loss Distance}
|
||||
\end{equation}
|
||||
|
||||
Example:
|
||||
\begin{itemize}
|
||||
\item Account: \$10,000
|
||||
\item Risk per trade: 1\% = \$100
|
||||
\item Stop loss: 50 pips
|
||||
\item Position size: \$100 / 50 pips = 2 pips per dollar
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Stop Loss Placement}
|
||||
|
||||
Stop losses protect capital:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Technical Stops}: Based on support/resistance levels
|
||||
\item \textbf{Percentage Stops}: Fixed percentage of entry price
|
||||
\item \textbf{ATR-Based Stops}: Based on Average True Range (volatility)
|
||||
\item \textbf{Trailing Stops}: Move with price to protect profits
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Take Profit Targets}
|
||||
|
||||
Profit targets lock in gains:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Fixed Targets}: Based on risk-reward ratio (e.g., 2:1, 3:1)
|
||||
\item \textbf{Technical Targets}: Based on support/resistance levels
|
||||
\item \textbf{Partial Exits}: Scale out positions at multiple levels
|
||||
\item \textbf{Trailing Stops}: Let winners run while protecting profits
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Market Timing and Session Optimization}
|
||||
|
||||
\subsubsection{Why Session-Based Trading Works}
|
||||
|
||||
Different trading sessions exhibit distinct characteristics:
|
||||
|
||||
\textbf{Asian Session (00:00-08:00 UTC):}
|
||||
\begin{itemize}
|
||||
\item Lower volatility
|
||||
\item Range-bound price action
|
||||
\item Ideal for mean reversion strategies
|
||||
\item AUD/USD and JPY pairs most active
|
||||
\end{itemize}
|
||||
|
||||
\textbf{London Session (08:00-16:00 UTC):}
|
||||
\begin{itemize}
|
||||
\item High volatility
|
||||
\item Strong trends
|
||||
\item Ideal for breakout and trend-following strategies
|
||||
\item EUR/USD, GBP/USD most active
|
||||
\end{itemize}
|
||||
|
||||
\textbf{New York Session (13:00-21:00 UTC):}
|
||||
\begin{itemize}
|
||||
\item High volatility
|
||||
\item Overlaps with London (13:00-16:00) = highest volatility
|
||||
\item Ideal for momentum strategies
|
||||
\item USD pairs most active
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Day-of-Week Patterns}
|
||||
|
||||
Certain days exhibit predictable patterns:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Monday}: Often gap-filling behavior
|
||||
\item \textbf{Friday}: Profit-taking before weekend
|
||||
\item \textbf{Midweek (Tue-Thu)}: Most reliable trends
|
||||
\end{itemize}
|
||||
|
||||
Many strategies restrict trading to Tuesday-Thursday for this reason.
|
||||
|
||||
\subsection{Strategy Diversification}
|
||||
|
||||
\subsubsection{Multi-Strategy Approach}
|
||||
|
||||
Combining multiple strategies reduces risk:
|
||||
|
||||
\textbf{Benefits:}
|
||||
\begin{enumerate}
|
||||
\item \textbf{Uncorrelated Returns}: Different strategies perform in different market conditions
|
||||
\item \textbf{Risk Reduction}: Losses in one strategy offset by gains in another
|
||||
\item \textbf{Consistent Performance}: Portfolio of strategies more stable than individual strategy
|
||||
\item \textbf{Market Adaptation}: Some strategies work in trending markets, others in ranging markets
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Example: RSI Follow/Reverse/EMA Cross}
|
||||
\begin{itemize}
|
||||
\item RSI Follow: Works in trending markets
|
||||
\item RSI Reverse: Works in ranging markets
|
||||
\item EMA Cross: Works in breakout conditions
|
||||
\item Combined: Adapts to various market conditions
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Backtesting and Optimization}
|
||||
|
||||
\subsubsection{Why Backtesting Matters}
|
||||
|
||||
Backtesting validates strategies before live trading:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Historical Validation}: Tests strategy on past data
|
||||
\item \textbf{Parameter Optimization}: Finds optimal parameter values
|
||||
\item \textbf{Risk Assessment}: Identifies maximum drawdowns
|
||||
\item \textbf{Performance Metrics}: Calculates win rate, profit factor, Sharpe ratio
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Key Performance Metrics}
|
||||
|
||||
\textbf{Win Rate:}
|
||||
\begin{equation}
|
||||
Win Rate = \frac{Winning Trades}{Total Trades} \times 100\%
|
||||
\end{equation}
|
||||
|
||||
\textbf{Profit Factor:}
|
||||
\begin{equation}
|
||||
Profit Factor = \frac{Total Profit}{Total Loss}
|
||||
\end{equation}
|
||||
A profit factor > 1.0 indicates profitability.
|
||||
|
||||
\textbf{Sharpe Ratio:}
|
||||
\begin{equation}
|
||||
Sharpe Ratio = \frac{Return - Risk Free Rate}{Standard Deviation of Returns}
|
||||
\end{equation}
|
||||
Higher Sharpe ratio indicates better risk-adjusted returns.
|
||||
|
||||
\textbf{Maximum Drawdown:}
|
||||
\begin{equation}
|
||||
Max Drawdown = \frac{Peak Equity - Trough Equity}{Peak Equity}
|
||||
\end{equation}
|
||||
Lower drawdown indicates better capital preservation.
|
||||
|
||||
\subsection{Common Pitfalls and How Strategies Avoid Them}
|
||||
|
||||
\subsubsection{Over-Trading}
|
||||
|
||||
\textbf{Problem:} Trading too frequently erodes profits through commissions and spreads.
|
||||
|
||||
\textbf{Solutions in Our Strategies:}
|
||||
\begin{itemize}
|
||||
\item Cooldown periods after trades
|
||||
\item Session-based restrictions
|
||||
\item Multiple confirmation requirements
|
||||
\item Maximum trades per event limits
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Revenge Trading}
|
||||
|
||||
\textbf{Problem:} Emotional trading after losses leads to poor decisions.
|
||||
|
||||
\textbf{Solutions:}
|
||||
\begin{itemize}
|
||||
\item Automated execution (no emotions)
|
||||
\item Cooldown periods after losses
|
||||
\item Maximum drawdown protection
|
||||
\item Strategy locking mechanisms
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Inadequate Risk Management}
|
||||
|
||||
\textbf{Problem:} Large losses wipe out multiple small wins.
|
||||
|
||||
\textbf{Solutions:}
|
||||
\begin{itemize}
|
||||
\item Strict stop losses on every trade
|
||||
\item Position sizing based on risk
|
||||
\item Maximum drawdown limits
|
||||
\item Trailing stops to protect profits
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Market Regime Changes}
|
||||
|
||||
\textbf{Problem:} Strategies that work in one market condition fail in others.
|
||||
|
||||
\textbf{Solutions:}
|
||||
\begin{itemize}
|
||||
\item Multi-strategy approaches
|
||||
\item Trend strength filters
|
||||
\item Volatility-based position sizing
|
||||
\item Market condition detection
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Real-World Profitability Factors}
|
||||
|
||||
\subsubsection{Execution Quality}
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Slippage}: Difference between expected and actual execution price
|
||||
\item \textbf{Spread Costs}: Bid-ask spread erodes profits
|
||||
\item \textbf{Latency}: Delays in execution can reduce profitability
|
||||
\item \textbf{Order Fills}: IOC (Immediate or Cancel) vs FOK (Fill or Kill) strategies
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Broker Selection}
|
||||
|
||||
Important factors:
|
||||
\begin{enumerate}
|
||||
\item \textbf{Spreads}: Tighter spreads = higher profits
|
||||
\item \textbf{Execution Speed}: Faster execution = better fills
|
||||
\item \textbf{Reliability}: Uptime and connection stability
|
||||
\item \textbf{Regulation}: Regulated brokers provide protection
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Market Conditions}
|
||||
|
||||
Strategies perform differently in various conditions:
|
||||
|
||||
\textbf{Trending Markets:}
|
||||
\begin{itemize}
|
||||
\item EMA-based strategies excel
|
||||
\item Breakout strategies perform well
|
||||
\item RSI follow strategies work
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Ranging Markets:}
|
||||
\begin{itemize}
|
||||
\item RSI reversal strategies excel
|
||||
\item Mean reversion approaches work
|
||||
\item Range-bound trading profitable
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Volatile Markets:}
|
||||
\begin{itemize}
|
||||
\item Larger stop losses required
|
||||
\item Position sizing must be reduced
|
||||
\item Trailing stops essential
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Conclusion: The Path to Profitability}
|
||||
|
||||
Successful algorithmic trading requires:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Sound Strategy}: Based on valid technical analysis principles
|
||||
\item \textbf{Risk Management}: Strict stop losses and position sizing
|
||||
\item \textbf{Market Timing}: Trading during optimal sessions and conditions
|
||||
\item \textbf{Diversification}: Multiple strategies for different market conditions
|
||||
\item \textbf{Discipline}: Following rules without emotion
|
||||
\item \textbf{Continuous Improvement}: Backtesting, optimization, and adaptation
|
||||
\end{enumerate}
|
||||
|
||||
The strategies presented in this paper incorporate these principles, explaining their profitability. However, past performance does not guarantee future results, and proper risk management is essential for long-term success.
|
||||
@@ -0,0 +1,282 @@
|
||||
\section{TradingView Pine Script Strategies}
|
||||
|
||||
TradingView's Pine Script provides a powerful platform for developing and backtesting trading strategies. This section examines a sophisticated multi-timeframe RSI strategy with EMA distance trading.
|
||||
|
||||
\subsection{Pine Script Overview}
|
||||
|
||||
Pine Script is TradingView's domain-specific language for creating custom indicators and strategies. Unlike MQL5, Pine Script is designed specifically for technical analysis and strategy development.
|
||||
|
||||
\subsection{SSE Index RSI Bounce Strategy}
|
||||
|
||||
This strategy is specifically designed for the Shanghai Stock Exchange (SSE) Index, combining multiple timeframe RSI analysis with EMA distance trading.
|
||||
|
||||
\subsubsection{Strategy Architecture}
|
||||
|
||||
The strategy implements three distinct entry mechanisms:
|
||||
|
||||
\textbf{1. Weekly RSI Bounce:}
|
||||
\begin{itemize}
|
||||
\item Monitors weekly RSI for oversold conditions
|
||||
\item Enters long when weekly RSI crosses above oversold level (27)
|
||||
\item Position size: 14\% of equity
|
||||
\item Targets major trend reversals
|
||||
\end{itemize}
|
||||
|
||||
\textbf{2. Daily RSI Bounce:}
|
||||
\begin{itemize}
|
||||
\item Monitors daily RSI for oversold conditions
|
||||
\item Enters long when daily RSI crosses above oversold level (27)
|
||||
\item Position size: 11\% of equity
|
||||
\item Captures short-term momentum shifts
|
||||
\end{itemize}
|
||||
|
||||
\textbf{3. EMA Distance Entry:}
|
||||
\begin{itemize}
|
||||
\item Enters when price extends 16+ pips from 200 EMA
|
||||
\item Requires price to remain above EMA
|
||||
\item Position size: 53\% of equity
|
||||
\item Exploits mean reversion opportunities
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Core Implementation}
|
||||
|
||||
\begin{lstlisting}[style=pinescriptstyle, caption=Pine Script Strategy Structure]
|
||||
//@version=6
|
||||
strategy("SSE Index RSI Bounce Strategy", overlay=true,
|
||||
default_qty_type=strategy.percent_of_equity,
|
||||
initial_capital=10000, pyramiding=100)
|
||||
|
||||
// Input parameters
|
||||
rsi_length = input.int(17, "RSI Length", minval=1)
|
||||
rsi_oversold = input.int(27, "RSI Oversold Level", minval=1, maxval=50)
|
||||
rsi_overbought = input.int(86, "RSI Overbought Level", minval=50, maxval=100)
|
||||
ema_length = input.int(177, "EMA Length", minval=1)
|
||||
|
||||
// Calculate indicators
|
||||
rsi_daily = ta.rsi(close, rsi_length)
|
||||
rsi_weekly = request.security(syminfo.tickerid, "1W", ta.rsi(close, rsi_length))
|
||||
ema_200 = ta.ema(close, ema_length)
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Multi-Timeframe Analysis}
|
||||
|
||||
Pine Script's \texttt{request.security()} function enables seamless multi-timeframe analysis:
|
||||
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Get weekly RSI
|
||||
rsi_weekly = request.security(syminfo.tickerid, "1W", ta.rsi(close, rsi_length))
|
||||
rsi_weekly_prev = request.security(syminfo.tickerid, "1W", ta.rsi(close, rsi_length)[1])
|
||||
|
||||
// Weekly bounce detection
|
||||
weekly_bounce = rsi_weekly_prev < rsi_oversold and rsi_weekly > rsi_oversold
|
||||
\end{lstlisting}
|
||||
|
||||
This allows the strategy to analyze weekly conditions while executing on any timeframe.
|
||||
|
||||
\subsubsection{Entry Logic}
|
||||
|
||||
\textbf{RSI Bounce Detection:}
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Daily RSI bounce: RSI was below 30 and now crosses above 30
|
||||
daily_bounce = rsi_daily[1] < rsi_oversold and rsi_daily > rsi_oversold
|
||||
|
||||
// Weekly RSI bounce: RSI was below 30 and now crosses above 30
|
||||
weekly_bounce = rsi_weekly_prev < rsi_oversold and rsi_weekly > rsi_oversold
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{EMA Distance Calculation:}
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Calculate pip size (adjusts for instrument)
|
||||
pip_size = syminfo.mintick * 10
|
||||
price_ema_distance = math.abs(close - ema_200) / pip_size
|
||||
|
||||
// EMA distance entry condition
|
||||
ema_distance_entry = price_ema_distance >= ema_distance_threshold * 100
|
||||
and close > ema_200
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Position Management}
|
||||
|
||||
The strategy uses separate position tracking for each entry type:
|
||||
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Track positions separately
|
||||
var int weekly_trade_count = 0
|
||||
var int daily_trade_count = 0
|
||||
var int ema_distance_trade_count = 0
|
||||
var float weekly_position_qty = 0.0
|
||||
var float daily_position_qty = 0.0
|
||||
var float ema_distance_position_qty = 0.0
|
||||
|
||||
// Entry execution
|
||||
if weekly_entry
|
||||
strategy.entry("Weekly_Long", strategy.long, qty=weekly_position_size,
|
||||
comment="Weekly RSI Bounce #" + str.tostring(weekly_trade_count + 1))
|
||||
weekly_trade_count := weekly_trade_count + 1
|
||||
weekly_position_qty := weekly_position_qty + weekly_position_size
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Exit Logic}
|
||||
|
||||
\textbf{Partial Exits:}
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Partial exit for weekly positions on daily RSI overbought
|
||||
if daily_rsi_overbought and weekly_position_qty > 0
|
||||
exit_qty = weekly_position_qty * (partial_exit_percent / 100)
|
||||
strategy.close("Weekly_Long", qty=exit_qty,
|
||||
comment="Weekly Partial Exit Daily OB")
|
||||
weekly_position_qty := math.max(0, weekly_position_qty - exit_qty)
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Complete Exits:}
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Complete exit for weekly positions on weekly RSI overbought
|
||||
if weekly_rsi_overbought and weekly_position_qty > 0
|
||||
strategy.close("Weekly_Long", comment="Complete Exit Weekly OB")
|
||||
weekly_position_qty := 0.0
|
||||
weekly_trade_count := 0
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{EMA Crossover Exit:}
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Exit all positions when EMA crosses from above price to below price
|
||||
ema_above_price_prev = ema_200[1] > close[1]
|
||||
ema_below_price_now = ema_200 < close
|
||||
ema_exit_condition = ema_above_price_prev and ema_below_price_now
|
||||
|
||||
if ema_exit_condition and strategy.position_size > 0
|
||||
strategy.close_all("EMA Cross Exit")
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Enhanced Version Features}
|
||||
|
||||
The enhanced version adds sophisticated filtering mechanisms:
|
||||
|
||||
\textbf{EMA Alignment Filter:}
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Calculate fast and slow EMAs for alignment check
|
||||
fast_ema = ta.ema(close, fast_ema_length)
|
||||
slow_ema = ta.ema(close, slow_ema_length)
|
||||
ema_alignment_distance = math.abs(fast_ema - slow_ema) / pip_size
|
||||
|
||||
// EMA Alignment Filter Logic
|
||||
ema_alignment_ok = false
|
||||
if ema_alignment_direction == "both"
|
||||
ema_alignment_ok := ema_alignment_distance >= ema_alignment_threshold
|
||||
else if ema_alignment_direction == "above"
|
||||
ema_alignment_ok := fast_ema > slow_ema and
|
||||
ema_alignment_distance >= ema_alignment_threshold
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Price Proximity Filter:}
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Prevent trades when price is too close to 200 EMA
|
||||
price_proximity_ok = price_ema_distance >= price_proximity_threshold * 100
|
||||
|
||||
// Enhanced EMA Distance Entry with filters
|
||||
ema_distance_entry = price_ema_distance >= ema_distance_threshold * 100
|
||||
and close > ema_200
|
||||
and ema_alignment_ok
|
||||
and price_proximity_ok
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Visual Feedback}
|
||||
|
||||
The strategy provides comprehensive visual feedback:
|
||||
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
// Background colors for conditions
|
||||
bgcolor(weekly_bounce ? color.new(color.green, 90) : na,
|
||||
title="Weekly RSI Bounce")
|
||||
bgcolor(daily_bounce ? color.new(color.blue, 90) : na,
|
||||
title="Daily RSI Bounce")
|
||||
bgcolor(ema_distance_entry ? color.new(color.purple, 90) : na,
|
||||
title="EMA Distance Entry")
|
||||
|
||||
// Plot entry and exit signals
|
||||
plotshape(weekly_entry, "Weekly Entry", shape.triangleup,
|
||||
location.belowbar, color.green, size=size.normal)
|
||||
plotshape(daily_entry, "Daily Entry", shape.triangleup,
|
||||
location.belowbar, color.blue, size=size.small)
|
||||
plotshape(ema_distance_entry, "EMA Distance Entry", shape.triangleup,
|
||||
location.belowbar, color.purple, size=size.normal)
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Information Table}
|
||||
|
||||
Real-time status display:
|
||||
|
||||
\begin{lstlisting}[style=pinescriptstyle]
|
||||
var table info_table = table.new(position.top_right, 2, 16,
|
||||
bgcolor=color.white, border_width=1)
|
||||
if barstate.islast
|
||||
table.cell(info_table, 0, 0, "Indicator", bgcolor=color.gray)
|
||||
table.cell(info_table, 1, 0, "Value", bgcolor=color.gray)
|
||||
table.cell(info_table, 0, 1, "Daily RSI", bgcolor=color.white)
|
||||
table.cell(info_table, 1, 1, str.tostring(rsi_daily, "#.##"),
|
||||
bgcolor=color.white)
|
||||
// ... additional cells
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Key Differences: Pine Script vs MQL5}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Pine Script vs MQL5 Comparison}
|
||||
\label{tab:pinescript_vs_mql5}
|
||||
\begin{tabular}{lll}
|
||||
\toprule
|
||||
\textbf{Feature} & \textbf{Pine Script} & \textbf{MQL5} \\
|
||||
\midrule
|
||||
Platform & TradingView (Cloud) & MetaTrader 5 (Desktop) \\
|
||||
Execution & Backtesting/Paper Trading & Live Trading \\
|
||||
Multi-Timeframe & \texttt{request.security()} & Manual timeframe switching \\
|
||||
Position Management & Built-in strategy functions & Manual CTrade class \\
|
||||
Visualization & Built-in plotting & Manual object creation \\
|
||||
Real-time Data & Cloud-based & Broker connection required \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{Strategy Rationale}
|
||||
|
||||
\textbf{Why This Strategy Works:}
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Multi-Timeframe Confirmation}: Weekly signals provide major trend direction, daily signals capture short-term opportunities
|
||||
\item \textbf{RSI Mean Reversion}: Oversold bounces in equity markets often lead to profitable reversals
|
||||
\item \textbf{EMA Distance Trading}: Extreme price deviations from EMA tend to revert, creating profit opportunities
|
||||
\item \textbf{Partial Profit Taking}: Scaling out positions at overbought levels locks in profits while allowing for continued upside
|
||||
\item \textbf{EMA Exit Protection}: Crossover exits protect capital during major trend reversals
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Market-Specific Optimization}
|
||||
|
||||
The strategy is optimized for Chinese equity markets:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Volatility Characteristics}: Chinese markets exhibit high volatility, making RSI bounces more frequent
|
||||
\item \textbf{Emotion-Driven Moves}: Retail-driven markets create more extreme RSI readings
|
||||
\item \textbf{Session Patterns}: Trading during specific hours captures optimal market conditions
|
||||
\item \textbf{Position Sizing}: Larger position sizes (up to 53\%) capitalize on high-probability setups
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Performance Considerations}
|
||||
|
||||
\textbf{Advantages of Pine Script:}
|
||||
\begin{itemize}
|
||||
\item Easy backtesting with historical data
|
||||
\item Cloud-based execution (no local resources required)
|
||||
\item Built-in visualization and debugging tools
|
||||
\item Community sharing and strategy marketplace
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Limitations:}
|
||||
\begin{itemize}
|
||||
\item Limited to TradingView platform
|
||||
\item No direct broker integration (requires manual execution or TradingView broker)
|
||||
\item Less control over execution details compared to MQL5
|
||||
\item Cloud dependency (requires internet connection)
|
||||
\end{itemize}
|
||||
|
||||
The TradingView strategy demonstrates how modern cloud-based platforms enable sophisticated multi-timeframe strategies with comprehensive risk management and visual feedback, complementing the MQL5 implementations for different trading needs and preferences.
|
||||
@@ -0,0 +1,31 @@
|
||||
category,metric,value
|
||||
retail_pnl,mean,8614729.4515151
|
||||
retail_pnl,median,8631163.993755288
|
||||
retail_pnl,std,1221404.5416973752
|
||||
retail_pnl,min,5461509.966302657
|
||||
retail_pnl,max,11248053.504957156
|
||||
retail_pnl,win_rate,1.0
|
||||
retail_pnl,sharpe,7.05313363215703
|
||||
big_player_pnl,mean,-7956785.540934292
|
||||
big_player_pnl,median,-8067419.647579128
|
||||
big_player_pnl,std,1756542.1388380504
|
||||
big_player_pnl,min,-12098888.920649894
|
||||
big_player_pnl,max,-2028789.0074428658
|
||||
big_player_pnl,win_rate,0.0
|
||||
big_player_pnl,sharpe,-4.529800546770653
|
||||
market_efficiency,mean,0.0
|
||||
market_efficiency,median,0.0
|
||||
market_efficiency,std,0.0
|
||||
market_efficiency,min,0.0
|
||||
market_efficiency,max,0.0
|
||||
nash_equilibrium,mean_price,1373.3520869439653
|
||||
nash_equilibrium,std_price,48.785408060992765
|
||||
nash_equilibrium,mean_deviation,12.737137777832599
|
||||
nash_equilibrium,mean_sentiment,0.4521046053554347
|
||||
fomo_herding,avg_sentiment_volatility,0.1383601368593139
|
||||
fomo_herding,avg_volume_volatility,33.55640988411156
|
||||
fomo_herding,sentiment_volume_correlation,0.6772045810140649
|
||||
fomo_herding,sentiment_volume_correlation_std,0.1179246963409413
|
||||
exploitation,mean,0.048455310069913445
|
||||
exploitation,median,0.05467332450371269
|
||||
exploitation,std,0.03449441341865835
|
||||
|
@@ -0,0 +1,101 @@
|
||||
equilibrium_price,equilibrium_retail_sentiment,price_deviation,simulation
|
||||
1447.8733950268422,0.47801989901527603,13.409977730738168,0
|
||||
1313.663535737757,0.445606239477453,12.165292574010012,1
|
||||
1361.4259559595214,0.41760991878726444,12.704991462926667,2
|
||||
1416.0626491538337,0.46289493154594,13.088133528472866,3
|
||||
1451.7907412152858,0.4860691633829841,13.325821105642742,4
|
||||
1474.0938626905786,0.4656986188710589,13.639549319465605,5
|
||||
1388.7414915334284,0.46310274882935926,13.017047889517302,6
|
||||
1314.4278578987771,0.4543068663205997,12.304249955502065,7
|
||||
1368.9303722958962,0.46678858127207823,12.531448648195175,8
|
||||
1455.4745585540472,0.4572452629310465,13.512716778224451,9
|
||||
1373.5786248578934,0.4544788059619787,12.792355134767524,10
|
||||
1418.9466602426405,0.44573521492839296,12.997856974946552,11
|
||||
1336.3272772704308,0.452065871379423,12.38664915516847,12
|
||||
1443.2416417963482,0.4698238557843468,13.612396114774537,13
|
||||
1392.6381229641108,0.4414853017802744,12.818522968441457,14
|
||||
1323.162880553666,0.4390131126074001,12.216922624920368,15
|
||||
1468.599884042251,0.45923814426462883,13.689553945071898,16
|
||||
1350.5576952918793,0.4437768911352807,12.521655857038056,17
|
||||
1321.0256338037009,0.4338254980999315,12.36248949301713,18
|
||||
1360.9052240153403,0.4622389074871943,12.90472873746832,19
|
||||
1381.96784411268,0.45796482748458195,12.797321557233362,20
|
||||
1322.260329766525,0.43025988786243385,12.161331267732079,21
|
||||
1371.9104903070024,0.4437538074689534,12.718888201238912,22
|
||||
1392.4784021937016,0.4600902606620035,13.026182722913985,23
|
||||
1370.7124085280252,0.4540354787611542,12.617710951529517,24
|
||||
1394.0130957440156,0.47039125819553734,13.005884638361243,25
|
||||
1339.052258249983,0.46556415004463575,12.500317940643821,26
|
||||
1358.4278306235958,0.44899860164203426,12.79840728090041,27
|
||||
1396.6526661056973,0.44167193867851096,13.258389804050193,28
|
||||
1390.3191912198383,0.47473490194617013,12.715730365786197,29
|
||||
1362.0786914284556,0.4531051970655923,12.676010411316541,30
|
||||
1398.6915149138053,0.46764620192072853,13.075287402012652,31
|
||||
1285.7798492616669,0.4335114728926592,12.100081435874996,32
|
||||
1380.4644626510726,0.4722628463498135,12.691952525849366,33
|
||||
1338.3420518018584,0.4474879227143614,12.329157786735381,34
|
||||
1429.1656220179534,0.4454024743396629,13.122172471925628,35
|
||||
1316.9866676649976,0.45163631176134533,12.117782937793125,36
|
||||
1442.7250361218337,0.46782970787894057,13.35714383329898,37
|
||||
1393.6737906519124,0.454548753344781,13.005295075008895,38
|
||||
1393.7039940721593,0.4678702390206391,13.190782177077818,39
|
||||
1423.8114040840742,0.4543604303922943,13.04453172796848,40
|
||||
1354.206069928975,0.44226494251652043,12.604528594625995,41
|
||||
1400.7181785684643,0.4664853657554793,12.947873111611626,42
|
||||
1329.568180782063,0.44215213271073833,12.312894277227555,43
|
||||
1325.4618983417672,0.4175282018234954,12.243816870884961,44
|
||||
1390.009320261334,0.4575311946450212,12.818723377029356,45
|
||||
1357.0889077887116,0.4396807874735435,12.672747163624356,46
|
||||
1335.337644331878,0.45601994884828834,12.499553998482822,47
|
||||
1409.0464657201403,0.4371366033181275,12.969428364019551,48
|
||||
1265.201640639625,0.441063300880349,11.792385272909144,49
|
||||
1355.8638874751846,0.4617934477133493,12.421536568949579,50
|
||||
1369.5262004471883,0.4645157820748979,12.64151468471009,51
|
||||
1345.4340372012095,0.4417527052714022,12.310063705633018,52
|
||||
1437.2902373216382,0.46069647655479506,13.346252622005581,53
|
||||
1455.8658954755329,0.44666986080671256,13.319312820875052,54
|
||||
1340.831265749096,0.45207543974288356,12.364571906628024,55
|
||||
1330.761367580891,0.45123277191185335,12.310297724515776,56
|
||||
1333.5950965870184,0.4620912392086873,12.436328478937307,57
|
||||
1387.7377424627548,0.4506737464698286,12.941428835652077,58
|
||||
1322.9812300661229,0.4374723305460012,12.20482354801271,59
|
||||
1340.0035637967069,0.4441162707228317,12.534632552116975,60
|
||||
1350.9936622855726,0.4527439311973239,12.7029060996593,61
|
||||
1378.258948174364,0.43138438903894105,12.726105527730013,62
|
||||
1328.4681298769676,0.44060454287797174,12.426338824756687,63
|
||||
1346.497914022904,0.46170633654711357,12.582857343926383,64
|
||||
1380.0703068012142,0.43461344137606844,12.410083425494292,65
|
||||
1321.4571827599696,0.44216801893783764,12.042894574502716,66
|
||||
1449.0695281637886,0.48315594500470044,13.442299741933168,67
|
||||
1249.2500796341183,0.43252737477591036,11.581656584725422,68
|
||||
1385.427512073855,0.43582395560405,13.027312102794722,69
|
||||
1324.34185146344,0.4365163236730455,12.239563559059762,70
|
||||
1443.9885467541696,0.4586155632505039,13.363967586926318,71
|
||||
1380.5943849119997,0.44368273441961925,12.596858847578046,72
|
||||
1373.4575392908378,0.4701312334596417,12.717895400608148,73
|
||||
1371.0754868035424,0.4649615122456692,12.805757360664733,74
|
||||
1340.9105538450317,0.4301428897161423,12.263955792770842,75
|
||||
1358.3266359001766,0.45685432196153786,12.824257718409102,76
|
||||
1420.1330374813558,0.4598375321400079,13.353019601042607,77
|
||||
1356.4379236793218,0.42626478349112906,12.61374843613421,78
|
||||
1401.765466005601,0.46143227219617505,12.859631701675996,79
|
||||
1417.2165185605998,0.45419889994726415,13.220748558726642,80
|
||||
1379.4458313798962,0.44698132799131385,12.687748896642102,81
|
||||
1424.510302102315,0.4644608930614276,13.224755752621276,82
|
||||
1326.5546985598946,0.45114214523950985,12.426096839664455,83
|
||||
1341.3022096990337,0.4376963116800946,12.55595525625449,84
|
||||
1339.6319611697677,0.4342183267179811,12.237472094749746,85
|
||||
1307.8694323317086,0.43698345018237683,12.081158056984089,86
|
||||
1416.24588646309,0.47526208701173933,12.977149094738111,87
|
||||
1373.1881616055648,0.4501428102080031,12.637826391382628,88
|
||||
1375.852681750436,0.44285256683850055,12.756657215609037,89
|
||||
1408.5598138576108,0.44993757698512543,12.94014703875385,90
|
||||
1354.3879789420166,0.4535986919888386,12.607591689446867,91
|
||||
1258.4955368148371,0.4579971950005238,11.52221817518219,92
|
||||
1296.2772354526833,0.46163579714004965,12.316328985011081,93
|
||||
1464.4387227717746,0.4538567360172558,13.57164142361563,94
|
||||
1436.8984101766366,0.4711380136416546,13.302846651834507,95
|
||||
1437.5482383971946,0.4543299808687397,13.275070910810722,96
|
||||
1434.7789506443082,0.45895311486768636,13.454922589749462,97
|
||||
1428.8013416269525,0.4378173410609378,13.253531430829918,98
|
||||
1301.4655952106093,0.45898711389749713,12.077363508248334,99
|
||||
|
@@ -0,0 +1,101 @@
|
||||
simulation,final_price,total_retail_pnl,total_big_player_pnl,avg_retail_sentiment,retail_sentiment_volatility,retail_volume_volatility,sentiment_volume_correlation,market_efficiency,equilibrium_price,equilibrium_sentiment
|
||||
0,1334.5531299819029,8538663.550678484,-10567812.520247236,0.4873064727853758,0.17559767459909273,50.76720681981193,0.8413660459448429,0,1447.8733950268422,0.47801989901527603
|
||||
1,1347.181372582273,8740457.350907166,-8045943.615315739,0.48668723820803,0.13669290026730158,34.69020868027012,0.731062550205287,0,1313.663535737757,0.445606239477453
|
||||
2,1443.8478747572294,8934820.843645275,-5317451.379970444,0.4860867415056627,0.11280162465629424,20.835278765891452,0.4603502004461008,0,1361.4259559595214,0.41760991878726444
|
||||
3,1356.426779671691,7718121.13239067,-7346043.6581982095,0.5112595533572952,0.11808230688719258,21.830162782883853,0.4756851222163644,0,1416.0626491538337,0.46289493154594
|
||||
4,1448.734542365047,10260905.066176381,-10783061.429217653,0.5048266304148424,0.1436055920715458,35.44763021118724,0.7098841721578628,0,1451.7907412152858,0.4860691633829841
|
||||
5,1461.1061938321416,9255823.20537786,-7289155.1593855275,0.4979875210459448,0.11774407120561121,21.3497981925947,0.4596498776217032,0,1474.0938626905786,0.4656986188710589
|
||||
6,1334.8039571862969,8613843.231625123,-8551452.161241364,0.4839422095466989,0.1646550176630392,49.73766446605985,0.8246107908768068,0,1388.7414915334284,0.46310274882935926
|
||||
7,1355.9829198071407,8909909.910612196,-8434039.553810185,0.5017448755476411,0.12274908717815863,21.8741634736089,0.5496247836612803,0,1314.4278578987771,0.4543068663205997
|
||||
8,1299.2882716409792,7772110.710805373,-8289241.963086789,0.47663615729460623,0.18256008237486293,55.599719260483354,0.8475401322319229,0,1368.9303722958962,0.46678858127207823
|
||||
9,1466.6717792191073,10631767.670595724,-9264632.536214754,0.49814070584989795,0.13939662433325156,36.223485906859985,0.7650991354540387,0,1455.4745585540472,0.4572452629310465
|
||||
10,1429.190534755681,10118208.189294808,-11696499.039782014,0.49790904782903395,0.1412513461496078,34.04110351080368,0.67134385750234,0,1373.5786248578934,0.4544788059619787
|
||||
11,1417.8331080533326,9218737.684892975,-9961098.165220387,0.5053605406973568,0.12454653606916755,24.799629757891203,0.5821655758604377,0,1418.9466602426405,0.44573521492839296
|
||||
12,1329.0945961692173,8523155.631481657,-8340068.860587724,0.5000925739446243,0.1290570106044845,24.45106011366567,0.6529020344692885,0,1336.3272772704308,0.452065871379423
|
||||
13,1464.490258493867,10195769.120048247,-7099834.390439872,0.5072653302771049,0.11549727410835064,21.332583111495133,0.4761159656183557,0,1443.2416417963482,0.4698238557843468
|
||||
14,1338.8496379510298,7475966.0556102265,-7401725.6662732465,0.46483350427564113,0.1695054668118581,51.835333679143716,0.817446679230841,0,1392.6381229641108,0.4414853017802744
|
||||
15,1292.0345937646848,6811355.380903413,-6215771.900021982,0.4702516721944348,0.15713328378244468,45.08094751328537,0.7786993986534929,0,1323.162880553666,0.4390131126074001
|
||||
16,1412.5298602137384,9320573.506780151,-8833800.645659188,0.49695990415225216,0.14350771848585273,37.40951472679465,0.7325734414720264,0,1468.599884042251,0.45923814426462883
|
||||
17,1350.3804533318755,8390795.883600645,-8841066.75616963,0.48410835067418795,0.16026372753757903,48.16514660576826,0.8076218336769443,0,1350.5576952918793,0.4437768911352807
|
||||
18,1353.8880797353158,8250940.562517967,-5332564.244718521,0.47739075198807074,0.1449370565718803,40.6604420024838,0.7779273579324755,0,1321.0256338037009,0.4338254980999315
|
||||
19,1387.888482139497,9813460.816965807,-8668163.091407077,0.48655877231446004,0.14770384854161295,40.434764227335066,0.8001981770781221,0,1360.9052240153403,0.4622389074871943
|
||||
20,1348.2968122066536,7615444.018921256,-6877883.375153725,0.5061587981253968,0.1169411691502462,21.502982985139585,0.47246758755638996,0,1381.96784411268,0.45796482748458195
|
||||
21,1306.1686826448918,6701112.384087701,-7270314.695597567,0.5011037189908241,0.12261214868558168,22.34340701188716,0.5256134422121052,0,1322.260329766525,0.43025988786243385
|
||||
22,1312.2115760432778,7153262.543439625,-7187735.791851051,0.49828430306576016,0.12899483002553122,25.019269101903294,0.6703145935202827,0,1371.9104903070024,0.4437538074689534
|
||||
23,1389.9736680471026,9044373.037421072,-8250101.404969409,0.48521178020290257,0.15068469731033937,41.16005586952965,0.7737035696047103,0,1392.4784021937016,0.4600902606620035
|
||||
24,1286.7205785752114,6916143.746288855,-6910263.708224738,0.4872155275332052,0.14262727870906508,36.21878103600047,0.747346380449183,0,1370.7124085280252,0.4540354787611542
|
||||
25,1343.1907359580393,8903191.196591515,-10746782.531812651,0.4818355889401554,0.17851118835064222,53.35385909010516,0.8455522612964729,0,1394.0130957440156,0.47039125819553734
|
||||
26,1346.2805321971216,9332112.756028192,-9575560.225914387,0.5022946730279984,0.13721957539987414,33.235343349008396,0.6453538798272516,0,1339.052258249983,0.46556415004463575
|
||||
27,1339.7584804552794,8449474.297751566,-8890910.048139896,0.48897810886739224,0.14355756320049753,36.97191221085066,0.73237459568682,0,1358.4278306235958,0.44899860164203426
|
||||
28,1345.1244398366684,8201787.530869359,-6720551.877655807,0.47268196222274367,0.14709697797608548,40.50036617989828,0.7442535601826906,0,1396.6526661056973,0.44167193867851096
|
||||
29,1389.907112246384,9558779.4084837,-9586752.407771593,0.5111799386955211,0.12045051860796156,23.728272316416987,0.4895543674336325,0,1390.3191912198383,0.47473490194617013
|
||||
30,1346.9219534679155,8402411.644822713,-9040492.928120432,0.4979865481942812,0.14492077259588146,36.120792894107424,0.742723636559463,0,1362.0786914284556,0.4531051970655923
|
||||
31,1504.0128124723922,11248053.504957154,-10809475.198359782,0.5048707999730357,0.12740218711887447,27.163509097885047,0.6450347097900759,0,1398.6915149138053,0.46764620192072853
|
||||
32,1212.1002996972697,5763663.117027633,-6106730.221122099,0.491400671435149,0.11984631858272021,21.904576293594147,0.5368141870154858,0,1285.7798492616669,0.4335114728926592
|
||||
33,1386.193498285732,9649508.232067727,-10108618.085532382,0.5047635044935125,0.1462121436794625,37.43792246225126,0.7797263229356967,0,1380.4644626510726,0.4722628463498135
|
||||
34,1301.9022334373124,7440655.914297966,-6872749.787200848,0.4950139443865688,0.1228867765772828,23.12786183808376,0.6016550517803871,0,1338.3420518018584,0.4474879227143614
|
||||
35,1455.703370132258,8502572.682465747,-6004273.469153947,0.4981156519006676,0.11402036786710826,21.03654379070399,0.45672528248202116,0,1429.1656220179534,0.4454024743396629
|
||||
36,1370.9168860009597,9429820.994721135,-9785396.299975824,0.5023365499080188,0.13064681361097452,27.28562398579973,0.6443034317025297,0,1316.9866676649976,0.45163631176134533
|
||||
37,1500.148434186434,11215184.593103329,-8567393.518601593,0.4954898672200253,0.1257238476716368,24.689561020966966,0.6548898904315501,0,1442.7250361218337,0.46782970787894057
|
||||
38,1355.3654984230295,8455223.874551727,-8749866.083502064,0.4849601094937233,0.15659252409289054,44.94479271558519,0.7902756992998764,0,1393.6737906519124,0.454548753344781
|
||||
39,1407.5308568467717,9695601.925396604,-9562130.207706565,0.4939300793252477,0.1576046806051865,43.92888208607774,0.7943641312894787,0,1393.7039940721593,0.4678702390206391
|
||||
40,1451.8351507277862,9875729.34925285,-7883031.171169614,0.48503800492277216,0.14135763029574866,36.79048828024231,0.7535396582095706,0,1423.8114040840742,0.4543604303922943
|
||||
41,1366.8636367183278,8452013.196655586,-7767439.946019993,0.4921291441752594,0.13268728234770347,31.149288551432708,0.6763036468943535,0,1354.206069928975,0.44226494251652043
|
||||
42,1319.0209715131637,7566897.376200336,-8208874.176830001,0.5170899419806422,0.12023336850016857,21.693531567536105,0.4861380660626831,0,1400.7181785684643,0.4664853657554793
|
||||
43,1354.3455542475208,7678877.238731557,-6305656.370763706,0.5000338936116165,0.11595432679931363,21.07532234199121,0.46947580757309626,0,1329.568180782063,0.44215213271073833
|
||||
44,1286.3745545934858,5537690.064275363,-2028789.0074428658,0.475464890504099,0.11050284127082513,20.534478056085664,0.4442387075394097,0,1325.4618983417672,0.4175282018234954
|
||||
45,1383.0451849639005,9136646.664203452,-8547688.06050946,0.4913152541894095,0.14518618783136014,37.19177380506461,0.7487349003549015,0,1390.009320261334,0.4575311946450212
|
||||
46,1373.4476171414922,8626335.933596635,-8120844.054197156,0.49289924655274986,0.13827486027941305,34.34196274737538,0.6662302789096499,0,1357.0889077887116,0.4396807874735435
|
||||
47,1361.9004696823379,8635992.05391394,-8053337.554801067,0.49755367462395406,0.12571714190677166,23.321450106267903,0.6022413493386214,0,1335.337644331878,0.45601994884828834
|
||||
48,1427.7605109934645,9006646.559124853,-7119872.549069271,0.49251047850195695,0.11371165019080415,22.392736436441474,0.463810340481642,0,1409.0464657201403,0.4371366033181275
|
||||
49,1232.8251914476873,7160439.787246127,-7731212.605018027,0.4939099746590862,0.1432787856991762,36.51523335537383,0.729378370944694,0,1265.201640639625,0.441063300880349
|
||||
50,1386.1251795158923,9635265.387650147,-9753984.356964162,0.4969512124674916,0.14769022393679807,36.94995201516179,0.7518987993489127,0,1355.8638874751846,0.4617934477133493
|
||||
51,1437.3105272725256,10108442.722160941,-7171908.443693737,0.5021599813604649,0.11746016374417065,21.923238932185967,0.5675381506947705,0,1369.5262004471883,0.4645157820748979
|
||||
52,1362.1854735795423,8027363.415150201,-5797372.456524908,0.47413273030810865,0.1545734808885145,44.90250452697583,0.7871994347995076,0,1345.4340372012095,0.4417527052714022
|
||||
53,1433.6464643245836,10049623.23348878,-10237717.720532663,0.49560466894955646,0.15184025574458127,43.27811844697392,0.7709575693482023,0,1437.2902373216382,0.46069647655479506
|
||||
54,1427.3176073371492,9052787.17357565,-8464198.80366773,0.49494835273001614,0.12192525048129271,24.56441461732739,0.6302231055766213,0,1455.8658954755329,0.44666986080671256
|
||||
55,1341.7488259066488,8556084.709967723,-9101098.40076696,0.49754523982929955,0.13430646629543272,32.52379159978048,0.7166598279912367,0,1340.831265749096,0.45207543974288356
|
||||
56,1395.6578644173205,8955003.22860884,-4955847.24544667,0.48801196660635016,0.11259265305542714,20.90044385308888,0.46085357532378307,0,1330.761367580891,0.45123277191185335
|
||||
57,1367.7187485033435,8786687.548429178,-8536792.024100812,0.5128370646071644,0.1191230091176826,21.502498661010087,0.4820907733329839,0,1333.5950965870184,0.4620912392086873
|
||||
58,1422.4771007508423,9863243.073029058,-7760855.348301851,0.47842431745950015,0.15522565016034676,44.04732582975304,0.8086442699817582,0,1387.7377424627548,0.4506737464698286
|
||||
59,1318.8439987315605,7136299.393734901,-6043100.238893595,0.46209842452609734,0.1838942633291262,57.96215188610348,0.8468189312096372,0,1322.9812300661229,0.4374723305460012
|
||||
60,1358.8816283030028,8723551.25685673,-7338406.934939845,0.49097691522109654,0.13637582996995573,32.016214268040784,0.7217378407301027,0,1340.0035637967069,0.4441162707228317
|
||||
61,1289.3916227546285,7409561.271513923,-7409065.615204027,0.4913153200563924,0.14332356960560297,35.64966069732459,0.6999780625025449,0,1350.9936622855726,0.4527439311973239
|
||||
62,1364.498667741881,7983189.695031407,-4445434.952241466,0.4741137569999341,0.1176885657990684,23.182999152122697,0.6369170323368237,0,1378.258948174364,0.43138438903894105
|
||||
63,1320.3369999393717,8272967.887068387,-7688551.769448651,0.46905831460797454,0.1754163851979239,53.11870387437581,0.8393435519655682,0,1328.4681298769676,0.44060454287797174
|
||||
64,1352.1483564863122,8752192.236882742,-7966592.660107628,0.4853224980237873,0.1548452470468789,42.59632397844714,0.7900569394673211,0,1346.497914022904,0.46170633654711357
|
||||
65,1336.3971508025213,7314946.976863022,-7715979.293870401,0.49393342205882235,0.13331676030996506,31.081993502839634,0.6574760252929415,0,1380.0703068012142,0.43461344137606844
|
||||
66,1310.0049797100583,6913136.1599321775,-6263910.356138324,0.5004225059474928,0.11712558674637798,21.948514711274328,0.47167023059241303,0,1321.4571827599696,0.44216801893783764
|
||||
67,1486.101119211978,11136083.21574244,-11941623.176681455,0.4858549615048351,0.18172536819644722,53.92412750639961,0.8492457883296618,0,1449.0695281637886,0.48315594500470044
|
||||
68,1212.7582702960758,6096325.653397747,-6405858.76748255,0.49187759721960495,0.13650753710060004,32.94217741899682,0.7028407719375658,0,1249.2500796341183,0.43252737477591036
|
||||
69,1414.4064567566213,8367184.7403790355,-6165360.492518427,0.49046483040707645,0.12129546403685398,23.059139510292667,0.6266954801847798,0,1385.427512073855,0.43582395560405
|
||||
70,1259.6764108122118,6628402.968572983,-8156365.298031117,0.49089296471011523,0.13987140016841232,33.72670425643056,0.6873404064046542,0,1324.34185146344,0.4365163236730455
|
||||
71,1468.2145586795243,9406214.90736325,-6016332.897432581,0.49403427307272907,0.11213966815322293,20.51946992752466,0.463971309835231,0,1443.9885467541696,0.4586155632505039
|
||||
72,1363.6970950664186,8071539.801564656,-7031085.413220679,0.48372187705231795,0.13728907144005728,34.926107075679504,0.6993156394487501,0,1380.5943849119997,0.44368273441961925
|
||||
73,1312.0300713278743,7905292.928078511,-8590112.363515824,0.4972033350640247,0.13578825737061218,31.53170813103009,0.6940965208559994,0,1373.4575392908378,0.4701312334596417
|
||||
74,1360.064863874254,9150312.614414137,-9471185.369880281,0.5137330120556376,0.1270081689727473,24.187078803488582,0.648341293303997,0,1371.0754868035424,0.4649615122456692
|
||||
75,1244.6599612046791,5461509.966302657,-6316765.5328871,0.4828351208790782,0.15085286128020817,40.68364900206108,0.7505995612038247,0,1340.9105538450317,0.4301428897161423
|
||||
76,1299.0521104974423,7546161.945453759,-7153783.742055117,0.4892547273889031,0.14024006734537237,36.63542610245759,0.7126494440283409,0,1358.3266359001766,0.45685432196153786
|
||||
77,1435.07443240129,9876621.641546307,-8403094.39308795,0.4922957069228228,0.13549794024316425,31.64229313140645,0.70711378638793,0,1420.1330374813558,0.4598375321400079
|
||||
78,1373.7651637239685,7417152.453249154,-3376143.7200010954,0.44852199942409093,0.1760363459483511,59.66511090113522,0.8472011029983096,0,1356.4379236793218,0.42626478349112906
|
||||
79,1385.9338207513722,8613101.572095832,-9526471.05713873,0.4832890657289796,0.16692451656392857,48.11511694472734,0.7921755511467742,0,1401.765466005601,0.46143227219617505
|
||||
80,1415.1381926019499,8715447.719830355,-8368982.572865687,0.4858735105610342,0.137724771139173,32.57054719593178,0.7170607824345318,0,1417.2165185605998,0.45419889994726415
|
||||
81,1414.1535690350333,9239206.370572936,-6562308.379885715,0.5051233258217455,0.11531618171367417,21.44664019669483,0.47098415700196683,0,1379.4458313798962,0.44698132799131385
|
||||
82,1466.911330962389,10150786.67408342,-7473477.79475407,0.5035315776764063,0.11630529902207483,22.005810879300693,0.4763751781383087,0,1424.510302102315,0.4644608930614276
|
||||
83,1364.6602962468296,9324214.704282897,-6518888.120004928,0.4864469370316258,0.13761522125544917,35.20529100121936,0.7239236674619852,0,1326.5546985598946,0.45114214523950985
|
||||
84,1347.8472038626364,8481050.489589171,-9059619.195447544,0.4868011359424531,0.1397479957258639,34.006163208158505,0.7407803792276575,0,1341.3022096990337,0.4376963116800946
|
||||
85,1317.3874167201154,7362772.053161179,-6887343.297364369,0.48559300101630976,0.1405586094501818,36.63772258535156,0.7212021657538173,0,1339.6319611697677,0.4342183267179811
|
||||
86,1271.9763329753898,6616261.865783306,-4728617.682443415,0.49098232992763274,0.12733989466758594,27.195575420197265,0.6487634915425831,0,1307.8694323317086,0.43698345018237683
|
||||
87,1405.2276224374375,10679514.013448551,-12098888.920649894,0.5082981958594361,0.14142953284991758,34.44427781280378,0.7478062750723347,0,1416.24588646309,0.47526208701173933
|
||||
88,1352.6694014207123,8156196.119415605,-8081501.740357192,0.4964196854263618,0.1306988382438878,29.13343524965282,0.6909848362896432,0,1373.1881616055648,0.4501428102080031
|
||||
89,1405.6615018099444,8906096.135196697,-6071421.755648228,0.48221005639091047,0.13390473021232152,33.94022211006872,0.7346955661737373,0,1375.852681750436,0.44285256683850055
|
||||
90,1408.0927360167893,9166979.878587108,-9223488.921106035,0.4962254854329748,0.14452263497178983,36.41375317193032,0.6927488771757327,0,1408.5598138576108,0.44993757698512543
|
||||
91,1384.440211916028,9365608.623953838,-10733871.819678023,0.4883037838362454,0.16768185648624134,46.76279981799216,0.8087170330726405,0,1354.3879789420166,0.4535986919888386
|
||||
92,1282.23821067072,8304516.233179453,-8727576.584080435,0.5006025906289336,0.13522383305460026,28.53170104567771,0.6918334833039435,0,1258.4955368148371,0.4579971950005238
|
||||
93,1252.4516393293195,7843026.140843166,-6883179.00583257,0.4855914885772674,0.12777138577981442,28.016757560837547,0.6975659925268378,0,1296.2772354526833,0.46163579714004965
|
||||
94,1441.4751356664694,9120837.866142763,-8413300.10434283,0.49481654284878324,0.13566310737482093,32.96770303021884,0.7018913798743247,0,1464.4387227717746,0.4538567360172558
|
||||
95,1478.2522122860535,10923298.952759968,-9743116.529335175,0.48776923263510646,0.14621861980720152,40.250360806629246,0.7383466636889376,0,1436.8984101766366,0.4711380136416546
|
||||
96,1416.5792394914415,9010021.713256381,-10136195.234207047,0.49402461106608825,0.1343712316545898,30.581802030914414,0.6788065807231017,0,1437.5482383971946,0.4543299808687397
|
||||
97,1450.7121895783473,10306168.865004288,-9192558.505706746,0.4922015060142475,0.13451308534935685,33.30060765083507,0.7258608318342297,0,1434.7789506443082,0.45895311486768636
|
||||
98,1402.7908176313597,8136279.085640515,-6681888.633099125,0.4925172751313516,0.12027762673460478,21.946107601656152,0.5829771583614528,0,1428.8013416269525,0.4378173410609378
|
||||
99,1330.1368778509707,9597380.737268595,-9217176.35268879,0.4836490687948424,0.16248449735080236,47.330326378745745,0.8124779855125113,0,1301.4655952106093,0.45898711389749713
|
||||
|
|
After Width: | Height: | Size: 782 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 557 KiB |
|
After Width: | Height: | Size: 420 KiB |
|
After Width: | Height: | Size: 426 KiB |
|
After Width: | Height: | Size: 459 KiB |
@@ -0,0 +1,115 @@
|
||||
\documentclass[12pt,a4paper]{article}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{listings}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{geometry}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{float}
|
||||
\usepackage{caption}
|
||||
\usepackage{subcaption}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{multirow}
|
||||
|
||||
% Page setup
|
||||
\geometry{margin=1in}
|
||||
\pagestyle{fancy}
|
||||
\fancyhf{}
|
||||
\fancyhead[L]{\leftmark}
|
||||
\fancyhead[R]{\thepage}
|
||||
\fancyfoot[C]{Algorithmic Trading Strategies: MQL5 and TradingView Implementation}
|
||||
|
||||
% Code listing setup for MQL5
|
||||
\lstdefinestyle{mql5style}{
|
||||
language=C++,
|
||||
basicstyle=\ttfamily\small,
|
||||
keywordstyle=\color{blue}\bfseries,
|
||||
commentstyle=\color{green!60!black},
|
||||
stringstyle=\color{red},
|
||||
numberstyle=\tiny\color{gray},
|
||||
numbers=left,
|
||||
numbersep=5pt,
|
||||
frame=single,
|
||||
breaklines=true,
|
||||
breakatwhitespace=false,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
tabsize=2,
|
||||
captionpos=b
|
||||
}
|
||||
|
||||
% Code listing setup for Pine Script
|
||||
\lstdefinestyle{pinescriptstyle}{
|
||||
language=Python,
|
||||
basicstyle=\ttfamily\small,
|
||||
keywordstyle=\color{blue}\bfseries,
|
||||
commentstyle=\color{green!60!black},
|
||||
stringstyle=\color{red},
|
||||
numberstyle=\tiny\color{gray},
|
||||
numbers=left,
|
||||
numbersep=5pt,
|
||||
frame=single,
|
||||
breaklines=true,
|
||||
breakatwhitespace=false,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
tabsize=2,
|
||||
captionpos=b
|
||||
}
|
||||
|
||||
% Title information
|
||||
\title{Algorithmic Trading Strategies:\\
|
||||
A Comprehensive Analysis of MQL5 Expert Advisors\\
|
||||
and TradingView Pine Script Implementations}
|
||||
\author{Algorithmic Trading Research}
|
||||
\date{\today}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\begin{abstract}
|
||||
This paper presents a comprehensive analysis of profitable algorithmic trading strategies implemented in both MetaTrader 5 (MQL5) and TradingView Pine Script. We examine multiple Expert Advisors (EAs) utilizing various technical indicators including RSI (Relative Strength Index), EMA (Exponential Moving Average), and Darvas Box theory. The strategies are optimized for different financial instruments including forex pairs (AUD/USD, EUR/USD), precious metals (XAU/USD, XAG/USD), cryptocurrencies (BTC/USD), and equity indices. Through detailed code analysis and strategy rationale, we demonstrate how systematic approaches to technical analysis, risk management, and market timing contribute to profitable trading outcomes. The paper covers fundamental MQL5 programming concepts, strategy implementation details, and the theoretical foundations that make these algorithms profitable in various market conditions.
|
||||
\end{abstract}
|
||||
|
||||
\tableofcontents
|
||||
\newpage
|
||||
|
||||
% Include chapters
|
||||
\input{chapters/introduction}
|
||||
\input{chapters/mql5_basics}
|
||||
\input{chapters/algorithms}
|
||||
\input{chapters/tradingview}
|
||||
\input{chapters/advanced_techniques}
|
||||
\input{chapters/profitability}
|
||||
\input{chapters/conclusion}
|
||||
|
||||
% Bibliography
|
||||
\begin{thebibliography}{99}
|
||||
\bibitem{darvas1957}
|
||||
Darvas, N. (1957). \textit{How I Made \$2,000,000 in the Stock Market}. Lyle Stuart.
|
||||
|
||||
\bibitem{wilder1978}
|
||||
Wilder, J. W. (1978). \textit{New Concepts in Technical Trading Systems}. Trend Research.
|
||||
|
||||
\bibitem{mql5docs}
|
||||
MetaQuotes Software Corp. (2024). \textit{MQL5 Documentation}. \url{https://www.mql5.com/en/docs}
|
||||
|
||||
\bibitem{tradingviewdocs}
|
||||
TradingView Inc. (2024). \textit{Pine Script Language Reference Manual}. \url{https://www.tradingview.com/pine-script-docs/}
|
||||
|
||||
\bibitem{vantharp1998}
|
||||
Van Tharp, K. (1998). \textit{Trade Your Way to Financial Freedom}. McGraw-Hill.
|
||||
|
||||
\bibitem{connors2012}
|
||||
Connors, L. A., \& Alvarez, C. (2012). \textit{High Probability ETF Trading}. TradingMarkets Publishing.
|
||||
|
||||
\end{thebibliography}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"order_book_liquidity": 27.337507902560162,
|
||||
"big_sentiment_threshold": 0.31249746155318936,
|
||||
"big_volume_threshold": 99.1788610573351,
|
||||
"big_trade_size_pct": 0.1435380702026215,
|
||||
"fundamental_reversion": 0.007385008311278914,
|
||||
"num_big_players": 9
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
# Trading Strategy Simulations
|
||||
|
||||
This directory contains Python scripts for simulating and analyzing advanced trading techniques.
|
||||
|
||||
## Scripts
|
||||
|
||||
### 1. martingale_simulation.py
|
||||
Analyzes the statistical properties and risk of martingale strategies.
|
||||
|
||||
**Key Analyses:**
|
||||
- Ruin probability calculations
|
||||
- Position size growth
|
||||
- Required capital analysis
|
||||
- Monte Carlo simulations
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python martingale_simulation.py
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `martingale_analysis.png`: Comprehensive analysis plots
|
||||
- Console output with statistics
|
||||
|
||||
### 2. trailing_stop_analysis.py
|
||||
Compares fixed stop loss vs trailing stop loss performance.
|
||||
|
||||
**Key Analyses:**
|
||||
- Return distribution comparison
|
||||
- Sharpe ratio improvement
|
||||
- Exit timing analysis
|
||||
- Sample price path visualization
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python trailing_stop_analysis.py
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `trailing_stop_analysis.png`: Comparison plots
|
||||
- Console output with performance metrics
|
||||
|
||||
### 3. partial_exit_analysis.py
|
||||
Analyzes the statistical benefits of partial exits.
|
||||
|
||||
**Key Analyses:**
|
||||
- Variance reduction calculation
|
||||
- Sharpe ratio optimization
|
||||
- Optimal exit percentage
|
||||
- Return distribution comparison
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python partial_exit_analysis.py
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `partial_exit_analysis.png`: Analysis plots
|
||||
- Console output with optimization results
|
||||
|
||||
### 4. grid_trading_analysis.py
|
||||
Analyzes grid trading performance in different market conditions.
|
||||
|
||||
**Key Analyses:**
|
||||
- Mean-reverting vs trending market performance
|
||||
- Optimal grid spacing
|
||||
- Trade frequency analysis
|
||||
- Profit distribution
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
python grid_trading_analysis.py
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- `grid_trading_analysis.png`: Market condition comparison
|
||||
- Console output with performance metrics
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Running All Simulations
|
||||
|
||||
```bash
|
||||
# Run all simulations
|
||||
python martingale_simulation.py
|
||||
python trailing_stop_analysis.py
|
||||
python partial_exit_analysis.py
|
||||
python grid_trading_analysis.py
|
||||
```
|
||||
|
||||
## Output Location
|
||||
|
||||
All figures are saved to `../figures/` directory:
|
||||
- `martingale_analysis.png`
|
||||
- `trailing_stop_analysis.png`
|
||||
- `partial_exit_analysis.png`
|
||||
- `grid_trading_analysis.png`
|
||||
|
||||
## Mathematical Foundations
|
||||
|
||||
These simulations implement:
|
||||
- Geometric Brownian Motion for price simulation
|
||||
- Ornstein-Uhlenbeck process for mean-reverting prices
|
||||
- Monte Carlo methods for statistical analysis
|
||||
- Kelly Criterion for position sizing
|
||||
- Sharpe ratio and other risk-adjusted metrics
|
||||
|
||||
## Notes
|
||||
|
||||
- Simulations use random number generation - results may vary slightly between runs
|
||||
- For reproducible results, set random seeds in scripts
|
||||
- Adjust parameters in each script to match your trading conditions
|
||||
- Results are illustrative - actual trading results will vary
|
||||
@@ -0,0 +1,250 @@
|
||||
"""
|
||||
Grid Trading Strategy Analysis
|
||||
Analyzes grid trading performance in different market conditions
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib
|
||||
matplotlib.use('Agg') # Use non-interactive backend
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas as pd
|
||||
from scipy.stats import norm
|
||||
|
||||
class GridTradingAnalyzer:
|
||||
def __init__(self, initial_price=100, grid_spacing=1.0, num_levels=10):
|
||||
self.initial_price = initial_price
|
||||
self.grid_spacing = grid_spacing
|
||||
self.num_levels = num_levels
|
||||
|
||||
def create_grid(self):
|
||||
"""Create grid price levels"""
|
||||
grid_levels = []
|
||||
for i in range(-self.num_levels, self.num_levels + 1):
|
||||
price = self.initial_price + i * self.grid_spacing
|
||||
grid_levels.append(price)
|
||||
return np.array(grid_levels)
|
||||
|
||||
def simulate_mean_reverting_price(self, num_steps=1000, mean_reversion_speed=0.1,
|
||||
volatility=0.5, mean_price=100):
|
||||
"""Simulate mean-reverting price (Ornstein-Uhlenbeck process)"""
|
||||
prices = [self.initial_price]
|
||||
dt = 1.0 / num_steps
|
||||
|
||||
for _ in range(num_steps):
|
||||
dW = np.random.normal(0, np.sqrt(dt))
|
||||
dS = mean_reversion_speed * (mean_price - prices[-1]) * dt + volatility * dW
|
||||
prices.append(prices[-1] + dS)
|
||||
|
||||
return np.array(prices)
|
||||
|
||||
def simulate_trending_price(self, num_steps=1000, drift=0.01, volatility=0.5):
|
||||
"""Simulate trending price (geometric Brownian motion)"""
|
||||
prices = [self.initial_price]
|
||||
dt = 1.0 / num_steps
|
||||
|
||||
for _ in range(num_steps):
|
||||
dW = np.random.normal(0, np.sqrt(dt))
|
||||
dS = drift * prices[-1] * dt + volatility * prices[-1] * dW
|
||||
prices.append(prices[-1] + dS)
|
||||
|
||||
return np.array(prices)
|
||||
|
||||
def calculate_grid_profits(self, prices, grid_levels, position_size=0.01):
|
||||
"""Calculate profits from grid trading"""
|
||||
positions = {} # Track open positions at each grid level
|
||||
total_profit = 0
|
||||
trades = []
|
||||
|
||||
for price in prices:
|
||||
# Check for grid hits
|
||||
for i, grid_price in enumerate(grid_levels):
|
||||
# Buy signal: price hits grid from above
|
||||
if price <= grid_price + 0.1 and price >= grid_price - 0.1:
|
||||
if i not in positions or positions[i] == 'sell':
|
||||
# Open buy position
|
||||
positions[i] = 'buy'
|
||||
trades.append({
|
||||
'type': 'buy',
|
||||
'price': grid_price,
|
||||
'time': len(trades)
|
||||
})
|
||||
|
||||
# Sell signal: price hits grid from below
|
||||
if price >= grid_price - 0.1 and price <= grid_price + 0.1:
|
||||
if i in positions and positions[i] == 'buy':
|
||||
# Close buy position (profit)
|
||||
profit = (price - grid_price) * position_size
|
||||
total_profit += profit
|
||||
del positions[i]
|
||||
trades.append({
|
||||
'type': 'sell',
|
||||
'price': price,
|
||||
'profit': profit,
|
||||
'time': len(trades)
|
||||
})
|
||||
|
||||
# Close remaining positions at final price
|
||||
final_price = prices[-1]
|
||||
for level, pos_type in positions.items():
|
||||
if pos_type == 'buy':
|
||||
profit = (final_price - grid_levels[level]) * position_size
|
||||
total_profit += profit
|
||||
|
||||
return total_profit, trades
|
||||
|
||||
def analyze_grid_trading(self, num_simulations=100, market_type='mean_reverting'):
|
||||
"""Analyze grid trading performance"""
|
||||
results = []
|
||||
|
||||
for sim in range(num_simulations):
|
||||
if market_type == 'mean_reverting':
|
||||
prices = self.simulate_mean_reverting_price()
|
||||
else:
|
||||
prices = self.simulate_trending_price()
|
||||
|
||||
grid_levels = self.create_grid()
|
||||
profit, trades = self.calculate_grid_profits(prices, grid_levels)
|
||||
|
||||
results.append({
|
||||
'simulation': sim,
|
||||
'profit': profit,
|
||||
'num_trades': len([t for t in trades if t['type'] == 'sell']),
|
||||
'final_price': prices[-1],
|
||||
'price_range': prices.max() - prices.min(),
|
||||
'max_drawdown': self.calculate_max_drawdown(prices)
|
||||
})
|
||||
|
||||
return pd.DataFrame(results)
|
||||
|
||||
def calculate_max_drawdown(self, prices):
|
||||
"""Calculate maximum drawdown"""
|
||||
peak = prices[0]
|
||||
max_dd = 0
|
||||
|
||||
for price in prices:
|
||||
if price > peak:
|
||||
peak = price
|
||||
dd = (peak - price) / peak
|
||||
if dd > max_dd:
|
||||
max_dd = dd
|
||||
|
||||
return max_dd
|
||||
|
||||
def optimize_grid_spacing(self, num_simulations=50, spacing_range=np.arange(0.5, 5.0, 0.5)):
|
||||
"""Find optimal grid spacing"""
|
||||
results = []
|
||||
|
||||
for spacing in spacing_range:
|
||||
self.grid_spacing = spacing
|
||||
df = self.analyze_grid_trading(num_simulations=num_simulations,
|
||||
market_type='mean_reverting')
|
||||
|
||||
results.append({
|
||||
'spacing': spacing,
|
||||
'mean_profit': df['profit'].mean(),
|
||||
'std_profit': df['profit'].std(),
|
||||
'sharpe_ratio': df['profit'].mean() / df['profit'].std() if df['profit'].std() > 0 else 0,
|
||||
'mean_trades': df['num_trades'].mean()
|
||||
})
|
||||
|
||||
return pd.DataFrame(results)
|
||||
|
||||
def plot_analysis(self, num_simulations=100):
|
||||
"""Plot analysis results"""
|
||||
# Analyze in different market conditions
|
||||
mean_reverting_results = self.analyze_grid_trading(num_simulations, 'mean_reverting')
|
||||
trending_results = self.analyze_grid_trading(num_simulations, 'trending')
|
||||
optimization_df = self.optimize_grid_spacing()
|
||||
|
||||
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
|
||||
|
||||
# Plot 1: Profit Distribution Comparison
|
||||
axes[0, 0].hist(mean_reverting_results['profit'], bins=30, alpha=0.5,
|
||||
label='Mean Reverting Market', color='green', edgecolor='black')
|
||||
axes[0, 0].hist(trending_results['profit'], bins=30, alpha=0.5,
|
||||
label='Trending Market', color='red', edgecolor='black')
|
||||
axes[0, 0].axvline(0, color='black', linestyle='--', linewidth=2)
|
||||
axes[0, 0].set_xlabel('Total Profit')
|
||||
axes[0, 0].set_ylabel('Frequency')
|
||||
axes[0, 0].set_title('Grid Trading Profit Distribution by Market Type')
|
||||
axes[0, 0].legend()
|
||||
axes[0, 0].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 2: Sample Price Path with Grid
|
||||
sample_prices = self.simulate_mean_reverting_price()
|
||||
grid_levels = self.create_grid()
|
||||
|
||||
axes[0, 1].plot(sample_prices, 'b-', linewidth=2, label='Price')
|
||||
for level in grid_levels:
|
||||
axes[0, 1].axhline(level, color='gray', linestyle='--', alpha=0.3)
|
||||
axes[0, 1].axhline(self.initial_price, color='red', linestyle='-',
|
||||
linewidth=2, label='Initial Price')
|
||||
axes[0, 1].set_xlabel('Time Step')
|
||||
axes[0, 1].set_ylabel('Price')
|
||||
axes[0, 1].set_title('Sample Price Path with Grid Levels')
|
||||
axes[0, 1].legend()
|
||||
axes[0, 1].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 3: Optimal Grid Spacing
|
||||
axes[1, 0].plot(optimization_df['spacing'], optimization_df['sharpe_ratio'],
|
||||
'b-o', linewidth=2, markersize=8, label='Sharpe Ratio')
|
||||
optimal_idx = optimization_df['sharpe_ratio'].idxmax()
|
||||
optimal_spacing = optimization_df.loc[optimal_idx, 'spacing']
|
||||
axes[1, 0].axvline(optimal_spacing, color='red', linestyle='--',
|
||||
label=f'Optimal: {optimal_spacing:.2f}')
|
||||
axes[1, 0].set_xlabel('Grid Spacing')
|
||||
axes[1, 0].set_ylabel('Sharpe Ratio')
|
||||
axes[1, 0].set_title('Optimal Grid Spacing Analysis')
|
||||
axes[1, 0].legend()
|
||||
axes[1, 0].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 4: Profit vs Number of Trades
|
||||
axes[1, 1].scatter(mean_reverting_results['num_trades'],
|
||||
mean_reverting_results['profit'],
|
||||
alpha=0.5, label='Mean Reverting', color='green')
|
||||
axes[1, 1].scatter(trending_results['num_trades'],
|
||||
trending_results['profit'],
|
||||
alpha=0.5, label='Trending', color='red')
|
||||
axes[1, 1].axhline(0, color='black', linestyle='--', linewidth=1)
|
||||
axes[1, 1].set_xlabel('Number of Trades')
|
||||
axes[1, 1].set_ylabel('Total Profit')
|
||||
axes[1, 1].set_title('Profit vs Trade Frequency')
|
||||
axes[1, 1].legend()
|
||||
axes[1, 1].grid(True, alpha=0.3)
|
||||
|
||||
plt.tight_layout()
|
||||
return fig, mean_reverting_results, trending_results, optimization_df
|
||||
|
||||
if __name__ == "__main__":
|
||||
analyzer = GridTradingAnalyzer(initial_price=100, grid_spacing=1.0, num_levels=10)
|
||||
|
||||
print("Running Grid Trading Analysis...")
|
||||
fig, mr_results, tr_results, opt_df = analyzer.plot_analysis(num_simulations=100)
|
||||
|
||||
print("\n=== Grid Trading Strategy Analysis ===")
|
||||
print(f"\nMean Reverting Market:")
|
||||
print(f" Mean Profit: ${mr_results['profit'].mean():.2f}")
|
||||
print(f" Std Dev: ${mr_results['profit'].std():.2f}")
|
||||
print(f" Win Rate: {(mr_results['profit'] > 0).mean():.2%}")
|
||||
print(f" Mean Trades: {mr_results['num_trades'].mean():.1f}")
|
||||
|
||||
print(f"\nTrending Market:")
|
||||
print(f" Mean Profit: ${tr_results['profit'].mean():.2f}")
|
||||
print(f" Std Dev: ${tr_results['profit'].std():.2f}")
|
||||
print(f" Win Rate: {(tr_results['profit'] > 0).mean():.2%}")
|
||||
print(f" Mean Trades: {tr_results['num_trades'].mean():.1f}")
|
||||
|
||||
optimal_idx = opt_df['sharpe_ratio'].idxmax()
|
||||
print(f"\nOptimal Grid Spacing: {opt_df.loc[optimal_idx, 'spacing']:.2f}")
|
||||
print(f" Optimal Sharpe Ratio: {opt_df.loc[optimal_idx, 'sharpe_ratio']:.4f}")
|
||||
|
||||
import os
|
||||
# Get the script directory and construct path to figures
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
figures_dir = os.path.join(script_dir, '..', 'figures')
|
||||
figures_path = os.path.abspath(figures_dir)
|
||||
os.makedirs(figures_path, exist_ok=True)
|
||||
|
||||
output_path = os.path.join(figures_path, 'grid_trading_analysis.png')
|
||||
plt.savefig(output_path, dpi=300, bbox_inches='tight')
|
||||
print(f"\nFigure saved to {output_path}")
|
||||
plt.close()
|
||||
@@ -0,0 +1,212 @@
|
||||
"""
|
||||
Martingale Strategy Simulation
|
||||
Analyzes the statistical properties and risk of martingale strategies
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib
|
||||
matplotlib.use('Agg') # Use non-interactive backend
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy import stats
|
||||
import pandas as pd
|
||||
|
||||
class MartingaleSimulator:
|
||||
def __init__(self, initial_balance=10000, base_lot=0.01, win_prob=0.5,
|
||||
win_amount=10, loss_amount=10, max_losses=10):
|
||||
self.initial_balance = initial_balance
|
||||
self.base_lot = base_lot
|
||||
self.win_prob = win_prob
|
||||
self.win_amount = win_amount
|
||||
self.loss_amount = loss_amount
|
||||
self.max_losses = max_losses
|
||||
|
||||
def calculate_position_size(self, consecutive_losses):
|
||||
"""Calculate position size after n consecutive losses"""
|
||||
return self.base_lot * (2 ** consecutive_losses)
|
||||
|
||||
def calculate_required_capital(self, consecutive_losses):
|
||||
"""Calculate total capital needed after n losses"""
|
||||
return self.base_lot * (2 ** (consecutive_losses + 1) - 1)
|
||||
|
||||
def simulate_trade_sequence(self, num_trades=1000):
|
||||
"""Simulate a sequence of trades"""
|
||||
balance = self.initial_balance
|
||||
consecutive_losses = 0
|
||||
trades = []
|
||||
ruin = False
|
||||
|
||||
for i in range(num_trades):
|
||||
if balance <= 0:
|
||||
ruin = True
|
||||
break
|
||||
|
||||
# Calculate position size
|
||||
position_size = self.calculate_position_size(consecutive_losses)
|
||||
required_capital = self.calculate_required_capital(consecutive_losses)
|
||||
|
||||
# Check if we have enough capital
|
||||
if required_capital > balance:
|
||||
ruin = True
|
||||
break
|
||||
|
||||
# Simulate trade outcome
|
||||
is_win = np.random.random() < self.win_prob
|
||||
|
||||
if is_win:
|
||||
# Win: recover all previous losses
|
||||
profit = position_size * self.win_amount
|
||||
balance += profit
|
||||
consecutive_losses = 0
|
||||
outcome = 'Win'
|
||||
else:
|
||||
# Loss: add to consecutive losses
|
||||
loss = position_size * self.loss_amount
|
||||
balance -= loss
|
||||
consecutive_losses += 1
|
||||
outcome = 'Loss'
|
||||
|
||||
trades.append({
|
||||
'trade': i + 1,
|
||||
'balance': balance,
|
||||
'position_size': position_size,
|
||||
'consecutive_losses': consecutive_losses,
|
||||
'outcome': outcome,
|
||||
'profit': profit if is_win else -loss
|
||||
})
|
||||
|
||||
return pd.DataFrame(trades), ruin
|
||||
|
||||
def monte_carlo_analysis(self, num_simulations=1000, num_trades=100):
|
||||
"""Run Monte Carlo simulation"""
|
||||
results = []
|
||||
ruin_count = 0
|
||||
|
||||
for sim in range(num_simulations):
|
||||
trades_df, ruin = self.simulate_trade_sequence(num_trades)
|
||||
if ruin:
|
||||
ruin_count += 1
|
||||
final_balance = 0
|
||||
else:
|
||||
final_balance = trades_df['balance'].iloc[-1]
|
||||
|
||||
results.append({
|
||||
'simulation': sim,
|
||||
'final_balance': final_balance,
|
||||
'ruin': ruin,
|
||||
'total_trades': len(trades_df),
|
||||
'max_consecutive_losses': trades_df['consecutive_losses'].max() if len(trades_df) > 0 else 0
|
||||
})
|
||||
|
||||
return pd.DataFrame(results), ruin_count / num_simulations
|
||||
|
||||
def plot_simulation_results(self, num_simulations=100):
|
||||
"""Plot simulation results"""
|
||||
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
|
||||
|
||||
# Run simulations
|
||||
results_df, ruin_prob = self.monte_carlo_analysis(num_simulations)
|
||||
|
||||
# Plot 1: Final Balance Distribution
|
||||
axes[0, 0].hist(results_df['final_balance'], bins=50, edgecolor='black')
|
||||
axes[0, 0].axvline(self.initial_balance, color='red', linestyle='--',
|
||||
label=f'Initial Balance: ${self.initial_balance:,.0f}')
|
||||
axes[0, 0].set_xlabel('Final Balance ($)')
|
||||
axes[0, 0].set_ylabel('Frequency')
|
||||
axes[0, 0].set_title(f'Final Balance Distribution\nRuin Probability: {ruin_prob:.2%}')
|
||||
axes[0, 0].legend()
|
||||
axes[0, 0].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 2: Ruin Probability vs Consecutive Losses
|
||||
max_losses_range = range(1, self.max_losses + 1)
|
||||
ruin_probs = []
|
||||
for n in max_losses_range:
|
||||
required = self.calculate_required_capital(n)
|
||||
ruin_probs.append(1.0 if required > self.initial_balance else 0.0)
|
||||
|
||||
axes[0, 1].plot(max_losses_range, ruin_probs, 'ro-', linewidth=2, markersize=8)
|
||||
axes[0, 1].set_xlabel('Consecutive Losses')
|
||||
axes[0, 1].set_ylabel('Ruin Probability')
|
||||
axes[0, 1].set_title('Ruin Probability vs Consecutive Losses')
|
||||
axes[0, 1].grid(True, alpha=0.3)
|
||||
axes[0, 1].set_ylim([-0.1, 1.1])
|
||||
|
||||
# Plot 3: Position Size Growth
|
||||
losses_range = range(0, self.max_losses + 1)
|
||||
position_sizes = [self.calculate_position_size(n) for n in losses_range]
|
||||
required_capital = [self.calculate_required_capital(n) for n in losses_range]
|
||||
|
||||
ax3_twin = axes[1, 0].twinx()
|
||||
line1 = axes[1, 0].plot(losses_range, position_sizes, 'b-o',
|
||||
label='Position Size', linewidth=2)
|
||||
line2 = ax3_twin.plot(losses_range, required_capital, 'r-s',
|
||||
label='Required Capital', linewidth=2)
|
||||
|
||||
axes[1, 0].set_xlabel('Consecutive Losses')
|
||||
axes[1, 0].set_ylabel('Position Size (Lots)', color='b')
|
||||
ax3_twin.set_ylabel('Required Capital ($)', color='r')
|
||||
axes[1, 0].set_title('Position Size and Capital Requirements')
|
||||
axes[1, 0].grid(True, alpha=0.3)
|
||||
|
||||
# Combine legends
|
||||
lines = line1 + line2
|
||||
labels = [l.get_label() for l in lines]
|
||||
axes[1, 0].legend(lines, labels, loc='upper left')
|
||||
|
||||
# Plot 4: Sample Trade Sequence
|
||||
sample_trades, _ = self.simulate_trade_sequence(50)
|
||||
axes[1, 1].plot(sample_trades['trade'], sample_trades['balance'],
|
||||
'g-', linewidth=2, label='Balance')
|
||||
axes[1, 1].axhline(self.initial_balance, color='red', linestyle='--',
|
||||
label='Initial Balance')
|
||||
axes[1, 1].set_xlabel('Trade Number')
|
||||
axes[1, 1].set_ylabel('Balance ($)')
|
||||
axes[1, 1].set_title('Sample Trade Sequence (50 trades)')
|
||||
axes[1, 1].legend()
|
||||
axes[1, 1].grid(True, alpha=0.3)
|
||||
|
||||
plt.tight_layout()
|
||||
return fig
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Create simulator
|
||||
simulator = MartingaleSimulator(
|
||||
initial_balance=10000,
|
||||
base_lot=0.01,
|
||||
win_prob=0.5,
|
||||
win_amount=10,
|
||||
loss_amount=10,
|
||||
max_losses=10
|
||||
)
|
||||
|
||||
# Run analysis
|
||||
print("Running Martingale Simulation...")
|
||||
results_df, ruin_prob = simulator.monte_carlo_analysis(num_simulations=1000, num_trades=100)
|
||||
|
||||
print(f"\n=== Martingale Strategy Analysis ===")
|
||||
print(f"Initial Balance: ${simulator.initial_balance:,.2f}")
|
||||
print(f"Win Probability: {simulator.win_prob:.1%}")
|
||||
print(f"\nMonte Carlo Results (1000 simulations):")
|
||||
print(f"Ruin Probability: {ruin_prob:.2%}")
|
||||
print(f"Mean Final Balance: ${results_df['final_balance'].mean():,.2f}")
|
||||
print(f"Median Final Balance: ${results_df['final_balance'].median():,.2f}")
|
||||
print(f"Std Dev Final Balance: ${results_df['final_balance'].std():,.2f}")
|
||||
print(f"Max Final Balance: ${results_df['final_balance'].max():,.2f}")
|
||||
print(f"Min Final Balance: ${results_df['final_balance'].min():,.2f}")
|
||||
|
||||
# Calculate statistics
|
||||
profitable_sims = (results_df['final_balance'] > simulator.initial_balance).sum()
|
||||
print(f"\nProfitable Simulations: {profitable_sims}/{len(results_df)} ({profitable_sims/len(results_df):.1%})")
|
||||
print(f"Average Max Consecutive Losses: {results_df['max_consecutive_losses'].mean():.2f}")
|
||||
|
||||
# Generate plots
|
||||
import os
|
||||
# Get the script directory and construct path to figures
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
figures_dir = os.path.join(script_dir, '..', 'figures')
|
||||
figures_path = os.path.abspath(figures_dir)
|
||||
os.makedirs(figures_path, exist_ok=True)
|
||||
|
||||
fig = simulator.plot_simulation_results(num_simulations=100)
|
||||
output_path = os.path.join(figures_path, 'martingale_analysis.png')
|
||||
plt.savefig(output_path, dpi=300, bbox_inches='tight')
|
||||
print(f"\nFigure saved to {output_path}")
|
||||
plt.close()
|
||||
@@ -0,0 +1,191 @@
|
||||
"""
|
||||
Partial Exit Strategy Analysis
|
||||
Analyzes the statistical benefits of partial exits
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib
|
||||
matplotlib.use('Agg') # Use non-interactive backend
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas as pd
|
||||
from scipy.stats import norm
|
||||
|
||||
class PartialExitAnalyzer:
|
||||
def __init__(self, initial_price=100, drift=0.0001, volatility=0.02):
|
||||
self.initial_price = initial_price
|
||||
self.drift = drift
|
||||
self.volatility = volatility
|
||||
|
||||
def simulate_price_path(self, num_steps=1000, dt=1/252):
|
||||
"""Simulate price using geometric Brownian motion"""
|
||||
prices = [self.initial_price]
|
||||
|
||||
for _ in range(num_steps):
|
||||
dW = np.random.normal(0, np.sqrt(dt))
|
||||
dS = self.drift * prices[-1] * dt + self.volatility * prices[-1] * dW
|
||||
prices.append(prices[-1] + dS)
|
||||
|
||||
return np.array(prices)
|
||||
|
||||
def calculate_full_exit_return(self, prices, exit_time):
|
||||
"""Calculate return for full exit at exit_time"""
|
||||
exit_price = prices[exit_time]
|
||||
return (exit_price - self.initial_price) / self.initial_price
|
||||
|
||||
def calculate_partial_exit_return(self, prices, partial_exit_time,
|
||||
partial_exit_pct, final_exit_time):
|
||||
"""Calculate return for partial exit strategy"""
|
||||
partial_exit_price = prices[partial_exit_time]
|
||||
final_exit_price = prices[final_exit_time]
|
||||
|
||||
# Partial exit profit
|
||||
partial_profit = partial_exit_pct * (partial_exit_price - self.initial_price) / self.initial_price
|
||||
|
||||
# Remaining position profit
|
||||
remaining_profit = (1 - partial_exit_pct) * (final_exit_price - self.initial_price) / self.initial_price
|
||||
|
||||
total_return = partial_profit + remaining_profit
|
||||
return total_return, partial_profit, remaining_profit
|
||||
|
||||
def analyze_partial_exit(self, num_simulations=1000, num_steps=1000,
|
||||
partial_exit_pct=0.5, partial_exit_time=500):
|
||||
"""Analyze partial exit strategy"""
|
||||
results = []
|
||||
|
||||
for sim in range(num_simulations):
|
||||
prices = self.simulate_price_path(num_steps)
|
||||
|
||||
# Full exit at end
|
||||
full_return = self.calculate_full_exit_return(prices, len(prices) - 1)
|
||||
|
||||
# Partial exit strategy
|
||||
partial_return, partial_profit, remaining_profit = self.calculate_partial_exit_return(
|
||||
prices, partial_exit_time, partial_exit_pct, len(prices) - 1)
|
||||
|
||||
results.append({
|
||||
'simulation': sim,
|
||||
'final_price': prices[-1],
|
||||
'partial_exit_price': prices[partial_exit_time],
|
||||
'full_return': full_return,
|
||||
'partial_return': partial_return,
|
||||
'partial_profit': partial_profit,
|
||||
'remaining_profit': remaining_profit,
|
||||
'variance_reduction': np.var([partial_profit, remaining_profit]) - np.var([full_return])
|
||||
})
|
||||
|
||||
return pd.DataFrame(results)
|
||||
|
||||
def optimize_exit_percentage(self, num_simulations=500, exit_percentages=np.arange(0.1, 0.9, 0.1)):
|
||||
"""Find optimal partial exit percentage"""
|
||||
results = []
|
||||
|
||||
for exit_pct in exit_percentages:
|
||||
df = self.analyze_partial_exit(num_simulations=num_simulations,
|
||||
partial_exit_pct=exit_pct)
|
||||
|
||||
mean_return = df['partial_return'].mean()
|
||||
std_return = df['partial_return'].std()
|
||||
sharpe = mean_return / std_return if std_return > 0 else 0
|
||||
|
||||
results.append({
|
||||
'exit_percentage': exit_pct,
|
||||
'mean_return': mean_return,
|
||||
'std_return': std_return,
|
||||
'sharpe_ratio': sharpe,
|
||||
'variance_reduction': df['variance_reduction'].mean()
|
||||
})
|
||||
|
||||
return pd.DataFrame(results)
|
||||
|
||||
def plot_analysis(self, num_simulations=1000):
|
||||
"""Plot analysis results"""
|
||||
results_df = self.analyze_partial_exit(num_simulations)
|
||||
optimization_df = self.optimize_exit_percentage()
|
||||
|
||||
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
|
||||
|
||||
# Plot 1: Return Distribution Comparison
|
||||
axes[0, 0].hist(results_df['full_return'], bins=50, alpha=0.5,
|
||||
label='Full Exit', color='red', edgecolor='black')
|
||||
axes[0, 0].hist(results_df['partial_return'], bins=50, alpha=0.5,
|
||||
label='Partial Exit (50%)', color='green', edgecolor='black')
|
||||
axes[0, 0].axvline(0, color='black', linestyle='--', linewidth=1)
|
||||
axes[0, 0].set_xlabel('Return')
|
||||
axes[0, 0].set_ylabel('Frequency')
|
||||
axes[0, 0].set_title('Return Distribution: Full vs Partial Exit')
|
||||
axes[0, 0].legend()
|
||||
axes[0, 0].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 2: Variance Reduction
|
||||
axes[0, 1].hist(results_df['variance_reduction'], bins=50, color='blue',
|
||||
edgecolor='black', alpha=0.7)
|
||||
axes[0, 1].axvline(0, color='red', linestyle='--', linewidth=2)
|
||||
axes[0, 1].axvline(results_df['variance_reduction'].mean(), color='green',
|
||||
linestyle='--', linewidth=2,
|
||||
label=f'Mean: {results_df["variance_reduction"].mean():.6f}')
|
||||
axes[0, 1].set_xlabel('Variance Reduction')
|
||||
axes[0, 1].set_ylabel('Frequency')
|
||||
axes[0, 1].set_title('Variance Reduction from Partial Exit')
|
||||
axes[0, 1].legend()
|
||||
axes[0, 1].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 3: Optimal Exit Percentage
|
||||
axes[1, 0].plot(optimization_df['exit_percentage'],
|
||||
optimization_df['sharpe_ratio'],
|
||||
'b-o', linewidth=2, markersize=8)
|
||||
optimal_idx = optimization_df['sharpe_ratio'].idxmax()
|
||||
optimal_pct = optimization_df.loc[optimal_idx, 'exit_percentage']
|
||||
optimal_sharpe = optimization_df.loc[optimal_idx, 'sharpe_ratio']
|
||||
axes[1, 0].axvline(optimal_pct, color='red', linestyle='--',
|
||||
label=f'Optimal: {optimal_pct:.1%}')
|
||||
axes[1, 0].set_xlabel('Partial Exit Percentage')
|
||||
axes[1, 0].set_ylabel('Sharpe Ratio')
|
||||
axes[1, 0].set_title('Sharpe Ratio vs Exit Percentage')
|
||||
axes[1, 0].legend()
|
||||
axes[1, 0].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 4: Variance Reduction vs Exit Percentage
|
||||
axes[1, 1].plot(optimization_df['exit_percentage'],
|
||||
optimization_df['variance_reduction'],
|
||||
'g-s', linewidth=2, markersize=8)
|
||||
axes[1, 1].axhline(0, color='red', linestyle='--', linewidth=1)
|
||||
axes[1, 1].set_xlabel('Partial Exit Percentage')
|
||||
axes[1, 1].set_ylabel('Variance Reduction')
|
||||
axes[1, 1].set_title('Variance Reduction vs Exit Percentage')
|
||||
axes[1, 1].grid(True, alpha=0.3)
|
||||
|
||||
plt.tight_layout()
|
||||
return fig, results_df, optimization_df
|
||||
|
||||
if __name__ == "__main__":
|
||||
analyzer = PartialExitAnalyzer()
|
||||
|
||||
print("Running Partial Exit Analysis...")
|
||||
fig, results_df, optimization_df = analyzer.plot_analysis(num_simulations=1000)
|
||||
|
||||
print("\n=== Partial Exit Strategy Analysis ===")
|
||||
print(f"\nFull Exit Results:")
|
||||
print(f" Mean Return: {results_df['full_return'].mean():.4f}")
|
||||
print(f" Std Dev: {results_df['full_return'].std():.4f}")
|
||||
print(f" Sharpe Ratio: {results_df['full_return'].mean() / results_df['full_return'].std():.4f}")
|
||||
|
||||
print(f"\nPartial Exit Results (50% exit):")
|
||||
print(f" Mean Return: {results_df['partial_return'].mean():.4f}")
|
||||
print(f" Std Dev: {results_df['partial_return'].std():.4f}")
|
||||
print(f" Sharpe Ratio: {results_df['partial_return'].mean() / results_df['partial_return'].std():.4f}")
|
||||
print(f" Mean Variance Reduction: {results_df['variance_reduction'].mean():.6f}")
|
||||
|
||||
optimal_idx = optimization_df['sharpe_ratio'].idxmax()
|
||||
print(f"\nOptimal Exit Percentage: {optimization_df.loc[optimal_idx, 'exit_percentage']:.1%}")
|
||||
print(f" Optimal Sharpe Ratio: {optimization_df.loc[optimal_idx, 'sharpe_ratio']:.4f}")
|
||||
|
||||
import os
|
||||
# Get the script directory and construct path to figures
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
figures_dir = os.path.join(script_dir, '..', 'figures')
|
||||
figures_path = os.path.abspath(figures_dir)
|
||||
os.makedirs(figures_path, exist_ok=True)
|
||||
|
||||
output_path = os.path.join(figures_path, 'partial_exit_analysis.png')
|
||||
plt.savefig(output_path, dpi=300, bbox_inches='tight')
|
||||
print(f"\nFigure saved to {output_path}")
|
||||
plt.close()
|
||||
@@ -0,0 +1,4 @@
|
||||
numpy>=1.21.0
|
||||
matplotlib>=3.4.0
|
||||
pandas>=1.3.0
|
||||
scipy>=1.7.0
|
||||
@@ -0,0 +1,230 @@
|
||||
"""
|
||||
Trailing Stop Loss Analysis
|
||||
Compares fixed stop loss vs trailing stop loss performance
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib
|
||||
matplotlib.use('Agg') # Use non-interactive backend
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas as pd
|
||||
from scipy.stats import norm
|
||||
|
||||
class TrailingStopAnalyzer:
|
||||
def __init__(self, initial_price=100, drift=0.0001, volatility=0.02,
|
||||
trailing_distance=0.02, fixed_stop_distance=0.02):
|
||||
self.initial_price = initial_price
|
||||
self.drift = drift
|
||||
self.volatility = volatility
|
||||
self.trailing_distance = trailing_distance
|
||||
self.fixed_stop_distance = fixed_stop_distance
|
||||
|
||||
def simulate_price_path(self, num_steps=1000, dt=1/252):
|
||||
"""Simulate price using geometric Brownian motion"""
|
||||
prices = [self.initial_price]
|
||||
|
||||
for _ in range(num_steps):
|
||||
dW = np.random.normal(0, np.sqrt(dt))
|
||||
dS = self.drift * prices[-1] * dt + self.volatility * prices[-1] * dW
|
||||
prices.append(prices[-1] + dS)
|
||||
|
||||
return np.array(prices)
|
||||
|
||||
def apply_fixed_stop(self, prices, stop_distance):
|
||||
"""Apply fixed stop loss"""
|
||||
stop_price = self.initial_price - stop_distance * self.initial_price
|
||||
exit_idx = None
|
||||
|
||||
for i, price in enumerate(prices):
|
||||
if price <= stop_price:
|
||||
exit_idx = i
|
||||
break
|
||||
|
||||
if exit_idx is None:
|
||||
exit_price = prices[-1]
|
||||
exit_idx = len(prices) - 1
|
||||
else:
|
||||
exit_price = stop_price
|
||||
|
||||
return exit_idx, exit_price
|
||||
|
||||
def apply_trailing_stop(self, prices, trailing_distance):
|
||||
"""Apply trailing stop loss"""
|
||||
stop_price = self.initial_price - trailing_distance * self.initial_price
|
||||
exit_idx = None
|
||||
|
||||
for i, price in enumerate(prices):
|
||||
# Update trailing stop (only moves up for long positions)
|
||||
new_stop = price - trailing_distance * price
|
||||
if new_stop > stop_price:
|
||||
stop_price = new_stop
|
||||
|
||||
# Check if stop is hit
|
||||
if price <= stop_price:
|
||||
exit_idx = i
|
||||
break
|
||||
|
||||
if exit_idx is None:
|
||||
exit_price = prices[-1]
|
||||
exit_idx = len(prices) - 1
|
||||
else:
|
||||
exit_price = stop_price
|
||||
|
||||
return exit_idx, exit_price, stop_price
|
||||
|
||||
def compare_strategies(self, num_simulations=1000, num_steps=1000):
|
||||
"""Compare fixed vs trailing stop"""
|
||||
results = []
|
||||
|
||||
for sim in range(num_simulations):
|
||||
prices = self.simulate_price_path(num_steps)
|
||||
|
||||
# Fixed stop
|
||||
fixed_exit_idx, fixed_exit_price = self.apply_fixed_stop(
|
||||
prices, self.fixed_stop_distance)
|
||||
fixed_return = (fixed_exit_price - self.initial_price) / self.initial_price
|
||||
|
||||
# Trailing stop
|
||||
trailing_exit_idx, trailing_exit_price, final_stop = self.apply_trailing_stop(
|
||||
prices, self.trailing_distance)
|
||||
trailing_return = (trailing_exit_price - self.initial_price) / self.initial_price
|
||||
|
||||
results.append({
|
||||
'simulation': sim,
|
||||
'final_price': prices[-1],
|
||||
'fixed_return': fixed_return,
|
||||
'trailing_return': trailing_return,
|
||||
'fixed_exit_time': fixed_exit_idx,
|
||||
'trailing_exit_time': trailing_exit_idx,
|
||||
'improvement': trailing_return - fixed_return
|
||||
})
|
||||
|
||||
return pd.DataFrame(results)
|
||||
|
||||
def plot_comparison(self, num_simulations=1000):
|
||||
"""Plot comparison results"""
|
||||
results_df = self.compare_strategies(num_simulations)
|
||||
|
||||
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
|
||||
|
||||
# Plot 1: Return Distribution Comparison
|
||||
axes[0, 0].hist(results_df['fixed_return'], bins=50, alpha=0.5,
|
||||
label='Fixed Stop', color='red', edgecolor='black')
|
||||
axes[0, 0].hist(results_df['trailing_return'], bins=50, alpha=0.5,
|
||||
label='Trailing Stop', color='green', edgecolor='black')
|
||||
axes[0, 0].axvline(0, color='black', linestyle='--', linewidth=1)
|
||||
axes[0, 0].set_xlabel('Return')
|
||||
axes[0, 0].set_ylabel('Frequency')
|
||||
axes[0, 0].set_title('Return Distribution Comparison')
|
||||
axes[0, 0].legend()
|
||||
axes[0, 0].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 2: Improvement Distribution
|
||||
axes[0, 1].hist(results_df['improvement'], bins=50, color='blue',
|
||||
edgecolor='black', alpha=0.7)
|
||||
axes[0, 1].axvline(0, color='red', linestyle='--', linewidth=2,
|
||||
label='No Improvement')
|
||||
axes[0, 1].axvline(results_df['improvement'].mean(), color='green',
|
||||
linestyle='--', linewidth=2,
|
||||
label=f'Mean: {results_df["improvement"].mean():.4f}')
|
||||
axes[0, 1].set_xlabel('Improvement (Trailing - Fixed)')
|
||||
axes[0, 1].set_ylabel('Frequency')
|
||||
axes[0, 1].set_title('Trailing Stop Improvement Distribution')
|
||||
axes[0, 1].legend()
|
||||
axes[0, 1].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 3: Sample Price Path with Stops
|
||||
sample_prices = self.simulate_price_path(500)
|
||||
_, fixed_exit = self.apply_fixed_stop(sample_prices, self.fixed_stop_distance)
|
||||
trailing_stops = []
|
||||
current_stop = self.initial_price - self.trailing_distance * self.initial_price
|
||||
|
||||
for price in sample_prices:
|
||||
new_stop = price - self.trailing_distance * price
|
||||
if new_stop > current_stop:
|
||||
current_stop = new_stop
|
||||
trailing_stops.append(current_stop)
|
||||
|
||||
axes[1, 0].plot(sample_prices, 'b-', label='Price', linewidth=2)
|
||||
axes[1, 0].axhline(self.initial_price - self.fixed_stop_distance * self.initial_price,
|
||||
color='red', linestyle='--', label='Fixed Stop', linewidth=2)
|
||||
axes[1, 0].plot(trailing_stops, 'g--', label='Trailing Stop', linewidth=2)
|
||||
axes[1, 0].set_xlabel('Time Step')
|
||||
axes[1, 0].set_ylabel('Price')
|
||||
axes[1, 0].set_title('Sample Price Path with Stop Losses')
|
||||
axes[1, 0].legend()
|
||||
axes[1, 0].grid(True, alpha=0.3)
|
||||
|
||||
# Plot 4: Performance Metrics Comparison
|
||||
metrics = ['Mean Return', 'Std Dev', 'Sharpe Ratio', 'Win Rate', 'Max Return']
|
||||
fixed_vals = [
|
||||
results_df['fixed_return'].mean(),
|
||||
results_df['fixed_return'].std(),
|
||||
results_df['fixed_return'].mean() / results_df['fixed_return'].std() if results_df['fixed_return'].std() > 0 else 0,
|
||||
(results_df['fixed_return'] > 0).mean(),
|
||||
results_df['fixed_return'].max()
|
||||
]
|
||||
trailing_vals = [
|
||||
results_df['trailing_return'].mean(),
|
||||
results_df['trailing_return'].std(),
|
||||
results_df['trailing_return'].mean() / results_df['trailing_return'].std() if results_df['trailing_return'].std() > 0 else 0,
|
||||
(results_df['trailing_return'] > 0).mean(),
|
||||
results_df['trailing_return'].max()
|
||||
]
|
||||
|
||||
x = np.arange(len(metrics))
|
||||
width = 0.35
|
||||
axes[1, 1].bar(x - width/2, fixed_vals, width, label='Fixed Stop', color='red', alpha=0.7)
|
||||
axes[1, 1].bar(x + width/2, trailing_vals, width, label='Trailing Stop', color='green', alpha=0.7)
|
||||
axes[1, 1].set_xlabel('Metric')
|
||||
axes[1, 1].set_ylabel('Value')
|
||||
axes[1, 1].set_title('Performance Metrics Comparison')
|
||||
axes[1, 1].set_xticks(x)
|
||||
axes[1, 1].set_xticklabels(metrics, rotation=45, ha='right')
|
||||
axes[1, 1].legend()
|
||||
axes[1, 1].grid(True, alpha=0.3, axis='y')
|
||||
|
||||
plt.tight_layout()
|
||||
return fig, results_df
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Create analyzer
|
||||
analyzer = TrailingStopAnalyzer(
|
||||
initial_price=100,
|
||||
drift=0.0001,
|
||||
volatility=0.02,
|
||||
trailing_distance=0.02,
|
||||
fixed_stop_distance=0.02
|
||||
)
|
||||
|
||||
print("Running Trailing Stop Analysis...")
|
||||
fig, results_df = analyzer.plot_comparison(num_simulations=1000)
|
||||
|
||||
print("\n=== Trailing Stop vs Fixed Stop Analysis ===")
|
||||
print(f"\nFixed Stop Results:")
|
||||
print(f" Mean Return: {results_df['fixed_return'].mean():.4f}")
|
||||
print(f" Std Dev: {results_df['fixed_return'].std():.4f}")
|
||||
print(f" Sharpe Ratio: {results_df['fixed_return'].mean() / results_df['fixed_return'].std():.4f}")
|
||||
print(f" Win Rate: {(results_df['fixed_return'] > 0).mean():.2%}")
|
||||
|
||||
print(f"\nTrailing Stop Results:")
|
||||
print(f" Mean Return: {results_df['trailing_return'].mean():.4f}")
|
||||
print(f" Std Dev: {results_df['trailing_return'].std():.4f}")
|
||||
print(f" Sharpe Ratio: {results_df['trailing_return'].mean() / results_df['trailing_return'].std():.4f}")
|
||||
print(f" Win Rate: {(results_df['trailing_return'] > 0).mean():.2%}")
|
||||
|
||||
print(f"\nImprovement:")
|
||||
improvement = results_df['trailing_return'].mean() - results_df['fixed_return'].mean()
|
||||
print(f" Mean Improvement: {improvement:.4f} ({improvement/results_df['fixed_return'].mean()*100:.1f}%)")
|
||||
print(f" Improvement Frequency: {(results_df['improvement'] > 0).mean():.2%}")
|
||||
|
||||
import os
|
||||
# Get the script directory and construct path to figures
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
figures_dir = os.path.join(script_dir, '..', 'figures')
|
||||
figures_path = os.path.abspath(figures_dir)
|
||||
os.makedirs(figures_path, exist_ok=True)
|
||||
|
||||
output_path = os.path.join(figures_path, 'trailing_stop_analysis.png')
|
||||
plt.savefig(output_path, dpi=300, bbox_inches='tight')
|
||||
print(f"\nFigure saved to {output_path}")
|
||||
plt.close()
|
||||