Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Sortino Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-0.535
Tracking Error
0.187
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
Portfolio Turnover
0%
from AlgorithmImports import *

class ForexCFDAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 1, 1)  # Start Date
        self.SetCash(100000)  # Set Strategy Cash

        # Forex symbol
        self.symbol = self.AddForex("EURUSD", Resolution.Daily).Symbol

        # Indicators
        self.daily_ema = self.EMA(self.symbol, 10, Resolution.Daily)
        self.atr = self.ATR(self.symbol, 100, Resolution.Daily)
        self.month_end_window = RollingWindow[TradeBar](2)  # For monthly EMA

        # State variables
        self.is_long_term_bullish = False
        self.batch_positions = []
        self.batch_entry_prices = []
        self.open_positions = 0
        self.basket_size = 5  # Define basket size
        self.atr_multiplier_for_space = 2  # Define ATR multiplier for spacing
        self.last_basket_position_time = self.Time
        self.trailing_stop = 0

    def OnEndOfDay(self, symbol):
        if symbol != self.symbol:
            return

        # Add the daily bar to the rolling window for monthly EMA calculation
        self.month_end_window.Add(self.CurrentSlice[symbol])

        # Update the monthly EMA at the end of each month
        if self.month_end_window.IsReady and self.Time.month != self.month_end_window[0].EndTime.month:
            monthly_close = self.month_end_window[0].Close
            self.monthly_ema.Update(self.month_end_window[0].EndTime, monthly_close)

    def OnData(self, data):
        # Ensure data for the symbol is available
        if not self.symbol in data:
            return

        # Update daily EMA and ATR
        if not self.daily_ema.Update(data[self.symbol]) or not self.atr.Update(data[self.symbol]):
            return

        # Update long-term bullish/bearish based on monthly EMA
        if self.month_end_window.IsReady and self.monthly_ema.IsReady:
            self.is_long_term_bullish = data[self.symbol].Close > self.monthly_ema.Current.Value

        # Position entry logic
        if (self.Time - self.last_basket_position_time).total_minutes() >= 120:
            if self.is_long_term_bullish and data[self.symbol].Close > self.daily_ema.Current.Value:
                self.EnterPosition('Long', data)
            elif not self.is_long_term_bearish and data[self.symbol].Close < self.daily_ema.Current.Value:
                    self.EnterPosition('Short', data)

    def EnterPosition(self, direction, data):
        if self.open_positions < self.basket_size:
            if self.open_positions == 0 or (data[self.symbol].Close - self.batch_entry_prices[-1][0] >= self.atr.Current.Value * self.atr_multiplier_for_space):
                lot_size = 0.05  # Define lot size
                if direction == 'Long':
                    self.Buy(self.symbol, lot_size)
                else:
                    self.Sell(self.symbol, lot_size)

                # Update state variables
                self.batch_positions.append(self.symbol)
                self.batch_entry_prices.append((data[self.symbol].Close, lot_size))
                self.open_positions += 1
                self.last_basket_position_time = self.Time

    def OnEndOfAlgorithm(self):
        # Liquidate all positions at the end of the algorithm
        self.Liquidate()

        ### Part 3: Risk Management
    def ExecuteTrailingStopLoss(self, data):
        atr_value = self.atr.Current.Value
        trailing_stop_distance = 3 * atr_value  # Example multiplier

        # Update trailing stop for each position
        for price, size in self.batch_entry_prices:
            if self.Portfolio[self.symbol].IsLong:
                self.trailing_stop = max(self.trailing_stop, price - trailing_stop_distance)
            elif self.Portfolio[self.symbol].IsShort:
                self.trailing_stop = min(self.trailing_stop, price + trailing_stop_distance)
    
        # Check and execute trailing stop
        current_price = data[self.symbol].Close
        if (self.Portfolio[self.symbol].IsLong and current_price <= self.trailing_stop) or \
           (self.Portfolio[self.symbol].IsShort and current_price >= self.trailing_stop):
            self.Liquidate(self.symbol)

    def OnData(self, data):
        # Previous OnData content...

        # Risk management
        if self.open_positions > 0:
            self.ExecuteTrailingStopLoss(data)

        ### Part 4: Monthly EMA Calculation

    def OnEndOfDay(self, symbol):
        # Previous OnEndOfDay content...

        # Update long-term bullish/bearish based on monthly EMA
        if self.month_end_window.IsReady and self.monthly_ema.IsReady:
            self.is_long_term_bullish = data[self.symbol].Close > self.monthly_ema.Current.Value