Live cash sync on a non-trading day double counts unsettled sale proceeds on a cash account
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
Hướng nghiên cứu
Start with Brokerages/Brokerage.cs, especially ShouldPerformCashSync and PerformCashSync, then read Common/Securities/DelayedSettlementModel.cs and Common/Securities/SecurityPortfolioManager.cs to trace how unsettled proceeds affect cash and margin. The issue proposes skipping syncs when no exchange is open or adjusting reconciliation for unsettled cash; compare those approaches against brokerage balance conventions. Done means weekend and holiday syncs no longer double count proceeds or inflate settled buying power.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Expected Behavior
On a live cash account, the daily brokerage cash sync (Brokerage.PerformCashSync) leaves TotalPortfolioValue unchanged when nothing has traded, deposited or withdrawn since the previous sync. Unsettled sale proceeds are counted once: either in UnsettledCashBook (before Lean's settlement) or in CashBook (after it), never in both.
Actual Behavior
After a sale on a Friday, the Saturday 07:45 ET cash sync double counts the proceeds until the Monday sync. The brokerage's balance already carries the proceeds (recognized at trade time), the sync writes that balance into CashBook, and UnsettledCashBook still holds the same proceeds because Lean settles them on the next trading day (Monday 06:00 ET). TotalPortfolioValue jumps up by the proceeds on Saturday and back down on Monday; the live Strategy Equity chart shows both jumps, and MarginRemaining (settled cash) is inflated for two days.
Observed on a live Interactive Brokers deployment (cash account, US equities, build 18226, SetBrokerageModel(InteractiveBrokersBrokerage, AccountType.Cash)):
# Friday 2026-11-06: two round trips; sells at 14:55:05 and 15:05:05 UTC, proceeds 1,128.62 USD
2026-11-06T20:55:01 TRACE:: Total margin information: TotalMarginUsed: 0.00, MarginRemaining: 1277.22
# Saturday: the sync runs although no settlement can happen before Monday
2026-11-08T12:45:00 TRACE:: Brokerage.PerformCashSync(): Sync cash balance
2026-11-08T12:45:00 TRACE:: Brokerage.PerformCashSync(): USD Delta: -1128.61
2026-11-08T12:45:10 TRACE:: Total margin information: TotalMarginUsed: 0.00, MarginRemaining: 2405.83
# Monday: Lean settled the 1,128.62 at 06:00 ET on top of the synced balance; the sync takes it out again
2026-11-09T12:45:00 TRACE:: Brokerage.PerformCashSync(): USD Delta: 1128.62
2026-11-09T12:45:10 TRACE:: Total margin information: TotalMarginUsed: 0.00, MarginRemaining: 2405.83
Strategy Equity samples from the deployment's results: 2,405.84 (2026-11-07) -> 3,534.45 (2026-11-08, exactly 2,405.84 + 1,128.62) -> 2,403.12 (2026-11-09). No order filled between those samples.
On the weekday syncs of the same run (2026-11-10 after Monday sales) there was no delta: the 06:00 ET settlement had moved the proceeds into CashBook before the 07:45 ET sync, as PR #8726 intended. The weekend is the case #8726 does not cover.
Analysis
Brokerages/Brokerage.cs:42sets the sync time to 07:45 New York;ShouldPerformCashSync(:578-588) re-arms on every New York calendar date, so the sync also runs on Saturdays, Sundays and market holidays.Brokerages/Brokerage.cs:654-660compares the brokerage balance withCashBook[currency].Amountonly and overwrites it.UnsettledCashBookis not consulted.Common/Securities/Equity/Equity.cs:33,38: T+1, settlement at 06:00.Common/Securities/DelayedSettlementModel.cs:66-77picks the settlement date by counting only days when the exchange is open, so a Friday (or pre-holiday) sale settles in Lean on the next trading day.- Between a non-trading-day sync and that settlement the proceeds are in both books.
SecurityPortfolioManager.GetMarginRemaining(Common/Securities/SecurityPortfolioManager.cs:594-597) subtractsUnsettledCashBookfromTotalPortfolioValue, soMarginRemaininggoes to the brokerage's full balance and aCashBuyingPowerModelaccount can buy with proceeds that are not yet settled at the brokerage (a cash account good-faith violation if it fills). - PR #8726 (merged 2025-04-28) fixed the weekday instance of this ordering by moving
DefaultSettlementTimeto 06:00 so that Lean settles before the sync. It assumed the sync and the settlement fall on the same day, which does not hold across a weekend or a holiday.
Proposed change
Either of these closes the gap; the first is the smaller change:
- In
ShouldPerformCashSync, skip days on which no security in the algorithm has an open exchange date (weekends, holidays): nothing trades or settles on such a day, so the Friday state stands until the Monday sync. Deposits made over the weekend would be picked up on Monday, as they are today for any deposit made after 07:45 ET. - In
PerformCashSync, reconcile against settled plus unsettled cash: setCashBook[c]tobrokerageBalance[c] - UnsettledCashBook[c].Amount(and log the delta against the sum), so that proceeds the brokerage recognized at trade time are not booked twice. This also covers a weekday where a brokerage credits a sale before Lean's 06:00 settlement.
Open question: brokerages differ in whether the reported balance includes unsettled proceeds (IB documents CashBalance as recognized at trade time; SettledCash is a separate key). Option 2 is only correct for the trade-time convention, so option 1 may be the safer default with option 2 behind a brokerage-model flag.
Reproduce
Not reproducible from a backtest: PerformCashSync runs only in live mode and the defect needs a brokerage balance across a weekend. The evidence is the live syslog quoted above (deltas, margin information) and the deployment's results archive (Strategy Equity samples).
Intercom conversation 215476803054103.
Syslog: L-902077a4f6c1f22ed66a958a2e229f37
Checklist
- I have completely filled out this template
- I have confirmed that this issue exists on the current
masterbranch - I have confirmed that this is not a duplicate issue by searching issues
- I have provided detailed steps to reproduce the issue
- Ngôn ngữ chính
- C#
- Star
- 22.5k
- Fork
- 5.4k
- Merge trung bình
- 22 giờ 6 phút
- Pull request đã merge (30 ngày)
- 81
Chuẩn bị môi trường
Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.
- Có Dockerfile hoặc tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của QuantConnect/Lean
-
PDF report generation can overwrite HTML when the destination extension is not lowercase .htmlĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
QuantConnect/Lean#10082 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
QuantConnect/Lean#10059 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Library Request: highspyĐang mởlibrary-request
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
QuantConnect/Lean#10034 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
QuantConnect/Lean#9965 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
QuantConnect/Lean#9955 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của QuantConnect/Lean
Issue tương tự
-
bug emitter:client:csharp
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
microsoft/typespec#12572 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
needs-area-label
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 2 ngày
-
AWS Lambda: KeyNotFoundException drops HTTP-triggered transactions when allowAllHeaders is disabledĐang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
newrelic/newrelic-dotnet-agent#3949 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area-networking
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
dotnet/aspnetcore#70545 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 87/100
Maintainer thường phản hồi trong vòng 1 ngày