Overall Statistics
Total Trades
721
Average Win
0.81%
Average Loss
-0.42%
Compounding Annual Return
1634.322%
Drawdown
52.200%
Expectancy
1.617
Net Profit
1091.724%
Sharpe Ratio
10.67
Probabilistic Sharpe Ratio
95.197%
Loss Rate
11%
Win Rate
89%
Profit-Loss Ratio
1.93
Alpha
10.809
Beta
-4.745
Annual Standard Deviation
1.03
Annual Variance
1.061
Information Ratio
10.492
Tracking Error
1.051
Treynor Ratio
-2.316
Total Fees
$0.00
Estimated Strategy Capacity
$360000.00
Lowest Capacity Asset
USDJPY 8G
Portfolio Turnover
89.89%
from datetime import datetime, timedelta
from decimal import Decimal

from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from QuantConnect.Algorithm.Framework.Risk import *
from QuantConnect.Algorithm.Framework.Selection import *
from QuantConnect.Brokerages import BrokerageName
from QuantConnect.Data.Consolidators import *
from QuantConnect.Data.Market import TradeBar
from QuantConnect.Data.UniverseSelection import *
from QuantConnect.Indicators import *
from QuantConnect.Indicators import IndicatorDataPoint
from QuantConnect.Orders import *
from QuantConnect.Orders import OrderDirection, OrderTicket
from QuantConnect.Orders.Fees import FeeModel, OrderFee
from QuantConnect.Securities import Security
from System import *
from System.Collections.Generic import List
import numpy as np
import math

class ForexStochasticStrategy(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2023, 1, 1) # Imposta la data di inizio a lunedì 5 novembre 2023
        self.SetEndDate(2023, 11, 13) # Imposta la data di fine a lunedì 6 novembre 2023

        self.SetCash(2000) # Imposta il saldo iniziale a 200 euro      
        
        self.symbol = self.AddForex("USDJPY", Resolution.Minute).Symbol

        self.SetBrokerageModel(BrokerageName.OandaBrokerage) # Or any brokerage you use

        self.stoch = self.STO(self.symbol, 14, 3, 3) # Using default settings for Stochastic
        self.rsi = self.RSI(self.symbol, 14, MovingAverageType.Wilders, Resolution.Minute)
        self.macd = self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Minute)
        self.ema = self.EMA(self.symbol, 14, Resolution.Minute)
        self.atr = self.ATR(self.symbol, 14, MovingAverageType.Wilders, Resolution.Minute)
        self.roc = self.ROC(self.symbol, 14, Resolution.Minute)
        self.cci = self.CCI(self.symbol, 20, MovingAverageType.Simple, Resolution.Minute)
        self.sma = self.SMA(self.symbol, 20, Resolution.Minute)
        self.adx = self.ADX(self.symbol, 14, Resolution.Minute)

        # Definizione dell'EMA con periodo ottimizzato
        self.optimalEmaPeriod = 30
        self.emaOptimized = self.EMA(self.symbol, self.optimalEmaPeriod, Resolution.Minute)


        self.closeWindow = RollingWindow[IndicatorDataPoint](14)

        # Other parameters
        self.stopLoss = 0.00030
        self.takeProfit = 0.00015
        self.lotSize = 2000

    def OnData(self, slice):
        # If the symbol's data is not present in the slice, return immediately
        if self.symbol not in slice:
            return
        
        # Get the TradeBar for the symbol
        bar = slice[self.symbol]

        # Add the closing price to the rolling window as an IndicatorDataPoint
        self.closeWindow.Add(IndicatorDataPoint(bar.EndTime, bar.Close))

        # Ensure all indicators are ready before proceeding
        if not (self.stoch.IsReady and self.rsi.IsReady and self.macd.IsReady and 
                    self.ema.IsReady and self.atr.IsReady and self.roc.IsReady and 
                    self.cci.IsReady and self.sma.IsReady and self.adx.IsReady and
                    self.emaOptimized.IsReady):
                return

        # Define the trading signals
        
        currentPrice = slice[self.symbol].Close

        isStochOverSold = self.stoch.StochK.Current.Value < 20 and self.stoch.StochD.Current.Value < 20
        isStochOverBought = self.stoch.StochK.Current.Value > 80 and self.stoch.StochD.Current.Value > 80
        isRSIOverSold = self.rsi.Current.Value < 24
        isRSIOverBought = self.rsi.Current.Value > 76
        isTrending = self.adx.Current.Value > 57.5

        if isStochOverSold and isRSIOverSold and isTrending:
            # Calcola la quantità in base alla dimensione del lotto desiderata
            quantity = self.lotSize
            #self.Log(quantity)
            
            # Piazza l'ordine di mercato
            self.MarketOrder(self.symbol, quantity)
            
            # Definisci i prezzi di stop loss e take profit
            stopPrice = bar.Close - self.stopLoss
            limitPrice = bar.Close + self.takeProfit

            #self.Debug(f"bar.Close---------{bar.Close}")
            #self.Debug(f"stopPrice---------{stopPrice}")
            #self.Debug(f"limitPrice---------{limitPrice}")
            
            # Piazza gli ordini di stop loss e take profit
            #self.StopMarketOrder(self.symbol, quantity, stopPrice)  # Quantità positiva per lo stop loss
            #self.LimitOrder(self.symbol, quantity, limitPrice)      # Quantità positiva per il take profit
        
        # Condizioni di ingresso per una posizione corta
        elif isStochOverBought and isRSIOverBought and isTrending:
            # Calcola la quantità in base alla dimensione del lotto desiderata
            quantity = self.lotSize
            #self.Log(quantity)

            # Piazza l'ordine di mercato
            self.MarketOrder(self.symbol, -quantity)
            
            # Definisci i prezzi di stop loss e take profit
            stopPrice = bar.Close + self.stopLoss
            limitPrice = bar.Close - self.takeProfit
            
            #self.Debug(f"bar.Close---------{bar.Close}")
            #self.Debug(f"stopPrice---------{stopPrice}")
            #self.Debug(f"limitPrice---------{limitPrice}")
            
            #Piazza gli ordini di stop loss e take profit
            #self.StopMarketOrder(self.symbol, -quantity, stopPrice) # Quantità negativa per lo stop loss
            #self.LimitOrder(self.symbol, -quantity, limitPrice)     #
from datetime import datetime, timedelta
from decimal import Decimal

from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from QuantConnect.Algorithm.Framework.Risk import *
from QuantConnect.Algorithm.Framework.Selection import *
from QuantConnect.Brokerages import BrokerageName
from QuantConnect.Data.Consolidators import *
from QuantConnect.Data.Market import TradeBar
from QuantConnect.Data.UniverseSelection import *
from QuantConnect.Indicators import *
from QuantConnect.Indicators import IndicatorDataPoint
from QuantConnect.Orders import *
from QuantConnect.Orders import OrderDirection, OrderTicket
from QuantConnect.Orders.Fees import FeeModel, OrderFee
from QuantConnect.Securities import Security
from System import *
from System.Collections.Generic import List
import numpy as np
import math



class ForexStochasticStrategy(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2023, 9, 1) # Imposta la data di inizio a lunedì 5 novembre 2023
        self.SetEndDate(2023, 11, 1) # Imposta la data di fine a lunedì 6 novembre 2023

        self.SetCash(5000) # Imposta il saldo iniziale a 200 euro      
        
        self.symbol = self.AddForex("EURUSD", Resolution.Minute).Symbol

        self.SetBrokerageModel(BrokerageName.OandaBrokerage) # Or any brokerage you use

        self.stoch = self.STO(self.symbol, 14, 3, 3) # Using default settings for Stochastic
        self.rsi = self.RSI(self.symbol, 14, MovingAverageType.Wilders, Resolution.Minute)
        self.macd = self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Minute)
        self.ema = self.EMA(self.symbol, 14, Resolution.Minute)
        self.atr = self.ATR(self.symbol, 14, MovingAverageType.Wilders, Resolution.Minute)
        self.roc = self.ROC(self.symbol, 14, Resolution.Minute)
        self.cci = self.CCI(self.symbol, 20, MovingAverageType.Simple, Resolution.Minute)
        self.sma = self.SMA(self.symbol, 20, Resolution.Minute)
        self.adx = self.ADX(self.symbol, 14, Resolution.Minute)

        self.parabolicSAR = self.PSAR(self.symbol, 0.02, 0.2)

        self.closeWindow = RollingWindow[IndicatorDataPoint](14)

        self.logReturnsWindow = RollingWindow[float](14) # finestra per i rendimenti logaritmici

        # Other parameters
        self.stopLoss = 0.00028
        self.takeProfit = 0.0015
        self.lotSize = 1200

    def OnData(self, slice):
        # If the symbol's data is not present in the slice, return immediately
        if self.symbol not in slice:
            return
        
        # Get the TradeBar for the symbol
        bar = slice[self.symbol]

        # Add the closing price to the rolling window as an IndicatorDataPoint
        self.closeWindow.Add(IndicatorDataPoint(bar.EndTime, bar.Close))

        # Ensure all indicators are ready before proceeding
        if not (self.stoch.IsReady and self.rsi.IsReady and self.macd.IsReady and 
                    self.ema.IsReady and self.atr.IsReady and self.roc.IsReady and 
                    self.cci.IsReady and self.sma.IsReady and self.adx.IsReady):
                return

        # Define the trading signals
        
        currentPrice = slice[self.symbol].Close

        isStochOverSold = self.stoch.StochK.Current.Value < 15 and self.stoch.StochD.Current.Value < 15
        isStochOverBought = self.stoch.StochK.Current.Value > 85 and self.stoch.StochD.Current.Value > 85
        isRSIOverSold = self.rsi.Current.Value < 20
        isRSIOverBought = self.rsi.Current.Value > 80
        isTrending = self.adx.Current.Value > 30

        # Calcola i rendimenti logaritmici e aggiungi alla finestra
        currentClose = slice[self.symbol].Close
        previousClose = self.closeWindow[1].Value # Prezzo di chiusura precedente
        logReturn = math.log(currentClose / previousClose)
        self.logReturnsWindow.Add(logReturn)

        historicalVolatility = np.std([x for x in self.logReturnsWindow])


        if isStochOverSold and isRSIOverSold and isTrending:
            # Calcola la quantità in base alla dimensione del lotto desiderata
            quantity = self.lotSize / self.Securities[self.symbol].Price
            self.Log(quantity)
            
            # Piazza l'ordine di mercato
            ticket = self.MarketOrder(self.symbol, quantity)
            
            # Definisci i prezzi di stop loss e take profit
            stopPrice = bar.Close - self.stopLoss
            limitPrice = bar.Close + self.takeProfit

            self.Debug(f"bar.Close---------{bar.Close}")
            self.Debug(f"stopPrice---------{stopPrice}")
            self.Debug(f"limitPrice---------{limitPrice}")
            
            # Piazza gli ordini di stop loss e take profit
            self.StopMarketOrder(self.symbol, quantity, stopPrice)  # Quantità positiva per lo stop loss
            self.LimitOrder(self.symbol, quantity, limitPrice)      # Quantità positiva per il take profit
        
        # Condizioni di ingresso per una posizione corta
        elif isStochOverBought and isRSIOverBought and isTrending:
            # Calcola la quantità in base alla dimensione del lotto desiderata
            quantity = self.lotSize / self.Securities[self.symbol].Price
            self.Log(quantity)

            # Piazza l'ordine di mercato
            ticket = self.MarketOrder(self.symbol, -quantity)
            
            # Definisci i prezzi di stop loss e take profit
            stopPrice = bar.Close + self.stopLoss
            limitPrice = bar.Close - self.takeProfit
            
            self.Debug(f"bar.Close---------{bar.Close}")
            self.Debug(f"stopPrice---------{stopPrice}")
            self.Debug(f"limitPrice---------{limitPrice}")
            
            # Piazza gli ordini di stop loss e take profit
            self.StopMarketOrder(self.symbol, -quantity, stopPrice) # Quantità negativa per lo stop loss
            self.LimitOrder(self.symbol, -quantity, limitPrice)     #

            
from datetime import datetime, timedelta
from decimal import Decimal

from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from QuantConnect.Algorithm.Framework.Risk import *
from QuantConnect.Algorithm.Framework.Selection import *
from QuantConnect.Brokerages import BrokerageName
from QuantConnect.Data.Consolidators import *
from QuantConnect.Data.Market import TradeBar
from QuantConnect.Data.UniverseSelection import *
from QuantConnect.Indicators import *
from QuantConnect.Indicators import IndicatorDataPoint
from QuantConnect.Orders import *
from QuantConnect.Orders import OrderDirection, OrderTicket
from QuantConnect.Orders.Fees import FeeModel, OrderFee
from QuantConnect.Securities import Security
from System import *
from System.Collections.Generic import List
import numpy as np
import math

class ForexStochasticStrategy(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2023, 1, 1) # Imposta la data di inizio a lunedì 5 novembre 2023
        self.SetEndDate(2023, 11, 13) # Imposta la data di fine a lunedì 6 novembre 2023

        self.SetCash(2000) # Imposta il saldo iniziale a 200 euro      
        
        self.symbol = self.AddForex("USDJPY", Resolution.Minute).Symbol

        self.SetBrokerageModel(BrokerageName.OandaBrokerage) # Or any brokerage you use

        self.stoch = self.STO(self.symbol, 14, 3, 3) # Using default settings for Stochastic
        self.rsi = self.RSI(self.symbol, 14, MovingAverageType.Wilders, Resolution.Minute)
        self.macd = self.MACD(self.symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Minute)
        self.ema = self.EMA(self.symbol, 14, Resolution.Minute)
        self.atr = self.ATR(self.symbol, 14, MovingAverageType.Wilders, Resolution.Minute)
        self.roc = self.ROC(self.symbol, 14, Resolution.Minute)
        self.cci = self.CCI(self.symbol, 20, MovingAverageType.Simple, Resolution.Minute)
        self.sma = self.SMA(self.symbol, 20, Resolution.Minute)
        self.adx = self.ADX(self.symbol, 14, Resolution.Minute)

        # Definizione dell'EMA con periodo ottimizzato
        self.optimalEmaPeriod = 30
        self.emaOptimized = self.EMA(self.symbol, self.optimalEmaPeriod, Resolution.Minute)


        self.closeWindow = RollingWindow[IndicatorDataPoint](14)

        # Other parameters
        self.stopLoss = 0.00030
        self.takeProfit = 0.00015
        self.lotSize = 2200

    def OnData(self, slice):
        # If the symbol's data is not present in the slice, return immediately
        if self.symbol not in slice:
            return
        
        # Get the TradeBar for the symbol
        bar = slice[self.symbol]

        # Add the closing price to the rolling window as an IndicatorDataPoint
        self.closeWindow.Add(IndicatorDataPoint(bar.EndTime, bar.Close))

        # Ensure all indicators are ready before proceeding
        if not (self.stoch.IsReady and self.rsi.IsReady and self.macd.IsReady and 
                    self.ema.IsReady and self.atr.IsReady and self.roc.IsReady and 
                    self.cci.IsReady and self.sma.IsReady and self.adx.IsReady and
                    self.emaOptimized.IsReady):
                return

        # Define the trading signals
        
        currentPrice = slice[self.symbol].Close

        isStochOverSold = self.stoch.StochK.Current.Value < 20 and self.stoch.StochD.Current.Value < 20
        isStochOverBought = self.stoch.StochK.Current.Value > 80 and self.stoch.StochD.Current.Value > 80
        isRSIOverSold = self.rsi.Current.Value < 28
        isRSIOverBought = self.rsi.Current.Value > 72
        isTrending = self.adx.Current.Value > 56.8

        if isStochOverSold and isRSIOverSold and isTrending:
            # Calcola la quantità in base alla dimensione del lotto desiderata
            quantity = self.lotSize
            #self.Log(quantity)
            
            # Piazza l'ordine di mercato
            self.MarketOrder(self.symbol, quantity)
            
            # Definisci i prezzi di stop loss e take profit
            stopPrice = bar.Close - self.stopLoss
            limitPrice = bar.Close + self.takeProfit

            #self.Debug(f"bar.Close---------{bar.Close}")
            #self.Debug(f"stopPrice---------{stopPrice}")
            #self.Debug(f"limitPrice---------{limitPrice}")
            
            # Piazza gli ordini di stop loss e take profit
            #self.StopMarketOrder(self.symbol, quantity, stopPrice)  # Quantità positiva per lo stop loss
            #self.LimitOrder(self.symbol, quantity, limitPrice)      # Quantità positiva per il take profit
        
        # Condizioni di ingresso per una posizione corta
        elif isStochOverBought and isRSIOverBought and isTrending:
            # Calcola la quantità in base alla dimensione del lotto desiderata
            quantity = self.lotSize
            #self.Log(quantity)

            # Piazza l'ordine di mercato
            self.MarketOrder(self.symbol, -quantity)
            
            # Definisci i prezzi di stop loss e take profit
            stopPrice = bar.Close + self.stopLoss
            limitPrice = bar.Close - self.takeProfit
            
            #self.Debug(f"bar.Close---------{bar.Close}")
            #self.Debug(f"stopPrice---------{stopPrice}")
            #self.Debug(f"limitPrice---------{limitPrice}")
            
            # Piazza gli ordini di stop loss e take profit
            #self.StopMarketOrder(self.symbol, -quantity, stopPrice) # Quantità negativa per lo stop loss
            #self.LimitOrder(self.symbol, -quantity, limitPrice)     #