Hi,
I am trying to replicate EmaCrossAlphaModel with local trade bar data I have on Binance crypto pairs. However it doesn't seem to generate any insights or trades.
TradeBar custom class (alphamodel from github below)
:
class BinanceTradeBarData(TradeBar):
def GetSource(self, config, date, isLiveMode):
ticker = config.Symbol.Value
date_str = date.strftime('%Y-%m')
source = os.path.join(Globals.DataFolder, "qc-trial", "longshort", f"{ticker}-1m-{date_str}.csv")
return SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile)
def Reader(self, config, line, date, isLiveMode):
coin = BinanceTradeBarData()
coin.Symbol = config.Symbol
data = line.split(",")
coin.Time = pd.to_datetime(data[0],unit='ms')
coin.EndTime = coin.Time + timedelta(minutes=1)
coin.Value = data[4]
coin.Open = float(data[1])
coin.High = float(data[2])
coin.Low = float(data[3])
coin.Close = float(data[4])
coin.Volume = float(data[5])
return coin
Algorithm:
class EMAwithCustomLocalData(QCAlgorithmFramework):
def Initialize(self):
# Set requested data resolution
self.UniverseSettings.Resolution = Resolution.Minute
self.SetTimeZone("UTC")
self.SetStartDate(2022, 2, 2) #Set Start Date
self.SetEndDate(2022, 3, 31) #Set End Date
self.SetCash(100000) #Set Strategy Cash
self.SetBrokerageModel(BrokerageName.Binance, AccountType.Margin)
self.SetWarmUp(50)
tickers = ['ADAUSDT','ALGOUSDT','ATOMUSDT','AVAXUSDT','AXSUSDT','BCHUSDT','BTCUSDT','DOGEUSDT','DOTUSDT','ETHUSDT']
symbols = [self.AddData(type=BinanceTradeBarData, ticker=ticker, resolution=Resolution.Minute).Symbol for ticker in tickers]
self.Debug(f"symbols: {symbols}")
self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) )
self.SetAlpha(EmaCrossAlphaModel(12, 26, Resolution.Minute))
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
self.SetRiskManagement(NullRiskManagementModel())
class EmaCrossAlphaModel(AlphaModel):
'''Alpha model that uses an EMA cross to create insights'''
def __init__(self,
fastPeriod = 12,
slowPeriod = 26,
resolution = Resolution.Daily):
'''Initializes a new instance of the EmaCrossAlphaModel class
Args:
fastPeriod: The fast EMA period
slowPeriod: The slow EMA period'''
self.fastPeriod = fastPeriod
self.slowPeriod = slowPeriod
self.resolution = resolution
self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(resolution), fastPeriod)
self.symbolDataBySymbol = {}
resolutionString = Extensions.GetEnumString(resolution, Resolution)
self.Name = '{}({},{},{})'.format(self.__class__.__name__, fastPeriod, slowPeriod, resolutionString)
def Update(self, algorithm, data):
'''Updates this alpha model with the latest data from the algorithm.
This is called each time the algorithm receives data for subscribed securities
Args:
algorithm: The algorithm instance
data: The new data available
Returns:
The new insights generated'''
insights = []
for symbol, symbolData in self.symbolDataBySymbol.items():
if symbolData.Fast.IsReady and symbolData.Slow.IsReady:
if symbolData.FastIsOverSlow:
if symbolData.Slow > symbolData.Fast:
insights.append(Insight.Price(symbolData.Symbol, self.predictionInterval, InsightDirection.Down))
elif symbolData.SlowIsOverFast:
if symbolData.Fast > symbolData.Slow:
insights.append(Insight.Price(symbolData.Symbol, self.predictionInterval, InsightDirection.Up))
symbolData.FastIsOverSlow = symbolData.Fast > symbolData.Slow
algorithm.Debug(f"insights: {insights}")
return insights
def OnSecuritiesChanged(self, algorithm, changes):
'''Event fired each time the we add/remove securities from the data feed
Args:
algorithm: The algorithm instance that experienced the change in securities
changes: The security additions and removals from the algorithm'''
for added in changes.AddedSecurities:
symbolData = self.symbolDataBySymbol.get(added.Symbol)
if symbolData is None:
symbolData = SymbolData(added, self.fastPeriod, self.slowPeriod, algorithm, self.resolution)
self.symbolDataBySymbol[added.Symbol] = symbolData
else:
# a security that was already initialized was re-added, reset the indicators
symbolData.Fast.Reset()
symbolData.Slow.Reset()
for removed in changes.RemovedSecurities:
data = self.symbolDataBySymbol.pop(removed.Symbol, None)
if data is not None:
# clean up our consolidators
data.RemoveConsolidators()
class SymbolData:
'''Contains data specific to a symbol required by this model'''
def __init__(self, security, fastPeriod, slowPeriod, algorithm, resolution):
self.Security = security
self.Symbol = security.Symbol
self.algorithm = algorithm
self.FastConsolidator = algorithm.ResolveConsolidator(security.Symbol, resolution)
self.SlowConsolidator = algorithm.ResolveConsolidator(security.Symbol, resolution)
algorithm.SubscriptionManager.AddConsolidator(security.Symbol, self.FastConsolidator)
algorithm.SubscriptionManager.AddConsolidator(security.Symbol, self.SlowConsolidator)
# create fast/slow EMAs
self.Fast = ExponentialMovingAverage(security.Symbol, fastPeriod, ExponentialMovingAverage.SmoothingFactorDefault(fastPeriod))
self.Slow = ExponentialMovingAverage(security.Symbol, slowPeriod, ExponentialMovingAverage.SmoothingFactorDefault(slowPeriod))
algorithm.RegisterIndicator(security.Symbol, self.Fast, self.FastConsolidator)
algorithm.RegisterIndicator(security.Symbol, self.Slow, self.SlowConsolidator)
algorithm.WarmUpIndicator(security.Symbol, self.Fast, resolution)
algorithm.WarmUpIndicator(security.Symbol, self.Slow, resolution)
# True if the fast is above the slow, otherwise false.
# This is used to prevent emitting the same signal repeatedly
self.FastIsOverSlow = False
def RemoveConsolidators(self):
self.algorithm.SubscriptionManager.RemoveConsolidator(self.Security.Symbol, self.FastConsolidator)
self.algorithm.SubscriptionManager.RemoveConsolidator(self.Security.Symbol, self.SlowConsolidator)
@property
def SlowIsOverFast(self):
return not self.FastIsOverSlow
Logs:
$ lean backtest strategies/test_strategy
←[?1h←=20220427 02:00:49.779 TRACE:: Config.Get(): Configuration key not found. Key: plugin-directory - Using default value:
20220427 02:00:49.797 TRACE:: Composer(): Loading Assemblies from /Lean/Launcher/bin/Debug
20220427 02:00:49.963 TRACE:: Python for .NET Assembly: Python.Runtime, Version=2.0.11.0, Culture=neutral, PublicKeyToken=5000fea6cba702dd
20220427 02:00:50.008 TRACE:: Config.Get(): Configuration key not found. Key: data-directory - Using default value: ../../../Data/
20220427 02:00:50.078 TRACE:: Config.Get(): Configuration key not found. Key: version-id - Using default value:
20220427 02:00:50.080 TRACE:: Config.Get(): Configuration key not found. Key: cache-location - Using default value: /Lean/Data
20220427 02:00:50.081 TRACE:: Engine.Main(): LEAN ALGORITHMIC TRADING ENGINE v2.5.0.0 Mode: DEBUG (64bit) Host: Atakan-SB2
20220427 02:00:50.101 TRACE:: Engine.Main(): Started 2:00 AM
20220427 02:00:50.109 TRACE:: Config.Get(): Configuration key not found. Key: lean-manager-type - Using default value: LocalLeanManager
20220427 02:00:50.142 TRACE:: JobQueue.NextJob(): Selected /LeanCLI/main.py
20220427 02:00:50.289 TRACE:: Config.GetValue(): scheduled-event-leaky-bucket-capacity - Using default value: 120
20220427 02:00:50.290 TRACE:: Config.GetValue(): scheduled-event-leaky-bucket-time-interval-minutes - Using default value: 1440
20220427 02:00:50.290 TRACE:: Config.GetValue(): scheduled-event-leaky-bucket-refill-amount - Using default value: 18
20220427 02:00:50.296 TRACE:: Config.Get(): Configuration key not found. Key: job-organization-id - Using default value:
20220427 02:00:50.298 TRACE:: Config.Get(): Configuration key not found. Key: data-permission-manager - Using default value: DataPermissionManager
20220427 02:00:50.323 TRACE:: AlgorithmManager.CreateTokenBucket(): Initializing LeakyBucket: Capacity: 120 RefillAmount: 18 TimeInterval: 1440
20220427 02:00:50.332 TRACE:: Config.GetValue(): algorithm-manager-time-loop-maximum - Using default value: 20
20220427 02:00:50.367 TRACE:: TextSubscriptionDataSourceReader.SetCacheSize(): Setting cache size to 71582788 items
20220427 02:00:50.868 TRACE:: Config.GetValue(): algorithm-creation-timeout - Using default value: 90
20220427 02:00:50.873 TRACE:: PythonInitializer.Initialize(): start...
PythonEngine.Initialize(): Runtime.Initialize()...
Runtime.Initialize(): Py_Initialize...
Runtime.Initialize(): PyEval_InitThreads...
Runtime.Initialize(): Initialize types...
Runtime.Initialize(): Initialize types end.
Runtime.Initialize(): AssemblyManager.Initialize()...
Runtime.Initialize(): AssemblyManager.UpdatePath()...
PythonEngine.Initialize(): GetCLRModule()...
PythonEngine.Initialize(): clr GetManifestResourceStream...
20220427 02:00:53.013 TRACE:: PythonInitializer.Initialize(): ended
20220427 02:00:53.025 TRACE:: AlgorithmPythonWrapper(): Python version 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:25:33)
[GCC 7.3.0]: Importing python module main
20220427 02:00:56.660 TRACE:: AlgorithmPythonWrapper(): main successfully imported.
20220427 02:00:56.666 TRACE:: AlgorithmPythonWrapper(): Creating IAlgorithm instance.
20220427 02:00:56.685 TRACE:: Config.GetValue(): api-data-update-period - Using default value: 1
20220427 02:00:56.958 TRACE:: Config.GetValue(): mute-python-library-logging - Using default value: True
20220427 02:00:57.006 TRACE:: LocalObjectStore.Initialize(): Storage Root: /Storage/QCAlgorithm. StorageFileCount 100. StorageLimitMB 5
20220427 02:00:57.047 TRACE:: BacktestingSetupHandler.Setup(): Setting up job: UID: 0, PID: 926796063, Version: 2.5.0.0, Source: WebIDE
20220427 02:00:57.059 TRACE:: Config.Get(): Configuration key not found. Key: security-data-feeds - Using default value:
20220427 02:00:57.354 TRACE:: Cash.EnsureCurrencyDataFeed(): Adding BTCBUSD for cash BTC currency feed
20220427 02:00:57.398 TRACE:: Config.GetValue(): data-feed-max-work-weight - Using default value: 400
20220427 02:00:57.399 TRACE:: Config.GetValue(): data-feed-workers-count - Using default value: 8
20220427 02:00:57.400 TRACE:: WeightedWorkScheduler(): will use 8 workers and MaxWorkWeight is 400
20220427 02:00:57.456 TRACE:: Config.GetValue(): show-missing-data-logs - Using default value: False
20220427 02:00:57.488 TRACE:: Failed to assign conversion rates for the following cash: BTC. Attempting to request daily resolution history to resolve conversion rate
20220427 02:00:57.503 TRACE:: BaseSetupHandler.SetupCurrencyConversions():
Symbol Quantity Conversion = Value in USD
USD: $ 100000.00 @ 1.00 = $100000.0
BTC: ฿ 0.00 @ 0.00 = $0
BUSD: $ 0.00 @ 1.00 = $0.0
USDC: $ 0.00 @ 1.00 = $0.0
-------------------------------------------------
CashBook Total Value: $100000.0
20220427 02:00:57.510 TRACE:: SetUp Backtesting: User: 0 ProjectId: 926796063 AlgoId: 1502134665
20220427 02:00:57.512 TRACE:: Dates: Start: 02/02/2022 End: 03/31/2022 Cash: ¤100,000.00 MaximumRuntime: 100.00:00:00 MaxOrders: 2147483647
20220427 02:00:57.520 TRACE:: BacktestingResultHandler(): Sample Period Set: 20.88
20220427 02:00:57.523 TRACE:: Time.TradeableDates(): Security Count: 11
20220427 02:00:57.530 TRACE:: Config.GetValue(): forward-console-messages - Using default value: True
20220427 02:00:57.536 TRACE:: JOB HANDLERS:
20220427 02:00:57.537 TRACE:: DataFeed: QuantConnect.Lean.Engine.DataFeeds.FileSystemDataFeed
20220427 02:00:57.537 TRACE:: Setup: QuantConnect.Lean.Engine.Setup.BacktestingSetupHandler
20220427 02:00:57.538 TRACE:: RealTime: QuantConnect.Lean.Engine.RealTime.BacktestingRealTimeHandler
20220427 02:00:57.538 TRACE:: Results: QuantConnect.Lean.Engine.Results.BacktestingResultHandler
20220427 02:00:57.539 TRACE:: Transactions: QuantConnect.Lean.Engine.TransactionHandlers.BacktestingTransactionHandler
20220427 02:00:57.540 TRACE:: Alpha: QuantConnect.Lean.Engine.Alphas.DefaultAlphaHandler
20220427 02:00:57.540 TRACE:: ObjectStore: QuantConnect.Lean.Engine.Storage.LocalObjectStore
20220427 02:00:57.541 TRACE:: History Provider: QuantConnect.Lean.Engine.HistoricalData.HistoryProviderManager
20220427 02:00:57.566 TRACE:: Debug: Launching analysis for 1502134665 with LEAN Engine v2.5.0.0
20220427 02:00:57.609 TRACE:: Event Name "Daily Sampling", scheduled to run at 2/2/2022 12:00:00 AM (UTC)...
20220427 02:00:57.609 TRACE:: AlgorithmManager.Run(): Begin DataStream - Start: 2/2/2022 12:00:00 AM Stop: 3/31/2022 11:59:59 PM
20220427 02:00:57.651 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: ALGOUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.651 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: AXSUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.652 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: BCHUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.652 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: AVAXUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.653 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: ATOMUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.654 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: ETHUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.655 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: DOTUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.655 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: ADAUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.656 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: DOGEUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.657 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: BTCUSDT: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:00:57.659 TRACE:: AlgorithmManager.Stream(): WarmupHistoryRequest: BTCBUSD 18N: Start: 2/1/2022 11:10:00 PM End: 2/2/2022 12:00:00 AM Resolution: Minute
20220427 02:01:07.894 TRACE:: Debug: symbols: [<QuantConnect.Symbol object at 0x7f527a964048>, <QuantConnect.Symbol object at 0x7f527a964320>, <QuantConnect.Symbol object at 0x7f527a964518>, <QuantConnect.Symbol object at 0x7f527a964710>, <QuantConnect.Symbol object at 0x7f527a964908>, <QuantConnect.Symbol object at 0x7f527a964b00>, <QuantConnect.Symbol object at 0x7f527a964cf8>, <QuantConnect.Symbol object at 0x7f527a964ef0>, <QuantConnect.Symbol object at 0x7f527a96e128>, <QuantConnect.Symbol object at 0x7f527a96e320>]
Algorithm warming up...
insights: []
20220427 02:01:07.917 TRACE:: AlgorithmManager.Stream(): Finished warmup
20220427 02:01:16.787 TRACE:: UniverseSelection.AddPendingInternalDataFeeds(): Adding internal benchmark data feed BTCUSDC,#0,BTCUSDC,Hour,TradeBar,Trade,Adjusted,OpenInterest,Internal
20220427 02:01:17.270 TRACE:: Debug: Algorithm finished warming up.
insights: []
20220427 02:01:57.583 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 119, Sample: 251, App: 924, CurrentTimeStepElapsed: 00:00.000
20220427 02:02:57.598 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 313, Sample: 553, App: 1212, CurrentTimeStepElapsed: 00:00.000
20220427 02:03:57.609 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 334, Sample: 246, App: 1384, CurrentTimeStepElapsed: 00:00.000
20220427 02:04:57.611 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 334, Sample: 144, App: 1384, CurrentTimeStepElapsed: 00:00.000
20220427 02:05:57.623 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 282, Sample: 141, App: 1385, CurrentTimeStepElapsed: 00:00.000
20220427 02:06:57.640 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 214, Sample: 117, App: 1368, CurrentTimeStepElapsed: 00:00.000
20220427 02:07:57.652 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 157, Sample: 87, App: 1194, CurrentTimeStepElapsed: 00:00.000
20220427 02:08:57.664 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 121, Sample: 97, App: 1160, CurrentTimeStepElapsed: 00:00.000
20220427 02:09:57.676 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 110, Sample: 113, App: 1163, CurrentTimeStepElapsed: 00:00.000
20220427 02:10:57.689 TRACE:: Isolator.ExecuteWithTimeLimit(): Used: 103, Sample: 79, App: 1147, CurrentTimeStepElapsed: 00:00.000
20220427 02:11:49.028 TRACE:: Synchronizer.GetEnumerator(): Exited thread.
20220427 02:11:49.029 TRACE:: AlgorithmManager.Run(): Firing On End Of Algorithm...
20220427 02:11:49.033 TRACE:: Engine.Run(): Exiting Algorithm Manager
20220427 02:11:49.038 TRACE:: FileSystemDataFeed.Exit(): Start. Setting cancellation token...
20220427 02:11:49.039 TRACE:: FileSystemDataFeed.Exit(): Exit Finished.
20220427 02:11:49.039 TRACE:: DefaultAlphaHandler.Exit(): Exiting...
20220427 02:11:49.046 TRACE:: DefaultAlphaHandler.Exit(): Ended
20220427 02:11:49.047 TRACE:: BacktestingResultHandler.Exit(): starting...
20220427 02:11:49.048 TRACE:: BacktestingResultHandler.Exit(): Saving logs...
20220427 02:11:49.055 TRACE:: Debug: Algorithm Id:(1502134665) completed in 651.49 seconds at 1k data points per second. Processing total of 836,812 data points.
20220427 02:11:49.055 TRACE:: StopSafely(): waiting for 'Result Thread' thread to stop...
20220427 02:11:49.055 TRACE:: Debug: Your log was successfully created and can be retrieved from: /Results/1502134665-log.txt
20220427 02:11:49.056 TRACE:: BacktestingResultHandler.Run(): Ending Thread...
20220427 02:11:49.175 TRACE::
STATISTICS:: Total Trades 0
STATISTICS:: Average Win 0%
STATISTICS:: Average Loss 0%
STATISTICS:: Compounding Annual Return 0%
STATISTICS:: Drawdown 0%
STATISTICS:: Expectancy 0
STATISTICS:: Net Profit 0%
STATISTICS:: Sharpe Ratio 0
STATISTICS:: Probabilistic Sharpe Ratio 0%
STATISTICS:: Loss Rate 0%
STATISTICS:: Win Rate 0%
STATISTICS:: Profit-Loss Ratio 0
STATISTICS:: Alpha 0
STATISTICS:: Beta 0
STATISTICS:: Annual Standard Deviation 0
STATISTICS:: Annual Variance 0
STATISTICS:: Information Ratio 0
STATISTICS:: Tracking Error 0
STATISTICS:: Treynor Ratio 0
STATISTICS:: Total Fees $0.00
STATISTICS:: Estimated Strategy Capacity $0
STATISTICS:: Lowest Capacity Asset
STATISTICS:: Fitness Score 0
STATISTICS:: Kelly Criterion Estimate 0
STATISTICS:: Kelly Criterion Probability Value 0
STATISTICS:: Sortino Ratio 79228162514264337593543950335
STATISTICS:: Return Over Maximum Drawdown 79228162514264337593543950335
STATISTICS:: Portfolio Turnover 0
STATISTICS:: Total Insights Generated 0
STATISTICS:: Total Insights Closed 0
STATISTICS:: Total Insights Analysis Completed 0
STATISTICS:: Long Insight Count 0
STATISTICS:: Short Insight Count 0
STATISTICS:: Long/Short Ratio 100%
STATISTICS:: Estimated Monthly Alpha Value $0
STATISTICS:: Total Accumulated Estimated Alpha Value $0
STATISTICS:: Mean Population Estimated Insight Value $0
STATISTICS:: Mean Population Direction 0%
STATISTICS:: Mean Population Magnitude 0%
STATISTICS:: Rolling Averaged Population Direction 0%
STATISTICS:: Rolling Averaged Population Magnitude 0%
STATISTICS:: OrderListHash d41d8cd98f00b204e9800998ecf8427e
20220427 02:11:49.175 TRACE:: BacktestingResultHandler.SendAnalysisResult(): Processed final packet
20220427 02:11:49.176 TRACE:: Engine.Run(): Disconnecting from brokerage...
20220427 02:11:49.177 TRACE:: Engine.Run(): Disposing of setup handler...
20220427 02:11:49.178 TRACE:: Engine.Main(): Analysis Completed and Results Posted.
Engine.Main(): Analysis Complete.
20220427 02:11:49.179 TRACE:: Engine.Main(): Packet removed from queue: 1502134665
20220427 02:11:49.180 TRACE:: LeanEngineSystemHandlers.Dispose(): start...
20220427 02:11:49.181 TRACE:: LeanEngineSystemHandlers.Dispose(): Disposed of system handlers.
20220427 02:11:49.182 TRACE:: LeanEngineAlgorithmHandlers.Dispose(): start...
20220427 02:11:49.192 TRACE:: LeanEngineAlgorithmHandlers.Dispose(): Disposed of algorithm handlers.
20220427 02:11:49.195 TRACE:: Program.Main(): Exiting Lean...
Successfully ran 'strategies\test_strategy' in the 'backtesting' environment and stored the output in 'strategies\test_strategy\backtests\2022-04-26_19-00-46'
It seems to process the data but nothing is happening.
Data processed line log:
20220427 02:11:49.055 TRACE:: Debug: Algorithm Id:(1502134665) completed in 651.49 seconds at 1k data points per second. Processing total of 836,812 data points.
Any help is greatly appreciated!
Fred Painchaud
Hi Notta,
Just a quick trial before I look at everything else.
Try with that code in your custom data class:
class BinanceTradeBarData(TradeBar):
changed to:
class BinanceTradeBarData(PythonData):
and also this:
coin.Open = float(data[1])
coin.High = float(data[2])
coin.Low = float(data[3])
coin.Close = float(data[4])
coin.Volume = float(data[5])
changed to:
coin["Open"] = float(data[1])
coin["High"] = float(data[2])
coin["Low"] = float(data[3])
coin["Close"] = float(data[4])
coin["Volume"] = float(data[5])
Fred
P.S. I'm not sure custom data will work with the framework. It might not be typed/tagged properly for LEAN, as in, it won't be SecurityType.Crypto or anything like that, it will be SecurityType.Base.
Nottakumasato
Thank you Fred Painchaud for the quick reply!
Similar results with no trades but the data points processed changed:
What do you mean by `P.S. I'm not sure custom data will work with the framework. It might not be typed/tagged properly for LEAN, as in, it won't be SecurityType.Crypto or anything like that, it will be SecurityType.Base.` ? So there is no way that I can use any kind of local csv data with the AlgorithmFramework?
Nottakumasato
Here is the class that inherits from PythonData:
Nottakumasato
Fred Painchaud following up on the AlgorithmFramework and custom data discrepancy: is there any preprocessing that I can do on the custom data or change something in the configuration to make it work with AlgorithmFramework?
Fred Painchaud
Hi,
Sorry, I can't load the code and play with it right now.
I'm thinking about some hack which would be to add that line:
coin["SecurityType"] = SecurityType.Crypto
after that line:
coin["Volume"] = float(data[5])
in your custom data class. Worth a try. Maybe it will shadow the real SecurityType which does not point to the proper enum value when you use custom data.
The problem is that custom data is not crypto, equity, or anything else - it is a special case. Thus, when LEAN processes that data, it does not look like a common type of data (equity, etc) and is not treated like common types.
You may need to format your data like normal crypto data is formatted within LEAN, put that formatted data in the data folder, and then use it like it was normal LEAN data. But then, you are more or less on your own.
Fred
Nottakumasato
Thank you Fred Painchaud however after adding the `SecurityType` line to the PythonData inherited class and the results are again empty.
The weird thing is if I use the custom data class in a single ticker & single indicator QCAlgorithm class, it works without any problems
Logs:
which suggests to me that the custom data class is working when there is a single ticker and within QCAlgorithm but something breaks when there are multiple tickers within a QCAlgorithmFramework.
I will also try multiple ticker in QCAlgorithm shortly and post back.
Fred Painchaud
It was just a test. No luck.
2 different lines of code |→ 2 different behaviors.
So yes, it can work under QCAlgorithm because it handles data differently than QCAlgorithmFramework. The latter could have been designed without custom data in mind.
Did not have time to check that out myself in detail so far in the code.
Does it work with a single ticker under Framework?
Fred
Nottakumasato
Here is a basic multiple ticker algorithm with the same custom data class
Logs:
So it looks like there is something wrong with QCAlgorithmFramework?
Nottakumasato
Fred Painchaud will try single ticker under Framework shortly too
Nottakumasato
Fred Painchaud I tried single ticker (BTCUSDT) within QCAlgorithm Framework (full code and logs at the bottom)
I also noticed two other lines in logs that warrants deeper investigations:
I did not add BTCBUSD as a symbol to this algorithm:
I also did not add a benchmark of BTCUSDC:
Full code:
Logs:
Nottakumasato
Fred Painchaud Seems I forgot to mention it above, but no trades again
Fred Painchaud
Hi Notta,
Yep, pretty much confirms that you cannot use the Custom Data idiom to trade with the Framework.
Data will need to come from the "front door" instead of the “Custom Data door”. To do it locally, you'll need to buy QC data or format your data into QC's so LEAN uses it like any other data and not the particular way Custom Data was designed.
Sorry.
Fred
Nottakumasato
Fred Painchaud great, nice to confirm this at least 😊
I will try the “format data into QC format” way. I looked at 3 examples from the data that LEAN downloads locally.
gdax
location: data/crypto/gdax/second/btcusd
files: YYYYMMDD_trade.zip
file format: no header. columns: time in milliseconds, open, high, low, close, volume
same format for the minute data of gdax except its location is under minute/btcusd/ instead of second/btcusd/
binance
location: data/crypto/binance/hour/
files: btcusdt_trade.zip
file format: no header. columns: datetime in YYYYMMDD mm:ss format, open, high, low, close, volume
So I should reformat my local files in these ways and put them under
Couple of questions:
Fred Painchaud
Hi Notta,
Spoiler alert: you will do it for sure - you're on the right track.
Follow the Data Explorer structure: https://www.quantconnect.com/data/tree .
Fred
Nottakumasato
Fred Painchaud
2. Understood.
One last question (I hope!): After formatting the data and putting them in their respective directories, what is the suggested way of adding that data to the AlgorithmFramework instance? Through `AddData()` or `AddCrypto` (Assuming its a crypto symbol)?
Fred Painchaud
Hi Notta,
AddData will only work if you pass it, and thus if you define, a custom data class/type. So back to square one. Thus, once you format your data into LEAN, you basically add your data to LEAN. So you will then use AddCrypto.
Fred
Nottakumasato
Fred Painchaud thank you! Will try this reformatting way and open a new thread if it doesn't work 😊
Nottakumasato
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!