Overall Statistics |
Total Trades 481 Average Win 1.79% Average Loss -3.81% Compounding Annual Return 111.371% Drawdown 44.500% Expectancy 0.203 Net Profit 550.161% Sharpe Ratio 1.825 Probabilistic Sharpe Ratio 73.297% Loss Rate 18% Win Rate 82% Profit-Loss Ratio 0.47 Alpha 0.762 Beta 0.192 Annual Standard Deviation 0.481 Annual Variance 0.231 Information Ratio 0.405 Tracking Error 0.687 Treynor Ratio 4.58 Total Fees $213323.56 Estimated Strategy Capacity $240000.00 Lowest Capacity Asset ETHUSD 10B Portfolio Turnover 19.63% |
from AlgorithmImports import * class PriceActionAlpha(AlphaModel): def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.hour = -1 self.selltrig = None self.buytrig = None self.currentopen = None self.consolidator = TradeBarConsolidator(timedelta(1)) self.consolidator.DataConsolidated += self.OnConsolidated self.window = RollingWindow[TradeBar](4) history = algorithm.History[TradeBar](self.symbol, 4*24*60, Resolution.Minute) for bar in history: self.consolidator.Update(bar) algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.consolidator) def OnConsolidated(self, sender, bar): self.window.Add(bar) self.currentopen = bar.Open if not self.window.IsReady: return df = self.algorithm.PandasConverter.GetDataFrame[TradeBar](self.window) k1 = 0.5 k2 = 0.5 HH, HC, LC, LL = max(df['high']), max(df['close']), min(df['close']), min(df['low']) if (HH - LC) >= (HC - LL): signalrange = HH - LC else: signalrange = HC - LL self.selltrig = self.currentopen - k2 * signalrange self.buytrig = self.currentopen + k1 * signalrange def Update(self, algorithm, data): # We only use hourly signals if not data.ContainsKey(self.symbol) or not self.window.IsReady: return [] if self.hour == algorithm.Time.hour: return [] self.hour = algorithm.Time.hour price = data[self.symbol].Price if algorithm.LiveMode: algorithm.Log(f'Buy Trigger {self.buytrig} > Price {price} > {self.selltrig}') if price >= self.buytrig: # self.algorithm.pcm.maxcap = (price - self.buytrig) / self.buytrig * self.algorithm.multiplier return [Insight(self.symbol, timedelta(days=365), InsightType.Price, InsightDirection.Up)] # magnitude = size, # confidence = size, # weight = size)] elif price < self.selltrig: algorithm.Insights.Cancel([self.symbol]) return []
from AlgorithmImports import * from alpha import PriceActionAlpha from pcm import EqualWeightingMaxCapPortfolioConstructionModel # BTCUSD Long Only Dual Thrust Algorithm # Originated by Michael Vitucci class DualThrustAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 1) self.SetEndDate(2022, 7, 1) self.SetCash(100000) self.SetBrokerageModel(BrokerageName.Kraken, AccountType.Margin) # self.stopLoss = self.GetParameter('stopLoss', 0.04) # self.takeProfit = self.GetParameter('takeProfit', 0.25) # self.lookback = self.GetParameter('lookback', 4) # self.maxcap = self.GetParameter('maxcap', 1.0) # self.multiplier = self.GetParameter('multiplier', 1) tickers = ['ETHUSD'] for ticker in tickers: symbol = self.AddCrypto(ticker, Resolution.Minute).Symbol self.AddAlpha(PriceActionAlpha(self, symbol)) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(lambda time: None)) # self.pcm = EqualWeightingMaxCapPortfolioConstructionModel() # self.SetPortfolioConstruction(self.pcm) # self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel()) # self.SetPortfolioConstruction(AccumulativeInsightPortfolioConstructionModel(percent = 0.64)) self.SetExecution(ImmediateExecutionModel()) # execution_model = VolumeWeightedAveragePriceExecutionModel() # execution_model.MaximumOrderQuantityPercentVolume = 0.05 # self.SetExecution(execution_model) # self.AddRiskManagement(MaximumDrawdownPercentPortfolio(self.stopLoss, isTrailing=True)) # self.AddRiskManagement(MaximumUnrealizedProfitPercentPerSecurity(self.takeProfit))
#region imports from AlgorithmImports import * #endregion # QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. # Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from AlgorithmImports import * class EqualWeightingMaxCapPortfolioConstructionModel(PortfolioConstructionModel): '''Provides an implementation of IPortfolioConstructionModel that gives equal weighting to all securities. The target percent holdings of each security is 1/N where N is the number of securities. For insights of direction InsightDirection.Up, long targets are returned and for insights of direction InsightDirection.Down, short targets are returned.''' def __init__(self, rebalance = Resolution.Daily, portfolioBias = PortfolioBias.LongShort, maxcap = 1.0): '''Initialize a new instance of EqualWeightingPortfolioConstructionModel Args: rebalance: Rebalancing parameter. If it is a timedelta, date rules or Resolution, it will be converted into a function. If None will be ignored. The function returns the next expected rebalance time for a given algorithm UTC DateTime. The function returns null if unknown, in which case the function will be called again in the next loop. Returning current time will trigger rebalance. portfolioBias: Specifies the bias of the portfolio (Short, Long/Short, Long)''' super().__init__() self.portfolioBias = portfolioBias self.maxcap = maxcap # If the argument is an instance of Resolution or Timedelta # Redefine rebalancingFunc rebalancingFunc = rebalance if isinstance(rebalance, int): rebalance = Extensions.ToTimeSpan(rebalance) if isinstance(rebalance, timedelta): rebalancingFunc = lambda dt: dt + rebalance if rebalancingFunc: self.SetRebalancingFunc(rebalancingFunc) 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 and self.RespectPortfolioBias(x) for x in activeInsights) percent = 0 if count == 0 else self.maxcap / count for insight in activeInsights: result[insight] = (insight.Direction if self.RespectPortfolioBias(insight) else InsightDirection.Flat) * percent return result def RespectPortfolioBias(self, insight): '''Method that will determine if a given insight respects the portfolio bias Args: insight: The insight to create a target for ''' return self.portfolioBias == PortfolioBias.LongShort or insight.Direction == self.portfolioBias