* Allow SetAccountCurrency after SetCash without throwing
Previously, calling SetAccountCurrency after SetCash threw an
InvalidOperationException. The portfolio manager now switches the
base account currency in place: the previous Cash entry (and its
balance) is preserved in the CashBook, and a notice is logged. When
the new account currency matches the existing one, an optional
startingCash overrides the previously set amount and the override
is logged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Simplify SetAccountCurrency remarks and drop unused message
Tightens the XML remarks to two cases (different currency: keep previous
in its own entry; matching currency: override). Also removes the now
unused CannotChangeAccountCurrencyAfterSettingCash string since the
portfolio no longer throws.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Simplify in-line comment in SetAccountCurrency
Drops the "Undo that migration" wording (residue from a previous fix
attempt) and just describes what the branch does: keep the previous
balance in its own currency entry while the new account currency starts
at zero.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Differentiate implicit vs explicit SetCash on account currency switch
SetCash(decimal) is currency-agnostic: the amount is "this many units of
the (eventual) account currency". Switching the account currency now
re-labels the amount onto the new currency instead of preserving the
previous one. SetCash(symbol, ...) for the current account currency keeps
the old behaviour of preserving the balance in its own CashBook entry.
Splits the existing tests by overload and adds a starting-cash variant
for the explicit case.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Mark base cash explicit on any SetCash(symbol, ...) call
Broaden _baseCashSymbolSetExplicitly so any call to the explicit-currency
overload signals the user is committing to named currencies, not just
calls whose symbol matches the current account currency. SetAccountCurrency
then preserves the previous base-currency balance in its own CashBook
entry whenever the user has touched the explicit overload at all.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Implement WaveTrendOscillator (bar indicator) per the linked issue. Adds
the indicator class, the WTO helper in QCAlgorithm.Indicators.cs, unit
tests inheriting CommonIndicatorTests<IBaseDataBar>, and the reference
CSV under Tests/TestData/.
The oscillator is computed from the typical price (HLC/3): an EMA
smooths it (ESA), a second EMA tracks its absolute deviation (D), the
normalized channel index (HLC3 - ESA) / (0.015 * D) is smoothed by a
third EMA to produce WT1, and an SMA of WT1 produces the signal line
WT2. Crossovers between WT1 and WT2 are commonly used as entry and exit
signals for momentum reversals.
Reference values were generated with TA-Lib (talib.EMA + talib.SMA)
following the script posted by @LouisSzeto in the issue thread.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Regression Tests / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
API Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Build & Test Lean / build (push) Has been cancelled
* fix: add AJY future-option expiry definition
- map AJY (AUD/JPY) FOP to SecondFridayBeforeThirdWednesdayOfContractMonth
- prior fallback to the AJY HMUZ-only future expiry collapsed serial-month FOPs (e.g. AJYN6) into their underlying quarterly Symbol
* fix: add ANE and ECD future-option expiry definitions
- map ANE (AUD/NZD) and ECD (EUR/CAD) FOPs to SecondFridayBeforeThirdWednesdayOfContractMonth
- prior fallback to the HMUZ-only future expiry collapsed serial-month FOPs into their underlying quarterly Symbol
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
* feature: add NASDAQ_SC and NASDAQ_INT equity exchanges
- map primary exchange codes S and T to new NASDAQ tier exchanges
- T was previously folded into NASDAQ, now returns NASDAQ_INT
- add V as alias for IEX in equity switch
- fix MEMX description (was copy of LTSE)
* feature: map equity exchange codes H and U to MIAX_PEARL and MEMX
* feature: consolidate NASDAQ_INT code T into NASDAQ_SC
Remove the separate NASDAQ_INT mapping in GetPrimaryExchange and map
exchange code "T" to NASDAQ_SC. Update ExchangeTest cases accordingly
and add coverage for IEX ("V") and MEMX ("U").
* feature: remove orphaned NASDAQ_INT exchange entry
Drop the NASDAQ_INT class entry from Exchange.cs. The "T" tape letter
already routes to Exchange.NASDAQ via GetPrimaryExchange, leaving the
class definition unreachable and inconsistent.
* fix: support BNFCR alternative collateral in CryptoFutureMarginModel for Binance (#9339)
* refactor: use classic switch in BinanceFuturesBrokerageModel.GetBuyingPowerModel
* fix: CryptoFutureMarginModel in BinanceCoinFuturesBrokerageModel
* refactor: simplify BinanceCryptoFutureMarginModel collateral conversion
* fix: restore IsCryptoCoinFuture guard in BinanceCryptoFutureMarginModel
* refactor: simplify BinanceCryptoFutureMarginModel to direct BNFCR lookup
Replace IsStableCoinWithoutPair foreach loop with a single TryGetValue
check for BNFCR. BNFCR is EU/EEA-only (MiCA Credits Trading Mode) so
the lookup is a no-op for all other users. Amount reflects availableBalance
from the Binance API — the total cross-margin pool already aggregated by
Binance — making the > 0 guard correct and avoiding CashBook iteration.
* feat: add regression algorithm for BNFCR as sole collateral on Binance USDⓈ-M futures
Asserts end-to-end that EU/MiCA accounts with zero USDT and BNFCR as
the only collateral can open ADAUSDT positions. Verifies buying power,
holdings AbsoluteHoldingsCost, TotalSaleVolume, TotalMarginUsed,
maintenance margin consistency and TotalUnrealizedProfit accuracy.
* refactor: BNFCR presence gate with CashBook iteration for supplementary collateral
Replace IsStableCoinWithoutPair and hardcoded asset list with CashBook
iteration gated by BNFCR presence. Binance controls which assets are in
the account — all with non-zero walletBalance are valid collateral.
Add tests for BNFCR zero balance and BTC collateral conversion.
* refactor: aggregate all collateral without reference equality check
* fix: shared collateral deduction across quote currencies for EU/MiCA BNFCR mode
- Extract virtual SharesCollateral in CryptoFutureMarginModel
- Override in BinanceCryptoFutureMarginModel: BNFCR present → all USDⓈ-M share pool
- Add BNFCRCurrency const
- Add SharedCollateralDeductsMaintenanceMarginAcrossQuoteCurrencies unit test
- Refactor regression algorithm to assert shared collateral across ADAUSDT/ETHUSDC
* refactor: remove dead IsCryptoCoinFuture guard from BinanceCryptoFutureMarginModel
- Remove IsCryptoCoinFuture() check (coin futures use BinanceCoinFuturesBrokerageModel, not this model)
- Call base.GetTotalCollateralAmount() instead of duplicating primaryCollateral.Amount
- Remove CoinFutureDoesNotIncludeBnfcrAsCollateral test (tested wrong margin model)
* refactor: make GetCollateralCash private in CryptoFutureMarginModel
- No longer accessed by subclasses after removing direct collateral checks from BinanceCryptoFutureMarginModel
Previously, each SwissArmyKnife instance could only compute a single
tool. To use multiple tools, users had to create separate instances.
Now all five tools (Gauss, Butter, HighPass, TwoPoleHighPass, BandPass)
are computed simultaneously and exposed as public properties.
Resolves#3270
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
API Tests / build (push) Has been cancelled
Benchmarks / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
* Improves Null Key Handling in Python
We aim to mimic the following behavior:
```python
>>> d = {1:2}
>>> None in d
False
>>> d.get(None) is None
True
>>> d.pop(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: None
>>> d.pop(None, None) is None
True
```
* Reverts dispose change
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
* Add ContractMultiplier setter to Cfd via CfdSymbolProperties
* Fix regression tests
* Solve review comments
* Address new review comments
* Fix regression tests
* Use ContractSymbolProperties as base class
* Minor fix
* Address review comment
* Add failing test for BRK.B OSI option ticker parsing
Adds test case to ParseOptionTickerOSI to reproduce issue #9341 where
Symbol.ParseOptionTickerOSI throws on tickers containing a dot (e.g. BRK.B).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix OSI option ticker regex to support dots in underlying symbol
Extends _optionTickerRegex from [A-Z0-9]+ to [A-Z0-9\.]+ so that
symbols like BRK.B are accepted by ParseOptionTickerOSI.
Fixes#9341
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Python Virtual Environments / build (push) Has been cancelled
Benchmarks / build (push) Has been cancelled
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
API Tests / build (push) Has been cancelled
* feat: add CreateOAuthTokenHandler factory to Brokerage base class
Introduce AuthenticationFailed event on TokenHandler raised when all
retry attempts are exhausted. Add CreateOAuthTokenHandler<TRequest,TResponse>
protected factory method on Brokerage that wires the event to OnMessage
(BrokerageMessageType.Error), triggering graceful Lean shutdown on
OAuth token refresh failure without requiring per-brokerage error logic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: token retry logic: move to OAuthTokenHandler
* refactor: replace generic OAuthTokenHandler with non-generic, require explicit token lifetime
- Remove generic type parameters <TRequest, TResponse> from OAuthTokenHandler and
CreateOAuthTokenHandler; use LeanAccessTokenMetaDataRequest and
AccessTokenMetaDataResponse directly
- Delete abstract AccessTokenMetaDataRequest; logic moved to LeanAccessTokenMetaDataRequest
- Make tokenLifetime a required constructor parameter — each brokerage must explicitly
declare its OAuth token lifetime to prevent silent 1-hour fallback bugs
- Move expiry tracking into the handler via _tokenExpiresAt (written under lock before the
volatile write of _tokenCredentials, ensuring correct visibility on the fast path)
- Simplify AccessTokenMetaDataResponse to a concrete class with { get; set; } properties
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: add unit tests for OAuthTokenHandler and AccessTokenMetaDataResponse
- Make ApiConnection.TryRequest<T>(HttpRequestMessage) virtual to allow
test subclasses to intercept without real HTTP calls
- Add AccessTokenMetaDataResponseTests: two parameterized cases verify that
TokenType defaults to Bearer when absent from JSON (CharlesSchwab pattern)
and deserializes correctly when present (Tastytrade pattern)
- Add OAuthTokenHandlerTests with FakeApiConnection stub:
CharlesSchwab-style response (no tokenType, 30-min lifetime) and
Tastytrade-style response (explicit tokenType + expiresIn/tokenId, 15-min lifetime)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: backward-compatible OAuth auth with new LeanOAuthTokenHandler hierarchy
- Restore master API: OAuthTokenHandler<TReq,TRes>, AccessTokenMetaDataRequest,
AccessTokenMetaDataResponse, and TokenHandler stay source-compatible for old consumers
- Extend TokenHandler with AuthenticationFailed event; simplify Send() (auth header only)
- Add LeanOAuthTokenHandler: non-generic, thread-safe double-checked locking, explicit
tokenLifetime, retry logic in GetAccessToken, fires AuthenticationFailed on exhaustion
- Add OAuthTokenRequest / OAuthTokenResponse: concrete Lean platform request/response
- Brokerage.CreateOAuthTokenHandler wires AuthenticationFailed to graceful shutdown
- Update tests: OAuthTokenResponseTests, LeanOAuthTokenHandlerTests, TokenHandlerTests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Some tweaks
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Martin Molinero <martin.molinero1@gmail.com>
* Use universe settings when adding derivatives
Use resolution, fill forward and extended market hours settings from universe settings when adding derivative securities (options, index options, futures and future options)
* Minor python syntax check fix
* Minor change
* Default resolution from universe settings for common lean types securities
* Minor test fix
* Cleanup
* Use consolidated bar as reference for new working bar initialization
* Update ValidateAndScan method and unit tests
* Fix issues with syntax check
* Solve review comments
* Minor fix
* Minor fix
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Benchmarks / build (push) Has been cancelled
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
* Fix: Reject unsupported 4-leg ComboLegLimit orders in InteractiveBrokersBrokerageModel (#9287)
* Minor tweaks
---------
Co-authored-by: Ahmed Ali <ahmedalli79x@gmail.com>
Co-authored-by: Martin Molinero <martin.molinero1@gmail.com>
* feat: add CanonicalDataDownloaderDecorator for chain support
Introduced CanonicalDataDownloaderDecorator to enable automatic resolution and parallel downloading of all contracts for canonical symbols (options and futures chains). Updated Program.cs and DownloaderDataProvider to use this decorator, ensuring seamless data retrieval for both canonical and non-canonical symbols. Refactored initialization logic to handle chain providers within the decorator and removed redundant code from Program.cs.
* feat: improve canonical symbol error handling in data downloader
* refactor: data downloader selection in DownloaderDataProvider
* refactor: CanonicalDataDownloaderDecorator construction
* feat: limit parallelism and improve contract data error handling
* refactor: canonical data downloader and provider usage
* remove: CanonicalNotSupportedException and refactor handling
* refactor: data downloader selection with selector class
Introduce DataDownloaderSelector to choose the correct IDataDownloader implementation based on data type, using CanonicalDataDownloaderDecorator only when needed. Update Program.cs and DownloaderDataProvider to use the selector, remove redundant initialization logic, and ensure proper resource disposal. This improves flexibility, correctness, and resource management for data downloads, especially for custom and canonical data types.
* fix: wrong selector condition
* refactor: change default log handler; add parallelism config to downloader
- Set ConsoleLogHandler as the default log handler in code and config
- Make contract download parallelism configurable via downloader-thread-count (default 4)
- Track and log number of processed contracts in CanonicalDataDownloaderDecorator
- Add error logging for missing universe data
- Improve logging clarity and code readability
* feat: prevent duplicate contract downloads in canonical chains
Introduce ContractDownloadParameters to uniquely identify contract/tick type/resolution combinations and cache them in CanonicalDataDownloaderDecorator, avoiding redundant downloads when contracts are shared across canonical symbol chains. Add date range optimization for contract downloads and unit tests for the new class.
* Revert "feat: prevent duplicate contract downloads in canonical chains"
This reverts commit 44386c4c788904531c473c60c2a173e2354561ec.
* feat: clamp contract date ranges, deduplicate downloads
Added AdjustDateRangeForContract to CanonicalDataDownloaderDecorator to clamp start/end dates based on contract expiry and security type. Introduced _contractsCache to prevent duplicate downloads across canonical chains and _processedContracts for logging. Updated contract retrieval logic for deduplication. Added NUnit tests to verify date range adjustments for futures and options.
* refactor: canonical contract date range adjustment logic
* test:feat: add test for non-option/future contract date adjustment
* feat: make look-back periods for canonical symbols configurable
* refactor: remove Lazy from CanonicalDataDownloaderDecorator
Revert "refactor: remove Lazy from CanonicalDataDownloaderDecorator"
This reverts commit 909c1299406688a19352273f8d0b5b3ea99c0fb9.
refactor: Inject IMapFileProvider into downloader selectors
Revert "refactor: Inject IMapFileProvider into downloader selectors"
This reverts commit 0add95269809680e425bfa6080e465bf16377e56.
Reapply "refactor: remove Lazy from CanonicalDataDownloaderDecorator"
This reverts commit 9e3c4bed078868a3c8dfedcab0e52d6dced1daad.
* refactor: data downloader dependency injection
* refactor: provider initialization in data downloader classes
* refactor: DataDownloaderSelector dependencies, add tests
- Require explicit IDataProvider in DataDownloaderSelector constructor, removing default and fallback logic
- Change default log handler to ConsoleLogHandler in Program.cs
- Pass DownloaderDataProvider as IDataProvider to DataDownloaderSelector
- Add DataDownloaderSelector unit tests to verify correct downloader selection and decorator usage
* feat: ensure factorFileProvider is initialized when defaulted
* fix: missed dataProvider in DataDownloaderSelector ctor
* refactor: improve IFactorFileProvider resolution in DataDownloaderSelector
Build & Test Lean / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
* Implement indicator-based option price model
This model uses IV and Greeks indicators to implement Lean's own option pricing model
* Minor fixes
* Address peer review
* Minor tests fixes
* Make the indicator based price model the default for options
* Address peer review
* Cleanup and minor changes
* Support indicators configuration for new pricing model
* Some cleanup
* Add QL option price model example algorithm
* Return lean models from static helpers
* Minor tests fixes
* Minor test fixes
* Address peer review
* Cleanup
* Fix unit tests
* Move QL models to OptionPriceModels.QuantLib.*
* Add forward tree helper method
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
* Enhance order request processing by grouping requests and adding concurrency tests
* Minor adjustment
---------
Co-authored-by: Adrian Tkacz <adrian.tkacz@creatdy.com>
Co-authored-by: Martin Molinero <martin.molinero1@gmail.com>
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
Report Generator Tests / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
* feat: improve symbol parsing for futures/options in downloader
* refactor: symbol parsing and unify ticker handling
* refactor: symbol parsing and loading in BaseDataDownloadConfig
* Fix trade drawdown calculation
* Cleanup
* Disable MAE. MFE and Drawdown calculation for FlatToFlat and FlatToReduced trade grouping methods
* Minor test fixes
Report Generator Tests / build (push) Has been cancelled
Python Virtual Environments / build (push) Has been cancelled
API Tests / build (push) Has been cancelled
Benchmarks / build (push) Has been cancelled
Research Regression Tests / build (push) Has been cancelled
Syntax Tests / build (push) Has been cancelled
Build & Test Lean / build (push) Has been cancelled
Regression Tests / build (push) Has been cancelled
* Add total performance statistics to live result files
* Truncate closed trades in live results
* Avoid adding totalPerformance to live minute result file
* Deprecated Trade.Symbol in favor of new Trade.Symbols
* Fixes for Trade serialization
* Add trades json serialization tests
* Cleanup