| 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 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.287 Tracking Error 0.347 Treynor Ratio 0 Total Fees $0.00 |
import datetime
class MorningBreakOut(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 1, 1) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
self.SetTimeZone("Europe/Berlin")
self.SetBrokerageModel(BrokerageName.OandaBrokerage)
# self.SetBenchmark("SPY")
symbols = []
symbols.append(Symbol.Create("DE30EUR", SecurityType.Cfd, Market.Oanda))
#3. Set a universe using self.SetUniverseSelection(), and pass in a ManualUniverseSelectionModel()
self.SetUniverseSelection(ManualUniverseSelectionModel(symbols))
#2. Set the resolution of the universe assets to daily resolution
self.UniverseSettings.Resolution = Resolution.Minute
# holds {"symbol": symbolData} instance for each symbol
self.symbolDataBySymbol = {}
# Call the MOMAlphaModel Class
self.SetAlpha( OMRAlphaModel(self.symbolDataBySymbol) )
self.SetPortfolioConstruction( AllInOrSplitEqually() )
self.SetRiskManagement( OpenPositionRiskManagement(self.symbolDataBySymbol) )
self.SetExecution( ImmediateExecutionModel(self.symbolDataBySymbol) )
def OnDataConsolidated(self, sender, quoteBar):
self.Log("OnDataConsolidated called on " + str(self.Time))
self.Log(str(quoteBar))
def OnSecuritiesChanged(self, changes):
'''We should use this event to setup any state required for our alpha calculations.
The method provides the algorithm object, and a list of securities changes. For example,
we could generate indicators for each symbol in this method and save the symbols and indicators to a dictionary.
'''
# Initialize SymbolData for each symbol
for added in changes.AddedSecurities:
self.Debug("securities change")
symbolData = self.symbolDataBySymbol.get(added.Symbol)
if symbolData is None:
symbolData = SymbolData(added)
symbolData.RegisterConsolidator(self, minutes=60)
self.symbolDataBySymbol[added.Symbol] = symbolData
class SymbolData:
'''Contains data specific to a symbol required by this model'''
def __init__(self, security):
self.Security = security
self.Symbol = security.Symbol
self._openingBar = None
self.oneR = None
def OnDataConsolidated(self, quoteBar):
if quoteBar.Time.hour == 9:
self.openingBar = quoteBar
self.oneR = abs(self.openingBar.High - self.openingBar.Low)
self.Debug(f"EndTime: {quoteBar.EndTime}, High: {quoteBar.High}, Low: {quoteBar.Low}, oneR: {abs(quoteBar.High-quoteBar.Low)}")
def RegisterConsolidator(self, algorithm, minutes=60):
openRangeCons = algorithm.Consolidate(self.Symbol, timedelta(minutes), self.OnDataConsolidated)
algorithm.SubscriptionManager.AddConsolidator(self.Symbol, openRangeCons)
@property
def openingBar(self):
return self._openingBar
@openingBar.setter
def openingBar(self, value):
self._openingBar = value
class OMRAlphaModel(AlphaModel):
def __init__(self, symbolDataBySymbol):
self.symbolDataBySymbol = symbolDataBySymbol
def Update(self, algorithm, data):
insights = []
for symbol, symbolData in self.symbolDataBySymbol.items():
if symbolData.openingBar is None: continue
algorithm.Debug("no openingBar")
direction = InsightDirection.Flat
if not algorithm.Portfolio[symbol].Invested:
# Entry
if data[symbol].Close >= symbolData.openingBar.High: direction = InsightDirection.Up
if data[symbol].Close <= symbolData.openingBar.Low: direction = InsightDirection.Down
insights.append(Insight(symbolData.Symbol, timedelta(1), InsightType.Price, direction, "Entry"))
# Take Profit
if algorithm.Portfolio[symbol].Invested:
if data[symbol].Close >= symbolData.openingBar.High + symbolData.oneR: InsightDirection.Down
if data[symbol].Close <= symbolData.openingBar.Low - symbolData.oneR: InsightDirection.Up
insights.append(Insight(symbolData.Symbol, timedelta(1), InsightType.Price, direction, "TakeProfit"))
return insights
class AllInOrSplitEqually(PortfolioConstructionModel):
def __init__(self):
pass
def DetermineTargetPercent(self, activeInsights):
'''Will determine the target percent for each insight
Args:
activeInsights: The active insights to generate a target for'''
result = {}
# give equal weighting to each security
count = sum(x.Direction != InsightDirection.Flat for x in activeInsights)
percent = 0 if count == 0 else 1.0 / count
for insight in activeInsights:
result[insight] = insight.Direction * percent
return result
class OpenPositionRiskManagement(RiskManagementModel):
def __init__(self, symbolDataBySymbol):
self.symbolDataBySymbol = symbolDataBySymbol
self.trailingStop = None
def ManageRisk(self, algorithm, targets):
targets = []
for symbol in self.symbolDataBySymbol:
# Time Exit if necessary
if algorithm.Time.time() >= datetime.time(21,15):
targets.append(PortfolioTarget(symbol, 0))
continue
# Trailing StopLoss
if algorithm.Portfolio[symbol].Quantity > 0:
self.trailingStop = round(self.symbolDataBySymbol[symbol].openingBar.High - self.oneR / 2, 1)
if algorithm.Securities[symbol].Close <= self.trailingStop:
targets.append(PortfolioTarget(symbol, 0))
if algorithm.Portfolio[symbol].Quantity < 0:
self.trailingStop = round(self.symbolDataBySymbol[symbol].openingBar.Low + self.oneR / 2, 1)
if algorithm.Securities[symbol].Close >= self.trailingStop:
targets.append(PortfolioTarget(symbol, 0))
return targets
class ImmediateExecutionModel(ExecutionModel):
'''Provides an implementation of IExecutionModel that immediately submits market orders to achieve the desired portfolio targets'''
def __init__(self, symbolDataBySymbol):
'''Initializes a new instance of the ImmediateExecutionModel class'''
self.targetsCollection = PortfolioTargetCollection()
self.symbolDataBySymbol = symbolDataBySymbol
def Execute(self, algorithm, targets):
'''Immediately submits orders for the specified portfolio targets.
Args:
algorithm: The algorithm instance
targets: The portfolio targets to be ordered'''
# for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
self.targetsCollection.AddRange(targets)
if self.targetsCollection.Count > 0:
for target in self.targetsCollection.OrderByMarginImpact(algorithm):
# calculate remaining quantity to be ordered
quantity = OrderSizing.GetUnorderedQuantity(algorithm, target)
if quantity != 0:
algorithm.MarketOrder(target.Symbol, quantity)
self.symbolDataBySymbol.openingBar = None
self.targetsCollection.ClearFulfilled(algorithm)