Compare commits

...

105 Commits
14799 ... 15134

Author SHA1 Message Date
Martin-Molinero
3507c91640 Fix future daily price scale factor update (#6963)
* Fix future daily price scale factor update

- Fix future daily price scale factor update which was happening 1 day
  late due to data and exchange time zone differences.
  Adding regression algorithm reproducing and asserting it.

* Address review
2023-02-14 20:09:59 -03:00
Jhonathan Abreu
ebb31d0fb4 Unsettled cash conversion rate update (#6961)
* Update unsettled cashbook cash conversion rates

Also moved conversion rate holding from Cash to the CurrencyConversion
instance

* Minor fixes

* Peer review

* Minor fixes

* Minor fixes

* Minor fixes
2023-02-14 18:19:25 -03:00
Ronit Jain
dcd60d0551 Add support for HTML reports conversion to PDF (#6960)
* add wkhtmltopdf to lean image

* convert html to pdf

* avoid black stripts at bottom of each page

* address reviews

* address review

* address reviews

* self review

* address review
2023-02-14 15:50:19 -03:00
Martin-Molinero
dc2c68c754 Fix security cache reset (#6959)
* Fix security cache reset

- Fix security cache reset so it only happens when no universe has it as
  a member. Adding regression algorithm reproducing issue

* Avoid non deterministic FillForward behavior
2023-02-14 12:09:27 -03:00
Jhonathan Abreu
2791765c94 Make Consolidate Calendar overload with tick type public (#6957) 2023-02-13 16:01:30 -03:00
Martin-Molinero
f270f25eca Fix default future chain universe selection (#6958)
* Fix default future chain universe selection

- Fix default future chain universe selection that should always return
  empty, no selection. In some cases it would allos some contracts
  though. Adding regression algorithm reproducing issue.

* Address review
2023-02-13 15:56:48 -03:00
Martin-Molinero
8235de42a0 Minor debugging improvements (#6954)
* Minor debugging improvements

- Improve exception message if user provides empty/null ticker
- Log margin information on algorithn initialization
- Add unit test asserting option strategy position groups resolve
  correctly for existing holdings

* Symbol Lazy SecurityDefinitionSymbolResolver

- Symbol will have a lazy SecurityDefinitionSymbolResolver instance
  resolution
2023-02-13 10:49:10 -03:00
Martin-Molinero
c2e21df18b Fix combo order prechecks (#6953)
- Apply combo order prechecks before submitting orders. Adding unit test
2023-02-10 19:11:45 -03:00
Jhonathan Abreu
35dfcd73ab Index options MHDB review (#6890)
* Index options MHDB review

* Update MHDB

* Update regression algorithms stats

* Update regression algorithms stats

* Add index and index options holidays

* Peer review

* Update algorithms stats
2023-02-10 14:37:44 -03:00
Jhonathan Abreu
3783900eef Move Brokerages namespace's messages to Messages folder (#6915) 2023-02-10 13:49:15 -03:00
Jhonathan Abreu
9fea859323 Symbol to industry-standard security identifier conversion (#6893)
* Implement SecurityDefinitionSymbolResolver backwards conversion (symbol -> standard id)

* Peer review

* Peer review

* Peer review
2023-02-10 13:12:13 -03:00
Jhonathan Abreu
6e2744af7c Move Securities namespace's messages to Messages folder (#6922)
* Move Securities namespace's messages to Messages folder

* Rebase related fixes

---------

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2023-02-10 11:31:11 -03:00
Martin-Molinero
962b91fc12 Fix Messages namespace collision 2023-02-10 10:50:03 -03:00
Louis Szeto
cf00d3c9f3 OptionStrategies for put calendar spread index weeklies example (#6951) 2023-02-10 10:44:47 -03:00
Louis Szeto
8af5c8b6f2 OptionStrategies for put butterfly index weeklies example (#6950) 2023-02-10 10:42:40 -03:00
Louis Szeto
1fcef8c024 OptionStrategies for Index Option Call Butterfly (#6949)
* OptionStrategies for call butterfly index weeklies example

* fix typo
2023-02-10 10:42:07 -03:00
Jhonathan Abreu
a912638496 Move QuantConnect namespace's messages to Messages folder (#6924) 2023-02-10 10:41:05 -03:00
Jhonathan Abreu
5611b5508a Binance crypto futures fee models (#6874)
* Add Binance Futures and Binance Coin Futures fee models

* Add unit tests

* Add unit tests

* Minor changes

* Peer review

* Peer review
2023-02-09 19:25:27 -03:00
Jhonathan Abreu
b3bd15d3c2 Move Notifications, Optimizer and Python namespaces' messages to Messages folder (#6931) 2023-02-09 19:23:39 -03:00
Jhonathan Abreu
25ab8bdacc Move small namespaces' messages to 'Messages' folder (#6930)
* Move Benchmarks, Exceptions and Indicators namespaces' messages to Messages folder

* Move Command namespace's messages to Messages folder
2023-02-09 19:17:40 -03:00
Jhonathan Abreu
38c5ef3e2b Add CME Ether futures to symbols database (#6884)
* Add Ether futures to symbols database

* Change ETH futures exchange time zone to US/Central

* Add new contracts FuturesExpiryFuntions

* Remove BTIC Micro BTC and BTIC Micro Ether securities

* Add Ether futures IB fees and price multiplier entry

* Update Ethereum price multiplier
2023-02-09 18:42:19 -03:00
Jhonathan Abreu
194f01e621 Move Algorithm namespace's messages to Messages folder (#6916) 2023-02-09 18:35:29 -03:00
Martin-Molinero
61b5231c50 Research GetOptionHistory Weekly Index Improvement (#6946)
- Improve research GetOptionHistory weekly index option support. Adding
  unit test
2023-02-09 18:35:20 -03:00
Louis Szeto
4a06fcdda0 OptionStrategies for Index Option Bull Put Spread (#6945) 2023-02-09 16:10:14 -03:00
Louis Szeto
8325fd18ca OptionStrategies for Index Option Bull Call Spread (#6944) 2023-02-09 16:07:43 -03:00
Louis Szeto
2bc8783082 OptionStrategies for Index Option Bear Put Spread (#6943) 2023-02-09 16:07:00 -03:00
Louis Szeto
0d9f011758 OptionStrategies for Index Option Bear Call Spread (#6942) 2023-02-09 16:06:12 -03:00
Jhonathan Abreu
6dfc6c710c Add algorithm parameters to result (#6878)
* Add algorithm parameters to result's AlgorithmConfiguration

* Peer review
2023-02-09 12:55:30 -03:00
Jhonathan Abreu
e30232e21b Portfolio.UnsettledCashBook update when quote currency is not the account currency (#6871)
* Tracking unsettled cash for non-USD account currency

* Add unit tests

* Peer review

* Move and rename CashBook.UpdateType to Globals
2023-02-09 12:53:52 -03:00
Louis Szeto
8730eeb8a9 Volume Renko Consolidator & Bar (#6888)
* Volume Renko Consolidator & Bar

* address peer review

* Minor fix on tests

---------

Co-authored-by: LouisSzeto <hke0073@hotmail.com>
2023-02-09 10:46:02 -03:00
Jhonathan Abreu
914485c595 Rename SubscriptionRequest.TradableDates to TradableDatesInDataTimeZone for clarity (#6892)
Usages were reviewed to make sure all of them expect it to be in data
time zone instead of exchange time zone
2023-02-08 20:28:37 -03:00
Jhonathan Abreu
02f085ee9e Validate date on security identifier generation (#6897) 2023-02-08 20:26:37 -03:00
Martin-Molinero
f4cf7b6733 Fix SPXW option strategies (#6939)
- Fix SPXW option strategies. Adding regression algorithm
2023-02-08 20:24:30 -03:00
Jhonathan Abreu
d427970762 Check minimum Forex limits in IB Brokerage Model (#6881)
* Checking both min and max forex order size limits in IB brokerage model

Also updated the limits table

* Address peer review
2023-02-08 16:40:18 -03:00
Jhonathan Abreu
66ff14b3bd Patch for missing tick data in history call (#6932)
* Patch for missing tick data in history call

* Update TODO comment to include info on the proposed solution
2023-02-06 13:50:59 -08:00
Jhonathan Abreu
a7a4af6b70 Add Security.SetMarginInterestRateModel methods and its python wrapper (#6879) 2023-02-06 07:57:55 -08:00
Alexandre Catarino
b1a6aa686c Replace Nodes Endpoint in SDK (#6899)
* Adds `project/nodes` Endpoint to SDK

* Removes `nodes` Endpoint from SDK

* Fixes Documentation for `ProjectNodesResponse`
2023-02-05 09:35:11 -08:00
Louis Szeto
14b10f5e81 Add example of bull/bear call spread using index option (#6889)
* Add example of bear call spread using index option

* consistency

* Add bull call spread

* peer review

* peer review

* address peer review

* bug fix

* fix filter

* Address peer review
2023-02-02 13:01:47 -08:00
Louis Szeto
4d85f27f00 Add bull/bear put spread sample algorithms for index weeklies (#6914)
* bear put spread

* bull put spread
2023-02-02 12:34:26 -08:00
Louis Szeto
c2efa65048 Add Call/Put Butterfly sample algorithms for index weeklies (#6913)
* Add index weeklies' Call/Put Butterfly sample algo

* Address peer review
2023-02-02 12:34:04 -08:00
Louis Szeto
75eaf21e43 Add example algo of call & put calendar spread with SPXW (#6907)
* Add example algo of call calendar spread with SPXW

* Add similar example for put calendar spread

* Refine

* consistency

* address peer review

* fix bug

* bug fix

* update

* Improved efficiency

* Address peer review
2023-02-02 12:33:17 -08:00
Louis Szeto
72a6ea9d31 Add SPXW Iron Condor example algorithm (#6880)
* Add SPXW Iron Condor example algorithm

* review

* peer review

* Address peer review
2023-02-02 12:26:34 -08:00
Jhonathan Abreu
2b9662c12e Fix quote tick python consolidate call (#6876) 2023-01-26 18:22:34 -08:00
Jhonathan Abreu
98314d98ed User-facing messages organization (first phase) (#6912)
* Move user-facing order-related messsages to the Messages class

* Group Messages by class

* Move more orders messages

* Minor changes and docs
2023-01-26 16:14:57 -08:00
Jhonathan Abreu
a860cfc32f Combo orders reduced size validation (#6864)
* Combo order legs ratio validation

* Minor changes and unit tests

* Minor changes

* Minor changes

* Minor changes

* Minor changes
2023-01-16 21:11:08 -03:00
Martin-Molinero
6563d6e394 Use any resolution for chain provider (#6860)
* Use any resolution for chain provider

- Use any data resolution available to source symbols for the file based
  chain provider. Adding unit test

* Fix selection timezone bug

- Fix universe selection timezone bug. Updating regression algorithms
2023-01-16 16:10:07 -03:00
Martin-Molinero
11cc062628 Combo limit orders price calculation (#6858)
* Fix limit price calculation for combo limit orders fills

* Update regression algorithms

* Address reviews

* Fix thread race condition

Co-authored-by: Jhonathan Abreu <jdabreu25@gmail.com>
2023-01-13 18:02:25 -03:00
Alexandre Catarino
e8b95b80e1 Polygon Handles Data Subscriptions with One Security Type (#6855)
* Handles Data Subscriptions with One Security Type

Polygon sells data subscriptions for security types separately, so we should not test whether the users have all three subscriptions, Equity, Forex, and Crypto. Users just need the type they will use.

Adds new crypto markets, and unit tests for them. Adapt unit test.

* Fixes ToolBox Downloader

Adds `--api-key` argument.
Closes #6687

* Address reviews

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2023-01-12 17:37:29 -03:00
Martin-Molinero
a52822853d Expand Index option support (#6849)
* Expand Index option support

- Adjust APIs so that the same underlying can be used
  for different options, adding support for SPX weekly options. Adding
  regression tests

* Fix IndexOption.IsStandard

* Add IndexOption test
2023-01-12 16:39:02 -03:00
ChadBett
73e46cc9ae TensorFlow Placeholder Fix (#6852)
Fixed this error from happening when running this code:

tf.placeholder() is not compatible with eager execution.
  at placeholder
    raise RuntimeError("tf.placeholder() is not compatible with "
 in array_ops.py: line 3341
  at NetTrain
    xs = tf.compat.v1.placeholder(tf.float32 in /QuantConnect/backtesting/./cache/algorithm/project/main.py: line 57
2023-01-11 11:18:47 -03:00
Ronit Jain
a9c4d29776 Feature add algorithm state information in result packets (#6839)
* add state to backtesting result packets

* self review

* add state in live results

* set runtime error in algorithm

* set hostname in job packets

* Set state when algorithm is null

* address review

* address reviews

* set runtime error when algorithm is not available during runtime
2023-01-11 10:54:38 -03:00
Jhonathan Abreu
6ed8cb5cae Backtest progress calculation (#6847)
* Fix backtest progress calculation

* Backtest progress monitor class

* Minor changes

* Lazy calculating the processed days count

* Minor changes

* Minor changes
2023-01-11 10:33:38 -03:00
Jhonathan Abreu
1d1dc07dfb Set DataNormalizationMode on AddSecurity method (#6845)
* Set DataNormalizationMode on AddSecurity method

* Minor changes
2023-01-10 13:03:00 -03:00
Jhonathan Abreu
bddebe279d Algorithm asserting options stategy orders with large quantities (#6843) 2023-01-09 14:21:16 -03:00
Martin-Molinero
81a334c525 Add Leg.Create method (#6842)
- Add Leg.Create method for sugar syntax, specially for python
2023-01-09 14:20:32 -03:00
Martin-Molinero
af26b66481 Update readme.md 2023-01-06 21:10:08 -03:00
Martin-Molinero
d7ead851a1 Update readme.md 2023-01-06 19:27:32 -03:00
Martin-Molinero
f428398900 Update readme.md 2023-01-06 19:22:07 -03:00
Martin-Molinero
19483702f8 Update readme.md 2023-01-06 18:36:42 -03:00
Martin-Molinero
146be2d0ba Update readme.md 2023-01-06 18:09:40 -03:00
Jhonathan Abreu
b54281b262 Combo orders (#6813)
* Feature combo orders

- Add support for combo orders

* Make fill model wait for all grouped orders to emit fills

* Add ComboFill to model multiple fills for combo orders

* Fill combo limit orders

Add some regression algorithms

* Add fill implementation for combo leg limit orders

* Add IFill as common interface for Fill and ComboFill

* Refactor combo orders removing IGroupOrder interface

Move the group order manager to the base Order class

* Update algorithms

* Handle combo order events atomically

* Refactor brokerage transaction event handler

* Refactor combo fill models

* Process fills in batch

* Combo orders fill model tests

* Combo leg limit orders algorithm

* Regression algorithms cleanup

* Fill and combo fill classes cleanup

* Housekeeping

* Refactor equity fill model to derive from base fill model

* Address review changes request

* Handling the new types of orders in the OrderJsonConverter

* Add regression algorithm to test combo orders update/cancel

* Add regression algorithm to test combo orders update/cancel

* Housekeeping

* Address review changes request

* Minor changes

* Security transaction handler method for setting order request id

* Extend public interface for placing combo orders

* Combo order tickets demo algorithm python version

* Tweaks and updates

* Minor fixes

* Minor changes

* Minor fixes

* Address reviews minor fixes

* Minor fixes

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2023-01-06 17:58:43 -03:00
Martin-Molinero
f12e8fc08e CryptoFutures adjustments (#6836)
* CryptoFutures adjustments

- Address reviews of CryptoFutures:
- Add new Slice MarginInterestRates collection
- Add new regression tests asserting funding rate application behaves
  the same no matter the resolution
- Add auxiliary data by type into the security cache
- Revert BuyingPowerModel changes

* Make interest rate application time deterministic
2023-01-05 18:07:01 -03:00
Alexandre Catarino
6b6ca5b460 Saves Dividend Payments to Security Holdings (#6830)
* Saves Dividend Payments to Security Holdings

Saves information about dividend payments to `SecurityHoldings`. This information will be used to factor in dividend payments to the `Profit` and `NetProfit`.
Adds `SecurityPortfolioManager.TotalNetProfit` to sum all the `SecurityHoldings.NetProfit`.

Adds regression and unit tests.

* Addresses Peer-Review

Improves Regression Test.
2023-01-03 18:37:00 -03:00
Martin-Molinero
ab4c3bf55e Live margin interest rate bug (#6833)
* Fix for live MarginInterestRate

* Add unit tests
2023-01-03 14:13:11 -03:00
hsm207
9c69ee5536 Update link to Lean CLI getting started (#6832) 2023-01-02 11:14:06 -03:00
Alexandre Catarino
89493b1546 Adds Pre-Market for LBS (#6831)
The lumber pre-opening window is from 6am to 9am Chicago.
https://www.cmegroup.com/trading-hours.html#foi=F&search=Lumber
2022-12-30 18:00:07 -03:00
Martin-Molinero
ee683933a3 Feature Perpetual Crypto Futures (#6807)
* WIP

* Add base currency cash

* Symbol properties and data processing

* Add basic template algorithm

* Add hourly crypto future algorithm

* Minor fixes after live trading testing

* CoinApiDataQueueHandler CryptoFuture support

* Address reviews

* Fix regression algorithms after update
2022-12-30 13:58:11 -03:00
Martin-Molinero
e87c98def8 Update readme.md 2022-12-28 15:39:59 -03:00
Martin-Molinero
239406ef5c Update ib gateway to latest (#6819) 2022-12-28 15:35:52 -03:00
Martin-Molinero
e13066273c Update readme.md 2022-12-26 17:25:34 -03:00
Martin-Molinero
7677b99bf6 Handle OnOptionNotification race condition (#6821)
- Handle OnOptionNotification race condition to take into account sell
  orders too. Updating unit tests
2022-12-26 17:21:51 -03:00
Ronit Jain
c21dd716ed use data channel property (#6826) 2022-12-26 15:23:18 -03:00
Martin-Molinero
f87eb88f27 Update holidays Christmas New Years 2022/23 (#6824) 2022-12-26 13:58:05 -03:00
Martin-Molinero
1d363e2c35 Fix brokerages tests order id update (#6822)
- Fix for brokerage test brokerage order id update handling
2022-12-22 20:02:35 -03:00
Martin-Molinero
98273097e5 Update readme.md 2022-12-22 10:43:39 -03:00
Martin-Molinero
cbdf25d713 Update readme.md 2022-12-21 21:19:44 -03:00
Martin-Molinero
dcfdbd8c82 Add OnOrderIdChangedEvent (#6816)
* Add OnOrderIdChangedEvent

- Add OnOrderIdChangedEvent so that brokerages can change the brokerage
  order ids on the original order directly

* Fix bug
2022-12-21 20:53:39 -03:00
Louis Szeto
b5b317f490 Basic template algorithm for continuous futures rollover (#6803)
* Basic template algorithm for continuous futures rollover handling

* update regression metric

* Update to multi-contract versions

* SymbolData implementation

* minor bug

* peer review

* order hash

* more abstraction
2022-12-20 11:37:32 -03:00
Martin-Molinero
0eecf5d139 Update gh-actions.yml 2022-12-20 11:12:43 -03:00
Alexandre Catarino
bc513ce0e7 Changes Crumb Location from Yahoo Downloader (#6812)
Yahoo has changed the location from the crumb which is no longer located in "CrumbStore",
2022-12-20 10:33:52 -03:00
Roman Yavnikov
019ce5aa76 TDAmeritrade brokerage fix (#6806)
* remove: support SecurityType.Future

* add SecurityType.Index and IndexOption
fix: error message in orderType support

* Update TDAmeritradeBrokerageModel.cs

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2022-12-16 19:47:03 -03:00
Martin-Molinero
c4329c4132 More resilient object store file read (#6800) 2022-12-13 15:25:47 -03:00
Roman Yavnikov
9618c376bf Feature tdameritrade brokerage setup (#6791)
* TDAmeritrade LEAN integration

* feature: update order model for TDAmeritrade brokerage
fix: typos

* fix: typo in license

* refactor: remove extra multiple op

* refactor: TDAmeritrade naming api-key

* remove: extra configs

* fix: PR comment

* Rename file

* feature: add to config `SubscriptionDataReaderHistoryProvider`

* remove: extra logic

* Address review

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2022-12-12 18:14:21 -03:00
Alexandre Catarino
3aabb11315 Allows Market-On-Close Orders Outside Buffer Period (#6769)
* Allows Market-On-Close Orders Outside Buffer Period

Market-On-Close orders can be submitted before and after the buffer period from 15:45 to 16:00 (Tested with TWS) meaning that we can submit MOC when the market is closed and, consequently, use daily resolution data.

* Adds Regression Test with Extended Market Hours

- Removes `nextMarketClose > Time` condition since it's unnecessary. If the algorithm Time is greater than the close of that day, `nextMarektClose` refers to the next day.

* Updates Unit Test

Updates `OrderQuantityConversionTest` because the MOC orders are submitted. They are placed at 7 pm and invalid before this pull request.

* Updates Summary of new Regression Tests
2022-12-08 19:46:58 -03:00
Jhonathan Abreu
4d2723f851 Update CME options scaling factors (#6774) 2022-12-06 16:41:04 -03:00
Jhonathan Abreu
86b74e0a09 Add IB weekly restart time entry to config file (#6773) 2022-12-06 14:52:46 -03:00
Jhonathan Abreu
41a730bc68 OTM option excerise orders improvements (#6767)
* Set fill price to zero in OTM exercise orders.

Improved the OTM exercise orders message.

* Update regression algorithms and unit tests

* Add IsInTheMoney property to OrderEvent

* Update SerializedOrderEvent

* Properly setting the option exercise order price to strike price or zero

* Minor changes

* Minor changes
2022-12-06 14:30:40 -03:00
Jhonathan Abreu
6b2dfb6b8c Update equity default settlement days (#6766) 2022-11-28 13:26:56 -03:00
Jhonathan Abreu
7a4ca7898e Add estimate option to optimizer for optimization estimate (#6763)
* Add 'estimate' option to optimizer launcher

* Add 'estimate' option to optimizer launcher

* Unit tests and minor tweaks

* Minor tweaks
2022-11-25 19:08:28 -03:00
Mathieu Paquette
60028ad48a fix(ToolBox/IQFeed): increase default buffer size (#6762)
fixes #6761
2022-11-25 10:40:52 -03:00
Derek Melchin
e9d690b35a Add missing </summary> tag (#6760) 2022-11-23 10:20:27 -03:00
Alexandre Catarino
db2cb57a3f Handles NaN or Infinity from QLNet Calculations (#6757) 2022-11-18 18:25:13 -03:00
Jhonathan Abreu
3c784e5b04 Revisit futures contract multipliers (#6753) 2022-11-18 18:24:45 -03:00
Jhonathan Abreu
31f8561330 Allow optional selector in classic renko consolidator in Python and C# (#6755) 2022-11-18 17:14:03 -03:00
Martin-Molinero
38b87d941a Update readme.md 2022-11-18 14:36:51 -03:00
Alexandre Catarino
83d59b5f9a Removes Volatility Model Warm Up Requirement (#6752)
* Fixes Regression Algorithm Testing No Warm Up Requirement

* Removes Volatility Model Warm Up Requirement

If the volatiliy model is not ready, we will use the Brenner and Subrahmanyam (1988) approximation (BS88).
Lean will not set the volatility model if the user doesn't, since the BS88 can handle the null model case.
2022-11-18 14:34:56 -03:00
Martin-Molinero
f19d8cb700 Add missing exchanges (#6754)
* Add missing exchanges

* Add missing conversion handling
2022-11-18 14:11:13 -03:00
Martin-Molinero
fcee43b56e Update readme.md 2022-11-17 14:38:14 -03:00
Martin-Molinero
7898e74148 Update readme.md 2022-11-17 13:50:31 -03:00
Louis Szeto
b34cea4458 Calculate Option Greeks with Implied Volatility (#6720)
* Using IV to calculate Greeks, and remove single-step stochastic approximation

* Correct calculation for theta, vega, rho

* Add calculation from Black Calculator and peer review

* Address peer review and added unit test

* Update some tests and correct vega/eho

* Fix Unit Test and Improve Comments

Fixes `IndexOptionCallITMGreeksExpiryRegressionAlgorithm` since `Vega` was really non-zero.

* Fix regression test and add IV calculation

* refactor and bug fixing on peer review

* refactor and bug fixing on peer review

* for rerun test

* add warning on IV estimation not coveraged and edit speed unit test to not exceed 2s per 1000 iteration

* update logging

* update logging and description

* Add default option pricing models and unit tests

* address review

* Added Fed interest rate as risk-free rate with unit tests and set as default for option greeks calculation, added regression algorithms, addressed peer review

* refactor structure of interest rate

* Skip Saturday and Sunday

* regression test fix

* peer review

* Fixes Interest Rate Provider Logic

* Minor tweaks

* Fix start date

* Minor test tweak

* Update interest rates

* Fix unit tests

* Add minor log

Co-authored-by: Alexandre Catarino <AlexCatarino@users.noreply.github.com>
Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2022-11-17 13:35:42 -03:00
Jhonathan Abreu
e9edb8ac29 Fix IndicatorExtensions for Python indicators (#6748)
* Fix using python custom indicators with extensions

* Minor changes to the algorithm

* Address PR comments
2022-11-16 18:36:46 -03:00
Jhonathan Abreu
33c57bbde4 Use selector on indicator warm up (#6746) 2022-11-15 19:59:59 -03:00
Jhonathan Abreu
94b9b13530 Make PlotIndicator able to receive IndicatorBase (#6745)
* Make PlotIndicator able to receive IndicatorBase

* Minor changes
2022-11-15 11:49:55 -03:00
Jhonathan Abreu
682b9aa760 Restrict index and cash-settled options exercise in IB brokerage (#6744)
* Limit exercise in IB brokerage for limit and cash-settled options

* Add regression algorithm

* Assert that index option is automatically exercised in regression algorithm
2022-11-15 11:03:43 -03:00
Jhonathan Abreu
98c6023748 Forbid european options exercise before expiry (#6734)
* Forbid european options exercise before expiry

* Minor tweaks

* Minor tweaks to tests
2022-11-11 19:32:44 -03:00
591 changed files with 25760 additions and 5849 deletions

View File

@@ -19,7 +19,7 @@ jobs:
run: dotnet build /p:Configuration=Release /v:quiet /p:WarningLevel=1 QuantConnect.Lean.sln
- name: Run Tests
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --filter "TestCategory!=TravisExclude&TestCategory!=ResearchRegressionTests" -- TestRunParameters.Parameter\(name=\"log-handler\", value=\"ConsoleErrorLogHandler\"\)
run: dotnet test ./Tests/bin/Release/QuantConnect.Tests.dll --blame-hang-timeout 300seconds --blame-crash --filter "TestCategory!=TravisExclude&TestCategory!=ResearchRegressionTests" -- TestRunParameters.Parameter\(name=\"log-handler\", value=\"ConsoleErrorLogHandler\"\)
- name: Generate & Publish python stubs
if: startsWith(github.ref, 'refs/tags/')

View File

@@ -220,7 +220,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 608437;
public long DataPoints => 612882;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -170,7 +170,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "4f50b8360ea317ef974801649088bd06"}
{"OrderListHash", "568fe7c2a11960436660db1231f2cfd2"}
};
}
}

View File

@@ -88,7 +88,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all time slices of algorithm
/// </summary>
public long DataPoints => 3338420;
public long DataPoints => 6023980;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -349,7 +349,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "f67306bc706a2cf66288f1cadf6148ed"}
{"OrderListHash", "85cbf92f01c2c91b5f710b7eeefecbe1"}
};
}
}

View File

@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 284403;
public long DataPoints => 709638;
/// <summary>
/// Data Points count of the algorithm history
@@ -156,7 +156,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-1.993"},
{"Return Over Maximum Drawdown", "-1.996"},
{"Portfolio Turnover", "0.01"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -123,7 +123,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 884815;
public long DataPoints => 2202510;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -0,0 +1,292 @@
/*
* 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.
*/
using System;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Brokerages;
using QuantConnect.Indicators;
using QuantConnect.Interfaces;
using QuantConnect.Securities;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Securities.CryptoFuture;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Minute resolution regression algorithm trading Coin and USDT binance futures long and short asserting the behavior
/// </summary>
public class BasicTemplateCryptoFutureAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Dictionary<Symbol, int> _interestPerSymbol = new();
private CryptoFuture _btcUsd;
private CryptoFuture _adaUsdt;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
SetStartDate(2022, 12, 13); // Set Start Date
SetEndDate(2022, 12, 13); // Set End Date
SetTimeZone(NodaTime.DateTimeZone.Utc);
try
{
SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Cash);
}
catch (InvalidOperationException)
{
// expected, we don't allow cash account type
}
SetBrokerageModel(BrokerageName.BinanceFutures, AccountType.Margin);
_btcUsd = AddCryptoFuture("BTCUSD");
_adaUsdt = AddCryptoFuture("ADAUSDT");
_fast = EMA(_btcUsd.Symbol, 30, Resolution.Minute);
_slow = EMA(_btcUsd.Symbol, 60, Resolution.Minute);
_interestPerSymbol[_btcUsd.Symbol] = 0;
_interestPerSymbol[_adaUsdt.Symbol] = 0;
// Default USD cash, set 1M but it wont be used
SetCash(1000000);
// the amount of BTC we need to hold to trade 'BTCUSD'
_btcUsd.BaseCurrency.SetAmount(0.005m);
// the amount of USDT we need to hold to trade 'ADAUSDT'
_adaUsdt.QuoteCurrency.SetAmount(200);
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
public override void OnData(Slice data)
{
var interestRates = data.Get<MarginInterestRate>();
foreach (var interestRate in interestRates)
{
_interestPerSymbol[interestRate.Key]++;
var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();
if (cachedInterestRate != interestRate.Value)
{
throw new Exception($"Unexpected cached margin interest rate for {interestRate.Key}!");
}
}
if (_fast > _slow)
{
if (!Portfolio.Invested && Transactions.OrdersCount == 0)
{
var ticket = Buy(_btcUsd.Symbol, 50);
if (ticket.Status != OrderStatus.Invalid)
{
throw new Exception($"Unexpected valid order {ticket}, should fail due to margin not sufficient");
}
Buy(_btcUsd.Symbol, 1);
var marginUsed = Portfolio.TotalMarginUsed;
var btcUsdHoldings = _btcUsd.Holdings;
// Coin futures value is 100 USD
var holdingsValueBtcUsd = 100;
if (Math.Abs(btcUsdHoldings.TotalSaleVolume - holdingsValueBtcUsd) > 1)
{
throw new Exception($"Unexpected TotalSaleVolume {btcUsdHoldings.TotalSaleVolume}");
}
if (Math.Abs(btcUsdHoldings.AbsoluteHoldingsCost - holdingsValueBtcUsd) > 1)
{
throw new Exception($"Unexpected holdings cost {btcUsdHoldings.HoldingsCost}");
}
// margin used is based on the maintenance rate
if (Math.Abs(btcUsdHoldings.AbsoluteHoldingsCost * 0.05m - marginUsed) > 1
|| _btcUsd.BuyingPowerModel.GetMaintenanceMargin(_btcUsd) != marginUsed)
{
throw new Exception($"Unexpected margin used {marginUsed}");
}
Buy(_adaUsdt.Symbol, 1000);
marginUsed = Portfolio.TotalMarginUsed - marginUsed;
var adaUsdtHoldings = _adaUsdt.Holdings;
// USDT/BUSD futures value is based on it's price
var holdingsValueUsdt = _adaUsdt.Price * _adaUsdt.SymbolProperties.ContractMultiplier * 1000;
if (Math.Abs(adaUsdtHoldings.TotalSaleVolume - holdingsValueUsdt) > 1)
{
throw new Exception($"Unexpected TotalSaleVolume {adaUsdtHoldings.TotalSaleVolume}");
}
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
{
throw new Exception($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
}
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost * 0.05m - marginUsed) > 1
|| _adaUsdt.BuyingPowerModel.GetMaintenanceMargin(_adaUsdt) != marginUsed)
{
throw new Exception($"Unexpected margin used {marginUsed}");
}
// position just opened should be just spread here
var profit = Portfolio.TotalUnrealizedProfit;
if ((5 - Math.Abs(profit)) < 0)
{
throw new Exception($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
}
if (Portfolio.TotalProfit != 0)
{
throw new Exception($"Unexpected TotalProfit {Portfolio.TotalProfit}");
}
}
}
else
{
// let's revert our position and double
if (Time.Hour > 10 && Transactions.OrdersCount == 3)
{
Sell(_btcUsd.Symbol, 3);
var btcUsdHoldings = _btcUsd.Holdings;
if (Math.Abs(btcUsdHoldings.AbsoluteHoldingsCost - 100 * 2) > 1)
{
throw new Exception($"Unexpected holdings cost {btcUsdHoldings.HoldingsCost}");
}
Sell(_adaUsdt.Symbol, 3000);
var adaUsdtHoldings = _adaUsdt.Holdings;
// USDT/BUSD futures value is based on it's price
var holdingsValueUsdt = _adaUsdt.Price * _adaUsdt.SymbolProperties.ContractMultiplier * 2000;
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
{
throw new Exception($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
}
// position just opened should be just spread here
var profit = Portfolio.TotalUnrealizedProfit;
if ((5 - Math.Abs(profit)) < 0)
{
throw new Exception($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
}
// we barely did any difference on the previous trade
if ((5 - Math.Abs(Portfolio.TotalProfit)) < 0)
{
throw new Exception($"Unexpected TotalProfit {Portfolio.TotalProfit}");
}
}
}
}
public override void OnEndOfAlgorithm()
{
if (_interestPerSymbol[_adaUsdt.Symbol] != 1)
{
throw new Exception($"Unexpected interest rate count {_interestPerSymbol[_adaUsdt.Symbol]}");
}
if (_interestPerSymbol[_btcUsd.Symbol] != 3)
{
throw new Exception($"Unexpected interest rate count {_interestPerSymbol[_btcUsd.Symbol]}");
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Debug(Time + " " + orderEvent);
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 7205;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "4"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.65"},
{"Estimated Strategy Capacity", "$630000000.00"},
{"Lowest Capacity Asset", "ADAUSDT 18R"},
{"Fitness Score", "0.001"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
{"Portfolio Turnover", "0.001"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d4520985f69c915060f6bee3b7926cf5"}
};
}
}

View File

@@ -0,0 +1,255 @@
/*
* 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.
*/
using System;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Indicators;
using QuantConnect.Interfaces;
using QuantConnect.Securities;
using QuantConnect.Brokerages;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Securities.CryptoFuture;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Hourly regression algorithm trading ADAUSDT binance futures long and short asserting the behavior
/// </summary>
public class BasicTemplateCryptoFutureHourlyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Dictionary<Symbol, int> _interestPerSymbol = new();
private CryptoFuture _adaUsdt;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
SetStartDate(2022, 12, 13);
SetEndDate(2022, 12, 13);
SetTimeZone(NodaTime.DateTimeZone.Utc);
try
{
SetBrokerageModel(BrokerageName.BinanceCoinFutures, AccountType.Cash);
}
catch (InvalidOperationException)
{
// expected, we don't allow cash account type
}
SetBrokerageModel(BrokerageName.BinanceCoinFutures, AccountType.Margin);
_adaUsdt = AddCryptoFuture("ADAUSDT", Resolution.Hour);
_fast = EMA(_adaUsdt.Symbol, 3, Resolution.Hour);
_slow = EMA(_adaUsdt.Symbol, 6, Resolution.Hour);
_interestPerSymbol[_adaUsdt.Symbol] = 0;
// Default USD cash, set 1M but it wont be used
SetCash(1000000);
// the amount of USDT we need to hold to trade 'ADAUSDT'
_adaUsdt.QuoteCurrency.SetAmount(200);
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
public override void OnData(Slice data)
{
var interestRates = data.Get<MarginInterestRate>();
foreach (var interestRate in interestRates)
{
_interestPerSymbol[interestRate.Key]++;
var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();
if (cachedInterestRate != interestRate.Value)
{
throw new Exception($"Unexpected cached margin interest rate for {interestRate.Key}!");
}
}
if (_fast > _slow)
{
if (!Portfolio.Invested && Transactions.OrdersCount == 0)
{
var ticket = Buy(_adaUsdt.Symbol, 100000);
if(ticket.Status != OrderStatus.Invalid)
{
throw new Exception($"Unexpected valid order {ticket}, should fail due to margin not sufficient");
}
Buy(_adaUsdt.Symbol, 1000);
var marginUsed = Portfolio.TotalMarginUsed;
var adaUsdtHoldings = _adaUsdt.Holdings;
// USDT/BUSD futures value is based on it's price
var holdingsValueUsdt = _adaUsdt.Price * _adaUsdt.SymbolProperties.ContractMultiplier * 1000;
if (Math.Abs(adaUsdtHoldings.TotalSaleVolume - holdingsValueUsdt) > 1)
{
throw new Exception($"Unexpected TotalSaleVolume {adaUsdtHoldings.TotalSaleVolume}");
}
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
{
throw new Exception($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
}
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost * 0.05m - marginUsed) > 1
|| _adaUsdt.BuyingPowerModel.GetMaintenanceMargin(_adaUsdt) != marginUsed)
{
throw new Exception($"Unexpected margin used {marginUsed}");
}
// position just opened should be just spread here
var profit = Portfolio.TotalUnrealizedProfit;
if ((5 - Math.Abs(profit)) < 0)
{
throw new Exception($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
}
if (Portfolio.TotalProfit != 0)
{
throw new Exception($"Unexpected TotalProfit {Portfolio.TotalProfit}");
}
}
}
else
{
// let's revert our position and double
if (Time.Hour > 10 && Transactions.OrdersCount == 2)
{
Sell(_adaUsdt.Symbol, 3000);
var adaUsdtHoldings = _adaUsdt.Holdings;
// USDT/BUSD futures value is based on it's price
var holdingsValueUsdt = _adaUsdt.Price * _adaUsdt.SymbolProperties.ContractMultiplier * 2000;
if (Math.Abs(adaUsdtHoldings.AbsoluteHoldingsCost - holdingsValueUsdt) > 1)
{
throw new Exception($"Unexpected holdings cost {adaUsdtHoldings.HoldingsCost}");
}
// position just opened should be just spread here
var profit = Portfolio.TotalUnrealizedProfit;
if ((5 - Math.Abs(profit)) < 0)
{
throw new Exception($"Unexpected TotalUnrealizedProfit {Portfolio.TotalUnrealizedProfit}");
}
// we barely did any difference on the previous trade
if ((5 - Math.Abs(Portfolio.TotalProfit)) < 0)
{
throw new Exception($"Unexpected TotalProfit {Portfolio.TotalProfit}");
}
}
if (Time.Hour >= 22 && Transactions.OrdersCount == 3)
{
Liquidate();
}
}
}
public override void OnEndOfAlgorithm()
{
if (_interestPerSymbol[_adaUsdt.Symbol] != 1)
{
throw new Exception($"Unexpected interest rate count {_interestPerSymbol[_adaUsdt.Symbol]}");
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Debug(Time + " " + orderEvent);
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 50;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.61"},
{"Estimated Strategy Capacity", "$520000000.00"},
{"Lowest Capacity Asset", "ADAUSDT 18R"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-364.224"},
{"Portfolio Turnover", "0.001"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "17f99ecc3f35f94fff1ea5694c40d32c"}
};
}
}

View File

@@ -0,0 +1,235 @@
/*
* 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.
*
*/
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Indicators;
using QuantConnect.Securities;
using QuantConnect.Securities.Future;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Example algorithm for trading continuous future
/// </summary>
public class BasicTemplateFutureRolloverAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Dictionary<Symbol, SymbolData> _symbolDataBySymbol = new();
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
SetStartDate(2013, 10, 8);
SetEndDate(2013, 12, 10);
SetCash(1000000);
var futures = new List<string> {
Futures.Indices.SP500EMini
};
foreach (var future in futures)
{
// Requesting data
var continuousContract = AddFuture(future,
resolution: Resolution.Daily,
extendedMarketHours: true,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
dataMappingMode: DataMappingMode.OpenInterest,
contractDepthOffset: 0
);
var symbolData = new SymbolData(this, continuousContract);
_symbolDataBySymbol.Add(continuousContract.Symbol, symbolData);
}
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
public override void OnData(Slice slice)
{
foreach (var kvp in _symbolDataBySymbol)
{
var symbol = kvp.Key;
var symbolData = kvp.Value;
// Call SymbolData.Update() method to handle new data slice received
symbolData.Update(slice);
// Check if information in SymbolData class and new slice data are ready for trading
if (!symbolData.IsReady || !slice.Bars.ContainsKey(symbol))
{
return;
}
var emaCurrentValue = symbolData.EMA.Current.Value;
if (emaCurrentValue < symbolData.Price && !symbolData.IsLong)
{
MarketOrder(symbolData.Mapped, 1);
}
else if (emaCurrentValue > symbolData.Price && !symbolData.IsShort)
{
MarketOrder(symbolData.Mapped, -1);
}
}
}
/// <summary>
/// Abstracted class object to hold information (state, indicators, methods, etc.) from a Symbol/Security in a multi-security algorithm
/// </summary>
public class SymbolData
{
private QCAlgorithm _algorithm;
private Future _future;
public ExponentialMovingAverage EMA;
public decimal Price;
public bool IsLong;
public bool IsShort;
public Symbol Symbol => _future.Symbol;
public Symbol Mapped => _future.Mapped;
/// <summary>
/// Check if symbolData class object are ready for trading
/// </summary>
public bool IsReady => Mapped != null && EMA.IsReady;
/// <summary>
/// Constructor to instantiate the information needed to be hold
/// </summary>
public SymbolData(QCAlgorithm algorithm, Future future)
{
_algorithm = algorithm;
_future = future;
EMA = algorithm.EMA(future.Symbol, 20, Resolution.Daily);
Reset();
}
/// <summary>
/// Handler of new slice of data received
/// </summary>
public void Update(Slice slice)
{
if (slice.SymbolChangedEvents.TryGetValue(Symbol, out var changedEvent))
{
var oldSymbol = changedEvent.OldSymbol;
var newSymbol = changedEvent.NewSymbol;
var tag = $"Rollover - Symbol changed at {_algorithm.Time}: {oldSymbol} -> {newSymbol}";
var quantity = _algorithm.Portfolio[oldSymbol].Quantity;
// Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
_algorithm.Liquidate(oldSymbol, tag: tag);
_algorithm.MarketOrder(newSymbol, quantity, tag: tag);
Reset();
}
Price = slice.Bars.ContainsKey(Symbol) ? slice.Bars[Symbol].Price : Price;
IsLong = _algorithm.Portfolio[Mapped].IsLong;
IsShort = _algorithm.Portfolio[Mapped].IsShort;
}
/// <summary>
/// Reset RollingWindow/indicator to adapt to newly mapped contract, then warm up the RollingWindow/indicator
/// </summary>
private void Reset()
{
EMA.Reset();
_algorithm.WarmUpIndicator(Symbol, EMA, Resolution.Daily);
}
/// <summary>
/// Disposal method to remove consolidator/update method handler, and reset RollingWindow/indicator to free up memory and speed
/// </summary>
public void Dispose()
{
EMA.Reset();
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 1345;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 4;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "0.53%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "3.011%"},
{"Drawdown", "0.000%"},
{"Expectancy", "0"},
{"Net Profit", "0.528%"},
{"Sharpe Ratio", "1.999"},
{"Probabilistic Sharpe Ratio", "83.704%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.023"},
{"Beta", "-0.004"},
{"Annual Standard Deviation", "0.011"},
{"Annual Variance", "0"},
{"Information Ratio", "-4.774"},
{"Tracking Error", "0.084"},
{"Treynor Ratio", "-4.853"},
{"Total Fees", "$4.30"},
{"Estimated Strategy Capacity", "$5900000000.00"},
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
{"Fitness Score", "0.002"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "1792.236"},
{"Portfolio Turnover", "0.002"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "40e4b91ec89383f6501d9ba324e50eb9"}
};
}
}

View File

@@ -188,8 +188,8 @@ namespace QuantConnect.Algorithm.CSharp
{"Fitness Score", "0.001"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-58.725"},
{"Return Over Maximum Drawdown", "-32.073"},
{"Sortino Ratio", "-58.8"},
{"Return Over Maximum Drawdown", "-32.114"},
{"Portfolio Turnover", "98.477"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -117,7 +117,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 11709;
public virtual long DataPoints => 15217;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -173,8 +173,8 @@ namespace QuantConnect.Algorithm.CSharp
{"Fitness Score", "0.006"},
{"Kelly Criterion Estimate", "-50.022"},
{"Kelly Criterion Probability Value", "0.711"},
{"Sortino Ratio", "-9.907"},
{"Return Over Maximum Drawdown", "-50.79"},
{"Sortino Ratio", "-10.107"},
{"Return Over Maximum Drawdown", "-51.815"},
{"Portfolio Turnover", "0.54"},
{"Total Insights Generated", "5"},
{"Total Insights Closed", "4"},

View File

@@ -41,7 +41,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 73252;
public override long DataPoints => 96027;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
@@ -73,8 +73,8 @@ namespace QuantConnect.Algorithm.CSharp
{"Fitness Score", "0.045"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-4.326"},
{"Return Over Maximum Drawdown", "-0.994"},
{"Sortino Ratio", "-4.328"},
{"Return Over Maximum Drawdown", "-0.995"},
{"Portfolio Turnover", "0.205"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -43,7 +43,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 13559;
public override long DataPoints => 17431;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm

View File

@@ -41,7 +41,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 205645;
public override long DataPoints => 248521;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm

View File

@@ -34,7 +34,7 @@ namespace QuantConnect.Algorithm.CSharp
protected Symbol SpxOption;
private ExponentialMovingAverage _emaSlow;
private ExponentialMovingAverage _emaFast;
protected virtual Resolution Resolution => Resolution.Minute;
protected virtual int StartDay => 4;
@@ -112,7 +112,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 16690;
public virtual long DataPoints => 15929;
/// <summary>
/// Data Points count of the algorithm history
@@ -124,34 +124,34 @@ namespace QuantConnect.Algorithm.CSharp
/// </summary>
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "4"},
{"Total Trades", "3"},
{"Average Win", "0%"},
{"Average Loss", "-53.10%"},
{"Compounding Annual Return", "-92.544%"},
{"Drawdown", "10.100%"},
{"Average Loss", "-7.01%"},
{"Compounding Annual Return", "-93.456%"},
{"Drawdown", "9.300%"},
{"Expectancy", "-1"},
{"Net Profit", "-9.915%"},
{"Sharpe Ratio", "-3.845"},
{"Probabilistic Sharpe Ratio", "0.053%"},
{"Net Profit", "-8.354%"},
{"Sharpe Ratio", "-4.078"},
{"Probabilistic Sharpe Ratio", "0.781%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.558"},
{"Beta", "0.313"},
{"Annual Standard Deviation", "0.112"},
{"Annual Variance", "0.013"},
{"Information Ratio", "-6.652"},
{"Tracking Error", "0.125"},
{"Treynor Ratio", "-1.379"},
{"Alpha", "-0.377"},
{"Beta", "0.178"},
{"Annual Standard Deviation", "0.069"},
{"Annual Variance", "0.005"},
{"Information Ratio", "-7.596"},
{"Tracking Error", "0.108"},
{"Treynor Ratio", "-1.583"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$13000000.00"},
{"Estimated Strategy Capacity", "$9100000.00"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.039"},
{"Fitness Score", "0.051"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.763"},
{"Return Over Maximum Drawdown", "-9.371"},
{"Portfolio Turnover", "0.278"},
{"Sortino Ratio", "-1.51"},
{"Return Over Maximum Drawdown", "-11.301"},
{"Portfolio Turnover", "0.338"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -165,7 +165,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "0668385036aba3e95127607dfc2f1a59"}
{"OrderListHash", "7f5f25fafc99bf45774e63bc528f3fc8"}
};
}
}

View File

@@ -12,10 +12,10 @@ namespace QuantConnect.Algorithm.CSharp
protected override Resolution Resolution => Resolution.Daily;
protected override int StartDay => 1;
// two complete weeks starting from the 5th plus the 18th bar
protected virtual int ExpectedBarCount => 2 * 5 + 1;
// two complete weeks starting from the 5th. The 18th bar is not included since it is a holiday
protected virtual int ExpectedBarCount => 2 * 5;
protected int BarCounter = 0;
/// <summary>
/// Purchase a contract when we are not invested, liquidate otherwise
/// </summary>
@@ -30,7 +30,7 @@ namespace QuantConnect.Algorithm.CSharp
{
Liquidate();
}
// Count how many slices we receive with SPX data in it to assert later
if (slice.ContainsKey(Spx))
{
@@ -59,7 +59,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 122;
public override long DataPoints => 121;
/// <summary>
/// Data Points count of the algorithm history
@@ -71,34 +71,34 @@ namespace QuantConnect.Algorithm.CSharp
/// </summary>
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "9"},
{"Total Trades", "8"},
{"Average Win", "0%"},
{"Average Loss", "-39.42%"},
{"Compounding Annual Return", "394.321%"},
{"Drawdown", "0.200%"},
{"Expectancy", "-1"},
{"Net Profit", "8.219%"},
{"Sharpe Ratio", "6.812"},
{"Probabilistic Sharpe Ratio", "91.380%"},
{"Loss Rate", "100%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "617.546%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
{"Net Profit", "8.460%"},
{"Sharpe Ratio", "9.015"},
{"Probabilistic Sharpe Ratio", "93.474%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "2.236"},
{"Beta", "-1.003"},
{"Annual Standard Deviation", "0.317"},
{"Annual Variance", "0.101"},
{"Information Ratio", "5.805"},
{"Tracking Error", "0.359"},
{"Treynor Ratio", "-2.153"},
{"Alpha", "3.218"},
{"Beta", "-1.013"},
{"Annual Standard Deviation", "0.347"},
{"Annual Variance", "0.12"},
{"Information Ratio", "7.709"},
{"Tracking Error", "0.394"},
{"Treynor Ratio", "-3.087"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.027"},
{"Fitness Score", "0.03"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "1776.081"},
{"Portfolio Turnover", "0.027"},
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
{"Portfolio Turnover", "0.03"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -112,7 +112,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "474e8e0e28ee84c869f8c69ec3efe371"}
{"OrderListHash", "dfb226b675ed498ecb67a89483a70da2"}
};
}
}

View File

@@ -8,7 +8,7 @@ namespace QuantConnect.Algorithm.CSharp
public class BasicTemplateIndexHourlyAlgorithm : BasicTemplateIndexDailyAlgorithm
{
protected override Resolution Resolution => Resolution.Hour;
protected override int ExpectedBarCount => base.ExpectedBarCount * 8;
protected override int ExpectedBarCount => base.ExpectedBarCount * 7;
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
@@ -23,7 +23,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 408;
public override long DataPoints => 389;
/// <summary>
/// Data Points count of the algorithm history
@@ -35,34 +35,34 @@ namespace QuantConnect.Algorithm.CSharp
/// </summary>
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "70"},
{"Total Trades", "69"},
{"Average Win", "0%"},
{"Average Loss", "-0.23%"},
{"Compounding Annual Return", "-34.441%"},
{"Average Loss", "-0.06%"},
{"Compounding Annual Return", "-39.390%"},
{"Drawdown", "2.000%"},
{"Expectancy", "-1"},
{"Net Profit", "-2.028%"},
{"Sharpe Ratio", "-11.139"},
{"Net Profit", "-1.998%"},
{"Sharpe Ratio", "-12.504"},
{"Probabilistic Sharpe Ratio", "0.000%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.269"},
{"Beta", "0.086"},
{"Annual Standard Deviation", "0.023"},
{"Alpha", "-0.313"},
{"Beta", "0.088"},
{"Annual Standard Deviation", "0.024"},
{"Annual Variance", "0.001"},
{"Information Ratio", "-3.624"},
{"Tracking Error", "0.094"},
{"Treynor Ratio", "-3.042"},
{"Information Ratio", "-3.871"},
{"Tracking Error", "0.104"},
{"Treynor Ratio", "-3.459"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$310000.00"},
{"Estimated Strategy Capacity", "$200000.00"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.002"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-14.51"},
{"Return Over Maximum Drawdown", "-17.213"},
{"Portfolio Turnover", "0.299"},
{"Sortino Ratio", "-15.488"},
{"Return Over Maximum Drawdown", "-20.691"},
{"Portfolio Turnover", "0.316"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -76,7 +76,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "3eb56c551f20e2ffa1c56c47c5ee6667"}
{"OrderListHash", "cbd2e7697a622b2ce3e24b6003db6f7d"}
};
}
}

View File

@@ -68,7 +68,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 381;
public override long DataPoints => 374;
/// <summary>
/// Data Points count of the algorithm history
@@ -121,7 +121,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "5f5df233d68d9115a0d81785de54e71d"}
{"OrderListHash", "607d309c5fb52a8b88310720b4a867e1"}
};
}
}

View File

@@ -38,7 +38,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 2212;
public override long DataPoints => 2136;
/// <summary>
/// Data Points count of the algorithm history
@@ -91,7 +91,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "f21910eb98ceaa39e02020de95354d86"}
{"OrderListHash", "482414c332d7780590e4a157dff60b85"}
};
}
}

View File

@@ -133,7 +133,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Information Ratio", "0"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$10.00"},
{"Total Fees", "$7.50"},
{"Estimated Strategy Capacity", "$84000.00"},
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
@@ -155,7 +155,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "0673d23c27fa8dd01da0aace0e866cc3"}
{"OrderListHash", "92610619a10e30863020cc84aa30be3b"}
};
}
}

View File

@@ -165,7 +165,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "6a88f302b7f29a2c59e4b1e978161da1"}
{"OrderListHash", "c9e110f2122451dabefcfe24287cadcf"}
};
}
}

View File

@@ -88,7 +88,7 @@ namespace QuantConnect.Algorithm.CSharp
Log(orderEvent.ToString());
// Check for our expected OTM option expiry
if (orderEvent.Message == "OTM")
if (orderEvent.Message.Contains("OTM", StringComparison.InvariantCulture))
{
// Assert it is at midnight (5AM UTC)
if (orderEvent.UtcTime != new DateTime(2016, 1, 16, 5, 0, 0))
@@ -175,7 +175,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "c6d089f1fb86379c74a7413a9c2f8553"}
{"OrderListHash", "0b52bbe98ade8e3aab943e64fcf4abfe"}
};
}
}

View File

@@ -153,7 +153,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "452e7a36e0a95e33d3457a908add3ead"}
{"OrderListHash", "0f8537495f5744c02191656d6b3f9205"}
};
}
}

View File

@@ -192,7 +192,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "50.0482%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "87603bd45898dd9c456745fa51f989a5"}
{"OrderListHash", "83c9fb13ee32284702779eff8d11c608"}
};
}
}

View File

@@ -0,0 +1,164 @@
/*
* 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.
*
*/
using System;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Interfaces;
using QuantConnect.Data.Market;
using System.Collections.Generic;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This example demonstrates how to add and trade SPX index weekly options
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="options" />
/// <meta name="tag" content="indexes" />
public class BasicTemplateSPXWeeklyIndexOptionsAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spxOption;
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 10);
SetCash(1000000);
var spx = AddIndex("SPX").Symbol;
// regular option SPX contracts
var spxOptions = AddIndexOption(spx);
spxOptions.SetFilter(u => u.Strikes(0, 1).Expiration(0, 30));
// weekly option SPX contracts
var spxw = AddIndexOption(spx, "SPXW");
spxw.SetFilter(u => u.Strikes(0, 1)
// single week ahead since there are many SPXW contracts and we want to preserve performance
.Expiration(0, 7)
.IncludeWeeklys());
_spxOption = spxw.Symbol;
}
/// <summary>
/// Index EMA Cross trading underlying.
/// </summary>
public override void OnData(Slice slice)
{
if (Portfolio.Invested)
{
return;
}
OptionChain chain;
if (slice.OptionChains.TryGetValue(_spxOption, out chain))
{
// we find at the money (ATM) put contract with closest expiration
var atmContract = chain
.OrderBy(x => x.Expiry)
.ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
.ThenByDescending(x => x.Right)
.FirstOrDefault();
if (atmContract != null)
{
// if found, buy until it expires
MarketOrder(atmContract.Symbol, 1);
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Debug(orderEvent.ToString());
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public virtual bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public virtual Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 64935;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public virtual int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "5"},
{"Average Win", "0%"},
{"Average Loss", "-0.73%"},
{"Compounding Annual Return", "48.896%"},
{"Drawdown", "0.500%"},
{"Expectancy", "-1"},
{"Net Profit", "0.511%"},
{"Sharpe Ratio", "-12.853"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.582"},
{"Beta", "-0.098"},
{"Annual Standard Deviation", "0.009"},
{"Annual Variance", "0"},
{"Information Ratio", "-95.086"},
{"Tracking Error", "0.076"},
{"Treynor Ratio", "1.206"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$7800000.00"},
{"Lowest Capacity Asset", "SPXW 31K54PVWHUJHQ|SPX 31"},
{"Fitness Score", "0.006"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "64.63"},
{"Return Over Maximum Drawdown", "508.46"},
{"Portfolio Turnover", "0.006"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "cd76a48553cb87074150374d4652fb64"}
};
}
}

View File

@@ -0,0 +1,168 @@
/*
* 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.
*
*/
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Interfaces;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Securities.Option;
using System;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This example demonstrates how to add and trade SPX index weekly option strategy
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="options" />
/// <meta name="tag" content="indexes" />
public class BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spxOption;
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 10);
SetCash(1000000);
var spx = AddIndex("SPX").Symbol;
// weekly option SPX contracts
var spxw = AddIndexOption(spx, "SPXW");
spxw.SetFilter(u => u.Strikes(0, 1)
// single week ahead since there are many SPXW contracts and we want to preserve performance
.Expiration(0, 7)
.IncludeWeeklys());
_spxOption = spxw.Symbol;
}
public override void OnData(Slice slice)
{
if (Portfolio.Invested)
{
return;
}
OptionChain chain;
if (slice.OptionChains.TryGetValue(_spxOption, out chain))
{
// we find the first expiration group of call options and order them in ascending strike
var contracts = chain
.Where(x => x.Right == OptionRight.Call)
.OrderBy(x => x.Expiry)
.GroupBy(x => x.Expiry)
.First()
.OrderBy(x => x.Strike)
.ToList();
if (contracts.Count > 1)
{
var smallerStrike = contracts[0];
var higherStrike = contracts[1];
// if found, buy until it expires
var optionStrategy = OptionStrategies.BearCallSpread(_spxOption, smallerStrike.Strike, higherStrike.Strike, smallerStrike.Expiry);
Buy(optionStrategy, 1);
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Debug(orderEvent.ToString());
if (orderEvent.Symbol.ID.Symbol != "SPXW")
{
throw new Exception("Unexpected order event symbol!");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public virtual bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public virtual Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 35091;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public virtual int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "4"},
{"Average Win", "0.46%"},
{"Average Loss", "0.00%"},
{"Compounding Annual Return", "41.434%"},
{"Drawdown", "0.100%"},
{"Expectancy", "115.281"},
{"Net Profit", "0.445%"},
{"Sharpe Ratio", "7.984"},
{"Probabilistic Sharpe Ratio", "95.977%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "231.56"},
{"Alpha", "0.046"},
{"Beta", "-0.005"},
{"Annual Standard Deviation", "0.001"},
{"Annual Variance", "0"},
{"Information Ratio", "-102.372"},
{"Tracking Error", "0.07"},
{"Treynor Ratio", "-2.467"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$4100000.00"},
{"Lowest Capacity Asset", "SPXW XKX6S2GM9PGU|SPX 31"},
{"Fitness Score", "0.001"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
{"Portfolio Turnover", "0.001"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "3571ecc4b2274878146f15167fcc683c"}
};
}
}

View File

@@ -0,0 +1,112 @@
/*
* 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.
*/
using QuantConnect.Orders;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm to test combo leg limit orders
/// </summary>
public class ComboLegLimitOrderAlgorithm : ComboOrderAlgorithm
{
protected override IEnumerable<OrderTicket> PlaceComboOrder(List<Leg> legs, int quantity, decimal? limitPrice = null)
{
return ComboLegLimitOrder(legs, quantity);
}
public override void OnEndOfAlgorithm()
{
base.OnEndOfAlgorithm();
if (FillOrderEvents.Zip(OrderLegs).Any(x => x.Second.OrderPrice < x.First.FillPrice))
{
throw new Exception($"Limit price expected to be greater that the fill price for each order. Limit prices: {string.Join(",", OrderLegs.Select(x => x.OrderPrice))} Fill prices: {string.Join(",", FillOrderEvents.Select(x => x.FillPrice))}");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public override bool CanRunLocally => true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public override Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 884208;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public override int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$7.50"},
{"Estimated Strategy Capacity", "$8000.00"},
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "c0f4b5d5c796e17949f7ec42c6569ce4"}
};
}
}

View File

@@ -0,0 +1,179 @@
/*
* 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.
*/
using QuantConnect.Orders;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm to test combo limit orders
/// </summary>
public class ComboLimitOrderAlgorithm : ComboOrderAlgorithm
{
private decimal _limitPrice;
private int _comboQuantity;
private int _fillCount;
private decimal _liquidatedQuantity;
private bool _liquidated;
protected override int ExpectedFillCount
{
get
{
// times 2 because of liquidation
return OrderLegs.Count * 2;
}
}
protected override IEnumerable<OrderTicket> PlaceComboOrder(List<Leg> legs, int quantity, decimal? limitPrice)
{
_limitPrice = limitPrice.Value;
_comboQuantity = quantity;
legs.ForEach(x => { x.OrderPrice = null; });
return ComboLimitOrder(legs, quantity, _limitPrice);
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
base.OnOrderEvent(orderEvent);
if (orderEvent.Status == OrderStatus.Filled)
{
_fillCount++;
if (_fillCount == OrderLegs.Count)
{
Liquidate();
}
else if (_fillCount < 2 * OrderLegs.Count)
{
_liquidatedQuantity += orderEvent.FillQuantity;
}
else if (_fillCount == 2 * OrderLegs.Count)
{
_liquidated = true;
var totalComboQuantity = _comboQuantity * OrderLegs.Select(x => x.Quantity).Sum();
if (_liquidatedQuantity != totalComboQuantity)
{
throw new Exception($"Liquidated quantity {_liquidatedQuantity} does not match combo quantity {totalComboQuantity}");
}
if (Portfolio.TotalHoldingsValue != 0)
{
throw new Exception($"Portfolio value {Portfolio.TotalPortfolioValue} is not zero");
}
}
}
}
public override void OnEndOfAlgorithm()
{
base.OnEndOfAlgorithm();
if (_limitPrice == null)
{
throw new Exception("Limit price was not set");
}
var fillPricesSum = FillOrderEvents.Take(OrderLegs.Count).Select(x => x.FillPrice * x.FillQuantity / _comboQuantity).Sum();
if (_limitPrice < fillPricesSum)
{
throw new Exception($"Limit price expected to be greater that the sum of the fill prices ({fillPricesSum}), but was {_limitPrice}");
}
if (!_liquidated)
{
throw new Exception("Combo order was not liquidated");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public override bool CanRunLocally => true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public override Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 884208;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public override int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "6"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$17.50"},
{"Estimated Strategy Capacity", "$5000.00"},
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "17a5427a539f2b02a626fda15d6eb13f"}
};
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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.
*/
using QuantConnect.Orders;
using System.Collections.Generic;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm to test combo market orders
/// </summary>
public class ComboMarketOrderAlgorithm : ComboOrderAlgorithm
{
protected override IEnumerable<OrderTicket> PlaceComboOrder(List<Leg> legs, int quantity, decimal? limitPrice = null)
{
legs.ForEach(x => { x.OrderPrice = null; });
return ComboMarketOrder(legs, quantity);
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public override bool CanRunLocally => true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public override Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 884208;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public override int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$7.50"},
{"Estimated Strategy Capacity", "$9000.00"},
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "47f02f5139c4c4def9b26e8f5433fdcc"}
};
}
}

View File

@@ -0,0 +1,139 @@
/*
* 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.
*/
using System;
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Orders;
using QuantConnect.Interfaces;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm asserting that combo orders are filled correctly and at the same time
/// </summary>
public abstract class ComboOrderAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _optionSymbol;
protected List<OrderEvent> FillOrderEvents { get; private set; } = new();
protected List<Leg> OrderLegs { get; private set; }
protected int ComboOrderQuantity { get; } = 10;
protected virtual int ExpectedFillCount
{
get
{
return OrderLegs.Count;
}
}
public override void Initialize()
{
SetStartDate(2015, 12, 24);
SetEndDate(2015, 12, 24);
SetCash(10000);
var equity = AddEquity("GOOG", leverage: 4, fillDataForward: true);
var option = AddOption(equity.Symbol, fillDataForward: true);
_optionSymbol = option.Symbol;
option.SetFilter(u => u.Strikes(-2, +2)
.Expiration(0, 180));
}
public override void OnData(Slice slice)
{
if (OrderLegs == null)
{
OptionChain chain;
if (IsMarketOpen(_optionSymbol) && slice.OptionChains.TryGetValue(_optionSymbol, out chain))
{
var callContracts = chain.Where(contract => contract.Right == OptionRight.Call)
.GroupBy(x => x.Expiry)
.OrderBy(grouping => grouping.Key)
.First()
.OrderBy(x => x.Strike)
.ToList();
// Let's wait until we have at least three contracts
if (callContracts.Count < 3)
{
return;
}
OrderLegs = new List<Leg>()
{
Leg.Create(callContracts[0].Symbol, 1, 16.7m),
Leg.Create(callContracts[1].Symbol, -2, 14.6m),
Leg.Create(callContracts[2].Symbol, 1, 14.0m)
};
PlaceComboOrder(OrderLegs, ComboOrderQuantity, 1.9m);
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Debug($" Order Event: {orderEvent}");
if (orderEvent.Status == OrderStatus.Filled)
{
FillOrderEvents.Add(orderEvent);
}
}
public override void OnEndOfAlgorithm()
{
if (OrderLegs == null)
{
throw new Exception("Combo order legs were not initialized");
}
if (FillOrderEvents.Count != ExpectedFillCount)
{
throw new Exception($"Expected {ExpectedFillCount} fill order events, found {FillOrderEvents.Count}");
}
var fillTimes = FillOrderEvents.Select(x => x.UtcTime).ToHashSet();
if (fillTimes.Count != 1)
{
throw new Exception($"Expected all fill order events to have the same time, found {string.Join(", ", fillTimes)}");
}
if (FillOrderEvents.Zip(OrderLegs).Any(x => x.First.FillQuantity != x.Second.Quantity * ComboOrderQuantity))
{
throw new Exception("Fill quantity does not match expected quantity for at least one order leg");
}
}
protected abstract IEnumerable<OrderTicket> PlaceComboOrder(List<Leg> legs, int quantity, decimal? limitPrice = null);
public abstract bool CanRunLocally { get; }
public abstract Language[] Languages { get; }
public abstract long DataPoints { get; }
public abstract int AlgorithmHistoryDataPoints { get; }
public abstract Dictionary<string, string> ExpectedStatistics { get; }
}
}

View File

@@ -0,0 +1,375 @@
/*
* 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.
*/
using System;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using System.Linq;
using QuantConnect.Data.Market;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Algorithm for testing submit/update/cancel for combo orders
/// </summary>
public class ComboOrderTicketDemoAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private readonly List<OrderTicket> _openMarketOrders = new();
private readonly List<OrderTicket> _openLegLimitOrders = new();
private readonly List<OrderTicket> _openLimitOrders = new();
private Symbol _optionSymbol;
private List<Leg> _orderLegs;
/// </summary>
public override void Initialize()
{
SetStartDate(2015, 12, 24);
SetEndDate(2015, 12, 24);
SetCash(100000);
var equity = AddEquity("GOOG", leverage: 4, fillDataForward: true);
var option = AddOption(equity.Symbol, fillDataForward: true);
_optionSymbol = option.Symbol;
option.SetFilter(u => u.Strikes(-2, +2)
.Expiration(0, 180));
}
public override void OnData(Slice data)
{
if (_orderLegs == null)
{
OptionChain chain;
if (IsMarketOpen(_optionSymbol) && data.OptionChains.TryGetValue(_optionSymbol, out chain))
{
var callContracts = chain.Where(contract => contract.Right == OptionRight.Call)
.GroupBy(x => x.Expiry)
.OrderBy(grouping => grouping.Key)
.First()
.OrderBy(x => x.Strike)
.ToList();
// Let's wait until we have at least three contracts
if (callContracts.Count < 3)
{
return;
}
_orderLegs = new List<Leg>()
{
Leg.Create(callContracts[0].Symbol, 1),
Leg.Create(callContracts[1].Symbol, -2),
Leg.Create(callContracts[2].Symbol, 1),
};
}
}
else
{
// COMBO MARKET ORDERS
ComboMarketOrders();
// COMBO LIMIT ORDERS
ComboLimitOrders();
// COMBO LEG LIMIT ORDERS
ComboLegLimitOrders();
}
}
private void ComboMarketOrders()
{
if (_openMarketOrders.Count != 0 || _orderLegs == null)
{
return;
}
Log("Submitting combo market orders");
var tickets = ComboMarketOrder(_orderLegs, 2, asynchronous: false);
_openMarketOrders.AddRange(tickets);
tickets = ComboMarketOrder(_orderLegs, 2, asynchronous: true);
_openMarketOrders.AddRange(tickets);
foreach (var ticket in tickets)
{
var response = ticket.Cancel("Attempt to cancel combo market order");
if (response.IsSuccess)
{
throw new Exception("Combo market orders should fill instantly, they should not be cancelable in backtest mode: " + response.OrderId);
}
}
}
private void ComboLimitOrders()
{
if (_openLimitOrders.Count == 0)
{
Log("Submitting ComboLimitOrder");
var currentPrice = _orderLegs.Sum(leg => leg.Quantity * Securities[leg.Symbol].Close);
var tickets = ComboLimitOrder(_orderLegs, 2, currentPrice - 2m);
_openLimitOrders.AddRange(tickets);
// These won't fill, we will test cancel with this
tickets = ComboLimitOrder(_orderLegs, -2, currentPrice + 3m);
_openLimitOrders.AddRange(tickets);
}
else
{
var combo1 = _openLimitOrders.Take(_orderLegs.Count).ToList();
var combo2 = _openLimitOrders.Skip(_orderLegs.Count).Take(_orderLegs.Count).ToList();
// check if either is filled and cancel the other
if (CheckGroupOrdersForFills(combo1, combo2))
{
return;
}
// if neither order has filled, bring in the limits by a penny
var ticket = combo1[0];
var newLimit = Math.Round(ticket.Get(OrderField.LimitPrice) + 0.01m, 2);
Debug($"Updating limits - Combo 1 {ticket.OrderId}: {newLimit.ToStringInvariant("0.00")}");
ticket.Update(new UpdateOrderFields
{
LimitPrice = newLimit,
Tag = "Update #" + (ticket.UpdateRequests.Count + 1)
});
ticket = combo2[0];
newLimit = Math.Round(ticket.Get(OrderField.LimitPrice) - 0.01m, 2);
Debug($"Updating limits - Combo 2 {ticket.OrderId}: {newLimit.ToStringInvariant("0.00")}");
ticket.Update(new UpdateOrderFields
{
LimitPrice = newLimit,
Tag = "Update #" + (ticket.UpdateRequests.Count + 1)
});
}
}
private void ComboLegLimitOrders()
{
if (_openLegLimitOrders.Count == 0)
{
Log("Submitting ComboLegLimitOrder");
// submit a limit order to buy 2 shares at .1% below the bar's close
foreach (var leg in _orderLegs)
{
var close = Securities[leg.Symbol].Close;
leg.OrderPrice = close * .999m;
}
var tickets = ComboLegLimitOrder(_orderLegs, quantity: 2);
_openLegLimitOrders.AddRange(tickets);
// submit another limit order to sell 2 shares at .1% above the bar's close
foreach (var leg in _orderLegs)
{
var close = Securities[leg.Symbol].Close;
leg.OrderPrice = close * 1.001m;
}
tickets = ComboLegLimitOrder(_orderLegs, -2);
_openLegLimitOrders.AddRange(tickets);
}
else
{
var combo1 = _openLegLimitOrders.Take(_orderLegs.Count).ToList();
var combo2 = _openLegLimitOrders.Skip(_orderLegs.Count).Take(_orderLegs.Count).ToList();
// check if either is filled and cancel the other
if (CheckGroupOrdersForFills(combo1, combo2))
{
return;
}
// if neither order has filled, bring in the limits by a penny
foreach (var ticket in combo1)
{
var newLimit = ticket.Get(OrderField.LimitPrice) + (ticket.Quantity > 0 ? 1m : -1m) * 0.01m;
Debug($"Updating limits - Combo #1: {newLimit.ToStringInvariant("0.00")}");
ticket.Update(new UpdateOrderFields
{
LimitPrice = newLimit,
Tag = "Update #" + (ticket.UpdateRequests.Count + 1)
});
}
foreach (var ticket in combo2)
{
var newLimit = ticket.Get(OrderField.LimitPrice) + (ticket.Quantity > 0 ? 1m : -1m) * 0.01m;
Debug($"Updating limits - Combo #2: {newLimit.ToStringInvariant("0.00")}");
ticket.Update(new UpdateOrderFields
{
LimitPrice = newLimit,
Tag = "Update #" + (ticket.UpdateRequests.Count + 1)
});
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
var order = Transactions.GetOrderById(orderEvent.OrderId);
if (orderEvent.Quantity == 0)
{
throw new Exception("OrderEvent quantity is Not expected to be 0, it should hold the current order Quantity");
}
if (orderEvent.Quantity != order.Quantity)
{
throw new Exception("OrderEvent quantity should hold the current order Quantity");
}
if (order is ComboLegLimitOrder && orderEvent.LimitPrice == 0)
{
throw new Exception("OrderEvent.LimitPrice is not expected to be 0 for ComboLegLimitOrder");
}
}
private bool CheckGroupOrdersForFills(List<OrderTicket> combo1, List<OrderTicket> combo2)
{
if (combo1.All(x => x.Status == OrderStatus.Filled))
{
if (combo2.Any(x => x.Status.IsOpen()))
{
Log(combo1[0].OrderType + ": Canceling combo #2, combo #1 is filled.");
combo2.ForEach(x => x.Cancel("Combo #1 filled."));
}
return true;
}
if (combo2.All(x => x.Status == OrderStatus.Filled))
{
if (combo1.Any(x => x.Status.IsOpen()))
{
Log(combo1[0].OrderType + ": Canceling combo #1, combo #2 is filled.");
combo1.ForEach(x => x.Cancel("Combo #2 filled."));
}
return true;
}
return false;
}
public override void OnEndOfAlgorithm()
{
var filledOrders = Transactions.GetOrders(x => x.Status == OrderStatus.Filled).ToList();
var orderTickets = Transactions.GetOrderTickets().ToList();
var openOrders = Transactions.GetOpenOrders();
var openOrderTickets = Transactions.GetOpenOrderTickets().ToList();
var remainingOpenOrders = Transactions.GetOpenOrdersRemainingQuantity();
// We expect 3 of the limit orders to be canceled
var expectedOrdersCount = 18;
var expectedFillsCount = 15;
if (filledOrders.Count != expectedFillsCount || orderTickets.Count != expectedOrdersCount)
{
throw new Exception($"There were expected {expectedFillsCount} filled orders and {expectedOrdersCount} order tickets, but there were {filledOrders.Count} filled orders and {orderTickets.Count} order tickets");
}
if (openOrders.Count != 0 || openOrderTickets.Count != 0)
{
throw new Exception($"No open orders or tickets were expected");
}
if (remainingOpenOrders != 0m)
{
throw new Exception($"No remaining quantity to be filled from open orders was expected");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 884208;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "15"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$15.00"},
{"Estimated Strategy Capacity", "$8000.00"},
{"Lowest Capacity Asset", "GOOCV W78ZERHAOVVQ|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "06328fbd9bbb25d9ec80b9151a7ceb7b"}
};
}
}

View File

@@ -30,7 +30,9 @@ namespace QuantConnect.Algorithm.CSharp
/// </summary>
public class ConsolidateRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private List<int> _consolidationCount;
private List<int> _consolidationCounts;
private List<SimpleMovingAverage> _smas;
private List<DateTime> _lastSmaUpdates;
private int _customDataConsolidator;
private Symbol _symbol;
@@ -40,38 +42,37 @@ namespace QuantConnect.Algorithm.CSharp
public override void Initialize()
{
SetStartDate(2013, 10, 08);
SetEndDate(2013, 10, 11);
SetEndDate(2013, 10, 20);
var SP500 = QuantConnect.Symbol.Create(Futures.Indices.SP500EMini, SecurityType.Future, Market.CME);
_symbol = FutureChainProvider.GetFutureContractList(SP500, StartDate).First();
AddFutureContract(_symbol);
_consolidationCount = new List<int> { 0, 0, 0, 0, 0, 0, 0, 0 };
_consolidationCounts = Enumerable.Repeat(0, 9).ToList();
_smas = _consolidationCounts.Select(_ => new SimpleMovingAverage(10)).ToList();
_lastSmaUpdates = _consolidationCounts.Select(_ => DateTime.MinValue).ToList();
var sma = new SimpleMovingAverage(10);
Consolidate<QuoteBar>(_symbol, time => new CalendarInfo(time.RoundDown(TimeSpan.FromDays(1)), TimeSpan.FromDays(1)),
bar => UpdateQuoteBar(sma, bar, 0));
bar => UpdateQuoteBar(bar, 0));
var sma2 = new SimpleMovingAverage(10);
Consolidate<QuoteBar>(_symbol, TimeSpan.FromDays(1), bar => UpdateQuoteBar(sma2, bar, 1));
Consolidate<QuoteBar>(_symbol, time => new CalendarInfo(time.RoundDown(TimeSpan.FromDays(1)), TimeSpan.FromDays(1)),
TickType.Quote, bar => UpdateQuoteBar(bar, 1));
var sma3 = new SimpleMovingAverage(10);
Consolidate(_symbol, Resolution.Daily, TickType.Quote, (Action<QuoteBar>)(bar => UpdateQuoteBar(sma3, bar, 2)));
Consolidate<QuoteBar>(_symbol, TimeSpan.FromDays(1), bar => UpdateQuoteBar(bar, 2));
var sma4 = new SimpleMovingAverage(10);
Consolidate(_symbol, TimeSpan.FromDays(1), bar => UpdateTradeBar(sma4, bar, 3));
Consolidate(_symbol, Resolution.Daily, TickType.Quote, (Action<QuoteBar>)(bar => UpdateQuoteBar(bar, 3)));
var sma5 = new SimpleMovingAverage(10);
Consolidate<TradeBar>(_symbol, TimeSpan.FromDays(1), bar => UpdateTradeBar(sma5, bar, 4));
Consolidate(_symbol, TimeSpan.FromDays(1), bar => UpdateTradeBar(bar, 4));
Consolidate<TradeBar>(_symbol, TimeSpan.FromDays(1), bar => UpdateTradeBar(bar, 5));
// custom data
var sma6 = new SimpleMovingAverage(10);
var symbol = AddData<CustomDataRegressionAlgorithm.Bitcoin>("BTC", Resolution.Minute).Symbol;
Consolidate<TradeBar>(symbol, TimeSpan.FromDays(1), bar => _customDataConsolidator++);
try
{
Consolidate<QuoteBar>(symbol, TimeSpan.FromDays(1), bar => { UpdateQuoteBar(sma6, bar, -1); });
Consolidate<QuoteBar>(symbol, TimeSpan.FromDays(1), bar => { UpdateQuoteBar(bar, -1); });
throw new Exception($"Expected {nameof(ArgumentException)} to be thrown");
}
catch (ArgumentException)
@@ -80,41 +81,56 @@ namespace QuantConnect.Algorithm.CSharp
}
// Test using abstract T types, through defining a 'BaseData' handler
var sma7 = new SimpleMovingAverage(10);
Consolidate(_symbol, Resolution.Daily, null, (Action<BaseData>)(bar => UpdateBar(sma7, bar, 5)));
Consolidate(_symbol, Resolution.Daily, null, (Action<BaseData>)(bar => UpdateBar(bar, 6)));
var sma8 = new SimpleMovingAverage(10);
Consolidate(_symbol, TimeSpan.FromDays(1), null, (Action<BaseData>)(bar => UpdateBar(sma8, bar, 6)));
Consolidate(_symbol, TimeSpan.FromDays(1), null, (Action<BaseData>)(bar => UpdateBar(bar, 7)));
var sma9 = new SimpleMovingAverage(10);
Consolidate(_symbol, TimeSpan.FromDays(1), (Action<BaseData>)(bar => UpdateBar(sma9, bar, 7)));
Consolidate(_symbol, TimeSpan.FromDays(1), (Action<BaseData>)(bar => UpdateBar(bar, 8)));
}
private void UpdateBar(SimpleMovingAverage sma, BaseData tradeBar, int position)
private void UpdateBar(BaseData tradeBar, int position)
{
if (!(tradeBar is TradeBar))
{
throw new Exception("Expected a TradeBar");
}
_consolidationCount[position]++;
sma.Update(tradeBar.EndTime, tradeBar.Value);
_consolidationCounts[position]++;
_smas[position].Update(tradeBar.EndTime, tradeBar.Value);
_lastSmaUpdates[position] = tradeBar.EndTime;
}
private void UpdateTradeBar(SimpleMovingAverage sma, TradeBar tradeBar, int position)
private void UpdateTradeBar(TradeBar tradeBar, int position)
{
_consolidationCount[position]++;
sma.Update(tradeBar.EndTime, tradeBar.High);
_consolidationCounts[position]++;
_smas[position].Update(tradeBar.EndTime, tradeBar.High);
_lastSmaUpdates[position] = tradeBar.EndTime;
}
private void UpdateQuoteBar(SimpleMovingAverage sma, QuoteBar quoteBar, int position)
private void UpdateQuoteBar(QuoteBar quoteBar, int position)
{
_consolidationCount[position]++;
sma.Update(quoteBar.EndTime, quoteBar.High);
_consolidationCounts[position]++;
_smas[position].Update(quoteBar.EndTime, quoteBar.High);
_lastSmaUpdates[position] = quoteBar.EndTime;
}
public override void OnEndOfAlgorithm()
{
if (_consolidationCount.Any(i => i != 3) || _customDataConsolidator == 0)
var expectedConsolidations = 8;
if (_consolidationCounts.Any(i => i != expectedConsolidations) || _customDataConsolidator == 0)
{
throw new Exception("Unexpected consolidation count");
}
for (var i = 0; i < _smas.Count; i++)
{
if (_smas[i].Samples != expectedConsolidations)
{
throw new Exception($"Expected {expectedConsolidations} samples in each SMA but found {_smas[i].Samples} in SMA in index {i}");
}
if (_smas[i].Current.Time != _lastSmaUpdates[i])
{
throw new Exception($"Expected SMA in index {i} to have been last updated at {_lastSmaUpdates[i]} but was {_smas[i].Current.Time}");
}
}
}
/// <summary>
@@ -142,7 +158,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 5450;
public long DataPoints => 12244;
/// <summary>
/// Data Points count of the algorithm history
@@ -157,31 +173,31 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "1"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "87589624.963%"},
{"Compounding Annual Return", "6636.699%"},
{"Drawdown", "15.900%"},
{"Expectancy", "0"},
{"Net Profit", "16.178%"},
{"Sharpe Ratio", "43229388091.465"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Sharpe Ratio", "640.32"},
{"Probabilistic Sharpe Ratio", "99.824%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "69177566862.121"},
{"Beta", "8.93"},
{"Annual Standard Deviation", "1.6"},
{"Annual Variance", "2.561"},
{"Information Ratio", "48583550955.512"},
{"Tracking Error", "1.424"},
{"Treynor Ratio", "7746445590.006"},
{"Alpha", "636.128"},
{"Beta", "5.924"},
{"Annual Standard Deviation", "1.012"},
{"Annual Variance", "1.024"},
{"Information Ratio", "696.123"},
{"Tracking Error", "0.928"},
{"Treynor Ratio", "109.405"},
{"Total Fees", "$23.65"},
{"Estimated Strategy Capacity", "$210000000.00"},
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
{"Fitness Score", "0.999"},
{"Fitness Score", "0.811"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "6752050.52"},
{"Portfolio Turnover", "2.638"},
{"Return Over Maximum Drawdown", "511.605"},
{"Portfolio Turnover", "0.811"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},

View File

@@ -134,7 +134,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 264153;
public long DataPoints => 689388;
/// <summary>
/// Data Points count of the algorithm history
@@ -172,7 +172,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.275"},
{"Return Over Maximum Drawdown", "2.603"},
{"Return Over Maximum Drawdown", "2.606"},
{"Portfolio Turnover", "0.01"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -150,7 +150,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 284403;
public long DataPoints => 709638;
/// <summary>
/// Data Points count of the algorithm history
@@ -188,7 +188,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.32"},
{"Return Over Maximum Drawdown", "2.573"},
{"Return Over Maximum Drawdown", "2.576"},
{"Portfolio Turnover", "0.016"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -115,8 +115,8 @@ namespace QuantConnect.Algorithm.CSharp
{"Fitness Score", "0.028"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.662"},
{"Return Over Maximum Drawdown", "-18.253"},
{"Sortino Ratio", "-1.666"},
{"Return Over Maximum Drawdown", "-18.301"},
{"Portfolio Turnover", "0.206"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -169,7 +169,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 284403;
public long DataPoints => 709638;
/// <summary>
/// Data Points count of the algorithm history
@@ -207,7 +207,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.32"},
{"Return Over Maximum Drawdown", "2.573"},
{"Return Over Maximum Drawdown", "2.576"},
{"Portfolio Turnover", "0.016"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -0,0 +1,168 @@
/*
* 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.
*/
using System;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Securities;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Securities.Future;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Continuous Futures Regression algorithm asserting bug fix for GH issue #6840
/// </summary>
public class ContinuousFuturesDailyRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private SymbolChangedEvent _symbolChangedEvent;
private Future _continuousContract;
private decimal _previousFactor;
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
SetStartDate(2013, 10, 08);
SetEndDate(2013, 12, 25);
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.ForwardPanamaCanal,
dataMappingMode: DataMappingMode.LastTradingDay,
contractDepthOffset: 0,
resolution: Resolution.Daily
);
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
public override void OnData(Slice data)
{
foreach (var changedEvent in data.SymbolChangedEvents.Values)
{
if (changedEvent.Symbol == _continuousContract.Symbol)
{
_symbolChangedEvent = changedEvent;
Log($"{Time} - SymbolChanged event: {changedEvent}. New expiration {_continuousContract.Mapped.ID.Date}");
}
}
if (!data.Bars.TryGetValue(_continuousContract.Symbol, out var continuousBar))
{
return;
}
var mappedBar = Securities[_continuousContract.Mapped].Cache.GetData<TradeBar>();
if (mappedBar == null || continuousBar.EndTime != mappedBar.EndTime)
{
return;
}
var priceFactor = continuousBar.Close - mappedBar.Close;
Debug($"{Time} - Price factor {priceFactor}");
if(_symbolChangedEvent != null)
{
if(_previousFactor == priceFactor)
{
throw new Exception($"Price factor did not change after symbol changed! {Time} {priceFactor}");
}
Quit("We asserted what we wanted");
}
_previousFactor = priceFactor;
}
public override void OnEndOfAlgorithm()
{
if (_symbolChangedEvent == null)
{
throw new Exception("Unexpected a symbol changed event but got none!");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 1395;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"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", "-4.63"},
{"Tracking Error", "0.088"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", ""},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
};
}
}

View File

@@ -0,0 +1,156 @@
/*
* 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.
*/
using System;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Interfaces;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Algorithm asserting that consolidated bars are of type <see cref="QuoteBar"/>
/// when <see cref="QCAlgorithm.Consolidate()"/> is called with <see cref="TickType.Quote"/>
/// </summary>
public class CorrectConsolidatedBarTypeForTickTypesAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private bool _quoteTickConsolidatorCalled;
private bool _tradeTickConsolidatorCalled;
private bool _openInterestTickConsolidatorCalled;
public override void Initialize()
{
SetStartDate(2013, 10, 7);
SetEndDate(2013, 10, 7);
var symbol = AddEquity("SPY", Resolution.Tick).Symbol;
Consolidate<QuoteBar>(symbol, TimeSpan.FromMinutes(1), TickType.Quote, QuoteTickConsolidationHandler);
Consolidate<TradeBar>(symbol, TimeSpan.FromMinutes(1), TickType.Trade, TradeTickConsolidationHandler);
Consolidate<TradeBar>(symbol, TimeSpan.FromMinutes(1), TickType.OpenInterest, OpenInterestTickConsolidationHandler);
}
public override void OnData(Slice slice)
{
if (Time.Hour > 9)
{
Quit("Early quit to save time");
}
}
public override void OnEndOfAlgorithm()
{
if (!_quoteTickConsolidatorCalled)
{
throw new Exception("QuoteTickConsolidationHandler was not called");
}
if (!_tradeTickConsolidatorCalled)
{
throw new Exception("TradeTickConsolidationHandler was not called");
}
if (!_openInterestTickConsolidatorCalled)
{
throw new Exception("OpenInterestTickConsolidationHandler was not called");
}
}
private void QuoteTickConsolidationHandler(QuoteBar consolidatedBar)
{
_quoteTickConsolidatorCalled = true;
}
private void TradeTickConsolidationHandler(TradeBar consolidatedBar)
{
_tradeTickConsolidatorCalled = true;
}
private void OpenInterestTickConsolidationHandler(TradeBar consolidatedBar)
{
_openInterestTickConsolidatorCalled = true;
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 393736;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", ""},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
};
}
}

View File

@@ -0,0 +1,165 @@
/*
* 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.
*
*/
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Interfaces;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using System;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm tarding an equity Covered Call option strategy using a combo limit order
/// </summary>
public class CoveredCallComboLimitOrderAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private DateTime _submittionTime;
private Symbol _optionSymbol;
public override void Initialize()
{
SetStartDate(2015, 12, 24);
SetEndDate(2015, 12, 24);
SetCash(200000);
var equity = AddEquity("GOOG", leverage: 4);
var option = AddOption(equity.Symbol);
_optionSymbol = option.Symbol;
option.SetFilter(u => u.Strikes(-1, +1).Expiration(0, 30));
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="slice">Slice object keyed by symbol containing the stock data</param>
public override void OnData(Slice slice)
{
if (!Portfolio.Invested && Transactions.OrdersCount == 0)
{
OptionChain chain;
if (IsMarketOpen(_optionSymbol) && slice.OptionChains.TryGetValue(_optionSymbol, out chain))
{
// we find at the money (ATM) call contract with closest expiration
var atmContract = chain
.OrderBy(x => x.Expiry)
.Where(contract => contract.Right == OptionRight.Call && chain.Underlying.Price > contract.Strike - 10)
.OrderBy(x => x.Strike)
.First();
var optionPrice = Securities[atmContract.Symbol].AskPrice;
var underlyingPrice = Securities["GOOG"].AskPrice;
// covered call
var legs = new List<Leg> { Leg.Create(atmContract.Symbol, -1), Leg.Create(atmContract.Symbol.Underlying, 100) };
var comboPrice = underlyingPrice - optionPrice;
if(comboPrice < 734m)
{
// just to make sure the price makes sense
throw new Exception($"Unexpected combo price {comboPrice}");
}
// place order slightly bellow price
ComboLimitOrder(legs, 6, comboPrice - 0.5m);
_submittionTime = Time;
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Debug(orderEvent.ToString());
if (orderEvent.Status.IsFill() && (Time - _submittionTime) < TimeSpan.FromMinutes(10))
{
// we want to make sure we fill because the price moved and hit our limit price
throw new Exception($"Unexpected fill time {Time} submittion time {_submittionTime}");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally => true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 864200;
/// </summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$8000.00"},
{"Lowest Capacity Asset", "GOOCV W78ZFMEBBB2E|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "addfbee330e5b80a186acf3c2d776982"}
};
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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.
*/
using System.Collections.Generic;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Daily regression algorithm trading ADAUSDT binance futures long and short asserting the behavior
/// </summary>
public class CryptoFutureDailyMarginInterestRegressionAlgorithm : CryptoFutureHourlyMarginInterestRegressionAlgorithm
{
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
Initialize(Resolution.Daily);
}
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 8;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public override Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "1"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.15"},
{"Estimated Strategy Capacity", "$3400000000.00"},
{"Lowest Capacity Asset", "ADAUSDT 18R"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "1287.681"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "2000bf26738e407192574b27086338a6"}
};
}
}

View File

@@ -0,0 +1,186 @@
/*
* 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.
*/
using System;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Interfaces;
using QuantConnect.Brokerages;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Securities.CryptoFuture;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Daily regression algorithm trading ADAUSDT binance futures long and short asserting the behavior
/// </summary>
public class CryptoFutureHourlyMarginInterestRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Dictionary<Symbol, int> _interestPerSymbol = new();
private decimal _amountAfterTrade;
protected CryptoFuture AdaUsdt;
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
Initialize(Resolution.Hour);
}
protected virtual void Initialize(Resolution resolution)
{
SetStartDate(2022, 12, 12);
SetEndDate(2022, 12, 13);
SetTimeZone(NodaTime.DateTimeZone.Utc);
SetBrokerageModel(BrokerageName.BinanceCoinFutures, AccountType.Margin);
AdaUsdt = AddCryptoFuture("ADAUSDT", resolution);
// Default USD cash, set 1M but it wont be used
SetCash(1000000);
// the amount of USDT we need to hold to trade 'ADAUSDT'
AdaUsdt.QuoteCurrency.SetAmount(200);
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
public override void OnData(Slice data)
{
var interestRates = data.Get<MarginInterestRate>();
foreach (var interestRate in interestRates)
{
_interestPerSymbol.TryGetValue(interestRate.Key, out var count);
_interestPerSymbol[interestRate.Key] = ++count;
var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();
if (cachedInterestRate != interestRate.Value)
{
throw new Exception($"Unexpected cached margin interest rate for {interestRate.Key}!");
}
}
if(interestRates.Count != data.MarginInterestRates.Count)
{
throw new Exception($"Unexpected cached margin interest rate data!");
}
if (Portfolio.Invested)
{
return;
}
Buy(AdaUsdt.Symbol, 1000);
_amountAfterTrade = Portfolio.CashBook["USDT"].Amount;
}
public override void OnEndOfAlgorithm()
{
if (!_interestPerSymbol.TryGetValue(AdaUsdt.Symbol, out var count) || count != 1)
{
throw new Exception($"Unexpected interest rate count {count}");
}
// negative because we are long. Rate * Value * Application Count
var expectedFundingRateDifference = - (0.0001m * AdaUsdt.Holdings.HoldingsValue * 3);
var finalCash = Portfolio.CashBook["USDT"].Amount;
if (Math.Abs(finalCash - (_amountAfterTrade + expectedFundingRateDifference)) > Math.Abs(expectedFundingRateDifference * 0.05m))
{
throw new Exception($"Unexpected interest rate count {Portfolio.CashBook["USDT"].Amount}");
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Debug(Time + " " + orderEvent);
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 50;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "1"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.15"},
{"Estimated Strategy Capacity", "$330000000.00"},
{"Lowest Capacity Asset", "ADAUSDT 18R"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "bc23ede7bb4af4d941723ed225768fcb"}
};
}
}

View File

@@ -0,0 +1,175 @@
/*
* 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.
*/
using QuantConnect.Interfaces;
using QuantConnect.Securities;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
using System;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Demonstration of using custom margin interest rate model in backtesting.
/// </summary>
/// <meta name="tag" content="custom margin interest rate models" />
public class CustomMarginInterestRateModelAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spy;
private decimal _cashAfterOrder;
public override void Initialize()
{
SetStartDate(2013, 10, 01);
SetEndDate(2013, 10, 31);
var security = AddEquity("SPY", Resolution.Hour);
_spy = security.Symbol;
// set the margin interest rate model
security.SetMarginInterestRateModel(new CustomMarginInterestRateModel());
}
public override void OnData(Slice slice)
{
if (!Portfolio.Invested)
{
SetHoldings(_spy, 1);
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status == OrderStatus.Filled)
{
_cashAfterOrder = Portfolio.Cash;
}
}
public override void OnEndOfAlgorithm()
{
var security = Securities[_spy];
var marginInterestRateModel = security.MarginInterestRateModel as CustomMarginInterestRateModel;
if (marginInterestRateModel == null)
{
throw new Exception("CustomMarginInterestRateModel was not set");
}
if (marginInterestRateModel.CallCount == 0)
{
throw new Exception("CustomMarginInterestRateModel was not called");
}
var expectedCash = _cashAfterOrder * (decimal)Math.Pow(1 + (double)marginInterestRateModel.InterestRate, marginInterestRateModel.CallCount);
// add a tolerance since using Math.Pow(double, double) given the lack of a decimal overload
if (Math.Abs(Portfolio.Cash - expectedCash) > 1e-10m)
{
throw new Exception($"Expected cash {expectedCash} but got {Portfolio.Cash}");
}
}
public class CustomMarginInterestRateModel : IMarginInterestRateModel
{
public decimal InterestRate { get; } = 0.01m;
public int CallCount { get; private set; }
public void ApplyMarginInterestRate(MarginInterestRateParameters parameters)
{
var security = parameters.Security;
var positionValue = security.Holdings.GetQuantityValue(security.Holdings.Quantity);
if (positionValue.Amount > 0)
{
positionValue.Cash.AddAmount(InterestRate * positionValue.Cash.Amount);
CallCount++;
}
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 330;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "1"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "93.409%"},
{"Drawdown", "2.400%"},
{"Expectancy", "0"},
{"Net Profit", "5.699%"},
{"Sharpe Ratio", "4.771"},
{"Probabilistic Sharpe Ratio", "85.653%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.145"},
{"Beta", "0.998"},
{"Annual Standard Deviation", "0.108"},
{"Annual Variance", "0.012"},
{"Information Ratio", "28.436"},
{"Tracking Error", "0.005"},
{"Treynor Ratio", "0.514"},
{"Total Fees", "$3.43"},
{"Estimated Strategy Capacity", "$150000000.00"},
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
{"Fitness Score", "0.045"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "14.855"},
{"Return Over Maximum Drawdown", "63.683"},
{"Portfolio Turnover", "0.045"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "701d5dfbbd5ffd8b60a76d61f15bae17"}
};
}
}

View File

@@ -0,0 +1,121 @@
/*
* 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.
*
*/
using System;
using System.Linq;
using QuantConnect.Interfaces;
using QuantConnect.Securities;
using System.Collections.Generic;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm reproducing GH issue #6829 where the default future chain selection would let some contracts through
/// </summary>
public class DefaultFutureChainRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2013, 10, 08);
SetEndDate(2013, 12, 10);
AddFuture(Futures.Metals.Gold);
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
foreach (var addedSecurity in changes.AddedSecurities.Where(added => !added.Symbol.IsCanonical()))
{
// With no future chain filters specified, it should return no contracts in security changes event.
// The canonical continuous future will get mapped and emit symbol changed events, while it's current mapped security is an internal feed
throw new Exception($"We expect no non canonical security to be added: {addedSecurity.Symbol}");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 473924;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"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", "-5.145"},
{"Tracking Error", "0.083"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", ""},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
};
}
}

View File

@@ -0,0 +1,123 @@
/*
* 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.
*
*/
using QuantConnect.Data;
using QuantConnect.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm which tests the default option price model
/// </summary>
/// <meta name="tag" content="options" />
public class DefaultOptionPriceModelRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 4);
SetCash(100000);
AddIndex("SPX");
AddIndexOption("SPX");
}
public override void OnData(Slice slice)
{
if (slice.OptionChains.Any(kvp => kvp.Value.Any(
contract => contract.Greeks.Delta == 0 &&
contract.Greeks.Gamma == 0 &&
contract.Greeks.Theta == 0 &&
contract.Greeks.Vega == 0 &&
contract.Greeks.Rho == 0)))
{
throw new Exception("All Greeks are zero - Pricing Model is not ready!");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 7008;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", ""},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
};
}
}

View File

@@ -28,7 +28,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 1450;
public override long DataPoints => 1850;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm

View File

@@ -92,7 +92,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 398985;
public virtual long DataPoints => 517960;
/// <summary>
/// Data Points count of the algorithm history
@@ -130,7 +130,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "5.652"},
{"Return Over Maximum Drawdown", "5.667"},
{"Portfolio Turnover", "0.023"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -123,7 +123,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 17600;
public long DataPoints => 16800;
/// <summary>
/// Data Points count of the algorithm history
@@ -138,31 +138,31 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-26.40%"},
{"Compounding Annual Return", "-99.821%"},
{"Compounding Annual Return", "-99.822%"},
{"Drawdown", "45.600%"},
{"Expectancy", "-1"},
{"Net Profit", "-26.400%"},
{"Sharpe Ratio", "-0.602"},
{"Probabilistic Sharpe Ratio", "19.127%"},
{"Sharpe Ratio", "-0.632"},
{"Probabilistic Sharpe Ratio", "17.057%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.559"},
{"Beta", "-0.807"},
{"Annual Standard Deviation", "1.582"},
{"Annual Variance", "2.502"},
{"Information Ratio", "-0.905"},
{"Tracking Error", "1.593"},
{"Treynor Ratio", "1.181"},
{"Alpha", "-0.692"},
{"Beta", "-0.545"},
{"Annual Standard Deviation", "1.515"},
{"Annual Variance", "2.296"},
{"Information Ratio", "-0.949"},
{"Tracking Error", "1.524"},
{"Treynor Ratio", "1.76"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$1000000.00"},
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
{"Fitness Score", "0.005"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.249"},
{"Return Over Maximum Drawdown", "-2.699"},
{"Portfolio Turnover", "0.016"},
{"Sortino Ratio", "-0.256"},
{"Return Over Maximum Drawdown", "-2.773"},
{"Portfolio Turnover", "0.017"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -176,7 +176,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "721fddfd1327f7adcc2883d1412708c9"}
{"OrderListHash", "97b069699024898ba02d73e0d9b5c92e"}
};
}
}

View File

@@ -29,7 +29,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 13223;
public override long DataPoints => 13676;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
@@ -56,13 +56,13 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.107"},
{"Treynor Ratio", "1.338"},
{"Total Fees", "$19.76"},
{"Estimated Strategy Capacity", "$2300000.00"},
{"Estimated Strategy Capacity", "$2400000.00"},
{"Lowest Capacity Asset", "DC V5E8PHPRCHJ8|DC V5E8P9SH0U0X"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.126"},
{"Return Over Maximum Drawdown", "-0.995"},
{"Return Over Maximum Drawdown", "-0.997"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -77,7 +77,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "2152bd1d4f1770068595a4c3bc8585ee"}
{"OrderListHash", "19ecd0218cb70c5d7fefcb5741a7d82b"}
};
}
}

View File

@@ -107,7 +107,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>0
public virtual long DataPoints => 5117455;
public virtual long DataPoints => 4900229;
/// <summary>
/// Data Points count of the algorithm history
@@ -160,7 +160,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d10e8665214344369e3e8f1c49dbdd67"}
{"OrderListHash", "b3674f70c87c91669dc25170e43e6af8"}
};
}
}

View File

@@ -0,0 +1,162 @@
/*
* 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.
*/
using QuantConnect.Data.Market;
using QuantConnect.Interfaces;
using System;
using System.Collections.Generic;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Demonstration of payments for cash dividends in backtesting. When data normalization mode is set
/// to "Raw" the dividends are paid as cash directly into your portfolio.
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="data event handlers" />
/// <meta name="tag" content="dividend event" />
public class DividendRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private decimal _sumOfDividends;
private Symbol _symbol;
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
SetStartDate(1998, 01, 01); //Set Start Date
SetEndDate(2006, 01, 01); //Set End Date
SetCash(100000); //Set Strategy Cash
// Find more symbols here: http://quantconnect.com/data
_symbol = AddEquity("SPY", Resolution.Daily,
dataNormalizationMode: DataNormalizationMode.Raw).Symbol;
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="data">TradeBars IDictionary object with your stock data</param>
public void OnData(TradeBars data)
{
if (Portfolio.Invested) return;
SetHoldings(_symbol, .5);
}
/// <summary>
/// Raises the data event.
/// </summary>
/// <param name="data">Data.</param>
public void OnData(Dividends data) // update this to Dividends dictionary
{
var dividend = data[_symbol];
var holdings = Portfolio[_symbol];
Debug($"{dividend.Time.ToStringInvariant("o")} >> DIVIDEND >> {dividend.Symbol} - " +
$"{dividend.Distribution.ToStringInvariant("C")} - {Portfolio.Cash} - " +
$"{holdings.Price.ToStringInvariant("C")}"
);
_sumOfDividends += dividend.Distribution * holdings.Quantity;
}
public override void OnEndOfAlgorithm()
{
// The expected value refers to sum of dividend payments
if (Portfolio.TotalProfit != _sumOfDividends)
{
throw new Exception($"Total Profit: Expected {_sumOfDividends}. Actual {Portfolio.TotalProfit}");
}
var expectNetProfit = _sumOfDividends - Portfolio.TotalFees;
if (Portfolio.TotalNetProfit != expectNetProfit)
{
throw new Exception($"Total Net Profit: Expected {expectNetProfit}. Actual {Portfolio.TotalNetProfit}");
}
if (Portfolio[_symbol].TotalDividends != _sumOfDividends)
{
throw new Exception($"{_symbol} Total Dividends: Expected {_sumOfDividends}. Actual {Portfolio[_symbol].TotalDividends}");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 16077;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new()
{
{ "Total Trades", "1" },
{ "Average Win", "0%" },
{ "Average Loss", "0%" },
{ "Compounding Annual Return", "2.354%" },
{ "Drawdown", "28.200%" },
{ "Expectancy", "0" },
{ "Net Profit", "20.462%" },
{ "Sharpe Ratio", "0.238" },
{ "Probabilistic Sharpe Ratio", "0.462%" },
{ "Loss Rate", "0%" },
{ "Win Rate", "0%" },
{ "Profit-Loss Ratio", "0" },
{ "Alpha", "-0.004" },
{ "Beta", "0.521" },
{ "Annual Standard Deviation", "0.083" },
{ "Annual Variance", "0.007" },
{ "Information Ratio", "-0.328" },
{ "Tracking Error", "0.076" },
{ "Treynor Ratio", "0.038" },
{ "Total Fees", "$2.56" },
{ "Estimated Strategy Capacity", "$24000000.00" },
{ "Lowest Capacity Asset", "SPY R735QTJ8XC9X" },
{ "Fitness Score", "0" },
{ "Kelly Criterion Estimate", "0" },
{ "Kelly Criterion Probability Value", "0" },
{ "Sortino Ratio", "0.355" },
{ "Return Over Maximum Drawdown", "0.083" },
{ "Portfolio Turnover", "0" },
{ "Total Insights Generated", "0" },
{ "Total Insights Closed", "0" },
{ "Total Insights Analysis Completed", "0" },
{ "Long Insight Count", "0" },
{ "Short Insight Count", "0" },
{ "Long/Short Ratio", "100%" },
{ "Estimated Monthly Alpha Value", "$0" },
{ "Total Accumulated Estimated Alpha Value", "$0" },
{ "Mean Population Estimated Insight Value", "$0" },
{ "Mean Population Direction", "0%" },
{ "Mean Population Magnitude", "0%" },
{ "Rolling Averaged Population Direction", "0%" },
{ "Rolling Averaged Population Magnitude", "0%" },
{ "OrderListHash", "e60d1af5917a9a4d7b41197ce665b296" }
};
}
}

View File

@@ -168,7 +168,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Kelly Criterion Estimate", "-24.978"},
{"Kelly Criterion Probability Value", "0.773"},
{"Sortino Ratio", "-0.966"},
{"Return Over Maximum Drawdown", "-5.15"},
{"Return Over Maximum Drawdown", "-5.151"},
{"Portfolio Turnover", "5.36"},
{"Total Insights Generated", "10"},
{"Total Insights Closed", "8"},

View File

@@ -0,0 +1,191 @@
/*
* 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.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm asserting that European options cannot be exercised before expiry
/// </summary>
public class EuropeanOptionsCannotBeExercisedBeforeExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Option _option;
private OptionContract _contract;
private bool _marketOrderDone;
private bool _exerciseBeforeExpiryDone;
private bool _exerciseOnExpiryDone;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 2, 1);
SetCash(200000);
var index = AddIndex("SPX", Resolution.Hour, fillDataForward: true);
var indexOption = AddIndexOption(index.Symbol, Resolution.Hour, fillDataForward: true);
indexOption.SetFilter(filterFunc => filterFunc);
_option = indexOption;
}
public override void OnData(Slice slice)
{
if ((_exerciseBeforeExpiryDone && _exerciseOnExpiryDone) || !_option.Exchange.ExchangeOpen)
{
return;
}
if (_contract == null)
{
OptionChain contracts;
if (!slice.OptionChains.TryGetValue(_option.Symbol, out contracts) || !contracts.Any())
{
return;
}
_contract = contracts.First();
}
var expiry = _contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone).Date;
if (!_exerciseBeforeExpiryDone && UtcTime.Date < expiry)
{
if (!_marketOrderDone)
{
if (MarketOrder(_contract.Symbol, 1).Status != OrderStatus.Filled)
{
throw new Exception("Expected market order to fill immediately");
}
_marketOrderDone = true;
}
if (ExerciseOption(_contract.Symbol, 1).Status == OrderStatus.Filled)
{
throw new Exception($"Expected European option to not be exercisable before its expiration date. " +
$"Time: {UtcTime}. Expiry: {_contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone)}");
}
_exerciseBeforeExpiryDone = true;
return;
}
if (!_exerciseOnExpiryDone && UtcTime.Date == expiry)
{
if (ExerciseOption(_contract.Symbol, 1).Status != OrderStatus.Filled)
{
throw new Exception($"Expected European option to be exercisable on its expiration date. " +
$"Time: {UtcTime}. Expiry: {_contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone)}");
}
_exerciseOnExpiryDone = true;
// We already tested everything, so we can stop the algorithm
Quit();
}
}
public override void OnEndOfAlgorithm()
{
if (!_exerciseBeforeExpiryDone || !_exerciseOnExpiryDone)
{
throw new Exception("Expected to try to exercise option before and on expiry");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all time slices of algorithm
/// </summary>
public long DataPoints => 1819;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-4.10%"},
{"Compounding Annual Return", "25.461%"},
{"Drawdown", "1.900%"},
{"Expectancy", "-1"},
{"Net Profit", "0.712%"},
{"Sharpe Ratio", "5.904"},
{"Probabilistic Sharpe Ratio", "90.591%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.967"},
{"Beta", "-0.359"},
{"Annual Standard Deviation", "0.123"},
{"Annual Variance", "0.015"},
{"Information Ratio", "0.289"},
{"Tracking Error", "0.176"},
{"Treynor Ratio", "-2.02"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$1700000.00"},
{"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
{"Fitness Score", "0.004"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "20.506"},
{"Portfolio Turnover", "0.004"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "f2313ed7c4a80765c7ac7bb421bf0e19"}
};
}
}

View File

@@ -85,7 +85,7 @@ namespace QuantConnect.Algorithm.CSharp
public override void OnEndOfAlgorithm()
{
if (!_afterMarketOpenQueue.Any() || !_beforeMarketCloseQueue.Any())
if (_afterMarketOpenQueue.Any() || _beforeMarketCloseQueue.Any())
{
throw new Exception($"_afterMarketOpenQueue and _beforeMarketCloseQueue should be empty");
}
@@ -100,7 +100,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 7;
public virtual long DataPoints => 27067;
/// </summary>
/// Data Points count of the algorithm history

View File

@@ -52,7 +52,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 7;
public override long DataPoints => 82827;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm

View File

@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 29802;
public virtual long DataPoints => 32062;
/// </summary>
/// Data Points count of the algorithm history

View File

@@ -52,7 +52,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public override long DataPoints => 95102;
public override long DataPoints => 103812;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm

View File

@@ -165,7 +165,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "6ae724ba0dbcbd1ca49dcfcdf94e0319"}
{"OrderListHash", "2c6f94edc9eb94b4a52998e8fac83f63"}
};
}
}

View File

@@ -253,7 +253,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "02b16807a77a858047996f15597ff145"}
{"OrderListHash", "f49b2e88c45554d43b6a36382aa946af"}
};
}
}

View File

@@ -218,7 +218,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "c1c4c793696f75c528527334563ae8df"}
{"OrderListHash", "3169abd2fe120400ab2da9daa6a51bc7"}
};
}
}

View File

@@ -229,7 +229,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "29bb2f59fa2ee3dab8ed2aecf6544189"}
{"OrderListHash", "61fc923519bea2059d8094378386ea42"}
};
}
}

View File

@@ -109,7 +109,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 24376;
public long DataPoints => 59677;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -254,7 +254,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "621491b86f9d0e1a6abf4a882f73a38b"}
{"OrderListHash", "d73af39b216690b0877d01ad4e4a654c"}
};
}
}

View File

@@ -227,7 +227,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "05dcd0b935d8206ca42ffc325fec4302"}
{"OrderListHash", "bea65dc6fb976b0fac2a239310734d91"}
};
}
}

View File

@@ -238,7 +238,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "bf5fe7396dd65efe92326817647d2350"}
{"OrderListHash", "abe6d3a5ce8cf541d4791cd606f8fb38"}
};
}
}

View File

@@ -221,7 +221,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "5c9cb56b3d08ac28a51d146ef6be7669"}
{"OrderListHash", "c22c968523508c5d3dc724e7a8ead3e9"}
};
}
}

View File

@@ -235,7 +235,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "cdf689416d6e6e04739cbaa7fb2f8b80"}
{"OrderListHash", "74ac36f88002d539a07b4270fb000d3a"}
};
}
}

View File

@@ -220,7 +220,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "5895d7c6447d4b1487e4705bc32b50a6"}
{"OrderListHash", "dcb6f577ec6dd3a732d8fd31279cb703"}
};
}
}

View File

@@ -117,8 +117,8 @@ namespace QuantConnect.Algorithm.CSharp
{"Fitness Score", "0.007"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-10.333"},
{"Return Over Maximum Drawdown", "-53.15"},
{"Sortino Ratio", "-10.433"},
{"Return Over Maximum Drawdown", "-53.661"},
{"Portfolio Turnover", "0.665"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},

View File

@@ -231,7 +231,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "271484857fd3dbf4e4a332485bcfa773"}
{"OrderListHash", "e36d25e5bf671a594ec4178c5cb2877d"}
};
}
}

View File

@@ -89,7 +89,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 136444;
public long DataPoints => 266369;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -129,7 +129,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 1187;
public long DataPoints => 1602;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -101,7 +101,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 1187;
public long DataPoints => 1602;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -93,7 +93,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 1246;
public long DataPoints => 1661;
/// <summary>
/// Data Points count of the algorithm history

View File

@@ -0,0 +1,69 @@
/*
* 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.
*/
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionBearCallSpreadAlgorithm : QCAlgorithm
{
private Symbol _vixw, _spy;
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
public override void Initialize()
{
SetStartDate(2020, 1, 1);
SetEndDate(2021, 1, 1);
SetCash(100000);
_spy = AddEquity("SPY", Resolution.Minute).Symbol;
var index = AddIndex("VIX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "VIXW", Resolution.Minute);
option.SetFilter((x) => x.Strikes(-5, 5).Expiration(15, 45));
_vixw = option.Symbol;
}
public override void OnData(Slice slice)
{
if (!Portfolio[_spy].Invested)
{
MarketOrder(_spy, 100);
}
// Return if hedge position presents
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_vixw, out var chain)) return;
// Get the nearest expiry date of the contracts
var expiry = chain.Min(x => x.Expiry);
// Select the call Option contracts with the nearest expiry and sort by strike price
var calls = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Call)
.OrderBy(x => x.Strike).ToArray();
if (calls.Length < 2) return;
// Buy the bear call spread
var bearCallSpread = OptionStrategies.BearCallSpread(_vixw, calls[0].Strike, calls[^1].Strike, expiry);
_tickets = Buy(bearCallSpread, 1);
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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.
*/
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionBearPutSpreadAlgorithm : QCAlgorithm
{
private Symbol _spxw;
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
public override void Initialize()
{
SetStartDate(2022, 1, 1);
SetEndDate(2022, 7, 1);
SetCash(100000);
var index = AddIndex("SPX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
option.SetFilter((x) => x.WeeklysOnly().Strikes(5, 10).Expiration(0, 0));
_spxw = option.Symbol;
}
public override void OnData(Slice slice)
{
// Return if open position exists
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
// Get the nearest expiry date of the contracts
var expiry = chain.Min(x => x.Expiry);
// Select the put Option contracts with the nearest expiry and sort by strike price
var puts = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Put)
.OrderBy(x => x.Strike).ToArray();
if (puts.Length < 2) return;
// Buy the bear put spread
var optionStrategy = OptionStrategies.BearPutSpread(_spxw, puts[^1].Strike, puts[0].Strike, expiry);
_tickets = Buy(optionStrategy, 1);
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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.
*/
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionBullCallSpreadAlgorithm : QCAlgorithm
{
private Symbol _spxw, _spy;
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
public override void Initialize()
{
SetStartDate(2020, 1, 1);
SetEndDate(2021, 1, 1);
SetCash(100000);
_spy = AddEquity("SPY", Resolution.Minute).Symbol;
var index = AddIndex("SPX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
option.SetFilter((x) => x.WeeklysOnly().Strikes(-5, 5).Expiration(40, 60));
_spxw = option.Symbol;
}
public override void OnData(Slice slice)
{
if (!Portfolio[_spy].Invested)
{
MarketOrder(_spy, 100);
}
// Return if hedge position presents
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
// Get the nearest expiry date of the contracts
var expiry = chain.Min(x => x.Expiry);
// Select the call Option contracts with the nearest expiry and sort by strike price
var calls = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Call)
.OrderBy(x => x.Strike).ToArray();
if (calls.Length < 2) return;
// Buy the bull call spread
var bullCallSpread = OptionStrategies.BullCallSpread(_spxw, calls[0].Strike, calls[^1].Strike, expiry);
_tickets = Buy(bullCallSpread, 1);
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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.
*/
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionBullPutSpreadAlgorithm : QCAlgorithm
{
private Symbol _spxw;
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
public override void Initialize()
{
SetStartDate(2019, 1, 1);
SetEndDate(2020, 1, 1);
SetCash(100000);
var index = AddIndex("SPX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
option.SetFilter((x) => x.WeeklysOnly().Strikes(-10, -5).Expiration(0, 0));
_spxw = option.Symbol;
}
public override void OnData(Slice slice)
{
// Return if open position exists
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
// Get the nearest expiry date of the contracts
var expiry = chain.Min(x => x.Expiry);
// Select the put Option contracts with the nearest expiry and sort by strike price
var puts = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Put)
.OrderBy(x => x.Strike).ToArray();
if (puts.Length < 2) return;
// Buy the bull put spread
var bullCallSpread = OptionStrategies.BullPutSpread(_spxw, puts[^1].Strike, puts[0].Strike, expiry);
_tickets = Buy(bullCallSpread, 1);
}
}
}

View File

@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 32708;
public long DataPoints => 31618;
/// <summary>
/// Data Points count of the algorithm history
@@ -133,31 +133,31 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "4"},
{"Average Win", "0%"},
{"Average Loss", "-0.06%"},
{"Compounding Annual Return", "-1.552%"},
{"Compounding Annual Return", "-1.693%"},
{"Drawdown", "0.100%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.110%"},
{"Sharpe Ratio", "-3.157"},
{"Net Profit", "-0.120%"},
{"Sharpe Ratio", "-3.156"},
{"Probabilistic Sharpe Ratio", "0.427%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.011"},
{"Alpha", "-0.012"},
{"Beta", "-0.004"},
{"Annual Standard Deviation", "0.003"},
{"Annual Standard Deviation", "0.004"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.405"},
{"Tracking Error", "0.138"},
{"Treynor Ratio", "2.704"},
{"Information Ratio", "-0.412"},
{"Tracking Error", "0.139"},
{"Treynor Ratio", "2.702"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-4619.237"},
{"Return Over Maximum Drawdown", "-14.266"},
{"Portfolio Turnover", "0.005"},
{"Sortino Ratio", "-4231.264"},
{"Return Over Maximum Drawdown", "-14.257"},
{"Portfolio Turnover", "0.006"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -171,7 +171,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "7d15f56731d38768ea81afac627f0657"}
{"OrderListHash", "a82af2f9ea9f06b920dbbc64c345dce4"}
};
}
}

View File

@@ -0,0 +1,88 @@
/*
* 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.
*/
using System;
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionCallButterflyAlgorithm : QCAlgorithm
{
private Symbol _spxw, _vxz;
private decimal _multiplier;
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
public override void Initialize()
{
SetStartDate(2020, 1, 1);
SetEndDate(2021, 1, 1);
SetCash(1000000);
_vxz = AddEquity("VXZ", Resolution.Minute).Symbol;
var index = AddIndex("SPX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
option.SetFilter((x) => x.IncludeWeeklys().Strikes(-3, 3).Expiration(15, 45));
_spxw = option.Symbol;
_multiplier = option.SymbolProperties.ContractMultiplier;
}
public override void OnData(Slice slice)
{
// The order of magnitude per SPXW order's value is 10000 times of VXZ
if (!Portfolio[_vxz].Invested)
{
MarketOrder(_vxz, 10000);
}
// Return if any opening index option position
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
// Get nearest expiry date
var expiry = chain.Min(x => x.Expiry);
// Select the call Option contracts with nearest expiry and sort by strike price
var calls = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Call).ToList();
if (calls.Count < 3) return;
var sortedCallStrikes = calls.Select(x => x.Strike).OrderBy(x => x).ToArray();
// Select ATM call
var atmStrike = calls.MinBy(x => Math.Abs(x.Strike - chain.Underlying.Value)).Strike;
// Get the strike prices for the ITM & OTM contracts, make sure they're in equidistance
var spread = Math.Min(atmStrike - sortedCallStrikes[0], sortedCallStrikes[^1] - atmStrike);
var itmStrike = atmStrike - spread;
var otmStrike = atmStrike + spread;
if (!sortedCallStrikes.Contains(otmStrike) || !sortedCallStrikes.Contains(itmStrike)) return;
// Buy the call butterfly
var callButterfly = OptionStrategies.CallButterfly(_spxw, otmStrike, atmStrike, itmStrike, expiry);
var price = callButterfly.UnderlyingLegs.Sum(x => Math.Abs(Securities[x.Symbol].Price * x.Quantity) * _multiplier);
if (price > 0)
{
var quantity = Portfolio.TotalPortfolioValue / price;
_tickets = Buy(callButterfly, (int)Math.Floor(quantity), asynchronous: true);
}
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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.
*/
using System;
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionCallCalendarSpreadAlgorithm : QCAlgorithm
{
private Symbol _vixw, _vxz, _spy;
private decimal _multiplier;
private List<Leg> _legs = new();
private DateTime _firstExpiry = DateTime.MaxValue;
public override void Initialize()
{
SetStartDate(2020, 1, 1);
SetEndDate(2021, 1, 1);
SetCash(50000);
_vxz = AddEquity("VXZ", Resolution.Minute).Symbol;
_spy = AddEquity("SPY", Resolution.Minute).Symbol;
var index = AddIndex("VIX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "VIXW", Resolution.Minute);
option.SetFilter((x) => x.Strikes(-2, 2).Expiration(15, 45));
_vixw = option.Symbol;
_multiplier = option.SymbolProperties.ContractMultiplier;
}
public override void OnData(Slice slice)
{
// Liquidate if the shorter term option is about to expire
if (_firstExpiry < Time.AddDays(2) && _legs.All(x => slice.ContainsKey(x.Symbol)))
{
Liquidate();
}
// Return if there is any opening position
else if (_legs.Any(x => Portfolio[x.Symbol].Invested))
{
return;
}
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_vixw, out var chain)) return;
// Get ATM strike price
var strike = chain.MinBy(x => Math.Abs(x.Strike - chain.Underlying.Value)).Strike;
// Select the ATM call Option contracts and sort by expiration date
var calls = chain.Where(x => x.Strike == strike && x.Right == OptionRight.Call)
.OrderBy(x => x.Expiry).ToArray();
if (calls.Length < 2) return;
_firstExpiry = calls[0].Expiry;
// Create combo order legs
_legs = new List<Leg>
{
Leg.Create(calls[0].Symbol, -1),
Leg.Create(calls[^1].Symbol, 1),
Leg.Create(_vxz, -100),
Leg.Create(_spy, -10)
};
var quantity = Portfolio.TotalPortfolioValue / _legs.Sum(x =>
{
var value = Math.Abs(Securities[x.Symbol].Price * x.Quantity);
return x.Symbol.ID.SecurityType == SecurityType.IndexOption
? value * _multiplier
: value;
});
ComboMarketOrder(_legs, -(int)Math.Floor(quantity), asynchronous: true);
}
}
}

View File

@@ -180,7 +180,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 20443;
public long DataPoints => 19503;
/// <summary>
/// Data Points count of the algorithm history
@@ -194,32 +194,32 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-49.28%"},
{"Compounding Annual Return", "301.490%"},
{"Average Loss", "-49.72%"},
{"Compounding Annual Return", "283.040%"},
{"Drawdown", "2.300%"},
{"Expectancy", "-1"},
{"Net Profit", "10.274%"},
{"Sharpe Ratio", "5.298"},
{"Probabilistic Sharpe Ratio", "88.621%"},
{"Net Profit", "9.904%"},
{"Sharpe Ratio", "4.871"},
{"Probabilistic Sharpe Ratio", "84.534%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "1.836"},
{"Beta", "-0.228"},
{"Annual Standard Deviation", "0.345"},
{"Annual Variance", "0.119"},
{"Information Ratio", "4.653"},
{"Tracking Error", "0.383"},
{"Treynor Ratio", "-8.001"},
{"Alpha", "1.754"},
{"Beta", "-0.237"},
{"Annual Standard Deviation", "0.358"},
{"Annual Variance", "0.128"},
{"Information Ratio", "4.298"},
{"Tracking Error", "0.395"},
{"Treynor Ratio", "-7.363"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.024"},
{"Fitness Score", "0.026"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "649.537"},
{"Return Over Maximum Drawdown", "1130.655"},
{"Portfolio Turnover", "0.024"},
{"Sortino Ratio", "43.148"},
{"Return Over Maximum Drawdown", "329.485"},
{"Portfolio Turnover", "0.026"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -233,7 +233,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "25cc4301125ffaa12dd8d8f4387adf06"}
{"OrderListHash", "f8b186afc142a2c7d42a43f2589d0a74"}
};
}
}

View File

@@ -13,16 +13,13 @@
* limitations under the License.
*/
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Securities;
using QuantConnect.Securities.Option;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Volatility;
namespace QuantConnect.Algorithm.CSharp
{
@@ -90,6 +87,7 @@ namespace QuantConnect.Algorithm.CSharp
var lambda = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Lambda).ToList();
var rho = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Rho).ToList();
var theta = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Theta).ToList();
var impliedVol = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.ImpliedVolatility).ToList();
var vega = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Vega).ToList();
// The commented out test cases all return zero.
@@ -116,9 +114,8 @@ namespace QuantConnect.Algorithm.CSharp
{
throw new AggregateException("Option contract Theta was equal to zero");
}
// The strike is far away from the underlying asset's price, and we're very close to expiry.
// Zero is an expected value here.
if (vega.Any(v => v != 0))
// Vega will equal 0 if the quote price and IV are way too off, causing the price is not sensitive to volatility change
if (vega.Zip(impliedVol, (v, iv) => (v, iv)).Any(x => x.v == 0 && x.iv < 10))
{
throw new AggregateException("Option contract Vega was equal to zero");
}
@@ -159,7 +156,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 20443;
public long DataPoints => 19503;
/// <summary>
/// Data Points count of the algorithm history
@@ -174,31 +171,31 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-56.91%"},
{"Compounding Annual Return", "44.906%"},
{"Compounding Annual Return", "46.347%"},
{"Drawdown", "9.800%"},
{"Expectancy", "-1"},
{"Net Profit", "2.644%"},
{"Sharpe Ratio", "5.789"},
{"Probabilistic Sharpe Ratio", "89.964%"},
{"Net Profit", "2.714%"},
{"Sharpe Ratio", "5.348"},
{"Probabilistic Sharpe Ratio", "86.253%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "2.169"},
{"Beta", "-0.238"},
{"Annual Standard Deviation", "0.373"},
{"Annual Variance", "0.139"},
{"Information Ratio", "5.17"},
{"Tracking Error", "0.409"},
{"Treynor Ratio", "-9.071"},
{"Alpha", "2.071"},
{"Beta", "-0.244"},
{"Annual Standard Deviation", "0.385"},
{"Annual Variance", "0.148"},
{"Information Ratio", "4.794"},
{"Tracking Error", "0.42"},
{"Treynor Ratio", "-8.443"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$44000000.00"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.023"},
{"Fitness Score", "0.025"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.535"},
{"Return Over Maximum Drawdown", "5.789"},
{"Portfolio Turnover", "0.03"},
{"Sortino Ratio", "0.64"},
{"Return Over Maximum Drawdown", "6.283"},
{"Portfolio Turnover", "0.032"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -212,7 +209,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "bd96db56c80107572e8fc13c8794279b"}
{"OrderListHash", "36bf137108b5b6dcdf2a408b252cb03a"}
};
}
}

View File

@@ -170,7 +170,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 16486;
public long DataPoints => 15596;
/// <summary>
/// Data Points count of the algorithm history
@@ -184,31 +184,31 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-0.01%"},
{"Compounding Annual Return", "-0.142%"},
{"Average Loss", "-0.02%"},
{"Compounding Annual Return", "-0.213%"},
{"Drawdown", "0.000%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.010%"},
{"Sharpe Ratio", "-4.584"},
{"Net Profit", "-0.015%"},
{"Sharpe Ratio", "-4.329"},
{"Probabilistic Sharpe Ratio", "0.015%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.001"},
{"Alpha", "-0.002"},
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.334"},
{"Information Ratio", "-0.338"},
{"Tracking Error", "0.138"},
{"Treynor Ratio", "-9.47"},
{"Treynor Ratio", "-7.266"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$22000.00"},
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-51177.748"},
{"Return Over Maximum Drawdown", "-14.362"},
{"Sortino Ratio", "-3.837"},
{"Return Over Maximum Drawdown", "-14.357"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -223,7 +223,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "e971949fb0d1cc8d034ad7cba97d09cc"}
{"OrderListHash", "75e3d7129bde6f02001043217f283b40"}
};
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.
*/
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Indicators;
using QuantConnect.Orders;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionIronCondorAlgorithm : QCAlgorithm
{
private Symbol _spxw;
private BollingerBands _bb;
public override void Initialize()
{
SetStartDate(2019, 9, 1);
SetEndDate(2019, 11, 1);
SetCash(100000);
var index = AddIndex("SPX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
option.SetFilter((x) => x.WeeklysOnly().Strikes(-5, 5).Expiration(0, 14));
_spxw = option.Symbol;
_bb = BB(index, 10, 2, resolution: Resolution.Daily);
WarmUpIndicator(index, _bb);
}
public override void OnData(Slice slice)
{
if (Portfolio.Invested) return;
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
// Get the closest expiry date
var expiry = chain.Min(x => x.Expiry);
var contracts = chain.Where(x => x.Expiry == expiry).ToList();
// Separate the call and put contracts and sort by Strike to find OTM contracts
var calls = contracts.Where(x => x.Right == OptionRight.Call)
.OrderByDescending(x => x.Strike).ToArray();
var puts = contracts.Where(x => x.Right == OptionRight.Put)
.OrderBy(x => x.Strike).ToArray();
if (calls.Length < 3 || puts.Length < 3) return;
// Create combo order legs
var price = _bb.Price.Current.Value;
var quantity = 1;
if (price > _bb.UpperBand.Current.Value || price < _bb.LowerBand.Current.Value)
{
quantity = -1;
}
var legs = new List<Leg>
{
Leg.Create(calls[0].Symbol, quantity),
Leg.Create(puts[0].Symbol, quantity),
Leg.Create(calls[2].Symbol, -quantity),
Leg.Create(puts[2].Symbol, -quantity),
};
ComboMarketOrder(legs, 10, asynchronous: true);
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* 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.
*/
using System;
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionPutButterflyAlgorithm : QCAlgorithm
{
private Symbol _spxw, _vxz;
private decimal _multiplier;
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
public override void Initialize()
{
SetStartDate(2020, 1, 1);
SetEndDate(2021, 1, 1);
SetCash(1000000);
_vxz = AddEquity("VXZ", Resolution.Minute).Symbol;
var index = AddIndex("SPX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "SPXW", Resolution.Minute);
option.SetFilter((x) => x.IncludeWeeklys().Strikes(-3, 3).Expiration(15, 45));
_spxw = option.Symbol;
_multiplier = option.SymbolProperties.ContractMultiplier;
}
public override void OnData(Slice slice)
{
// The order of magnitude per SPXW order's value is 10000 times of VXZ
if (!Portfolio[_vxz].Invested)
{
MarketOrder(_vxz, 10000);
}
// Return if any opening index option position
if (_tickets.Any(x => Portfolio[x.Symbol].Invested)) return;
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_spxw, out var chain)) return;
// Get nearest expiry date
var expiry = chain.Min(x => x.Expiry);
// Select the put Option contracts with nearest expiry and sort by strike price
var puts = chain.Where(x => x.Expiry == expiry && x.Right == OptionRight.Put).ToList();
if (puts.Count < 3) return;
var sortedPutStrikes = puts.Select(x => x.Strike).OrderBy(x => x).ToArray();
// Select ATM put
var atmStrike = puts.MinBy(x => Math.Abs(x.Strike - chain.Underlying.Value)).Strike;
// Get the strike prices for the ITM & OTM contracts, make sure they're in equidistance
var spread = Math.Min(atmStrike - sortedPutStrikes[0], sortedPutStrikes[^1] - atmStrike);
var otmStrike = atmStrike - spread;
var itmStrike = atmStrike + spread;
if (!sortedPutStrikes.Contains(otmStrike) || !sortedPutStrikes.Contains(itmStrike)) return;
// Buy the put butterfly
var putButterfly = OptionStrategies.PutButterfly(_spxw, itmStrike, atmStrike, otmStrike, expiry);
var price = putButterfly.UnderlyingLegs.Sum(x => Math.Abs(Securities[x.Symbol].Price * x.Quantity) * _multiplier);
if (price > 0)
{
var quantity = Portfolio.TotalPortfolioValue / price;
_tickets = Buy(putButterfly, (int)Math.Floor(quantity), asynchronous: true);
}
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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.
*/
using System;
using System.Linq;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
public class IndexOptionPutCalendarSpreadAlgorithm : QCAlgorithm
{
private Symbol _vixw, _vxz;
private IEnumerable<OrderTicket> _tickets = Enumerable.Empty<OrderTicket>();
private DateTime _firstExpiry = DateTime.MaxValue;
public override void Initialize()
{
SetStartDate(2020, 1, 1);
SetEndDate(2023, 1, 1);
SetCash(50000);
_vxz = AddEquity("VXZ", Resolution.Minute).Symbol;
var index = AddIndex("VIX", Resolution.Minute).Symbol;
var option = AddIndexOption(index, "VIXW", Resolution.Minute);
option.SetFilter((x) => x.Strikes(-2, 2).Expiration(15, 45));
_vixw = option.Symbol;
}
public override void OnData(Slice slice)
{
if (!Portfolio[_vxz].Invested)
{
MarketOrder(_vxz, 100);
}
var indexOptionsInvested = _tickets.Where(x => Portfolio[x.Symbol].Invested).ToList();
// Liquidate if the shorter term option is about to expire
if (_firstExpiry < Time.AddDays(2) && _tickets.All(x => slice.ContainsKey(x.Symbol)))
{
foreach (var holding in indexOptionsInvested)
{
Liquidate(holding.Symbol);
}
}
// Return if there is any opening index option position
else if (indexOptionsInvested.Count > 0)
{
return;
}
// Get the OptionChain
if (!slice.OptionChains.TryGetValue(_vixw, out var chain)) return;
// Get ATM strike price
var strike = chain.MinBy(x => Math.Abs(x.Strike - chain.Underlying.Value)).Strike;
// Select the ATM put Option contracts and sort by expiration date
var puts = chain.Where(x => x.Strike == strike && x.Right == OptionRight.Put)
.OrderBy(x => x.Expiry).ToArray();
if (puts.Length < 2) return;
_firstExpiry = puts[0].Expiry;
// Sell the put calendar spread
var putCalendarSpread = OptionStrategies.PutCalendarSpread(_vixw, strike, _firstExpiry, puts[^1].Expiry);
_tickets = Sell(putCalendarSpread, 1, asynchronous: true);
}
}
}

View File

@@ -185,7 +185,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 20425;
public long DataPoints => 19485;
/// <summary>
/// Data Points count of the algorithm history
@@ -199,32 +199,32 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-51.53%"},
{"Compounding Annual Return", "-81.170%"},
{"Drawdown", "13.800%"},
{"Average Loss", "-51.16%"},
{"Compounding Annual Return", "-80.264%"},
{"Drawdown", "13.400%"},
{"Expectancy", "-1"},
{"Net Profit", "-11.084%"},
{"Sharpe Ratio", "-1.893"},
{"Probabilistic Sharpe Ratio", "0.513%"},
{"Net Profit", "-10.784%"},
{"Sharpe Ratio", "-1.791"},
{"Probabilistic Sharpe Ratio", "1.276%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.683"},
{"Beta", "0.218"},
{"Annual Standard Deviation", "0.356"},
{"Annual Variance", "0.126"},
{"Information Ratio", "-1.94"},
{"Tracking Error", "0.37"},
{"Treynor Ratio", "-3.083"},
{"Alpha", "-0.67"},
{"Beta", "0.223"},
{"Annual Standard Deviation", "0.369"},
{"Annual Variance", "0.136"},
{"Information Ratio", "-1.843"},
{"Tracking Error", "0.383"},
{"Treynor Ratio", "-2.965"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX 31KC0UJHC75TA|SPX 31"},
{"Fitness Score", "0.005"},
{"Fitness Score", "0.006"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.662"},
{"Return Over Maximum Drawdown", "-7.157"},
{"Portfolio Turnover", "0.025"},
{"Sortino Ratio", "-0.638"},
{"Return Over Maximum Drawdown", "-6.853"},
{"Portfolio Turnover", "0.027"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -238,7 +238,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "6df8b200489a2f217cd514592ee98663"}
{"OrderListHash", "f12712654608a831bf73f3d8747997f9"}
};
}
}

View File

@@ -169,7 +169,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 20519;
public long DataPoints => 19579;
/// <summary>
/// Data Points count of the algorithm history
@@ -183,31 +183,31 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-0.37%"},
{"Compounding Annual Return", "-5.132%"},
{"Average Loss", "-0.36%"},
{"Compounding Annual Return", "-4.999%"},
{"Drawdown", "0.400%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.370%"},
{"Sharpe Ratio", "-3.253"},
{"Probabilistic Sharpe Ratio", "0.221%"},
{"Net Profit", "-0.360%"},
{"Sharpe Ratio", "-3.306"},
{"Probabilistic Sharpe Ratio", "0.170%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.037"},
{"Beta", "0.007"},
{"Alpha", "-0.036"},
{"Beta", "0.006"},
{"Annual Standard Deviation", "0.011"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.595"},
{"Information Ratio", "-0.588"},
{"Tracking Error", "0.137"},
{"Treynor Ratio", "-5.349"},
{"Treynor Ratio", "-5.609"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.628"},
{"Return Over Maximum Drawdown", "-14.021"},
{"Sortino Ratio", "-1.669"},
{"Return Over Maximum Drawdown", "-14.031"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -222,7 +222,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "b0c50080f0229facd065721f1f5d715e"}
{"OrderListHash", "d783bad741a034d6742f0d9b6cfc676d"}
};
}
}

View File

@@ -171,7 +171,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 20443;
public long DataPoints => 19503;
/// <summary>
/// Data Points count of the algorithm history
@@ -184,33 +184,33 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "48.82%"},
{"Average Win", "49.16%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "-80.089%"},
{"Drawdown", "13.400%"},
{"Compounding Annual Return", "-79.233%"},
{"Drawdown", "13.000%"},
{"Expectancy", "0"},
{"Net Profit", "-10.734%"},
{"Sharpe Ratio", "-1.921"},
{"Probabilistic Sharpe Ratio", "0.511%"},
{"Net Profit", "-10.464%"},
{"Sharpe Ratio", "-1.813"},
{"Probabilistic Sharpe Ratio", "1.295%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.671"},
{"Beta", "0.211"},
{"Annual Standard Deviation", "0.344"},
{"Annual Variance", "0.118"},
{"Information Ratio", "-1.963"},
{"Tracking Error", "0.36"},
{"Treynor Ratio", "-3.133"},
{"Alpha", "-0.659"},
{"Beta", "0.216"},
{"Annual Standard Deviation", "0.358"},
{"Annual Variance", "0.128"},
{"Information Ratio", "-1.862"},
{"Tracking Error", "0.373"},
{"Treynor Ratio", "-3.009"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.005"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.676"},
{"Return Over Maximum Drawdown", "-7.289"},
{"Portfolio Turnover", "0.024"},
{"Sortino Ratio", "-0.65"},
{"Return Over Maximum Drawdown", "-6.959"},
{"Portfolio Turnover", "0.025"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -224,7 +224,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "856448f4cbba4fc39af8dba369c054df"}
{"OrderListHash", "ea4fe706e695a600d4f8ff65fb336e48"}
};
}
}

View File

@@ -163,7 +163,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 16486;
public long DataPoints => 15596;
/// <summary>
/// Data Points count of the algorithm history
@@ -176,24 +176,24 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "0.01%"},
{"Average Win", "0.02%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "0.142%"},
{"Compounding Annual Return", "0.214%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
{"Net Profit", "0.010%"},
{"Sharpe Ratio", "4.589"},
{"Probabilistic Sharpe Ratio", "98.983%"},
{"Net Profit", "0.015%"},
{"Sharpe Ratio", "4.336"},
{"Probabilistic Sharpe Ratio", "98.801%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.001"},
{"Alpha", "0.002"},
{"Beta", "-0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.32"},
{"Information Ratio", "-0.316"},
{"Tracking Error", "0.138"},
{"Treynor Ratio", "-9.479"},
{"Treynor Ratio", "-7.277"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$22000.00"},
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
@@ -216,7 +216,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "76ffdfc100ba7778009e35966bd92cfc"}
{"OrderListHash", "d5090abe5701a66559fcd4d1cb254a62"}
};
}
}

View File

@@ -175,7 +175,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 20425;
public long DataPoints => 19485;
/// <summary>
/// Data Points count of the algorithm history
@@ -188,33 +188,33 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "51.07%"},
{"Average Win", "50.61%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "319.986%"},
{"Drawdown", "2.400%"},
{"Compounding Annual Return", "299.724%"},
{"Drawdown", "2.300%"},
{"Expectancy", "0"},
{"Net Profit", "10.624%"},
{"Sharpe Ratio", "5.415"},
{"Probabilistic Sharpe Ratio", "88.697%"},
{"Net Profit", "10.234%"},
{"Sharpe Ratio", "4.986"},
{"Probabilistic Sharpe Ratio", "84.774%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "1.938"},
{"Beta", "-0.235"},
{"Annual Standard Deviation", "0.356"},
{"Annual Variance", "0.127"},
{"Information Ratio", "4.787"},
{"Tracking Error", "0.393"},
{"Treynor Ratio", "-8.187"},
{"Alpha", "1.847"},
{"Beta", "-0.243"},
{"Annual Standard Deviation", "0.368"},
{"Annual Variance", "0.136"},
{"Information Ratio", "4.425"},
{"Tracking Error", "0.405"},
{"Treynor Ratio", "-7.549"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX 31KC0UJHC75TA|SPX 31"},
{"Fitness Score", "0.025"},
{"Fitness Score", "0.026"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "634.943"},
{"Return Over Maximum Drawdown", "1184.633"},
{"Portfolio Turnover", "0.025"},
{"Sortino Ratio", "45.186"},
{"Return Over Maximum Drawdown", "348.282"},
{"Portfolio Turnover", "0.026"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -228,7 +228,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "77d9040316634cb6b9e8cd2e4e192fd5"}
{"OrderListHash", "6cdc8adaaa3f02bd674f038d443ffbaf"}
};
}
}

View File

@@ -162,7 +162,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 20519;
public long DataPoints => 19579;
/// <summary>
/// Data Points count of the algorithm history
@@ -175,24 +175,24 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "0.35%"},
{"Average Win", "0.33%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "5.091%"},
{"Compounding Annual Return", "4.797%"},
{"Drawdown", "0.000%"},
{"Expectancy", "0"},
{"Net Profit", "0.350%"},
{"Sharpe Ratio", "3.182"},
{"Probabilistic Sharpe Ratio", "90.575%"},
{"Net Profit", "0.330%"},
{"Sharpe Ratio", "3.126"},
{"Probabilistic Sharpe Ratio", "89.571%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.036"},
{"Beta", "-0.008"},
{"Alpha", "0.034"},
{"Beta", "-0.007"},
{"Annual Standard Deviation", "0.011"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.066"},
{"Information Ratio", "-0.081"},
{"Tracking Error", "0.139"},
{"Treynor Ratio", "-4.733"},
{"Treynor Ratio", "-4.529"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
@@ -200,7 +200,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "514.964"},
{"Return Over Maximum Drawdown", "323.257"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -215,7 +215,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "12861ef440f68994997aeb24c8027748"}
{"OrderListHash", "8a9af32decfdffa4a21c04751c69c2df"}
};
}
}

View File

@@ -0,0 +1,144 @@
/*
* 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.
*/
using System;
using System.Collections.Generic;
using QuantConnect.Interfaces;
using QuantConnect.Util;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Algorithm illustrating how to get a security's industry-standard identifier from its <see cref="Symbol"/>
/// </summary>
public class IndustryStandardSecurityIdentifiersRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
public override void Initialize()
{
SetStartDate(2013, 10, 07);
SetEndDate(2013, 10, 07);
var spy = AddEquity("SPY").Symbol;
var spyCusip = spy.CUSIP;
var spyCompositeFigi = spy.CompositeFIGI;
var spySedol = spy.SEDOL;
var spyIsin = spy.ISIN;
CheckSymbolRepresentation(spyCusip, "CUSIP");
CheckSymbolRepresentation(spyCompositeFigi, "Composite FIGI");
CheckSymbolRepresentation(spySedol, "SEDOL");
CheckSymbolRepresentation(spyIsin, "ISIN");
// Check Symbol API vs QCAlgorithm API
CheckAPIsSymbolRepresentations(spyCusip, CUSIP(spy), "CUSIP");
CheckAPIsSymbolRepresentations(spyCompositeFigi, CompositeFIGI(spy), "Composite FIGI");
CheckAPIsSymbolRepresentations(spySedol, SEDOL(spy), "SEDOL");
CheckAPIsSymbolRepresentations(spyIsin, ISIN(spy), "ISIN");
Log($"\nSPY CUSIP: {spyCusip}" +
$"\nSPY Composite FIGI: {spyCompositeFigi}" +
$"\nSPY SEDOL: {spySedol}" +
$"\nSPY ISIN: {spyIsin}");
}
private static void CheckSymbolRepresentation(string symbol, string standard)
{
if (symbol.IsNullOrEmpty())
{
throw new Exception($"{standard} symbol representation is null or empty");
}
}
private static void CheckAPIsSymbolRepresentations(string symbolApiSymbol, string algorithmApiSymbol, string standard)
{
if (symbolApiSymbol != algorithmApiSymbol)
{
throw new Exception($@"Symbol API {standard} symbol representation ({symbolApiSymbol}) does not match QCAlgorithm API {
standard} symbol representation ({algorithmApiSymbol})");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 795;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", ""},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
};
}
}

View File

@@ -0,0 +1,204 @@
/*
* 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.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Brokerages;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm asserting that InteractiveBrokers brokerage model does not support index options exercise
/// </summary>
public class InteractiveBrokersBrokerageDisablesIndexOptionsExerciseRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Option _option;
private OptionContract _contract;
private bool _marketOrderDone;
private bool _triedExercise;
private bool _automaticallyExercised;
private decimal _initialCash = 200000;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 30);
SetCash(_initialCash);
SetBrokerageModel(new InteractiveBrokersBrokerageModel());
var index = AddIndex("SPX", Resolution.Hour, fillDataForward: true);
var indexOption = AddIndexOption(index.Symbol, Resolution.Hour, fillDataForward: true);
indexOption.SetFilter(filterFunc => filterFunc.CallsOnly());
_option = indexOption;
}
public override void OnData(Slice slice)
{
if (_triedExercise || !_option.Exchange.ExchangeOpen)
{
return;
}
if (_contract == null)
{
OptionChain contracts;
if (!slice.OptionChains.TryGetValue(_option.Symbol, out contracts) || !contracts.Any())
{
return;
}
_contract = contracts.First();
}
var expiry = _contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone).Date;
if (UtcTime.Date < expiry && !_marketOrderDone)
{
if (MarketOrder(_contract.Symbol, 1).Status != OrderStatus.Filled)
{
throw new Exception("Expected market order to fill immediately");
}
_marketOrderDone = true;
return;
}
if (!_triedExercise && UtcTime.Date == expiry)
{
if (ExerciseOption(_contract.Symbol, 1).Status == OrderStatus.Filled)
{
throw new Exception($"Expected index option to not be exercisable on its expiration date. " +
$"Time: {UtcTime}. Expiry: {_contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone)}");
}
_triedExercise = true;
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
// The manual exercise failed and we are not placing any other orders, so this is the automatic exercise
if (orderEvent.Status == OrderStatus.Filled &&
_marketOrderDone &&
_triedExercise &&
UtcTime.Date >= _contract.Expiry.ConvertToUtc(_option.Exchange.TimeZone).Date)
{
var profit = Portfolio.TotalPortfolioValue - _initialCash;
if (profit < 0)
{
throw new Exception($"Expected profit to be positive. Actual: {profit}");
}
_automaticallyExercised = true;
}
}
public override void OnEndOfAlgorithm()
{
if (!_triedExercise)
{
throw new Exception("Expected to try to exercise index option before and on expiry");
}
if (!_automaticallyExercised || Portfolio.Cash <= _initialCash)
{
throw new Exception("Expected index option to have ben automatically exercised on expiry and to have received cash");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all time slices of algorithm
/// </summary>
public long DataPoints => 1934;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-4.10%"},
{"Compounding Annual Return", "10.590%"},
{"Drawdown", "1.900%"},
{"Expectancy", "-1"},
{"Net Profit", "0.712%"},
{"Sharpe Ratio", "3.343"},
{"Probabilistic Sharpe Ratio", "87.312%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.081"},
{"Annual Variance", "0.007"},
{"Information Ratio", "3.343"},
{"Tracking Error", "0.081"},
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$1700000.00"},
{"Lowest Capacity Asset", "SPX XL80P3HB5O6M|SPX 31"},
{"Fitness Score", "0.001"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.651"},
{"Return Over Maximum Drawdown", "6.583"},
{"Portfolio Turnover", "0.002"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "b9dfd17bb95246e5d04d9e6c4b959d71"}
};
}
}

View File

@@ -0,0 +1,165 @@
/*
* 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.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Algorithm asserting that orders for option strategies can be placed with large quantities as long as there is margin available.
/// This asserts the expected behavior in GH issue #5693
/// </summary>
public class LargeQuantityOptionStrategyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _optionSymbol;
public override void Initialize()
{
SetStartDate(2015, 12, 24);
SetEndDate(2015, 12, 24);
SetCash(100000);
SetSecurityInitializer(x => x.SetMarketPrice(GetLastKnownPrice(x)));
var equity = AddEquity("GOOG");
var option = AddOption("GOOG");
_optionSymbol = option.Symbol;
option.SetFilter(-2, +2, 0, 180);
}
public override void OnData(Slice slice)
{
if (Portfolio.Invested || !slice.OptionChains.TryGetValue(_optionSymbol, out var chain))
{
return;
}
var putContractsWithLatestExpiry = chain
// puts only
.Where(x => x.Right == OptionRight.Put)
// contracts with latest expiry
.GroupBy(x => x.Expiry)
.OrderBy(x => x.Key)
.Last()
// ordered by strike
.OrderBy(x => x.Strike)
.ToList();
if (putContractsWithLatestExpiry.Count < 2)
{
return;
}
var longContract = putContractsWithLatestExpiry[0];
var shortContract = putContractsWithLatestExpiry[1];
var strategy = OptionStrategies.BearPutSpread(_optionSymbol, shortContract.Strike, longContract.Strike, shortContract.Expiry);
// Before option strategies orders were place as combo orders, only a quantity up to 18 could be used in this case,
// even though the remaining margin was enough to support a larger quantity. See GH issue #5693.
// We want to assert that with combo orders, large quantities can be used on option strategies
Order(strategy, 19);
Quit($"Margin used: {Portfolio.TotalMarginUsed}; Remaining: {Portfolio.MarginRemaining}");
}
public override void OnEndOfAlgorithm()
{
var filledOrders = Transactions.GetOrders(x => x.Status == OrderStatus.Filled).ToList();
if (filledOrders.Count != 2)
{
throw new Exception($"Expected 2 filled orders but found {filledOrders.Count}");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 2262;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 25;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$9.50"},
{"Estimated Strategy Capacity", "$6000.00"},
{"Lowest Capacity Asset", "GOOCV 30AKMELSHQVZA|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "f063bcbcfbf501dab9c573bd493363b1"}
};
}
}

View File

@@ -0,0 +1,176 @@
/*
* 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.
*
*/
using System;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression test is a version of <see cref="MarketOnCloseOrderBufferRegressionAlgorithm"/>
/// where we test market-on-close modeling with data from the post market.
/// </summary>
public class MarketOnCloseOrderBufferExtendedMarketHoursRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private OrderTicket _validOrderTicket;
private OrderTicket _invalidOrderTicket;
private OrderTicket _validOrderTicketAtMidnight;
private OrderTicket _validOrderTicketExtendedMarketHours;
public override void Initialize()
{
SetStartDate(2013, 10, 7); //Set Start Date
SetEndDate(2013, 10, 8); //Set End Date
var ticker = "SPY";
AddEquity(ticker, Resolution.Minute, extendedMarketHours: true);
Schedule.On(DateRules.Tomorrow, TimeRules.Midnight, () =>
{
_validOrderTicketAtMidnight = MarketOnCloseOrder("SPY", 2);
});
// Modify our submission buffer time to 10 minutes
Orders.MarketOnCloseOrder.SubmissionTimeBuffer = TimeSpan.FromMinutes(10);
}
public override void OnData(Slice slice)
{
// Test our ability to submit MarketOnCloseOrders
// Because we set our buffer to 10 minutes, any order placed
// before 3:50PM should be accepted, any after marked invalid
if (Time.Hour == 15 && Time.Minute == 49 && _validOrderTicket == null)
{
// Will not throw an order error and execute
_validOrderTicket = MarketOnCloseOrder("SPY", 2);
}
if (Time.Hour == 15 && Time.Minute == 51 && _invalidOrderTicket == null)
{
// Will throw an order error and be marked invalid
_invalidOrderTicket = MarketOnCloseOrder("SPY", 2);
}
if (Time.Hour == 16 && Time.Minute == 48 && _validOrderTicketExtendedMarketHours == null)
{
// Will not throw an order error and execute
_validOrderTicketExtendedMarketHours = MarketOnCloseOrder("SPY", 2);
}
}
public override void OnEndOfAlgorithm()
{
// Set it back to default for other regressions
Orders.MarketOnCloseOrder.SubmissionTimeBuffer = Orders.MarketOnCloseOrder.DefaultSubmissionTimeBuffer;
// Verify that our good order filled
if (_validOrderTicket.Status != OrderStatus.Filled)
{
throw new Exception("Valid order failed to fill");
}
// Verify our order was marked invalid
if (_invalidOrderTicket.Status != OrderStatus.Invalid)
{
throw new Exception("Invalid order was not rejected");
}
// Verify that our second good order filled
if (_validOrderTicketExtendedMarketHours.Status != OrderStatus.Filled)
{
throw new Exception("Valid order during extended market hours failed to fill");
}
// Verify that our third good order filled
if (_validOrderTicketAtMidnight.Status != OrderStatus.Filled)
{
throw new Exception("Valid order at midnight failed to fill");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 3862;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 0;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new()
{
{"Total Trades", "3"},
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$910000000.00"},
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-46.084"},
{"Return Over Maximum Drawdown", "-198.32"},
{"Portfolio Turnover", "0.004"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "21a9fc316b33b82d2d99c508040649cd"}
};
}
}

View File

@@ -26,15 +26,21 @@ namespace QuantConnect.Algorithm.CSharp
{
private OrderTicket _validOrderTicket;
private OrderTicket _invalidOrderTicket;
private OrderTicket _validOrderTicketExtendedMarketHours;
public override void Initialize()
{
SetStartDate(2013, 10, 4); //Set Start Date
SetEndDate(2013, 10, 4); //Set End Date
SetStartDate(2013, 10, 7); //Set Start Date
SetEndDate(2013, 10, 8); //Set End Date
var ticker = "SPY";
AddEquity(ticker, Resolution.Minute);
Schedule.On(DateRules.Today, TimeRules.At(17,00), () =>
{
_validOrderTicketExtendedMarketHours = MarketOnCloseOrder("SPY", 2);
});
// Modify our submission buffer time to 10 minutes
Orders.MarketOnCloseOrder.SubmissionTimeBuffer = TimeSpan.FromMinutes(10);
}
@@ -44,14 +50,13 @@ namespace QuantConnect.Algorithm.CSharp
// Test our ability to submit MarketOnCloseOrders
// Because we set our buffer to 10 minutes, any order placed
// before 3:50PM should be accepted, any after marked invalid
if (Time.Hour == 15 && Time.Minute == 49)
if (Time.Hour == 15 && Time.Minute == 49 && _validOrderTicket == null)
{
// Will not throw an order error and execute
_validOrderTicket = MarketOnCloseOrder("SPY", 2);
}
if (Time.Hour == 15 && Time.Minute == 51)
if (Time.Hour == 15 && Time.Minute == 51 && _invalidOrderTicket == null)
{
// Will throw an order error and be marked invalid
_invalidOrderTicket = MarketOnCloseOrder("SPY", 2);
@@ -74,6 +79,12 @@ namespace QuantConnect.Algorithm.CSharp
{
throw new Exception("Invalid order was not rejected");
}
// Verify that our second good order filled
if (_validOrderTicketExtendedMarketHours.Status != OrderStatus.Filled)
{
throw new Exception("Valid order during extended market hours failed to fill");
}
}
/// <summary>
@@ -89,7 +100,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 795;
public long DataPoints => 1582;
/// <summary>
/// Data Points count of the algorithm history
@@ -99,9 +110,9 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
public Dictionary<string, string> ExpectedStatistics => new()
{
{"Total Trades", "1"},
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "0%"},
@@ -120,15 +131,15 @@ namespace QuantConnect.Algorithm.CSharp
{"Information Ratio", "0"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$23000000000.00"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$18000000000.00"},
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
{"Fitness Score", "0"},
{"Fitness Score", "0.001"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-261.069"},
{"Portfolio Turnover", "0.002"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -142,7 +153,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "8c2178d2b47a3773c217e9d0e3eaa179"}
{"OrderListHash", "1a356e0edb136b31a7f12c661cf5de74"}
};
}
}

View File

@@ -0,0 +1,121 @@
/*
* 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.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Interfaces;
namespace QuantConnect.Algorithm.CSharp
{
public class MissingTickDataAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
public override void Initialize()
{
SetStartDate(2013, 10, 08);
SetEndDate(2013, 10, 08);
var spy = AddEquity("SPY", Resolution.Tick).Symbol;
var start = new DateTime(2013, 10, 07, 15, 0, 0);
var slices = History(new[] { spy }, start, start.AddSeconds(10), Resolution.Tick).ToList();
var tickCountInSliceHistoryCall = slices.Sum(x => x.Ticks[spy].Count);
var ticks = History<Tick>(spy, start, start.AddSeconds(10), Resolution.Tick).ToList();
var tickCountInTickHistoryCall = ticks.Count;
if (tickCountInSliceHistoryCall != tickCountInTickHistoryCall)
{
throw new Exception($@"Tick count mismatch in Slice and Tick history calls: History() returned {
tickCountInSliceHistoryCall} ticks, while History<Tick>() returned {tickCountInTickHistoryCall} ticks");
}
// Early quit, we already tested what we wanted
Quit();
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public Language[] Languages { get; } = { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public long DataPoints => 0;
/// <summary>
/// Data Points count of the algorithm history
/// </summary>
public int AlgorithmHistoryDataPoints => 1610;
/// <summary>
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"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"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", ""},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
{"Long Insight Count", "0"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$0"},
{"Total Accumulated Estimated Alpha Value", "$0"},
{"Mean Population Estimated Insight Value", "$0"},
{"Mean Population Direction", "0%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
};
}
}

Some files were not shown because too many files have changed in this diff Show More