Overall Statistics |
Total Trades 11626 Average Win 0.00% Average Loss 0.00% Compounding Annual Return -0.025% Drawdown 0.200% Expectancy -0.640 Net Profit -0.096% Sharpe Ratio -34.647 Sortino Ratio -37.64 Probabilistic Sharpe Ratio 0.087% Loss Rate 80% Win Rate 20% Profit-Loss Ratio 0.76 Alpha -0.019 Beta -0.001 Annual Standard Deviation 0.001 Annual Variance 0 Information Ratio -0.453 Tracking Error 0.191 Treynor Ratio 32.422 Total Fees $0.00 Estimated Strategy Capacity $1800000.00 Lowest Capacity Asset EURUSD 8G Portfolio Turnover 0.01% |
from AlgorithmImports import * class ForexCFDAlgorithm(QCAlgorithm): def Initialize(self): # Initialization settings self.SetStartDate(2020, 1, 1) self.SetCash(100000) self.symbol = self.AddForex("EURUSD", Resolution.Daily).Symbol self.monthly_ema = self.EMA(self.symbol, 30, Resolution.Daily) self.last_monthly_ema_update = self.Time.month self.daily_ema = self.EMA(self.symbol, 10, Resolution.Daily) self.atr = self.ATR(self.symbol, 100, Resolution.Daily) self.is_long_term_bullish = False self.batch_positions = [] self.batch_stop_loss = 0 self.batch_entry_prices = [] self.last_position_time = self.Time self.trailing_stop = 0 self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.Every(timedelta(minutes=120)), self.TimeBasedPositionEntry) def OnData(self, data): self.Log("Triggered OnData") # Ensure data for the symbol is available if not self.symbol in data: return if self.monthly_ema.IsReady: self.is_long_term_bullish = data[self.symbol].Close > self.monthly_ema.Current.Value if self.daily_ema.IsReady and self.atr.IsReady: self.ExecuteStrategy(data) if self.monthly_ema.IsReady: self.is_long_term_bullish = data[self.symbol].Close > self.monthly_ema.Current.Value # Execute strategy based on daily data if self.daily_ema.IsReady and self.atr.IsReady: self.ExecuteStrategy(data) def ExecuteStrategy(self, data): self.Log("Triggered ExecuteStrategy") # Entry logic based on long-term trend and daily EMA if not self.atr.IsReady or not self.daily_ema.IsReady: return # Ensure that the ATR and EMA indicators are ready # Check for long-term bullish trend and a positive crossover on daily EMA if self.is_long_term_bullish and data[self.symbol].Close > self.daily_ema.Current.Value: # Check if it's time to enter a new batch position if len(self.batch_positions) < 5 and (self.Time - self.last_position_time) >= timedelta(minutes=120): self.EnterPosition('Long') # Check for long-term bearish trend and a negative crossover on daily EMA elif not self.is_long_term_bullish and data[self.symbol].Close < self.daily_ema.Current.Value: # Check if it's time to enter a new batch position if len(self.batch_positions) < 5 and (self.Time - self.last_position_time) >= timedelta(minutes=120): self.EnterPosition('Short') # Update trailing stop and manage the batch #self.UpdateTrailingStopAndManageBatch() def ExecuteTrailingStopLoss(self): self.Log("Triggered ExecuteTrailingStopLoss") # Assuming the trailing stop is based on the ATR 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: # For long positions self.trailing_stop = max(self.trailing_stop, price - trailing_stop_distance) else: # For short positions self.trailing_stop = min(self.trailing_stop, price + trailing_stop_distance) # Check if the current price has hit the trailing stop current_price = self.Securities[self.symbol].Price 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) self.batch_positions.clear() self.batch_entry_prices.clear() def EnterPosition(self, direction): # Enter the trade self.Log("Triggered EnterPosition") if direction == 'Long': lot_size = 1 self.Buy(self.symbol, lot_size) else: lot_size = -1 self.Sell(self.symbol, lot_size) # Add this position to batch tracking self.batch_positions.append(self.symbol) self.batch_entry_prices.append((self.Securities[self.symbol].Price, lot_size)) def TimeBasedPositionEntry(self): # Check if it's time to consider a new position self.Log("Triggered TimeBasedPositionEntry") if self.Time - self.last_position_time >= timedelta(minutes=120): # Check the strategy conditions if self.is_long_term_bullish and self.Securities[self.symbol].Price > self.daily_ema.Current.Value: self.EnterPosition('Long') elif not self.is_long_term_bullish and self.Securities[self.symbol].Price < self.daily_ema.Current.Value: self.EnterPosition('Short')