Overall Statistics
Total Trades
411
Average Win
0.24%
Average Loss
-0.32%
Compounding Annual Return
0.999%
Drawdown
4.300%
Expectancy
0.039
Net Profit
1.672%
Sharpe Ratio
0.232
Probabilistic Sharpe Ratio
13.544%
Loss Rate
40%
Win Rate
60%
Profit-Loss Ratio
0.75
Alpha
0.008
Beta
0.006
Annual Standard Deviation
0.038
Annual Variance
0.001
Information Ratio
-0.831
Tracking Error
0.132
Treynor Ratio
1.391
Total Fees
$0.00
from datetime import datetime
import decimal as d
from QuantConnect.Indicators import *
from NodaTime import DateTimeZone

class ExchangeRateGrinder(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2018, 6, 17)  # Set Start Date
        self.SetCash(100000)  # Set Strategy Cash
        self.tickers = ["EURUSD"]
        self.SetWarmUp(20)
        self.market = Market.Oanda
        self.res = Resolution.Hour
        self.bb = {}
        self.states = {} 
        self.risk = 0.2
        self.SetTimeZone(DateTimeZone.Utc)

        for ticker in self.tickers: 
            symbol = self.AddForex(ticker,self.res, self.market).Symbol
            self.bb[symbol] = self.BB(ticker, 20, 1.5, MovingAverageType.Simple, self.res)
            self.states[symbol] = 0
            
    def OnData(self,data):
        self.cash = self.Portfolio.Cash
        self.investment = self.cash * self.risk
        self.Debug(self.investment)

        if self.Time.hour >= 22 or self.Time.hour <= 8: #only trading between 10pm and 8am UTC
            for symbol in self.bb:
                self.holdings = self.Portfolio[symbol].Quantity
                price = self.Securities[symbol].Price 
                lower = self.bb[symbol].LowerBand.Current.Value
                upper = self.bb[symbol].UpperBand.Current.Value
                middle = self.bb[symbol].MiddleBand.Current.Value
                self.Debug(price)
                
                # if already long - liquidate if >= mean 
                if (self.states[symbol] == 1) and (price >= middle):
                    self.Liquidate(symbol)
                    self.states[symbol] = 0
    
                # if already short - liquidate if <=mean
                if (self.states[symbol] == -1) and (price <= middle):
                    self.Liquidate(symbol)
                    self.states[symbol] = 0
                    
                # if close is below lower band go long 
                if price <= lower:
                    # and not already holding or short 
                    if self.states[symbol] <= 0:
                        self.Liquidate(symbol)
                        self.SetHoldings(symbol, 1)
                        self.states[symbol] = 1 
                
                # if close is abover upper band go short 
                if price >= upper:
                    # and not already holding or long 
                    if self.states[symbol] >= 0:
                        self.Liquidate(symbol)
                        self.SetHoldings(symbol, -1)
                        self.states[symbol] = -1