Compare commits

..

86 Commits
13060 ... 13402

Author SHA1 Message Date
Alexandre Catarino
3d3733c0fb Adds Market.HKFE to InteractiveBrokersFeeModel (#6127)
Adds `Market.HKFE` to `InteractiveBrokersFeeModel` in the Futures Options case.
2021-12-22 19:32:07 -03:00
Martin-Molinero
1303ccf843 Update readme.md 2021-12-22 17:16:41 -03:00
Martin-Molinero
3b5f3fcf42 Update readme.md 2021-12-22 16:18:09 -03:00
Andreas Sundebo
e2de241c2b Feature 5090 add api optimization methods (#6108)
* Move Optimizer-related DTOs and JSON converters into Common/Optimizer

* Add REST methods for Optimization

* Move OptimizationStatus into Common

* Change optimizationId parameter type to string

* Update Optimization and add lightweight optimization object

* Rename lightweight optimization to BaseOptimization and remove unneccessary properties

* Remove snapshotId from Optimization, add ParameterSet to Backtest

* Add missing IApi.cs method signatures

* Move ParameterSet into Common

* Replace Backtest with OptimizationBacktest

* Update UpdateOptimization to not include null or empty name and layout params in the request

* Change Objective targetTemplate regex pattern from ['(.+)'] to (.+) to prevent escaping target strings without whitespace

* Return Estimate object when calling EstimateOptimization

* Use DefaultNamingStrategy when serializing constraint operators

* Revert "Change Objective targetTemplate regex pattern from ['(.+)'] to (.+) to prevent escaping target strings without whitespace"

This reverts commit fbe7de0fd7.

* Update Api method signatures

* Add unit tests

* Fix XML comment referring to the old class name

* Fix XML summary for OptimizationResponseWrapper

* Address review feedback
- Remove unused testOrganizationId
- Change NodeType from string to NodeType enum
- Clarify unit types for Estimate time and balance
- Simplify JsonConverter classes

* Add accessors to Common/Api classes

* Define performance metrics names in PerformanceMetrics class

* Remove unnecessary branching logic from GetSeriesValues method

* Add crefs and examples to XML comments in the Api class

* Revert "Change NodeType from string to NodeType enum"

* Remove layout param from UpdateOptimization method

* Backtest property ParameterSet should be of type ParameterSet

* Add asserts for deserialization in OptimizationBacktestJsonConverterTests

* Replace the three target-related properties with Criterion

* Add serialization and deserialization tests for Optimization

* Remove Optimization Serialization test

* Add EstimateDeserialization test

* Add asserts for integration tests

* Address self review

* Revert test case

* Update Nodes.cs

* Update Nodes.cs

* Set Aborted status when Optimization fails to start

* Add ParameterSetJsonConverter and ParameterSetJsonConverterTests

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2021-12-22 13:14:56 -03:00
Martin-Molinero
68e2a9170a Do not send internal SecurityChanges to Algorithm (#6118)
* Do not send internal SecurityChanges to Algorithm

- Will not send internal security changes to the Algorithm by default.
  Following custom security changes filter pattern. Updating regression
  algorithms to assert behavior.
- The universe member will know wether it was added with internal
  configurations or not

* Address reviews use a separate collection for internals

* Refactor solution. Adding security changes constructor class
2021-12-21 20:24:32 -03:00
Adalyat Nazirov
d395f704b3 Bug 6115 adjust dates (#6124)
* GH-6115: adjust dates

* fix

* use another approach

* Add lean data writter multiple days data unit test

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2021-12-21 17:33:36 -03:00
Martin-Molinero
4d1fc7e05a Handle security added and removed in the same loop (#6120)
* Handle security added and removed in the same loop

- Correctly handle adding and removing a security in the same loop.
  Adding regression test

* Adding comments
2021-12-21 11:59:45 -03:00
Martin-Molinero
e3a562d3c9 Add file and line number to documentation attribute (#6122) 2021-12-20 17:30:04 -08:00
Martin-Molinero
4fdd60d146 Use 64 when saving zips update dotnetZip (#6114) 2021-12-20 16:39:06 -03:00
Martin-Molinero
abbb50e209 Minor improvements for data reading and caching (#6113)
* Minor improvements for data reading and caching

* Address reviews

* Adjust zip cache error check
2021-12-16 19:58:37 -03:00
Alexandre Catarino
0e1cc288a6 Change Default Market of CFD to OANDA (#6107)
Oanda is currently the only provider.
2021-12-13 17:58:57 -03:00
Martin-Molinero
3b826535c7 Fix for ConcurrentDictionary Thread Safety (#6105)
- ConcurrentDictionary with OrderBy is not thread safe, adding thread
  safe extension method. Adding unit tests
2021-12-13 10:45:58 -03:00
Martin-Molinero
59da486e30 IB will correctly create non USD currency contract (#6103)
- IB will create contract based on SPDB entry for symbol. Adding unit
  test
2021-12-10 13:56:32 -03:00
Martin-Molinero
f42d7bb3a2 Align universe security and configuration TZ (#6102)
* Align universe security and configuration TZ

- Make sure universe security and configuration tz are aligned always.
  Adding unit test reproducing issue

* Address review UserDefinedUniverse will use UTC TZ
2021-12-09 15:53:56 -03:00
Martin-Molinero
87bd0d7792 CompositeDataQueueHandler handles duplicate configs (#6101)
* CompositeDataQueueHandler handles duplicate configs

- CompositeDataQueueHandler will handle duplicate subscriptions sharing
  the same config. Adding unit tests

* Refactor bug solution after review

- LiveSubscriptionEnumerator will not long perform any symbol mapping
  but will just trigger a new subscription call when remapped.
- CompositeDHQ will handling symbol mapping and keep track of these
  mapped configs to trigger unsubscribe accordengly. Adding unit tests

* Adjust solution after review

- To avoid breaking uniqueness of SubscriptionDataConfig will be adding
  a private `mapped` property that will change equality of mapped
  configs to avoid them clashing. Adding unit tests

* Rename IDQH subscription extension methods
2021-12-09 14:53:04 -03:00
Louis Szeto
8ca9258e70 API Reference for docs v2 (#6098)
API Reference for docs v2 

Co-authored-by: Alexandre Catarino <AlexCatarino@users.noreply.github.com>
2021-12-08 16:25:36 -08:00
Martin-Molinero
72105539fc Minor Exchanges cleanup (#6100) 2021-12-06 19:27:27 -03:00
Anuj Patel
589e8a9293 fix Kraken fee model (#6096)
* Update KrakenFeeModel.cs

* Update KrakenFeeModelTests.cs

Co-authored-by: Anuj Patel <91538343+anuj-mitul-patel@users.noreply.github.com>
2021-12-06 11:59:20 -03:00
Martin-Molinero
dd27a382f7 Composite data queue handler IUniverseProvider (#6097)
* Minor performance improvements

* CompositeDataQueueHandler is UniverseProvider

- CompositeDataQueueHandler implements the UniverseProvider interface.
  Adding unit tests
2021-12-06 10:27:18 -03:00
Jovad Uribe
62a8aee38c Kaufman Efficiency Ratio Indicator (#6050)
* Indicator

* Fixed logic error

* Removed old files, added KER into KAMA

* Removed old comments

* Added requested changes

* Minor clean up

* Refactors KaufmanEfficiencyRatio and KaufmanAdaptiveMovingAverage

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
Co-authored-by: Alexandre Catarino <AlexCatarino@users.noreply.github.com>
2021-12-04 18:55:09 -03:00
Alexandre Catarino
7e7c27416b Updates KeltnerChannels to Update MiddleBand with EndTime (#6084)
* Updates KeltnerChannels to Update MiddleBand with EndTime

* Adds Unit Test

This unit test shows that the timestamp of the MiddleBand and the indication are aligned as expected.
2021-12-03 19:43:32 -03:00
Martin-Molinero
26f2f88c67 Add documentation attribute default value (#6095) 2021-12-03 18:47:47 -03:00
Martin-Molinero
c08c129860 Add documentation attribute (#6094) 2021-12-03 18:23:06 -03:00
Martin-Molinero
bae10389ae Update readme.md 2021-12-03 17:15:58 -03:00
Martin-Molinero
4301d7cead Update readme.md 2021-12-03 17:08:06 -03:00
Martin-Molinero
d49f1d0d6c Update readme.md 2021-12-03 16:34:47 -03:00
Ronit Jain
264c3c8374 Composite IDQH - Support multiple live data feeds (#6047)
* initial commit

* Follow IDQH implementation

* Expect a list of data handlers from LiveNodePacket

* Return null if can not subscribe

* refctor to add check for subscription

* initialze null

* Add tests

* Check subscribe retuns null/not-null

* cleanup

* Read all required IDQH credentails to job

* Use CDQH to handle all IDQH instances

* constructor abstraction to call from setjob

* use flag

* remove redundant because derived will call initialize on it

* abstract and initialize from setjob

* handle null enumerators

* get creds from data handlers

* handle single data handler value from data-queue-handler

* Fix to support a json array

* Fix missed constructor call

* change access modifier to access from Tests files

* Add test to get brokerageFactory from dataQueueHandler

* Fix init flag to handle all conditions

* Add docs

* initialize from setjob

* Check if websocket open before using

* change defination of initialzie to include tradier

* clean up

* change defination

* fix wrong api key name

* return empty enumerator

* check websocket open before sending request

* check connection before subscribing

* fix to include more cases

* check websocket open before sending request

* Minor refactoring

* reafctor and use IsConnected

* remove unused

* clean up

* Fix test cases

* reverse change

* include config changes

* connect to websocket from setjob

* check websocket connection from setjob

* clean up

* include condition for IDQH that are not brokerage

* Address review

* Add market check condition before subscribe

* Remove deprecated

* Minor fix for deserializing data queue handler

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2021-12-03 16:18:41 -03:00
Martin-Molinero
8a1f67edfc Minor fixes (#6093)
- Update Atreyu fees
- Remove redundant check in AlphaStreamBrokerageModel
- Fix option contract removal and second addition. Adding unit test
2021-12-03 12:54:49 -03:00
Martin-Molinero
5f434f2fa5 SetupHandlers will exit if errors on initialize (#6092)
- SetupHandlers will exit right away if detect errors on initialize.
  Adding unit tests
2021-12-02 19:24:51 -03:00
Martin-Molinero
e37f8ae878 Fix for adding continuous future and future contract at the same time (#6091)
- Fix for adding continuous future and manually adding contract at the
  same time. Continuous future was using the user defined universe
  symbol and caused clashes. Adding regression test reproducing the issue.
2021-12-02 18:13:52 -03:00
Martin-Molinero
b4e95209f6 Fix for IB Option position race condition (#6090)
- Fix for IB option position update race condition, where the BTH would
  incorrectly assume it should trigger an early option assignment. Adding unit tests
2021-12-02 17:09:50 -03:00
Martin-Molinero
ea65c61dc8 Minor InteractiveBrokers fix (#6089)
- IB needs to notify the `DefaultBrokerageMessageHandler` we have re
  connected else it might kill the algorithm
2021-12-01 19:26:25 -03:00
Ricardo Andrés Marino Rojas
6bf6ff1a6a Fix bug in ConsumeMultipleMinutes() test (#6083)
* Give `code()` more time per iteration

* Another proposed solution

* Revert "Another proposed solution"

This reverts commit 29bf5a7554.

* Add an AutoResetEvent field in `TimeConsumer()`

* Avoid change TimeMonitor implementation

* Remove changes in `TimeConsumer.cs`

* Requested changes

* Avoid re-implementation
2021-11-30 21:44:42 -03:00
Martin-Molinero
d1a35e6281 Continuous Futures Refactor. Live Mappings (#6076)
* Continuous Futures Refactor. Live Mappings

- Adding support for live mappings. LiveTradingDataFeed will handle any
  symbol mapping at the configuration layer and resubscribe through the
  IDQH
- Refactoring continuous futures adding ContinuousFutureUniverse that
  will select the currently mapped security

* Minor fixes

- Remove addition of configurations in UniverseSelection step, leave
  resposability for universe.
- LiveTradingDF future unit test will only assert slice data for non
  internal feeds.
- ContinuousContractUniverse will respect internal option interest
  subscription

* Address review
2021-11-30 21:38:50 -03:00
Martin-Molinero
fed1fa929b Fix low resolution index TradeBar parsing (#6081)
- Fix low resolution Index TradeBar parsing. Updating unit tests. Adding
  unit tests
2021-11-29 12:59:16 -03:00
Ricardo Andrés Marino Rojas
9e7962f5a2 Add Overload in SecurityTransactionManager Methods to Support Python Functions (#6068)
* Add PyObject overload

* Nit changes and unit tests

* Regression tests

* Nit changes

* Requested changes

* Requested changes

* Handle null parameter cases
2021-11-26 16:15:54 -03:00
Andreas Sundebo
3e66733413 Properly handle pending CancelOrderRequests during backtesting (#6021)
* Properly handle pending CancelOrderRequests

To avoid unneccessary "Insufficient buying power to complete order" errors showing up as Invalid orders we need to skip further processing of pending CancelOrderRequests in the BacktestingBrokerage and instead let them be properly removed during the next transaction handler run.

* Update BacktestingBrokerage.cs
2021-11-26 14:47:30 -03:00
Colton Sellers
c11a09e08a Feature Index Option Low Resolution Support (#6075)
* Activate Index and IndexOptions low res

* Add Index and IndexOption low res data

* Add IndexOption regressions

* Fix bug with IndexOption QuoteBar data not being scaled

* nit - update comment for _scaleFactor

* Update data and regressions to reflect fix in data

* Tweak regressions
2021-11-26 13:11:35 -03:00
Anuj Patel
f06bab944d fix incorrect Kraken and Coinbase Pro fee values (#6071)
* fix Coinbase Pro fee values

fee values changed to reflect most recent fee schedule, see 
* https://blog.coinbase.com/updates-to-coinbase-pro-fee-structure-b3d9ee586108
* https://help.coinbase.com/en/pro/trading-and-funding/trading-rules-and-fees/fees
* https://pro.coinbase.com/fees

* fix Kraken fee values

all fee values multiplied by 1/100 to correct inaccuracy, see
* https://www.kraken.com/features/fee-schedule#kraken-pro

* changes time to after latest fees have been set and replaces old expected values
2021-11-24 16:57:20 -03:00
Ricardo Andrés Marino Rojas
df63b6f5d6 Renaming requested changes (#6072) 2021-11-24 09:58:37 -03:00
Colton Sellers
1358bd8115 Future and FutureOption low res support (#6069)
* Fixes for FutureOptions support in LeanData

* Add CreateCanonicalOption() utility function for Symbol.cs

* Add aggregated Futures/FuturesOptions data to Lean

* Add FutureOptions regressions for daily/hourly data

* Allow Futures to be added with low resolution

* Add Future regressions using hour/daily data

* Nit - Python Class names

* Add reviews

* Add alias into CreateCanonicalOption
2021-11-24 09:53:21 -03:00
Martin-Molinero
40cc7a808a Skip subscribing to canonical symbols (#6070) 2021-11-22 21:00:45 -03:00
Martin-Molinero
e3a4fa1838 Update readme.md 2021-11-22 12:54:51 -03:00
bmello4688
1d8243ecac Add tick type to data downloader get (price data) call in order for a… (#6057)
* Add tick type to data downloader get (price data) call in order for api's with rate limits to handle not making an api call at all.

* Added DTO object to pass into data downloader get

* Added missing header for new file

* Address review. Minor tweaks

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2021-11-22 12:00:16 -03:00
Martin-Molinero
a8c81cad2a Fixes for continuous futures history requests (#6067)
* Fixes for continuous futures history requests

- Fixes for continuous future history requests and warmup. Adding
  regression test

* Address reviews
2021-11-19 20:52:15 -03:00
Martin-Molinero
5f95a9ba77 Bug fix python history requests enumerable data (#6066)
* Fix for python enumerable data history request

- Fix for python enumerable type data history request. Adding unit test.

* Add methods for adding data points into a baseDataCollection
2021-11-19 14:58:48 -03:00
Ricardo Andrés Marino Rojas
a9b914c9ef Fix: IB Subscribe Cannot Find HangSeng Futures (#6064)
* Fix Bug

* Nit change

* Change `LookupSymbols()` method implementation

* Nit change

* Revert "Nit change"

This reverts commit 7bad6d195d.

* Nit change
2021-11-18 20:56:22 -03:00
Martin-Molinero
5436275901 Remove comments from MHDB json file (#6065) 2021-11-18 20:41:02 -03:00
Martin-Molinero
0a315b0ae6 Update readme.md 2021-11-17 19:59:03 -03:00
Colton Sellers
33599b473d Refactor Delistings Processing (#6059)
* Move processing of delistings to Brokerage

* Deal with case that exchange is not open on OptionSymbol.ID.Date

* Refactor solution to use DelistingNotification event

* Adjust some regression expected liquidation time

* Mark some todos on deprecated functions

* Update expected liqudation time for Py regressions

* Update regressions that have been validated

* Use HandlePositionAssigned for assignment orders

* Update regressions

* Update some missed unit tests; remove one that is already covered by regression

* Cleanup deprecated backend functions

* nit - small cleanup adjustment

* Post rebase fix

* Address review

* Minor tweak to py regression
2021-11-17 17:43:35 -03:00
Jovad Uribe
325e788728 Super Trend Indicator (#6013)
* Super Trend Indicator #4653

* Updated test data

Previous test data was wrong

* Reduced if statement

* Updated tests

Replacing spy test data with dwac test data from trading view.

* Minor comment update

* Minor tweaks

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2021-11-17 12:19:26 -03:00
Martin-Molinero
57ac4d6497 Add import for System.Drawing (#6063) 2021-11-17 11:28:09 -03:00
Martin-Molinero
664dca2236 Tradier websocket bug fix (#6061)
- Tradier brokerage will use BaseWebsocketsBrokerage which handled
  websocket resubscription. Minor API changes
2021-11-16 18:44:38 -03:00
Ricardo Andrés Marino Rojas
5415fe6bc0 Beta indicator (#6042)
* First BetaIndicator prototype
- In construction

* Fist BetaIndicator version and unit tests

* More unit tests and regression test

* Nit change

* Requested changes

* Nit changes

* Requested changes

* Adjust beta formula slightly and nit changes

* Nit change
2021-11-15 15:57:24 -03:00
Martin-Molinero
b2517cbbb4 Fix DiskDataCacheProvider. Expanding unit test (#6058) 2021-11-15 15:57:09 -03:00
Martin-Molinero
b8b0d18993 Continuous futures (#6034)
* Continuous Future Contracts

* Mapping approach

* Tweaks WIP

* Live mapping

* Live mapping

- Add support for live mapping, refreshing mapfiles
- Fix future expiration functions
- Adding unit tests

* Update moq test package

* Continuous futures price scaling

* Refactor price factors scaling

* Factor file related renames

* Address reviews
2021-11-15 14:44:30 -03:00
Martin-Molinero
ad865e2a53 Add new CustomWeight, AlphaModel for AlphaStreams (#6052)
- Add new CustomWeight PCM for alpha streams
- Add new AlphaStreams AlphaModule that will handle security additions
  and removals, removing this logic from AlphaStreamsBasicTemplateAlgo
2021-11-15 14:33:16 -03:00
Martin-Molinero
57f0d17c5d Remove user plan enum (#6055)
* Remove user plan enum

- Get maximum order and runtime from job controls
- Remove user plan enum definitions

* Add log for BacktestingSetupHandler maximums
2021-11-12 19:37:23 -03:00
Ricardo Andrés Marino Rojas
d234d69abc Give timer more time (#6053) 2021-11-12 13:41:56 -03:00
Colton Sellers
dd4da7ba95 Feature Daily/Hourly Options Support (#6017)
* Create generic writing for LeanDataWriter, + notes on todos

* Make Options Daily/Hourly data store by year

* Refactor Generic Write

* Permit hour and daily resolutions for options

* Refactor writer to merge when needed with other files

* Cleanup redundancies, run write tasks in parallel

* Make needed classes/vars available

* Update tests to reflect new naming convention for daily hourly options data

* Add Byte[] overloads for ZipData functions in compression

* Implemented Store() for ZipDataCacheProvider

* Have LeanDataWriter use a DataCacheProvider

* ZipDataCacheProvider cleanup

* ZipDataCacheProvider tweaks, doesn't support storing non-zips

* Test adjustments

* Update LeanDataWriter to use Write instead of SaveDailyHourly/SaveMinuteSecond

* Implement tests to verify DownloadAndSave behavior

* Nit cleanup on DownloadAndSave tests

* Fix for options daily/hourly underlying equity subscription read

* Add daily/hourly options data and regressions

* Add missing open interest for hourly

* Fix writing of OpenInterest Daily/Hourly data

* Update data

* Fix Date typo in regression

* Use daily algorithm to test delisting

* Revisions part 1

* Expand test for DataCacheProviders; refactor DiskDataCacheProvider

* nit - test adjustments

* ZipDataCacheProvider test setup refactor

* Adjust multithreaded read/write test; fixes for ZipDataCacheProvider

* Move DiskDataCacheProvider to its own file and add write test

* Remove _appendToZips; always overwrite entry or create zip

* Add mapping regression for daily options

* nit - add license to regression

* Fix Tick write case where more than one data point for a DateTime

* Fix data issue

* Address review

* Tweaks for tests

* Stop Store() early if no entry name is given
2021-11-11 20:05:31 -03:00
Martin-Molinero
27f5223cd2 Pin dotnet interactive version for net5 (#6048) 2021-11-10 13:00:59 -03:00
Adalyat Nazirov
b3d3df3a3c rate limit is dependent on Account Tier, Tier1 by default (#6046) 2021-11-09 16:44:29 -03:00
Ricardo Andrés Marino Rojas
3c1ddb7b96 Enable Warm Up process in MacdAlphaModel (#6037)
* Warm up MACD indicators
- When a security is added in the MACD alpha model, it's warm up at once

* Add unit tests

* Nit change

* Code style and nit changes
2021-11-04 12:15:32 -03:00
Ronit Jain
926ac3879a Add try-catch and null check (#6038) 2021-11-03 20:07:47 -03:00
Martin-Molinero
0327b2012c Add default value for Exchange security types (#6032) 2021-11-01 12:05:15 -03:00
Martin-Molinero
cd5e1d9c54 Can serialize unknown exchange. Adding test (#6031) 2021-10-29 09:13:52 -07:00
Ricardo Andrés Marino Rojas
fc6ddc2120 Feature 5988 WarmUpIndicator() method for indicators written in Python (#6027)
* Implement IIndicatorWarmUpPeriodProvider
- Implement IIndicatorWarmUpPeriodProvider in PythonIndicator.cs
- Make a unit test to check whether the WarmUpPeriod is working as expected
- Make a regression test to check the new feature at a system level

* Nit change

* Change Period parameter for WarmUpPeriod parameter
- Change regression test to check if the new parameter keep backwards compatibility with indicators that do not set WarmUpPeriod

* Documentation change

* Fix tests bugs
- In CommonIndicatorTests.cs before finish the test it checks the period.value with the number of samples but for default the period.value was set to -1

* Change names

* Change WarmUp and RegisterIndicator methods
- Lean WarmUp indicator skip custom python indicators that don't define WarmUpPeriod parameter

* Call WarmUpIndicator manually
- Add a new "bridge" method called WarmUpIndicator in QCAlgorithm.Python.cs to set up everything to call WarmUpIndicator in QCAlgorithm.Indicators.cs
- Change the regression algorithm to warm up the indicators manually

* Remove unnecessary code and add more tests

* Nit change

* Revert "Nit change"

This reverts commit da411f59c9.

* Fix bugs

* Try fix bugs

* Add C# regression test
- More nit changes
- Fix bugs

* Requested changes

* Remove unnecessary code

* Requested changes

* Nit changes
- Add new Python class to check a custom indicator, which doesn't inherits from PythonIndicator, warms up properly

* Reduce redundant code

* Fix bug and add more unit and regression tests

* - Add more unit tests

* Nit change

* Test cleanup

Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2021-10-28 20:29:22 -03:00
Ricardo Andrés Marino Rojas
013b9ea850 Set WarmUpPeriod value in MarketProfile constructor (#6029)
- Remove unnecessary attribute `_period` in MarketProfile
- Set the value of WarmUpPeriod to the period in MarketProfile constructor
- Fix unit test to check VolumeProfile and TimeProfile indicators are being warmed up properly and its WarmUpPeriod parameter isn't zero
2021-10-28 19:54:11 -03:00
Martin-Molinero
9f29e3bf4e Some performance improvements for IndexOptions (#6025)
- Some performance improvements for IndexOptions specially affects
  debugging C# algorithms.
2021-10-27 20:26:51 -03:00
Alexandre Catarino
4ecdf14ce8 Include Security Master Url to ApiDataProvider Error Message (#6023) 2021-10-27 14:58:15 -03:00
Martin-Molinero
ede2d4a5e4 Lazy loading of the SecurityDefinition file (#6024)
- Perform a lazy loading of the security definitions file. Adding unit
  tests
2021-10-27 14:57:50 -03:00
Martin-Molinero
8c71dbc8ba Revert "Feature 5988 IIndicatorWarmUpPeriodProvider for custom PythonIndicator (#5992)" (#6022)
This reverts commit 995f598999.
2021-10-26 22:07:22 -03:00
Martin-Molinero
d17865b2cf CoinApi read previous date file (#6019)
- If available, CoinApi converter will read previous date files to
  rescue initial midnight ticks for the processing date. Also make sure
  to drop ticks from tomorrow
2021-10-25 20:26:12 -03:00
Martin-Molinero
7b3b560dea Foundation update CVXPY 1.1.15 (#6020)
- Update cvxpy python package version to latest 1.1.15. To avoid
  installation issue `error in cvxpy setup command: use_2to3 is invalid`
2021-10-25 18:45:07 -03:00
Ricardo Andrés Marino Rojas
995f598999 Feature 5988 IIndicatorWarmUpPeriodProvider for custom PythonIndicator (#5992)
* Implement IIndicatorWarmUpPeriodProvider
- Implement IIndicatorWarmUpPeriodProvider in PythonIndicator.cs
- Make a unit test to check whether the WarmUpPeriod is working as expected
- Make a regression test to check the new feature at a system level

* Nit change

* Change Period parameter for WarmUpPeriod parameter
- Change regression test to check if the new parameter keep backwards compatibility with indicators that do not set WarmUpPeriod

* Documentation change

* Fix tests bugs
- In CommonIndicatorTests.cs before finish the test it checks the period.value with the number of samples but for default the period.value was set to -1

* Change names

* Change WarmUp and RegisterIndicator methods
- Lean WarmUp indicator skip custom python indicators that don't define WarmUpPeriod parameter

* Call WarmUpIndicator manually
- Add a new "bridge" method called WarmUpIndicator in QCAlgorithm.Python.cs to set up everything to call WarmUpIndicator in QCAlgorithm.Indicators.cs
- Change the regression algorithm to warm up the indicators manually

* Remove unnecessary code and add more tests

* Nit change

* Revert "Nit change"

This reverts commit da411f59c9.

* Fix bugs

* Try fix bugs

* Add C# regression test
- More nit changes
- Fix bugs

* Requested changes

* Remove unnecessary code

* Requested changes

* Nit changes
- Add new Python class to check a custom indicator, which doesn't inherits from PythonIndicator, warms up properly

* Reduce redundant code
2021-10-25 18:08:57 -03:00
Martin-Molinero
43c271a568 Atreyu template algorithm change traget SPY exchange (#6016) 2021-10-25 15:43:35 -03:00
IlshatGaripov
2e4252c92b LiveTradingResultHandler -> changes access modifier of SetNextStatusUpdate (#6015) 2021-10-25 11:17:35 -03:00
Adalyat Nazirov
0f189aa2b4 FTX brokerage rejects STOP order if market price missed (#6009)
* cannot submit stop orders with bad trigger price

* unit tests

* expect price data
2021-10-25 11:14:41 -03:00
IlshatGaripov
f55588e4c6 SecurityHolding -> impl. ToString() (#6014) 2021-10-25 11:07:34 -03:00
Martin-Molinero
58ccdee1b1 PythonNet version bump 2.0.10 (#6010) 2021-10-22 20:27:38 -03:00
Colton Sellers
6bd2859f64 Update to PythonNet 2.0.9 (#6004) 2021-10-21 20:06:38 -03:00
Alexandre Catarino
3ff7882dbf Round AverageLoss to Avoid Very Small Numbers (#6003) 2021-10-21 17:00:31 -03:00
Martin-Molinero
dace6d7ee1 Fix index live target exchange (#6000) 2021-10-20 17:26:25 -03:00
Colton Sellers
71d9eed07e BuyingPowerModel Fixes (#5996)
* Refactor error message for reproducability

* WIP Refactor GetMaximumOrderQuantityForTargetBuyingPower

* Additional tweaks and tests

* Address shorted margin case

* Reinstate tests with new modified function

* Update regression

* Some cleanup

* Expand test set

* Refactor solution

* Address review

* Final adjustments and cleanup

* Expand error message for GetAmountToOrder for safety and reproducibility

* Address reviews
2021-10-20 16:37:20 -03:00
Stas Kotykhin
c4a4550a66 Override History provider in kraken environment (#5998)
* add history-provider field to config.json

* Add comment
2021-10-20 16:36:34 -03:00
bmello4688
67081a8a05 Add virtual overrides for pivotpointshighlow computations (#5987)
* Add base class for pivotpointshighlow

* abstracts do not work well with python switch to virtuals and use pivotpointhighlow as base implementation

* added missing documentatino header

* moved reset back to original location
2021-10-19 21:45:18 -03:00
542 changed files with 17726 additions and 5049 deletions

View File

@@ -0,0 +1,131 @@
/*
* 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.Interfaces;
using System.Collections.Generic;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm reproducing GH issue #5971 where we add and remove an option in the same loop
/// </summary>
public class AddAndRemoveSecuritySameLoopRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _contract;
private bool _hasRemoved;
public override void Initialize()
{
SetStartDate(2014, 06, 06);
SetEndDate(2014, 06, 09);
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
UniverseSettings.MinimumTimeInUniverse = TimeSpan.Zero;
var aapl = AddEquity("AAPL").Symbol;
_contract = OptionChainProvider.GetOptionContractList(aapl, Time)
.OrderBy(symbol => symbol.ID.Symbol)
.FirstOrDefault(optionContract => optionContract.ID.OptionRight == OptionRight.Call
&& optionContract.ID.OptionStyle == OptionStyle.American);
}
public override void OnData(Slice slice)
{
if (_hasRemoved)
{
throw new Exception("Expect a single call to OnData where we removed the option and underlying");
}
_hasRemoved = true;
AddOptionContract(_contract);
// changed my mind!
RemoveOptionContract(_contract);
RemoveSecurity(_contract.Underlying);
RemoveSecurity(AddEquity("SPY", Resolution.Daily).Symbol);
}
public override void OnEndOfAlgorithm()
{
if (!_hasRemoved)
{
throw new Exception("We did not remove the option contract!");
}
}
/// <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>
/// 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", "-9.486"},
{"Tracking Error", "0.008"},
{"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,151 @@
/*
* 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.Indicators;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression test to explain how Beta indicator works
/// </summary>
public class AddBetaIndicatorRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Beta _beta;
private SimpleMovingAverage _sma;
private decimal _lastSMAValue;
public override void Initialize()
{
SetStartDate(2013, 10, 07);
SetEndDate(2013, 10, 15);
SetCash(10000);
AddEquity("IBM");
AddEquity("SPY");
EnableAutomaticIndicatorWarmUp = true;
_beta = B("IBM", "SPY", 3, Resolution.Daily);
_sma = SMA("SPY", 3, Resolution.Daily);
_lastSMAValue = 0;
if (!_beta.IsReady)
{
throw new Exception("_beta indicator was expected to be ready");
}
}
public override void OnData(Slice data)
{
if (!Portfolio.Invested)
{
var price = data["IBM"].Close;
Buy("IBM", 10);
LimitOrder("IBM", 10, price * 0.1m);
StopMarketOrder("IBM", 10, price / 0.1m);
}
if (_beta.Current.Value < 0m || _beta.Current.Value > 2.80m)
{
throw new Exception($"_beta value was expected to be between 0 and 2.80 but was {_beta.Current.Value}");
}
Log($"Beta between IBM and SPY is: {_beta.Current.Value}");
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
var order = Transactions.GetOrderById(orderEvent.OrderId);
var goUpwards = _lastSMAValue < _sma.Current.Value;
_lastSMAValue = _sma.Current.Value;
if (order.Status == OrderStatus.Filled)
{
if (order.Type == OrderType.Limit && Math.Abs(_beta.Current.Value - 1) < 0.2m && goUpwards)
{
Transactions.CancelOpenOrders(order.Symbol);
}
}
if (order.Status == OrderStatus.Canceled)
{
Log(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 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>
/// 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", "12.939%"},
{"Drawdown", "0.300%"},
{"Expectancy", "0"},
{"Net Profit", "0.289%"},
{"Sharpe Ratio", "4.233"},
{"Probabilistic Sharpe Ratio", "68.349%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.035"},
{"Beta", "0.122"},
{"Annual Standard Deviation", "0.024"},
{"Annual Variance", "0.001"},
{"Information Ratio", "-3.181"},
{"Tracking Error", "0.142"},
{"Treynor Ratio", "0.842"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$35000000.00"},
{"Lowest Capacity Asset", "IBM R735QTJ8XC9X"},
{"Fitness Score", "0.022"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "8.508"},
{"Return Over Maximum Drawdown", "58.894"},
{"Portfolio Turnover", "0.022"},
{"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", "bd88c6a0e10c7e146b05377205101a12"}
};
}
}

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.Linq;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Interfaces;
using QuantConnect.Securities;
using System.Collections.Generic;
using QuantConnect.Securities.Future;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Continuous Futures Regression algorithm. Asserting and showcasing the behavior of adding a continuous future
/// and a future contract at the same time
/// </summary>
public class AddFutureContractWithContinuousRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _currentMappedSymbol;
private Future _continuousContract;
private Future _futureContract;
private bool _ended;
/// <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, 6);
SetEndDate(2013, 10, 10);
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
dataMappingMode: DataMappingMode.LastTradingDay,
contractDepthOffset: 0
);
_futureContract = AddFutureContract(FutureChainProvider.GetFutureContractList(_continuousContract.Symbol, Time).First());
}
/// <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)
{
if (_ended)
{
throw new Exception($"Algorithm should of ended!");
}
if (data.Keys.Count > 2)
{
throw new Exception($"Getting data for more than 2 symbols! {string.Join(",", data.Keys.Select(symbol => symbol))}");
}
if (UniverseManager.Count != 3)
{
throw new Exception($"Expecting 3 universes (chain, continuous and user defined) but have {UniverseManager.Count}");
}
if (!Portfolio.Invested)
{
Buy(_futureContract.Symbol, 1);
Buy(_continuousContract.Mapped, 1);
RemoveSecurity(_futureContract.Symbol);
RemoveSecurity(_continuousContract.Symbol);
_ended = true;
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status == OrderStatus.Filled)
{
Log($"{orderEvent}");
}
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
Debug($"{Time}-{changes}");
if (changes.AddedSecurities.Any(security => security.Symbol != _continuousContract.Symbol && security.Symbol != _futureContract.Symbol)
|| changes.RemovedSecurities.Any(security => security.Symbol != _continuousContract.Symbol && security.Symbol != _futureContract.Symbol))
{
throw new Exception($"We got an unexpected security changes {changes}");
}
}
/// <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>
/// 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", "3"},
{"Average Win", "0%"},
{"Average Loss", "-0.03%"},
{"Compounding Annual Return", "-2.503%"},
{"Drawdown", "0.000%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.032%"},
{"Sharpe Ratio", "0"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.678"},
{"Tracking Error", "0.243"},
{"Treynor Ratio", "0"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$2100000.00"},
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
{"Fitness Score", "0.419"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-81.557"},
{"Portfolio Turnover", "0.837"},
{"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", "68775c18eb40c1bde212653faec4016e"}
};
}
}

View File

@@ -139,8 +139,8 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.049"},
{"Treynor Ratio", "1.372"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$45000000.00"},
{"Lowest Capacity Asset", "AOL R735QTJ8XC9X"},
{"Estimated Strategy Capacity", "$67000000.00"},
{"Lowest Capacity Asset", "AOL VRKS95ENLBYE|AOL R735QTJ8XC9X"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
@@ -160,7 +160,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "b006bb7864c0b2f1a6552fb2aa7f03b8"}
{"OrderListHash", "4f50b8360ea317ef974801649088bd06"}
};
}
}

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.Linq;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using System.Collections.Generic;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression algorithm reproducing GH issue #6073 where we remove and re add an option and expect it to work
/// </summary>
public class AddOptionContractTwiceRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _contract;
private bool _hasRemoved;
private bool _reAdded;
public override void Initialize()
{
SetStartDate(2014, 06, 06);
SetEndDate(2014, 06, 09);
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
UniverseSettings.MinimumTimeInUniverse = TimeSpan.Zero;
UniverseSettings.FillForward = false;
AddEquity("SPY", Resolution.Daily);
var aapl = QuantConnect.Symbol.Create("AAPL", SecurityType.Equity, Market.USA);
_contract = OptionChainProvider.GetOptionContractList(aapl, Time)
.OrderBy(symbol => symbol.ID.Symbol)
.FirstOrDefault(optionContract => optionContract.ID.OptionRight == OptionRight.Call
&& optionContract.ID.OptionStyle == OptionStyle.American);
AddOptionContract(_contract);
}
public override void OnData(Slice slice)
{
if (_hasRemoved)
{
if (!_reAdded && slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
{
throw new Exception("Getting data for removed option and underlying!");
}
if (!Portfolio.Invested && _reAdded)
{
var option = Securities[_contract];
var optionUnderlying = Securities[_contract.Underlying];
if (option.IsTradable && optionUnderlying.IsTradable
&& slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
{
Buy(_contract, 1);
}
}
if (!Securities[_contract].IsTradable
&& !Securities[_contract.Underlying].IsTradable
&& !_reAdded)
{
// ha changed my mind!
AddOptionContract(_contract);
_reAdded = true;
}
}
if (slice.ContainsKey(_contract) && slice.ContainsKey(_contract.Underlying))
{
if (!_hasRemoved)
{
RemoveOptionContract(_contract);
RemoveSecurity(_contract.Underlying);
_hasRemoved = true;
}
}
}
public override void OnEndOfAlgorithm()
{
if (!_hasRemoved)
{
throw new Exception("We did not remove the option contract!");
}
if (!_reAdded)
{
throw new Exception("We did not re add the option contract!");
}
}
/// <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>
/// 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.05%"},
{"Compounding Annual Return", "-4.548%"},
{"Drawdown", "0.100%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.051%"},
{"Sharpe Ratio", "0"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "-9.486"},
{"Tracking Error", "0.008"},
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$30000.00"},
{"Lowest Capacity Asset", "AAPL VXBK4Q9ZIFD2|AAPL R735QTJ8XC9X"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-89.181"},
{"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", "7fbcd12db40304d50b3a34d7878eb3cf"}
};
}
}

View File

@@ -30,7 +30,7 @@ namespace QuantConnect.Algorithm.CSharp
{
private Symbol _aapl;
private const string Ticker = "AAPL";
private FactorFile _factorFile;
private CorporateFactorProvider _factorFile;
private readonly IEnumerator<decimal> _expectedAdjustedVolume = new List<decimal> { 6164842, 3044047, 3680347, 3468303, 2169943, 2652523,
1499707, 1518215, 1655219, 1510487 }.GetEnumerator();
private readonly IEnumerator<decimal> _expectedAdjustedAskSize = new List<decimal> { 215600, 5600, 25200, 8400, 5600, 5600, 2800,
@@ -56,7 +56,7 @@ namespace QuantConnect.Algorithm.CSharp
factorFileProvider.Initialize(mapFileProvider, dataProvider);
_factorFile = factorFileProvider.Get(_aapl);
_factorFile = factorFileProvider.Get(_aapl) as CorporateFactorProvider;
}
/// <summary>
@@ -83,7 +83,7 @@ namespace QuantConnect.Algorithm.CSharp
if (_expectedAdjustedVolume.MoveNext() && _expectedAdjustedVolume.Current != aaplData.Volume)
{
// Our values don't match lets try and give a reason why
var dayFactor = _factorFile.GetSplitFactor(aaplData.Time);
var dayFactor = _factorFile.GetPriceScale(aaplData.Time, DataNormalizationMode.SplitAdjusted);
var probableAdjustedVolume = aaplData.Volume / dayFactor;
if (_expectedAdjustedVolume.Current == probableAdjustedVolume)
@@ -107,7 +107,7 @@ namespace QuantConnect.Algorithm.CSharp
if (_expectedAdjustedAskSize.MoveNext() && _expectedAdjustedAskSize.Current != aaplQuoteData.LastAskSize)
{
// Our values don't match lets try and give a reason why
var dayFactor = _factorFile.GetSplitFactor(aaplQuoteData.Time);
var dayFactor = _factorFile.GetPriceScale(aaplQuoteData.Time, DataNormalizationMode.SplitAdjusted);
var probableAdjustedAskSize = aaplQuoteData.LastAskSize / dayFactor;
if (_expectedAdjustedAskSize.Current == probableAdjustedAskSize)
@@ -126,7 +126,7 @@ namespace QuantConnect.Algorithm.CSharp
if (_expectedAdjustedBidSize.MoveNext() && _expectedAdjustedBidSize.Current != aaplQuoteData.LastBidSize)
{
// Our values don't match lets try and give a reason why
var dayFactor = _factorFile.GetSplitFactor(aaplQuoteData.Time);
var dayFactor = _factorFile.GetPriceScale(aaplQuoteData.Time, DataNormalizationMode.SplitAdjusted);
var probableAdjustedBidSize = aaplQuoteData.LastBidSize / dayFactor;
if (_expectedAdjustedBidSize.Current == probableAdjustedBidSize)

View File

@@ -13,15 +13,12 @@
* limitations under the License.
*/
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Interfaces;
using QuantConnect.Brokerages;
using QuantConnect.Securities;
using System.Collections.Generic;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Data.Custom.AlphaStreams;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Portfolio;
@@ -32,8 +29,6 @@ namespace QuantConnect.Algorithm.CSharp
/// </summary>
public class AlphaStreamsBasicTemplateAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Dictionary<Symbol, HashSet<Symbol>> _symbolsPerAlpha = new Dictionary<Symbol, HashSet<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>
@@ -42,10 +37,10 @@ namespace QuantConnect.Algorithm.CSharp
SetStartDate(2018, 04, 04);
SetEndDate(2018, 04, 06);
SetAlpha(new AlphaStreamAlphaModule());
SetExecution(new ImmediateExecutionModel());
Settings.MinimumOrderMarginPortfolioPercentage = 0.01m;
SetPortfolioConstruction(new EqualWeightingAlphaStreamsPortfolioConstructionModel());
SetSecurityInitializer(new BrokerageModelSecurityInitializer(BrokerageModel,
new FuncSecuritySeeder(GetLastKnownPrices)));
@@ -55,77 +50,11 @@ namespace QuantConnect.Algorithm.CSharp
}
}
/// <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 portfolioState in data.Get<AlphaStreamsPortfolioState>().Values)
{
ProcessPortfolioState(portfolioState);
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Log($"OnOrderEvent: {orderEvent}");
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
changes.FilterCustomSecurities = false;
foreach (var addedSecurity in changes.AddedSecurities)
{
if (addedSecurity.Symbol.IsCustomDataType<AlphaStreamsPortfolioState>())
{
if (!_symbolsPerAlpha.ContainsKey(addedSecurity.Symbol))
{
_symbolsPerAlpha[addedSecurity.Symbol] = new HashSet<Symbol>();
}
// warmup alpha state, adding target securities
ProcessPortfolioState(addedSecurity.Cache.GetData<AlphaStreamsPortfolioState>());
}
}
Log($"OnSecuritiesChanged: {changes}");
}
private bool UsedBySomeAlpha(Symbol asset)
{
return _symbolsPerAlpha.Any(pair => pair.Value.Contains(asset));
}
private void ProcessPortfolioState(AlphaStreamsPortfolioState portfolioState)
{
if (portfolioState == null)
{
return;
}
var alphaId = portfolioState.Symbol;
if (!_symbolsPerAlpha.TryGetValue(alphaId, out var currentSymbols))
{
_symbolsPerAlpha[alphaId] = currentSymbols = new HashSet<Symbol>();
}
var newSymbols = new HashSet<Symbol>(currentSymbols.Count);
foreach (var symbol in portfolioState.PositionGroups?.SelectMany(positionGroup => positionGroup.Positions).Select(state => state.Symbol) ?? Enumerable.Empty<Symbol>())
{
// only add it if it's not used by any alpha (already added check)
if (newSymbols.Add(symbol) && !UsedBySomeAlpha(symbol))
{
AddSecurity(symbol, resolution: UniverseSettings.Resolution, extendedMarketHours: UniverseSettings.ExtendedMarketHours);
}
}
_symbolsPerAlpha[alphaId] = newSymbols;
foreach (var symbol in currentSymbols.Where(symbol => !UsedBySomeAlpha(symbol)))
{
RemoveSecurity(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>

View File

@@ -14,9 +14,11 @@
*/
using System;
using QuantConnect.Interfaces;
using System.Collections.Generic;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Data.Custom.AlphaStreams;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Selection;
@@ -26,7 +28,7 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Example algorithm consuming an alpha streams portfolio state and trading based on it
/// </summary>
public class AlphaStreamsUniverseSelectionTemplateAlgorithm : AlphaStreamsBasicTemplateAlgorithm
public class AlphaStreamsUniverseSelectionTemplateAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
@@ -36,6 +38,7 @@ namespace QuantConnect.Algorithm.CSharp
SetStartDate(2018, 04, 04);
SetEndDate(2018, 04, 06);
SetAlpha(new AlphaStreamAlphaModule());
SetExecution(new ImmediateExecutionModel());
Settings.MinimumOrderMarginPortfolioPercentage = 0.01m;
SetPortfolioConstruction(new EqualWeightingAlphaStreamsPortfolioConstructionModel());
@@ -65,10 +68,20 @@ namespace QuantConnect.Algorithm.CSharp
}
}
/// <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>
/// 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>
public virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "0%"},

View File

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

View File

@@ -45,7 +45,7 @@ namespace QuantConnect.Algorithm.CSharp
{
// Can specify the default exchange to execute an order on.
// If not specified will default to the primary exchange
Exchange = Exchange.NASDAQ,
Exchange = Exchange.BATS,
// Currently only support order for the day
TimeInForce = TimeInForce.Day
};
@@ -59,7 +59,7 @@ namespace QuantConnect.Algorithm.CSharp
{
if (!Portfolio.Invested)
{
// will set 25% of our buying power with a market order that will be routed to exchange set in the default order properties (NASDAQ)
// will set 25% of our buying power with a market order that will be routed to exchange set in the default order properties (BATS)
SetHoldings("SPY", 0.25m);
// will increase our SPY holdings to 50% of our buying power with a market order that will be routed to ARCA
SetHoldings("SPY", 0.50m, orderProperties: new AtreyuOrderProperties { Exchange = Exchange.ARCA });
@@ -86,10 +86,10 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "93.443%"},
{"Compounding Annual Return", "93.340%"},
{"Drawdown", "1.100%"},
{"Expectancy", "0"},
{"Net Profit", "0.847%"},
{"Net Profit", "0.846%"},
{"Sharpe Ratio", "6.515"},
{"Probabilistic Sharpe Ratio", "67.535%"},
{"Loss Rate", "0%"},
@@ -102,14 +102,14 @@ namespace QuantConnect.Algorithm.CSharp
{"Information Ratio", "6.515"},
{"Tracking Error", "0.11"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.52"},
{"Total Fees", "$1.20"},
{"Estimated Strategy Capacity", "$8600000.00"},
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
{"Fitness Score", "0.124"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "78.376"},
{"Return Over Maximum Drawdown", "78.222"},
{"Portfolio Turnover", "0.124"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -124,7 +124,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "867df80d1338dc526316a01e68435498"}
{"OrderListHash", "01a751a837beafd90015b2fd82edf994"}
};
}
}

View File

@@ -0,0 +1,161 @@
/*
* 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.Orders;
using QuantConnect.Interfaces;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Indicators;
using QuantConnect.Securities;
using QuantConnect.Securities.Future;
using Futures = QuantConnect.Securities.Futures;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Basic Continuous Futures Template Algorithm
/// </summary>
public class BasicTemplateContinuousFutureAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Future _continuousContract;
private Security _currentContract;
private SimpleMovingAverage _fast;
private SimpleMovingAverage _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(2013, 7, 1);
SetEndDate(2014, 1, 1);
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
dataMappingMode: DataMappingMode.LastTradingDay,
contractDepthOffset: 0
);
_fast = SMA(_continuousContract.Symbol, 3, Resolution.Daily);
_slow = SMA(_continuousContract.Symbol, 10, 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)
{
Log($"{Time} - SymbolChanged event: {changedEvent}");
}
if (!Portfolio.Invested)
{
if(_fast > _slow)
{
_currentContract = Securities[_continuousContract.Mapped];
Buy(_currentContract.Symbol, 1);
}
}
else if(_fast < _slow)
{
Liquidate();
}
if (_currentContract != null && _currentContract.Symbol != _continuousContract.Mapped)
{
Log($"{Time} - rolling position from {_currentContract.Symbol} to {_continuousContract.Mapped}");
var currentPositionSize = _currentContract.Holdings.Quantity;
Liquidate(_currentContract.Symbol);
Buy(_continuousContract.Mapped, currentPositionSize);
_currentContract = Securities[_continuousContract.Mapped];
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
Debug($"{orderEvent}");
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
Debug($"{Time}-{changes}");
}
/// <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>
/// 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.00%"},
{"Compounding Annual Return", "-0.007%"},
{"Drawdown", "0.000%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.004%"},
{"Sharpe Ratio", "-0.369"},
{"Probabilistic Sharpe Ratio", "10.640%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "-2.751"},
{"Tracking Error", "0.082"},
{"Treynor Ratio", "-0.616"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
{"Fitness Score", "0.007"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-0.738"},
{"Portfolio Turnover", "0.01"},
{"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", "bd7fbe57802dfedb36c85609b7234016"}
};
}
}

View File

@@ -0,0 +1,152 @@
/*
* 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.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This example demonstrates how to add futures with daily resolution.
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="benchmarks" />
/// <meta name="tag" content="futures" />
public class BasicTemplateFuturesDailyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _contractSymbol;
protected virtual Resolution Resolution => Resolution.Daily;
// S&P 500 EMini futures
private const string RootSP500 = Futures.Indices.SP500EMini;
// Gold futures
private const string RootGold = Futures.Metals.Gold;
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2013, 10, 08);
SetEndDate(2013, 10, 10);
SetCash(1000000);
var futureSP500 = AddFuture(RootSP500, Resolution);
var futureGold = AddFuture(RootGold, Resolution);
// set our expiry filter for this futures chain
// SetFilter method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
futureSP500.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
futureGold.SetFilter(0, 182);
}
/// <summary>
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
/// </summary>
/// <param name="slice">The current slice of data keyed by symbol string</param>
public override void OnData(Slice slice)
{
if (!Portfolio.Invested)
{
foreach(var chain in slice.FutureChains)
{
// find the front contract expiring no earlier than in 90 days
var contract = (
from futuresContract in chain.Value.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Time.Date.AddDays(90)
select futuresContract
).FirstOrDefault();
// if found, trade it
if (contract != null)
{
_contractSymbol = contract.Symbol;
MarketOrder(_contractSymbol, 1);
}
}
}
else
{
Liquidate();
}
}
/// <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>
/// 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", "6"},
{"Average Win", "0%"},
{"Average Loss", "-0.10%"},
{"Compounding Annual Return", "-23.119%"},
{"Drawdown", "0.300%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.276%"},
{"Sharpe Ratio", "-13.736"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.526"},
{"Beta", "0.057"},
{"Annual Standard Deviation", "0.015"},
{"Annual Variance", "0"},
{"Information Ratio", "-31.088"},
{"Tracking Error", "0.189"},
{"Treynor Ratio", "-3.51"},
{"Total Fees", "$11.10"},
{"Estimated Strategy Capacity", "$200000000.00"},
{"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-17.118"},
{"Return Over Maximum Drawdown", "-83.844"},
{"Portfolio Turnover", "0.16"},
{"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", "512f55519e5221c7e82e1d9f5ddd1b9f"}
};
}
}

View File

@@ -0,0 +1,96 @@
/*
* 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.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regressions tests the BasicTemplateFuturesDailyAlgorithm with hour data
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="benchmarks" />
/// <meta name="tag" content="futures" />
public class BasicTemplateFuturesHourlyAlgorithm : BasicTemplateFuturesDailyAlgorithm
{
private Symbol _contractSymbol;
protected override Resolution Resolution => Resolution.Hour;
/// <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 { get; } = 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, Language.Python };
/// <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", "140"},
{"Average Win", "0.01%"},
{"Average Loss", "-0.02%"},
{"Compounding Annual Return", "-38.171%"},
{"Drawdown", "0.400%"},
{"Expectancy", "-0.369"},
{"Net Profit", "-0.394%"},
{"Sharpe Ratio", "-24.82"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "66%"},
{"Win Rate", "34%"},
{"Profit-Loss Ratio", "0.84"},
{"Alpha", "0.42"},
{"Beta", "-0.041"},
{"Annual Standard Deviation", "0.01"},
{"Annual Variance", "0"},
{"Information Ratio", "-65.112"},
{"Tracking Error", "0.253"},
{"Treynor Ratio", "6.024"},
{"Total Fees", "$259.00"},
{"Estimated Strategy Capacity", "$130000.00"},
{"Lowest Capacity Asset", "GC VOFJUCDY9XNH"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-43.422"},
{"Return Over Maximum Drawdown", "-100.459"},
{"Portfolio Turnover", "4.716"},
{"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", "320067074c8dd771f69602ab07001f1e"}
};
}
}

View File

@@ -30,36 +30,39 @@ namespace QuantConnect.Algorithm.CSharp
/// <meta name="tag" content="indexes" />
public class BasicTemplateIndexAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
protected Symbol Spx;
protected Symbol SpxOption;
private ExponentialMovingAverage _emaSlow;
private ExponentialMovingAverage _emaFast;
protected virtual Resolution Resolution => Resolution.Minute;
protected virtual int StartDay => 4;
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 15);
SetStartDate(2021, 1, StartDay);
SetEndDate(2021, 1, 18);
SetCash(1000000);
// Use indicator for signal; but it cannot be traded
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
Spx = AddIndex("SPX", Resolution).Symbol;
// Trade on SPX ITM calls
_spxOption = QuantConnect.Symbol.CreateOption(
_spx,
SpxOption = QuantConnect.Symbol.CreateOption(
Spx,
Market.USA,
OptionStyle.European,
OptionRight.Call,
3200m,
new DateTime(2021, 1, 15));
AddIndexOptionContract(_spxOption, Resolution.Minute);
AddIndexOptionContract(SpxOption, Resolution);
_emaSlow = EMA(_spx, 80);
_emaFast = EMA(_spx, 200);
_emaSlow = EMA(Spx, 80);
_emaFast = EMA(Spx, 200);
}
/// <summary>
@@ -67,7 +70,7 @@ namespace QuantConnect.Algorithm.CSharp
/// </summary>
public override void OnData(Slice slice)
{
if (!slice.Bars.ContainsKey(_spx) || !slice.Bars.ContainsKey(_spxOption))
if (!slice.Bars.ContainsKey(Spx) || !slice.Bars.ContainsKey(SpxOption))
{
return;
}
@@ -80,7 +83,7 @@ namespace QuantConnect.Algorithm.CSharp
if (_emaFast > _emaSlow)
{
SetHoldings(_spxOption, 1);
SetHoldings(SpxOption, 1);
}
else
{
@@ -90,7 +93,7 @@ namespace QuantConnect.Algorithm.CSharp
public override void OnEndOfAlgorithm()
{
if (Portfolio[_spx].TotalSaleVolume > 0)
if (Portfolio[Spx].TotalSaleVolume > 0)
{
throw new Exception("Index is not tradable.");
}
@@ -99,46 +102,46 @@ namespace QuantConnect.Algorithm.CSharp
/// <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;
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 Language[] Languages { get; } = { Language.CSharp, Language.Python };
public virtual Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <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 virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "4"},
{"Average Win", "0%"},
{"Average Loss", "-53.10%"},
{"Compounding Annual Return", "-96.172%"},
{"Compounding Annual Return", "-92.544%"},
{"Drawdown", "10.100%"},
{"Expectancy", "-1"},
{"Net Profit", "-9.915%"},
{"Sharpe Ratio", "-4.068"},
{"Probabilistic Sharpe Ratio", "0.055%"},
{"Sharpe Ratio", "-3.845"},
{"Probabilistic Sharpe Ratio", "0.053%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.745"},
{"Beta", "0.432"},
{"Annual Standard Deviation", "0.126"},
{"Annual Variance", "0.016"},
{"Information Ratio", "-7.972"},
{"Tracking Error", "0.132"},
{"Treynor Ratio", "-1.189"},
{"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"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$14000000.00"},
{"Estimated Strategy Capacity", "$13000000.00"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.044"},
{"Fitness Score", "0.039"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.96"},
{"Return Over Maximum Drawdown", "-10.171"},
{"Portfolio Turnover", "0.34"},
{"Sortino Ratio", "-1.763"},
{"Return Over Maximum Drawdown", "-9.371"},
{"Portfolio Turnover", "0.278"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -152,7 +155,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "52521ab779446daf4d38a7c9bbbdd893"}
{"OrderListHash", "0668385036aba3e95127607dfc2f1a59"}
};
}
}

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using QuantConnect.Data;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression for running an Index algorithm with Daily data
/// </summary>
public class BasicTemplateIndexDailyAlgorithm : BasicTemplateIndexAlgorithm
{
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;
protected int BarCounter = 0;
/// <summary>
/// Purchase a contract when we are not invested, liquidate otherwise
/// </summary>
public override void OnData(Slice slice)
{
if (!Portfolio.Invested)
{
// SPX Index is not tradable, but we can trade an option
MarketOrder(SpxOption, 1);
}
else
{
Liquidate();
}
// Count how many slices we receive with SPX data in it to assert later
if (slice.ContainsKey(Spx))
{
BarCounter++;
}
}
public override void OnEndOfAlgorithm()
{
if (BarCounter != ExpectedBarCount)
{
throw new ArgumentException($"Bar Count {BarCounter} is not expected count of {ExpectedBarCount}");
}
}
/// <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 { get; } = 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>
/// 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", "9"},
{"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%"},
{"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"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
{"Fitness Score", "0.027"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "1776.081"},
{"Portfolio Turnover", "0.027"},
{"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", "474e8e0e28ee84c869f8c69ec3efe371"}
};
}
}

View File

@@ -0,0 +1,72 @@
using System.Collections.Generic;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression for running an Index algorithm with Hourly data
/// </summary>
public class BasicTemplateIndexHourlyAlgorithm : BasicTemplateIndexDailyAlgorithm
{
protected override Resolution Resolution => Resolution.Hour;
protected override int ExpectedBarCount => base.ExpectedBarCount * 8;
/// <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 { get; } = 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>
/// 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", "70"},
{"Average Win", "0%"},
{"Average Loss", "-0.23%"},
{"Compounding Annual Return", "-34.441%"},
{"Drawdown", "2.000%"},
{"Expectancy", "-1"},
{"Net Profit", "-2.028%"},
{"Sharpe Ratio", "-11.139"},
{"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"},
{"Annual Variance", "0.001"},
{"Information Ratio", "-3.624"},
{"Tracking Error", "0.094"},
{"Treynor Ratio", "-3.042"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$310000.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"},
{"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", "3eb56c551f20e2ffa1c56c47c5ee6667"}
};
}
}

View File

@@ -30,20 +30,22 @@ namespace QuantConnect.Algorithm.CSharp
private Symbol _spx;
private ExponentialMovingAverage _emaSlow;
private ExponentialMovingAverage _emaFast;
protected virtual Resolution Resolution => Resolution.Minute;
protected virtual int StartDay => 4;
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetStartDate(2021, 1, StartDay);
SetEndDate(2021, 2, 1);
SetCash(1000000);
// Use indicator for signal; but it cannot be traded.
// We will instead trade on SPX options
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
var spxOptions = AddIndexOption(_spx, Resolution.Minute);
_spx = AddIndex("SPX", Resolution).Symbol;
var spxOptions = AddIndexOption(_spx, Resolution);
spxOptions.SetFilter(filterFunc => filterFunc.CallsOnly());
_emaSlow = EMA(_spx, 80);
@@ -122,17 +124,17 @@ namespace QuantConnect.Algorithm.CSharp
/// <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; } = false;
public virtual bool CanRunLocally { get; } = false;
/// <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 };
public virtual Language[] Languages { get; } = { Language.CSharp, Language.Python };
/// <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 virtual Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "8220"},
{"Average Win", "0.00%"},

View File

@@ -0,0 +1,117 @@
/*
* 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;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression for running an IndexOptions algorithm with Daily data
/// </summary>
public class BasicTemplateIndexOptionsDailyAlgorithm : BasicTemplateIndexOptionsAlgorithm
{
protected override Resolution Resolution => Resolution.Daily;
protected override int StartDay => 1;
/// <summary>
/// Index EMA Cross trading index options of the index.
/// </summary>
public override void OnData(Slice slice)
{
foreach (var chain in slice.OptionChains.Values)
{
// Select the contract with the lowest AskPrice
var contract = chain.Contracts.OrderBy(x => x.Value.AskPrice).FirstOrDefault().Value;
if (contract == null)
{
return;
}
if (Portfolio.Invested)
{
Liquidate();
}
else
{
MarketOrder(contract.Symbol, 1);
}
}
}
/// <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 { get; } = 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>
/// 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", "9"},
{"Average Win", "0%"},
{"Average Loss", "-0.01%"},
{"Compounding Annual Return", "-0.091%"},
{"Drawdown", "0.000%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.008%"},
{"Sharpe Ratio", "-4.033"},
{"Probabilistic Sharpe Ratio", "0.013%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.001"},
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.447"},
{"Tracking Error", "0.136"},
{"Treynor Ratio", "-4.612"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-50718.291"},
{"Return Over Maximum Drawdown", "-11.386"},
{"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", "5f5df233d68d9115a0d81785de54e71d"}
};
}
}

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>
/// Regression for running an IndexOptions algorithm with Hourly data
/// </summary>
public class BasicTemplateIndexOptionsHourlyAlgorithm : BasicTemplateIndexOptionsDailyAlgorithm
{
protected override Resolution Resolution => Resolution.Hour;
/// <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 { get; } = 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>
/// 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", "70"},
{"Average Win", "0.00%"},
{"Average Loss", "0.00%"},
{"Compounding Annual Return", "0%"},
{"Drawdown", "0.000%"},
{"Expectancy", "0.000"},
{"Net Profit", "0%"},
{"Sharpe Ratio", "0"},
{"Probabilistic Sharpe Ratio", "36.504%"},
{"Loss Rate", "97%"},
{"Win Rate", "3%"},
{"Profit-Loss Ratio", "34.00"},
{"Alpha", "0"},
{"Beta", "-0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.449"},
{"Tracking Error", "0.138"},
{"Treynor Ratio", "-0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"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", "f21910eb98ceaa39e02020de95354d86"}
};
}
}

View File

@@ -0,0 +1,171 @@
/*
* 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.Orders;
using QuantConnect.Interfaces;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This example demonstrates how to add options for a given underlying equity security.
/// It also shows how you can prefilter contracts easily based on strikes and expirations, and how you
/// can inspect the option chain to pick a specific option contract to trade.
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="options" />
/// <meta name="tag" content="filter selection" />
public class BasicTemplateOptionsDailyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private const string UnderlyingTicker = "GOOG";
public Symbol OptionSymbol;
private bool _optionExpired;
public override void Initialize()
{
SetStartDate(2015, 12, 23);
SetEndDate(2016, 1, 20);
SetCash(100000);
var equity = AddEquity(UnderlyingTicker, Resolution.Daily);
var option = AddOption(UnderlyingTicker, Resolution.Daily);
OptionSymbol = option.Symbol;
option.SetFilter(x => x.CallsOnly().Strikes(0, 1).Expiration(0, 30));
// use the underlying equity as the benchmark
SetBenchmark(equity.Symbol);
}
/// <summary>
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
/// </summary>
/// <param name="slice">The current slice of data keyed by symbol string</param>
public override void OnData(Slice slice)
{
if (!Portfolio.Invested)
{
OptionChain chain;
if (slice.OptionChains.TryGetValue(OptionSymbol, out chain))
{
// Grab us the contract nearest expiry that is not today
var contractsByExpiration = chain.Where(x => x.Expiry != Time.Date).OrderBy(x => x.Expiry);
var contract = contractsByExpiration.FirstOrDefault();
if (contract != null)
{
// if found, trade it
MarketOrder(contract.Symbol, 1);
}
}
}
}
/// <summary>
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
/// </summary>
/// <param name="orderEvent">Order event details containing details of the evemts</param>
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
public override void OnOrderEvent(OrderEvent orderEvent)
{
Log(orderEvent.ToString());
// Check for our expected OTM option expiry
if (orderEvent.Message == "OTM")
{
// Assert it is at midnight (5AM UTC)
if (orderEvent.UtcTime != new DateTime(2016, 1, 16, 5, 0, 0))
{
throw new ArgumentException($"Expiry event was not at the correct time, {orderEvent.UtcTime}");
}
_optionExpired = true;
}
}
public override void OnEndOfAlgorithm()
{
// Assert we had our option expire and fill a liquidation order
if (_optionExpired != true)
{
throw new ArgumentException("Algorithm did not process the option expiration like 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>
/// 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", "-1.31%"},
{"Compounding Annual Return", "-15.304%"},
{"Drawdown", "1.300%"},
{"Expectancy", "-1"},
{"Net Profit", "-1.311%"},
{"Sharpe Ratio", "-3.31"},
{"Probabilistic Sharpe Ratio", "0.035%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.034"},
{"Annual Variance", "0.001"},
{"Information Ratio", "-3.31"},
{"Tracking Error", "0.034"},
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$18000.00"},
{"Lowest Capacity Asset", "GOOCV W78ZFMML01JA|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.496"},
{"Return Over Maximum Drawdown", "-11.673"},
{"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", "c6d089f1fb86379c74a7413a9c2f8553"}
};
}
}

View File

@@ -41,7 +41,7 @@ namespace QuantConnect.Algorithm.CSharp
public override void Initialize()
{
SetStartDate(2015, 12, 24);
SetEndDate(2015, 12, 24);
SetEndDate(2015, 12, 28);
SetCash(100000);
var equity = AddEquity(UnderlyingTicker);
@@ -104,14 +104,14 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "0%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
{"Net Profit", "0%"},
{"Average Loss", "-0.40%"},
{"Compounding Annual Return", "-21.622%"},
{"Drawdown", "0.300%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.311%"},
{"Sharpe Ratio", "0"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "0%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
@@ -124,12 +124,12 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0"},
{"Fitness Score", "0.188"},
{"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", "-73.268"},
{"Portfolio Turnover", "0.376"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -143,7 +143,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "92d8a50efe230524512404dab66b19dd"}
{"OrderListHash", "452e7a36e0a95e33d3457a908add3ead"}
};
}
}

View File

@@ -36,7 +36,7 @@ namespace QuantConnect.Algorithm.CSharp
UniverseSettings.Resolution = Resolution.Minute;
SetStartDate(2014, 06, 05);
SetEndDate(2014, 06, 06);
SetEndDate(2014, 06, 09);
SetCash(100000);
// set framework models
@@ -142,47 +142,47 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "4"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
{"Average Win", "0.14%"},
{"Average Loss", "-0.28%"},
{"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"},
{"Drawdown", "385.400%"},
{"Expectancy", "-0.249"},
{"Net Profit", "-386.489%"},
{"Sharpe Ratio", "-0.033"},
{"Probabilistic Sharpe Ratio", "1.235%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.50"},
{"Alpha", "-95.983"},
{"Beta", "263.726"},
{"Annual Standard Deviation", "30.617"},
{"Annual Variance", "937.371"},
{"Information Ratio", "-0.044"},
{"Tracking Error", "30.604"},
{"Treynor Ratio", "-0.004"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$74000.00"},
{"Lowest Capacity Asset", "AAPL 2ZQGWTSSZ0WLI|AAPL R735QTJ8XC9X"},
{"Fitness Score", "0"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "AAPL R735QTJ8XC9X"},
{"Fitness Score", "0.168"},
{"Kelly Criterion Estimate", "0.327"},
{"Kelly Criterion Probability Value", "1"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "26"},
{"Return Over Maximum Drawdown", "0"},
{"Portfolio Turnover", "0.224"},
{"Total Insights Generated", "28"},
{"Total Insights Closed", "24"},
{"Total Insights Analysis Completed", "24"},
{"Long Insight Count", "26"},
{"Long Insight Count", "28"},
{"Short Insight Count", "0"},
{"Long/Short Ratio", "100%"},
{"Estimated Monthly Alpha Value", "$31.01809"},
{"Estimated Monthly Alpha Value", "$13.64796"},
{"Total Accumulated Estimated Alpha Value", "$1.89555"},
{"Mean Population Estimated Insight Value", "$0.07898125"},
{"Mean Population Direction", "50%"},
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "50.0482%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "ce06ddfa4b2ffeb666a8910ac8836992"}
{"OrderListHash", "87603bd45898dd9c456745fa51f989a5"}
};
}
}

View File

@@ -0,0 +1,158 @@
/*
* 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.Orders;
using QuantConnect.Interfaces;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This example demonstrates how to add options for a given underlying equity security.
/// It also shows how you can prefilter contracts easily based on strikes and expirations, and how you
/// can inspect the option chain to pick a specific option contract to trade.
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="options" />
/// <meta name="tag" content="filter selection" />
public class BasicTemplateOptionsHourlyAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private const string UnderlyingTicker = "AAPL";
public Symbol OptionSymbol;
public override void Initialize()
{
SetStartDate(2014, 6, 6);
SetEndDate(2014, 6, 9);
SetCash(100000);
var equity = AddEquity(UnderlyingTicker, Resolution.Hour);
var option = AddOption(UnderlyingTicker, Resolution.Hour);
OptionSymbol = option.Symbol;
// set our strike/expiry filter for this option chain
option.SetFilter(u => u.Strikes(-2, +2)
// Expiration method accepts TimeSpan objects or integer for days.
// The following statements yield the same filtering criteria
.Expiration(0, 180));
// .Expiration(TimeSpan.Zero, TimeSpan.FromDays(180)));
// use the underlying equity as the benchmark
SetBenchmark(equity.Symbol);
}
/// <summary>
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
/// </summary>
/// <param name="slice">The current slice of data keyed by symbol string</param>
public override void OnData(Slice slice)
{
if (!Portfolio.Invested && IsMarketOpen(OptionSymbol))
{
OptionChain chain;
if (slice.OptionChains.TryGetValue(OptionSymbol, out chain))
{
// we find at the money (ATM) put contract with farthest expiration
var atmContract = chain
.OrderByDescending(x => x.Expiry)
.ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
.ThenByDescending(x => x.Right)
.FirstOrDefault();
if (atmContract != null)
{
// if found, trade it
MarketOrder(atmContract.Symbol, 1);
MarketOnCloseOrder(atmContract.Symbol, -1);
}
}
}
}
/// <summary>
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
/// </summary>
/// <param name="orderEvent">Order event details containing details of the evemts</param>
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
public override void OnOrderEvent(OrderEvent orderEvent)
{
Log(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 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>
/// 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.07%"},
{"Compounding Annual Return", "-12.496%"},
{"Drawdown", "0.200%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.134%"},
{"Sharpe Ratio", "-8.839"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.083"},
{"Beta", "-0.054"},
{"Annual Standard Deviation", "0.008"},
{"Annual Variance", "0"},
{"Information Ratio", "-18.699"},
{"Tracking Error", "0.155"},
{"Treynor Ratio", "1.296"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$1000.00"},
{"Lowest Capacity Asset", "AAPL 2ZTXYMUAHCIAU|AAPL R735QTJ8XC9X"},
{"Fitness Score", "0.04"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-118.28"},
{"Portfolio Turnover", "0.081"},
{"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", "81e8a822d43de2165c1d3f52964ec312"}
};
}
}

View File

@@ -37,7 +37,7 @@ namespace QuantConnect.Algorithm.CSharp
SetEndDate(2019, 2, 21);
SetCash("EUR", 100000);
_symbol = AddCfd("DE30EUR", Resolution.Minute, Market.Oanda).Symbol;
_symbol = AddCfd("DE30EUR").Symbol;
SetBenchmark(_symbol);
}

View File

@@ -0,0 +1,184 @@
/*
* 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.Securities;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Securities.Future;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Continuous Back Month Raw Futures Regression algorithm. Asserting and showcasing the behavior of adding a continuous future
/// </summary>
public class ContinuousBackMonthRawFutureRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private List<SymbolChangedEvent> _mappings = new();
private Future _continuousContract;
private DateTime _lastDateLog;
/// <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, 7, 1);
SetEndDate(2014, 1, 1);
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.Raw,
dataMappingMode: DataMappingMode.FirstDayMonth,
contractDepthOffset: 1
);
}
/// <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)
{
if (data.Keys.Count != 1)
{
throw new Exception($"We are getting data for more than one symbols! {string.Join(",", data.Keys.Select(symbol => symbol))}");
}
foreach (var changedEvent in data.SymbolChangedEvents.Values)
{
if (changedEvent.Symbol == _continuousContract.Symbol)
{
_mappings.Add(changedEvent);
Log($"SymbolChanged event: {changedEvent}");
var currentExpiration = changedEvent.Symbol.Underlying.ID.Date;
// +4 months cause we are actually using the back month, es is quarterly contract
var frontMonthExpiration = FuturesExpiryFunctions.FuturesExpiryFunction(_continuousContract.Symbol)(Time.AddMonths(1 + 4));
if (currentExpiration != frontMonthExpiration.Date)
{
throw new Exception($"Unexpected current mapped contract expiration {currentExpiration}" +
$" @ {Time} it should be AT front month expiration {frontMonthExpiration}");
}
}
}
if (_lastDateLog.Month != Time.Month && _continuousContract.HasData)
{
_lastDateLog = Time;
Log($"{Time}- {Securities[_continuousContract.Symbol].GetLastData()}");
if (Portfolio.Invested)
{
Liquidate();
}
else
{
// This works because we set this contract as tradable, even if it's a canonical security
Buy(_continuousContract.Symbol, 1);
}
if(Time.Month == 1 && Time.Year == 2013)
{
var response = History(new[] { _continuousContract.Symbol }, 60 * 24 * 90);
if (!response.Any())
{
throw new Exception("Unexpected empty history response");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status == OrderStatus.Filled)
{
Log($"{orderEvent}");
}
}
public override void OnEndOfAlgorithm()
{
var expectedMappingCounts = 2;
if (_mappings.Count != expectedMappingCounts)
{
throw new Exception($"Unexpected symbol changed events: {_mappings.Count}, was expecting {expectedMappingCounts}");
}
}
/// <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>
/// 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", "1.16%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "2.311%"},
{"Drawdown", "1.600%"},
{"Expectancy", "0"},
{"Net Profit", "1.159%"},
{"Sharpe Ratio", "0.753"},
{"Probabilistic Sharpe Ratio", "39.483%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.006"},
{"Beta", "0.099"},
{"Annual Standard Deviation", "0.022"},
{"Annual Variance", "0"},
{"Information Ratio", "-2.732"},
{"Tracking Error", "0.076"},
{"Treynor Ratio", "0.165"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$3900000.00"},
{"Lowest Capacity Asset", "ES 1S1"},
{"Fitness Score", "0.007"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.563"},
{"Return Over Maximum Drawdown", "1.87"},
{"Portfolio Turnover", "0.01"},
{"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", "8aa2ed1319e8bb5beb403476a5aebfef"}
};
}
}

View File

@@ -0,0 +1,197 @@
/*
* 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.Securities;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Securities.Future;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Continuous Futures Back Month #1 Regression algorithm. Asserting and showcasing the behavior of adding a continuous future
/// </summary>
public class ContinuousFutureBackMonthRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private List<SymbolChangedEvent> _mappings = new();
private Future _continuousContract;
private DateTime _lastDateLog;
/// <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, 7, 1);
SetEndDate(2014, 1, 1);
try
{
AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.BackwardsPanamaCanal,
dataMappingMode: DataMappingMode.OpenInterest,
contractDepthOffset: 5
);
throw new Exception("Expected out of rage exception. We don't support that many back months");
}
catch (ArgumentOutOfRangeException)
{
// expected
}
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.BackwardsPanamaCanal,
dataMappingMode: DataMappingMode.OpenInterest,
contractDepthOffset: 1
);
}
/// <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)
{
if (data.Keys.Count != 1)
{
throw new Exception($"We are getting data for more than one symbols! {string.Join(",", data.Keys.Select(symbol => symbol))}");
}
foreach (var changedEvent in data.SymbolChangedEvents.Values)
{
if (changedEvent.Symbol == _continuousContract.Symbol)
{
_mappings.Add(changedEvent);
Log($"SymbolChanged event: {changedEvent}");
var backMonthExpiration = changedEvent.Symbol.Underlying.ID.Date;
var frontMonthExpiration = FuturesExpiryFunctions.FuturesExpiryFunction(_continuousContract.Symbol)(Time.AddMonths(1));
if (backMonthExpiration <= frontMonthExpiration.Date)
{
throw new Exception($"Unexpected current mapped contract expiration {backMonthExpiration}" +
$" @ {Time} it should be AFTER front month expiration {frontMonthExpiration}");
}
}
}
if (_lastDateLog.Month != Time.Month && _continuousContract.HasData)
{
_lastDateLog = Time;
Log($"{Time}- {Securities[_continuousContract.Symbol].GetLastData()}");
if (Portfolio.Invested)
{
Liquidate();
}
else
{
// This works because we set this contract as tradable, even if it's a canonical security
Buy(_continuousContract.Symbol, 1);
}
if(Time.Month == 1 && Time.Year == 2013)
{
var response = History(new[] { _continuousContract.Symbol }, 60 * 24 * 90);
if (!response.Any())
{
throw new Exception("Unexpected empty history response");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status == OrderStatus.Filled)
{
Log($"{orderEvent}");
}
}
public override void OnEndOfAlgorithm()
{
var expectedMappingCounts = 2;
if (_mappings.Count != expectedMappingCounts)
{
throw new Exception($"Unexpected symbol changed events: {_mappings.Count}, was expecting {expectedMappingCounts}");
}
}
/// <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>
/// 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", "3"},
{"Average Win", "1.16%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "2.229%"},
{"Drawdown", "1.600%"},
{"Expectancy", "0"},
{"Net Profit", "1.118%"},
{"Sharpe Ratio", "0.726"},
{"Probabilistic Sharpe Ratio", "38.511%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.007"},
{"Beta", "0.099"},
{"Annual Standard Deviation", "0.022"},
{"Annual Variance", "0"},
{"Information Ratio", "-2.74"},
{"Tracking Error", "0.076"},
{"Treynor Ratio", "0.159"},
{"Total Fees", "$5.55"},
{"Estimated Strategy Capacity", "$290000.00"},
{"Lowest Capacity Asset", "ES 1S1"},
{"Fitness Score", "0.009"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.498"},
{"Return Over Maximum Drawdown", "1.803"},
{"Portfolio Turnover", "0.014"},
{"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", "e669103cc598f59d85f5e8d5f0b8df30"}
};
}
}

View File

@@ -0,0 +1,163 @@
/*
* 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.Interfaces;
using QuantConnect.Securities;
using System.Collections.Generic;
using QuantConnect.Securities.Future;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Continuous Futures History Regression algorithm. Asserting and showcasing the behavior of adding a continuous future
/// </summary>
public class ContinuousFutureHistoryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Future _continuousContract;
private bool _warmedUp;
/// <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, 10);
SetEndDate(2013, 10, 11);
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
dataMappingMode: DataMappingMode.OpenInterest,
contractDepthOffset: 1
);
SetWarmup(10);
}
/// <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)
{
if (IsWarmingUp)
{
// warm up data
_warmedUp = true;
if (!_continuousContract.HasData)
{
throw new Exception($"ContinuousContract did not get any data during warmup!");
}
var backMonthExpiration = data.Keys.Single().Underlying.ID.Date;
var frontMonthExpiration = FuturesExpiryFunctions.FuturesExpiryFunction(_continuousContract.Symbol)(Time.AddMonths(1));
if (backMonthExpiration <= frontMonthExpiration.Date)
{
throw new Exception($"Unexpected current mapped contract expiration {backMonthExpiration}" +
$" @ {Time} it should be AFTER front month expiration {frontMonthExpiration}");
}
}
if (data.Keys.Count != 1)
{
throw new Exception($"We are getting data for more than one symbols! {string.Join(",", data.Keys.Select(symbol => symbol))}");
}
if (!Portfolio.Invested)
{
Buy(_continuousContract.Symbol, 1);
}
}
public override void OnEndOfAlgorithm()
{
if (!_warmedUp)
{
throw new Exception("Algorithm didn't warm up!");
}
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
Debug($"{Time}-{changes}");
if (changes.AddedSecurities.Any(security => security.Symbol != _continuousContract.Symbol)
|| changes.RemovedSecurities.Any(security => security.Symbol != _continuousContract.Symbol))
{
throw new Exception($"We got an unexpected security changes {changes}");
}
}
/// <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>
/// 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", "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", "$1.85"},
{"Estimated Strategy Capacity", "$42000000.00"},
{"Lowest Capacity Asset", "ES 1S1"},
{"Fitness Score", "0.76"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "79228162514264337593543950335"},
{"Portfolio Turnover", "0.76"},
{"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", "4de9344671d542e30066338e2bf9d400"}
};
}
}

View File

@@ -0,0 +1,212 @@
/*
* 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.Securities;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Securities.Future;
using QuantConnect.Data.UniverseSelection;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Continuous Futures Regression algorithm. Asserting and showcasing the behavior of adding a continuous future
/// </summary>
public class ContinuousFutureRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private List<SymbolChangedEvent> _mappings = new();
private Symbol _currentMappedSymbol;
private Future _continuousContract;
private DateTime _lastMonth;
/// <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, 7, 1);
SetEndDate(2014, 1, 1);
_continuousContract = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
dataMappingMode: DataMappingMode.LastTradingDay,
contractDepthOffset: 0
);
}
/// <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)
{
// we subtract a minute cause we can get data on the market close, from the previous minute
if (!_continuousContract.Exchange.DateTimeIsOpen(Time.AddMinutes(-1)))
{
if (data.Bars.Count > 0 || data.QuoteBars.Count > 0)
{
throw new Exception($"We are getting data during closed market!");
}
}
var currentlyMappedSecurity = Securities[_continuousContract.Mapped];
if (data.Keys.Count != 1)
{
throw new Exception($"We are getting data for more than one symbols! {string.Join(",", data.Keys.Select(symbol => symbol))}");
}
foreach (var changedEvent in data.SymbolChangedEvents.Values)
{
if (changedEvent.Symbol == _continuousContract.Symbol)
{
_mappings.Add(changedEvent);
Log($"{Time} - SymbolChanged event: {changedEvent}");
if (_currentMappedSymbol == _continuousContract.Mapped)
{
throw new Exception($"Continuous contract current symbol did not change! {_continuousContract.Mapped}");
}
var currentExpiration = changedEvent.Symbol.Underlying.ID.Date;
var frontMonthExpiration = FuturesExpiryFunctions.FuturesExpiryFunction(_continuousContract.Symbol)(Time.AddMonths(1));
if (currentExpiration != frontMonthExpiration.Date)
{
throw new Exception($"Unexpected current mapped contract expiration {currentExpiration}" +
$" @ {Time} it should be AT front month expiration {frontMonthExpiration}");
}
}
}
if (_lastMonth.Month != Time.Month && currentlyMappedSecurity.HasData)
{
_lastMonth = Time;
Log($"{Time}- {currentlyMappedSecurity.GetLastData()}");
if (Portfolio.Invested)
{
Liquidate();
}
else
{
// This works because we set this contract as tradable, even if it's a canonical security
Buy(currentlyMappedSecurity.Symbol, 1);
}
if(Time.Month == 1 && Time.Year == 2013)
{
var response = History(new[] { _continuousContract.Symbol }, 60 * 24 * 90);
if (!response.Any())
{
throw new Exception("Unexpected empty history response");
}
}
}
_currentMappedSymbol = _continuousContract.Mapped;
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status == OrderStatus.Filled)
{
Log($"{orderEvent}");
}
}
public override void OnSecuritiesChanged(SecurityChanges changes)
{
Debug($"{Time}-{changes}");
if (changes.AddedSecurities.Any(security => security.Symbol != _continuousContract.Symbol)
|| changes.RemovedSecurities.Any(security => security.Symbol != _continuousContract.Symbol))
{
throw new Exception($"We got an unexpected security changes {changes}");
}
}
public override void OnEndOfAlgorithm()
{
var expectedMappingCounts = 2;
if (_mappings.Count != expectedMappingCounts)
{
throw new Exception($"Unexpected symbol changed events: {_mappings.Count}, was expecting {expectedMappingCounts}");
}
}
/// <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>
/// 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", "3"},
{"Average Win", "1.21%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "2.392%"},
{"Drawdown", "1.600%"},
{"Expectancy", "0"},
{"Net Profit", "1.199%"},
{"Sharpe Ratio", "0.775"},
{"Probabilistic Sharpe Ratio", "40.287%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.006"},
{"Beta", "0.099"},
{"Annual Standard Deviation", "0.022"},
{"Annual Variance", "0"},
{"Information Ratio", "-2.726"},
{"Tracking Error", "0.076"},
{"Treynor Ratio", "0.169"},
{"Total Fees", "$5.55"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
{"Fitness Score", "0.01"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.516"},
{"Return Over Maximum Drawdown", "1.935"},
{"Portfolio Turnover", "0.016"},
{"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", "8ad040c62ad255e4f9cd423364147e85"}
};
}
}

View File

@@ -0,0 +1,202 @@
/*
* 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.Market;
using QuantConnect.Interfaces;
using QuantConnect.Indicators;
using QuantConnect.Data;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Regression test to check custom indicators warms up properly
/// when one of them define WarmUpPeriod parameter and the other doesn't
/// </summary>
public class CustomWarmUpPeriodIndicatorAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private CustomSMA _customNotWarmUp;
private CSMAWithWarmUp _customWarmUp;
public override void Initialize()
{
SetStartDate(2013, 10, 7);
SetEndDate(2013, 10, 11);
AddEquity("SPY", Resolution.Second);
// Create two custom indicators, where one of them defines WarmUpPeriod parameter
_customNotWarmUp = new CustomSMA("_customNotWarmUp", 60);
_customWarmUp = new CSMAWithWarmUp("_customWarmUp", 60);
// Register the daily data of "SPY" to automatically update both indicators
RegisterIndicator("SPY", _customWarmUp, Resolution.Minute);
RegisterIndicator("SPY", _customNotWarmUp, Resolution.Minute);
// Warm up _customWarmUp indicator
WarmUpIndicator("SPY", _customWarmUp, Resolution.Minute);
// Check _customWarmUp indicator has already been warmed up with the requested data
if (!_customWarmUp.IsReady)
{
throw new Exception("_customWarmUp indicator was expected to be ready");
}
if (_customWarmUp.Samples != 60)
{
throw new Exception("_customWarmUp indicator was expected to have processed 60 datapoints already");
}
// Try to warm up _customNotWarmUp indicator. It's expected from LEAN to skip the warm up process
// because this indicator doesn't implement IIndicatorWarmUpPeriodProvider
WarmUpIndicator("SPY", _customNotWarmUp, Resolution.Minute);
// Check _customNotWarmUp indicator is not ready, because the warm up process was skipped
if (_customNotWarmUp.IsReady)
{
throw new Exception("_customNotWarmUp indicator wasn't expected to be warmed up");
}
}
public void OnData(TradeBars data)
{
if (!Portfolio.Invested)
{
SetHoldings("SPY", 1);
}
if (Time.Second == 0)
{
// Compute the difference between the indicators values
var diff = Math.Abs(_customNotWarmUp.Current.Value - _customWarmUp.Current.Value);
// Check _customNotWarmUp indicator is ready when the number of samples is bigger than its period
if (_customNotWarmUp.IsReady != (_customNotWarmUp.Samples >= 60))
{
throw new Exception("_customNotWarmUp indicator was expected to be ready when the number of samples were bigger that its WarmUpPeriod parameter");
}
// Check their values are the same when both are ready
if (diff > 1e-10m && _customNotWarmUp.IsReady && _customWarmUp.IsReady)
{
throw new Exception($"The values of the indicators are not the same. The difference is {diff}");
}
}
}
/// <summary>
/// Custom implementation of SimpleMovingAverage.
/// Represents the traditional simple moving average indicator (SMA) without WarmUpPeriod parameter defined
/// </summary>
private class CustomSMA : IndicatorBase<IBaseData>
{
private Queue<IBaseData> _queue;
private int _period;
public CustomSMA(string name, int period)
: base(name)
{
_queue = new Queue<IBaseData>();
_period = period;
}
public override bool IsReady => _queue.Count == _period;
protected override decimal ComputeNextValue(IBaseData input)
{
_queue.Enqueue(input);
if (_queue.Count > _period)
{
_queue.Dequeue();
}
var items = (_queue.ToArray());
var sum = 0m;
Array.ForEach(items, i => sum += i.Value);
return sum / _queue.Count;
}
}
/// <summary>
/// Custom implementation of SimpleMovingAverage.
/// Represents the traditional simple moving average indicator (SMA) with WarmUpPeriod defined
/// </summary>
private class CSMAWithWarmUp : CustomSMA, IIndicatorWarmUpPeriodProvider
{
public CSMAWithWarmUp(string name, int period)
: base(name, period)
{
WarmUpPeriod = period;
}
public int WarmUpPeriod { get; private set; }
}
/// <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>
/// 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", "272.157%"},
{"Drawdown", "2.200%"},
{"Expectancy", "0"},
{"Net Profit", "1.694%"},
{"Sharpe Ratio", "8.897"},
{"Probabilistic Sharpe Ratio", "67.609%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.003"},
{"Beta", "0.998"},
{"Annual Standard Deviation", "0.222"},
{"Annual Variance", "0.049"},
{"Information Ratio", "-14.534"},
{"Tracking Error", "0.001"},
{"Treynor Ratio", "1.98"},
{"Total Fees", "$3.45"},
{"Estimated Strategy Capacity", "$310000000.00"},
{"Lowest Capacity Asset", "SPY R735QTJ8XC9X"},
{"Fitness Score", "0.246"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "9.761"},
{"Return Over Maximum Drawdown", "107.509"},
{"Portfolio Turnover", "0.249"},
{"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", "e10039d74166b161f3ea2851a5e85843"}
};
}
}

View File

@@ -94,14 +94,14 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "1.63%"},
{"Average Win", "1.64%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "7.292%"},
{"Compounding Annual Return", "7.329%"},
{"Drawdown", "1.300%"},
{"Expectancy", "0"},
{"Net Profit", "1.634%"},
{"Sharpe Ratio", "2.351"},
{"Probabilistic Sharpe Ratio", "94.365%"},
{"Net Profit", "1.642%"},
{"Sharpe Ratio", "2.36"},
{"Probabilistic Sharpe Ratio", "94.555%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
@@ -109,17 +109,17 @@ namespace QuantConnect.Algorithm.CSharp
{"Beta", "0.158"},
{"Annual Standard Deviation", "0.03"},
{"Annual Variance", "0.001"},
{"Information Ratio", "-4.444"},
{"Information Ratio", "-4.44"},
{"Tracking Error", "0.075"},
{"Treynor Ratio", "0.439"},
{"Total Fees", "$3.70"},
{"Treynor Ratio", "0.441"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$170000000.00"},
{"Lowest Capacity Asset", "ES VMKLFZIH2MTD"},
{"Fitness Score", "0.019"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "1.362"},
{"Return Over Maximum Drawdown", "9.699"},
{"Sortino Ratio", "1.369"},
{"Return Over Maximum Drawdown", "9.749"},
{"Portfolio Turnover", "0.023"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -134,7 +134,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "00d6dc8775da38f7f79defad06de240a"}
{"OrderListHash", "4c5e32aedcd5bb67642d1629628fe615"}
};
}
}

View File

@@ -137,13 +137,13 @@ namespace QuantConnect.Algorithm.CSharp
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.592"},
{"Beta", "-0.737"},
{"Alpha", "-0.559"},
{"Beta", "-0.807"},
{"Annual Standard Deviation", "1.582"},
{"Annual Variance", "2.502"},
{"Information Ratio", "-0.905"},
{"Tracking Error", "1.592"},
{"Treynor Ratio", "1.292"},
{"Tracking Error", "1.593"},
{"Treynor Ratio", "1.181"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$1000000.00"},
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
@@ -166,7 +166,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "4ae4c1d8e4054c41908fd36e893699a6"}
{"OrderListHash", "721fddfd1327f7adcc2883d1412708c9"}
};
}
}

View File

@@ -140,34 +140,34 @@ namespace QuantConnect.Algorithm.CSharp
/// </summary>
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-3.23%"},
{"Compounding Annual Return", "-79.990%"},
{"Drawdown", "4.300%"},
{"Average Loss", "-5.58%"},
{"Compounding Annual Return", "-87.694%"},
{"Drawdown", "5.600%"},
{"Expectancy", "-1"},
{"Net Profit", "-4.312%"},
{"Sharpe Ratio", "-5.637"},
{"Probabilistic Sharpe Ratio", "0.005%"},
{"Net Profit", "-5.578%"},
{"Sharpe Ratio", "-4.683"},
{"Probabilistic Sharpe Ratio", "0.008%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.5"},
{"Beta", "-0.346"},
{"Annual Standard Deviation", "0.092"},
{"Annual Variance", "0.008"},
{"Information Ratio", "-4.312"},
{"Tracking Error", "0.131"},
{"Treynor Ratio", "1.493"},
{"Total Fees", "$55.05"},
{"Estimated Strategy Capacity", "$43000.00"},
{"Alpha", "-0.622"},
{"Beta", "-0.877"},
{"Annual Standard Deviation", "0.142"},
{"Annual Variance", "0.02"},
{"Information Ratio", "-3.844"},
{"Tracking Error", "0.186"},
{"Treynor Ratio", "0.759"},
{"Total Fees", "$36.70"},
{"Estimated Strategy Capacity", "$65000.00"},
{"Lowest Capacity Asset", "AAA SEVKGI6HF885"},
{"Fitness Score", "0.002"},
{"Fitness Score", "0.003"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-15.687"},
{"Return Over Maximum Drawdown", "-18.549"},
{"Portfolio Turnover", "0.334"},
{"Sortino Ratio", "-10.959"},
{"Return Over Maximum Drawdown", "-15.72"},
{"Portfolio Turnover", "0.224"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -181,7 +181,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "e357cfa77fd5e5b974c68d550fa66490"}
{"OrderListHash", "2d66947eafcca81ba9a2cd3bb351eee2"}
};
}
}

View File

@@ -108,9 +108,9 @@ namespace QuantConnect.Algorithm.CSharp
{"Average Loss", "-0.02%"},
{"Compounding Annual Return", "-0.111%"},
{"Drawdown", "0.100%"},
{"Expectancy", "-0.679"},
{"Net Profit", "-0.112%"},
{"Sharpe Ratio", "-0.966"},
{"Expectancy", "-0.678"},
{"Net Profit", "-0.111%"},
{"Sharpe Ratio", "-0.967"},
{"Probabilistic Sharpe Ratio", "0.000%"},
{"Loss Rate", "80%"},
{"Win Rate", "20%"},
@@ -121,8 +121,8 @@ namespace QuantConnect.Algorithm.CSharp
{"Annual Variance", "0"},
{"Information Ratio", "-1.075"},
{"Tracking Error", "0.107"},
{"Treynor Ratio", "1.354"},
{"Total Fees", "$37.00"},
{"Treynor Ratio", "1.353"},
{"Total Fees", "$14.80"},
{"Estimated Strategy Capacity", "$860000000.00"},
{"Lowest Capacity Asset", "DC V5E8P9SH0U0X"},
{"Fitness Score", "0"},
@@ -144,7 +144,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "de309ab56d2fcd80ff03df2802d9feda"}
{"OrderListHash", "d10e8665214344369e3e8f1c49dbdd67"}
};
}
}

View File

@@ -139,7 +139,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "2b3ac55337ce5619fc0388ccdac72c54"}
{"OrderListHash", "604291218c630343a896bfa2f3104932"}
};
}
}

View File

@@ -119,32 +119,32 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "6"},
{"Average Win", "2.93%"},
{"Average Win", "2.94%"},
{"Average Loss", "-4.15%"},
{"Compounding Annual Return", "-5.673%"},
{"Drawdown", "5.700%"},
{"Expectancy", "-0.148"},
{"Net Profit", "-2.802%"},
{"Sharpe Ratio", "-0.456"},
{"Probabilistic Sharpe Ratio", "9.156%"},
{"Compounding Annual Return", "-5.589%"},
{"Drawdown", "5.600%"},
{"Expectancy", "-0.145"},
{"Net Profit", "-2.760%"},
{"Sharpe Ratio", "-0.45"},
{"Probabilistic Sharpe Ratio", "9.306%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.70"},
{"Profit-Loss Ratio", "0.71"},
{"Alpha", "-0.036"},
{"Beta", "-0.012"},
{"Annual Standard Deviation", "0.08"},
{"Annual Variance", "0.006"},
{"Information Ratio", "-0.15"},
{"Information Ratio", "-0.149"},
{"Tracking Error", "0.387"},
{"Treynor Ratio", "3.008"},
{"Total Fees", "$14.80"},
{"Estimated Strategy Capacity", "$180000000.00"},
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
{"Treynor Ratio", "2.943"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$280000000.00"},
{"Lowest Capacity Asset", "ES XFH59UPBIJ7O|ES XFH59UK0MYO1"},
{"Fitness Score", "0.017"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.097"},
{"Return Over Maximum Drawdown", "-1.002"},
{"Sortino Ratio", "-0.096"},
{"Return Over Maximum Drawdown", "-0.993"},
{"Portfolio Turnover", "0.043"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -159,7 +159,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "fc9eb9b0a644e4890d5ec3d40367d0e1"}
{"OrderListHash", "18f8a17034aa12be40581baecca96788"}
};
}
}

View File

@@ -126,7 +126,7 @@ namespace QuantConnect.Algorithm.CSharp
private void AssertFutureOptionOrderExercise(OrderEvent orderEvent, Security future, Security optionContract)
{
var expectedLiquidationTimeUtc = new DateTime(2020, 6, 19, 20, 0, 0);
var expectedLiquidationTimeUtc = new DateTime(2020, 6, 20, 4, 0, 0);
if (orderEvent.Direction == OrderDirection.Sell && future.Holdings.Quantity != 0)
{
@@ -203,13 +203,13 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"Average Win", "1.22%"},
{"Average Loss", "-7.42%"},
{"Compounding Annual Return", "-12.482%"},
{"Average Win", "1.26%"},
{"Average Loss", "-7.41%"},
{"Compounding Annual Return", "-12.424%"},
{"Drawdown", "6.300%"},
{"Expectancy", "-0.417"},
{"Net Profit", "-6.282%"},
{"Sharpe Ratio", "-1.225"},
{"Expectancy", "-0.415"},
{"Net Profit", "-6.252%"},
{"Sharpe Ratio", "-1.226"},
{"Probabilistic Sharpe Ratio", "0.002%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
@@ -218,12 +218,12 @@ namespace QuantConnect.Algorithm.CSharp
{"Beta", "0.004"},
{"Annual Standard Deviation", "0.07"},
{"Annual Variance", "0.005"},
{"Information Ratio", "-0.284"},
{"Information Ratio", "-0.283"},
{"Tracking Error", "0.379"},
{"Treynor Ratio", "-23.801"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$180000000.00"},
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
{"Treynor Ratio", "-23.811"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$270000000.00"},
{"Lowest Capacity Asset", "ES XFH59UPBIJ7O|ES XFH59UK0MYO1"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
@@ -243,7 +243,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "c59d790b89d76f1ad3bb7738b28567c9"}
{"OrderListHash", "b738fdaf1dae6849884df9e51eb6482b"}
};
}
}

View File

@@ -168,32 +168,32 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"Average Win", "8.71%"},
{"Average Loss", "-34.89%"},
{"Compounding Annual Return", "-50.850%"},
{"Drawdown", "29.200%"},
{"Expectancy", "-0.375"},
{"Net Profit", "-29.224%"},
{"Sharpe Ratio", "-0.977"},
{"Average Win", "8.93%"},
{"Average Loss", "-34.88%"},
{"Compounding Annual Return", "-50.632%"},
{"Drawdown", "29.100%"},
{"Expectancy", "-0.372"},
{"Net Profit", "-29.072%"},
{"Sharpe Ratio", "-0.978"},
{"Probabilistic Sharpe Ratio", "0.012%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.25"},
{"Alpha", "-0.341"},
{"Profit-Loss Ratio", "0.26"},
{"Alpha", "-0.339"},
{"Beta", "0.017"},
{"Annual Standard Deviation", "0.348"},
{"Annual Variance", "0.121"},
{"Information Ratio", "-0.715"},
{"Tracking Error", "0.506"},
{"Treynor Ratio", "-19.652"},
{"Total Fees", "$37.00"},
{"Estimated Strategy Capacity", "$33000000.00"},
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
{"Fitness Score", "0.056"},
{"Annual Standard Deviation", "0.347"},
{"Annual Variance", "0.12"},
{"Information Ratio", "-0.714"},
{"Tracking Error", "0.505"},
{"Treynor Ratio", "-19.672"},
{"Total Fees", "$9.25"},
{"Estimated Strategy Capacity", "$50000000.00"},
{"Lowest Capacity Asset", "ES XFH59UPBIJ7O|ES XFH59UK0MYO1"},
{"Fitness Score", "0.055"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.155"},
{"Return Over Maximum Drawdown", "-1.741"},
{"Return Over Maximum Drawdown", "-1.743"},
{"Portfolio Turnover", "0.152"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -208,7 +208,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "ca0898608da51d972723b1065a3f0d47"}
{"OrderListHash", "ed0cbd8487dd45519e5d0225e51ba29c"}
};
}
}

View File

@@ -179,11 +179,11 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-4.03%"},
{"Compounding Annual Return", "-8.103%"},
{"Average Loss", "-4.02%"},
{"Compounding Annual Return", "-8.099%"},
{"Drawdown", "4.000%"},
{"Expectancy", "-1"},
{"Net Profit", "-4.029%"},
{"Net Profit", "-4.027%"},
{"Sharpe Ratio", "-1.175"},
{"Probabilistic Sharpe Ratio", "0.009%"},
{"Loss Rate", "100%"},
@@ -195,8 +195,8 @@ namespace QuantConnect.Algorithm.CSharp
{"Annual Variance", "0.002"},
{"Information Ratio", "-0.206"},
{"Tracking Error", "0.376"},
{"Treynor Ratio", "-23.48"},
{"Total Fees", "$3.70"},
{"Treynor Ratio", "-23.481"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$200000000.00"},
{"Lowest Capacity Asset", "ES XFH59UPHGV9G|ES XFH59UK0MYO1"},
{"Fitness Score", "0"},
@@ -218,7 +218,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "5dc2591837f882d173d2d4852b3b0626"}
{"OrderListHash", "cf1c12b839e49456dc2793f0e63c7803"}
};
}
}

View File

@@ -0,0 +1,169 @@
/*
* 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 System.Reflection;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests using FutureOptions daily resolution
/// </summary>
public class FutureOptionDailyRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
protected OrderTicket Ticket;
protected Symbol DcOption;
protected virtual Resolution Resolution => Resolution.Daily;
public override void Initialize()
{
SetStartDate(2012, 1, 3);
SetEndDate(2012, 1, 4);
// Add our underlying future contract
var dc = AddFutureContract(
QuantConnect.Symbol.CreateFuture(
Futures.Dairy.ClassIIIMilk,
Market.CME,
new DateTime(2012, 4, 1)),
Resolution).Symbol;
// Attempt to fetch a specific future option contract
DcOption = OptionChainProvider.GetOptionContractList(dc, Time)
.Where(x => x.ID.StrikePrice == 17m && x.ID.OptionRight == OptionRight.Call)
.Select(x => AddFutureOptionContract(x, Resolution).Symbol)
.FirstOrDefault();
// Validate it is the expected contract
var expectedContract = QuantConnect.Symbol.CreateOption(dc, Market.CME, OptionStyle.American,
OptionRight.Call, 17m,
new DateTime(2012, 4, 01));
if (DcOption != expectedContract)
{
throw new Exception($"Contract {DcOption} was not the expected contract {expectedContract}");
}
ScheduleBuySell();
}
protected virtual void ScheduleBuySell()
{
// Schedule a purchase of this contract tomorrow at 1AM
Schedule.On(DateRules.Tomorrow, TimeRules.At(1,0,0), () =>
{
Ticket = MarketOrder(DcOption, 1);
});
// Schedule liquidation tomorrow at 6PM
Schedule.On(DateRules.Tomorrow, TimeRules.At(18,0,0), () =>
{
Liquidate();
});
}
public override void OnData(Slice slice)
{
// Assert we are only getting data at 7PM (12AM UTC)
if (slice.Time.Hour != 19)
{
throw new ArgumentException($"Expected data at 7PM each day; instead was {slice.Time}");
}
}
/// <summary>
/// Ran at the end of the algorithm to ensure the algorithm has no holdings
/// </summary>
/// <exception cref="Exception">The algorithm has holdings</exception>
public override void OnEndOfAlgorithm()
{
if (Portfolio.Invested)
{
throw new Exception($"Expected no holdings at end of algorithm, but are invested in: {string.Join(", ", Portfolio.Keys)}");
}
if (Ticket.Status != OrderStatus.Filled)
{
throw new Exception("Future option order failed to fill correctly");
}
}
/// <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>
/// 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", "2"},
{"Average Win", "0%"},
{"Average Loss", "-0.82%"},
{"Compounding Annual Return", "-66.089%"},
{"Drawdown", "0.800%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.824%"},
{"Sharpe Ratio", "-6.993"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0.466"},
{"Beta", "-7.501"},
{"Annual Standard Deviation", "0.092"},
{"Annual Variance", "0.009"},
{"Information Ratio", "-7.586"},
{"Tracking Error", "0.105"},
{"Treynor Ratio", "0.086"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "DC V5E8P9VAH3IC|DC V5E8P9SH0U0X"},
{"Fitness Score", "0.006"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-80.233"},
{"Portfolio Turnover", "0.013"},
{"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", "f00013930ab4c104a6177485d8090b31"}
};
}
}

View File

@@ -0,0 +1,118 @@
/*
* 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 System.Reflection;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests using FutureOptions hourly resolution
/// </summary>
public class FutureOptionHourlyRegressionAlgorithm : FutureOptionDailyRegressionAlgorithm
{
protected override Resolution Resolution => Resolution.Hour;
protected override void ScheduleBuySell()
{
// Schedule a purchase of this contract at Noon
Schedule.On(DateRules.Today, TimeRules.Noon, () =>
{
Ticket = MarketOrder(DcOption, 1);
});
// Schedule liquidation at 6PM
Schedule.On(DateRules.Today, TimeRules.At(18,0,0), () =>
{
Liquidate();
});
}
public override void OnData(Slice slice)
{
// Assert we are only getting data only hourly intervals
if (slice.Time.Minute != 0)
{
throw new ArgumentException($"Expected data only on hourly intervals; instead was {slice.Time}");
}
}
/// <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 { get; } = 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, Language.Python };
/// <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", "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.70"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "DC V5E8P9VAH3IC|DC V5E8P9SH0U0X"},
{"Fitness Score", "0.01"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-101.911"},
{"Portfolio Turnover", "0.02"},
{"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", "665d06e4f758724b5b9576b14fd18743"}
};
}
}

View File

@@ -127,7 +127,7 @@ namespace QuantConnect.Algorithm.CSharp
private void AssertFutureOptionOrderExercise(OrderEvent orderEvent, Security future, Security optionContract)
{
var expectedLiquidationTimeUtc = new DateTime(2020, 6, 19, 20, 0, 0);
var expectedLiquidationTimeUtc = new DateTime(2020, 6, 20, 4, 0, 0);
if (orderEvent.Direction == OrderDirection.Buy && future.Holdings.Quantity != 0)
{
@@ -204,31 +204,31 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"Average Win", "4.15%"},
{"Average Loss", "-8.27%"},
{"Compounding Annual Return", "-8.944%"},
{"Drawdown", "4.500%"},
{"Expectancy", "-0.249"},
{"Net Profit", "-4.457%"},
{"Sharpe Ratio", "-1.282"},
{"Average Win", "4.18%"},
{"Average Loss", "-8.26%"},
{"Compounding Annual Return", "-8.884%"},
{"Drawdown", "4.400%"},
{"Expectancy", "-0.247"},
{"Net Profit", "-4.427%"},
{"Sharpe Ratio", "-1.283"},
{"Probabilistic Sharpe Ratio", "0.001%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.50"},
{"Alpha", "-0.062"},
{"Beta", "0.003"},
{"Profit-Loss Ratio", "0.51"},
{"Alpha", "-0.061"},
{"Beta", "0.002"},
{"Annual Standard Deviation", "0.048"},
{"Annual Variance", "0.002"},
{"Information Ratio", "-0.222"},
{"Information Ratio", "-0.221"},
{"Tracking Error", "0.376"},
{"Treynor Ratio", "-24.53"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$220000000.00"},
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
{"Treynor Ratio", "-24.544"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$330000000.00"},
{"Lowest Capacity Asset", "ES 31EL5FAOOQON8|ES XFH59UK0MYO1"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.224"},
{"Sortino Ratio", "-0.225"},
{"Return Over Maximum Drawdown", "-2.009"},
{"Portfolio Turnover", "0.023"},
{"Total Insights Generated", "0"},
@@ -244,7 +244,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "d3fa88c3acadb9345ceac76a2dd3b520"}
{"OrderListHash", "99f96f433bc76c31cb25bcd9117a6bf1"}
};
}
}

View File

@@ -178,11 +178,11 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "2"},
{"Average Win", "0%"},
{"Average Loss", "-5.12%"},
{"Compounding Annual Return", "-10.230%"},
{"Average Loss", "-5.11%"},
{"Compounding Annual Return", "-10.226%"},
{"Drawdown", "5.100%"},
{"Expectancy", "-1"},
{"Net Profit", "-5.116%"},
{"Net Profit", "-5.114%"},
{"Sharpe Ratio", "-1.164"},
{"Probabilistic Sharpe Ratio", "0.009%"},
{"Loss Rate", "100%"},
@@ -195,7 +195,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Information Ratio", "-0.243"},
{"Tracking Error", "0.378"},
{"Treynor Ratio", "-23.284"},
{"Total Fees", "$3.70"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$360000000.00"},
{"Lowest Capacity Asset", "ES 31EL5FBZBMXES|ES XFH59UK0MYO1"},
{"Fitness Score", "0"},
@@ -217,7 +217,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "a35054d03fd2caa0a96cbe12e427e928"}
{"OrderListHash", "ec799886c15ac6c4b8fb3d873d7e6b14"}
};
}
}

View File

@@ -189,31 +189,31 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "3"},
{"Average Win", "10.05%"},
{"Average Loss", "-5.63%"},
{"Compounding Annual Return", "8.083%"},
{"Average Loss", "-5.60%"},
{"Compounding Annual Return", "8.148%"},
{"Drawdown", "0.500%"},
{"Expectancy", "0.393"},
{"Net Profit", "3.855%"},
{"Sharpe Ratio", "1.087"},
{"Probabilistic Sharpe Ratio", "53.360%"},
{"Expectancy", "0.397"},
{"Net Profit", "3.886%"},
{"Sharpe Ratio", "1.088"},
{"Probabilistic Sharpe Ratio", "53.421%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "1.79"},
{"Alpha", "0.057"},
{"Beta", "-0.002"},
{"Annual Standard Deviation", "0.052"},
{"Annual Standard Deviation", "0.053"},
{"Annual Variance", "0.003"},
{"Information Ratio", "0.093"},
{"Information Ratio", "0.094"},
{"Tracking Error", "0.379"},
{"Treynor Ratio", "-23.26"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$200000000.00"},
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
{"Treynor Ratio", "-23.276"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$300000000.00"},
{"Lowest Capacity Asset", "ES XFH59UP5K75W|ES XFH59UK0MYO1"},
{"Fitness Score", "0.02"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "17.201"},
{"Return Over Maximum Drawdown", "17.34"},
{"Portfolio Turnover", "0.02"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -228,7 +228,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "8e380e4d5c5e3e145ba388f7853829bb"}
{"OrderListHash", "8a33f32b29bcc66d4dd779b36df9a010"}
};
}
}

View File

@@ -173,12 +173,12 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "2"},
{"Average Win", "1.81%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "3.752%"},
{"Compounding Annual Return", "3.756%"},
{"Drawdown", "0.000%"},
{"Expectancy", "0"},
{"Net Profit", "1.809%"},
{"Net Profit", "1.811%"},
{"Sharpe Ratio", "1.183"},
{"Probabilistic Sharpe Ratio", "60.809%"},
{"Probabilistic Sharpe Ratio", "60.811%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
@@ -188,15 +188,15 @@ namespace QuantConnect.Algorithm.CSharp
{"Annual Variance", "0"},
{"Information Ratio", "0.012"},
{"Tracking Error", "0.375"},
{"Treynor Ratio", "-24.051"},
{"Total Fees", "$3.70"},
{"Treynor Ratio", "-24.052"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$78000000.00"},
{"Lowest Capacity Asset", "ES XFH59UPNF7B8|ES XFH59UK0MYO1"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "95.495"},
{"Return Over Maximum Drawdown", "95.594"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -211,7 +211,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "35baadd70ec72c735eadbf55d702fe04"}
{"OrderListHash", "8cb012d36057103bf26a897fe5fa54d6"}
};
}
}

View File

@@ -185,32 +185,32 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"Average Win", "10.18%"},
{"Average Loss", "-8.05%"},
{"Compounding Annual Return", "2.726%"},
{"Average Win", "10.19%"},
{"Average Loss", "-8.02%"},
{"Compounding Annual Return", "2.790%"},
{"Drawdown", "0.500%"},
{"Expectancy", "0.133"},
{"Net Profit", "1.318%"},
{"Sharpe Ratio", "0.855"},
{"Probabilistic Sharpe Ratio", "42.696%"},
{"Expectancy", "0.135"},
{"Net Profit", "1.348%"},
{"Sharpe Ratio", "0.862"},
{"Probabilistic Sharpe Ratio", "42.945%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "1.27"},
{"Alpha", "0.019"},
{"Alpha", "0.02"},
{"Beta", "-0.001"},
{"Annual Standard Deviation", "0.022"},
{"Annual Variance", "0"},
{"Information Ratio", "-0.007"},
{"Annual Standard Deviation", "0.023"},
{"Annual Variance", "0.001"},
{"Information Ratio", "-0.006"},
{"Tracking Error", "0.375"},
{"Treynor Ratio", "-20.534"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$130000000.00"},
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
{"Treynor Ratio", "-20.61"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$200000000.00"},
{"Lowest Capacity Asset", "ES 31EL5FAOUP0P0|ES XFH59UK0MYO1"},
{"Fitness Score", "0.021"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "5.725"},
{"Return Over Maximum Drawdown", "5.859"},
{"Portfolio Turnover", "0.022"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -225,7 +225,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "519cc7c39703b6e6913dbe98468da872"}
{"OrderListHash", "eb37251ad1e32dd348af8a69e1888053"}
};
}
}

View File

@@ -170,12 +170,12 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "2"},
{"Average Win", "3.28%"},
{"Average Win", "3.29%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "6.865%"},
{"Compounding Annual Return", "6.869%"},
{"Drawdown", "0.000%"},
{"Expectancy", "0"},
{"Net Profit", "3.284%"},
{"Net Profit", "3.286%"},
{"Sharpe Ratio", "1.205"},
{"Probabilistic Sharpe Ratio", "61.483%"},
{"Loss Rate", "0%"},
@@ -188,14 +188,14 @@ namespace QuantConnect.Algorithm.CSharp
{"Information Ratio", "0.07"},
{"Tracking Error", "0.377"},
{"Treynor Ratio", "-24.401"},
{"Total Fees", "$3.70"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$80000000.00"},
{"Lowest Capacity Asset", "ES 31EL5FAJQ6SBO|ES XFH59UK0MYO1"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "150.763"},
{"Return Over Maximum Drawdown", "150.849"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -210,7 +210,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "5571280f1efb15dd3899896fb72385ff"}
{"OrderListHash", "76ed4eaa5f6ed50aa6134aecfbbe9e29"}
};
}
}

View File

@@ -38,7 +38,7 @@ namespace QuantConnect.Algorithm.CSharp
private readonly DateTime _expectedExpiryWarningTime = new DateTime(2020, 6, 19);
private readonly DateTime _expectedExpiryDelistingTime = new DateTime(2020, 6, 20);
private readonly DateTime _expectedLiquidationTime = new DateTime(2020, 6, 19, 16, 0, 0);
private readonly DateTime _expectedLiquidationTime = new DateTime(2020, 6, 20);
public override void Initialize()
{
@@ -183,15 +183,15 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "3"},
{"Average Win", "10.15%"},
{"Average Loss", "-11.34%"},
{"Compounding Annual Return", "-2.578%"},
{"Compounding Annual Return", "-2.573%"},
{"Drawdown", "2.300%"},
{"Expectancy", "-0.053"},
{"Net Profit", "-2.345%"},
{"Expectancy", "-0.052"},
{"Net Profit", "-2.341%"},
{"Sharpe Ratio", "-0.867"},
{"Probabilistic Sharpe Ratio", "0.001%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.89"},
{"Profit-Loss Ratio", "0.90"},
{"Alpha", "-0.014"},
{"Beta", "0.001"},
{"Annual Standard Deviation", "0.016"},
@@ -199,7 +199,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Information Ratio", "-0.603"},
{"Tracking Error", "0.291"},
{"Treynor Ratio", "-13.292"},
{"Total Fees", "$7.40"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$45000000.00"},
{"Lowest Capacity Asset", "ES XFH59UK0MYO1"},
{"Fitness Score", "0.005"},
@@ -221,7 +221,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "0128b145984582f5eba7e95881d9b62d"}
{"OrderListHash", "67d8ad460ff796937ee252c3e4340e62"}
};
}
}

View File

@@ -195,12 +195,12 @@ namespace QuantConnect.Algorithm.CSharp
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "1.836"},
{"Beta", "-0.217"},
{"Beta", "-0.228"},
{"Annual Standard Deviation", "0.345"},
{"Annual Variance", "0.119"},
{"Information Ratio", "4.66"},
{"Tracking Error", "0.382"},
{"Treynor Ratio", "-8.405"},
{"Information Ratio", "4.653"},
{"Tracking Error", "0.383"},
{"Treynor Ratio", "-8.001"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
@@ -223,7 +223,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "6dda4f153b0be9fdf55026da439f90f6"}
{"OrderListHash", "25cc4301125ffaa12dd8d8f4387adf06"}
};
}
}

View File

@@ -173,13 +173,13 @@ namespace QuantConnect.Algorithm.CSharp
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "2.168"},
{"Beta", "-0.226"},
{"Alpha", "2.169"},
{"Beta", "-0.238"},
{"Annual Standard Deviation", "0.373"},
{"Annual Variance", "0.139"},
{"Information Ratio", "5.177"},
{"Tracking Error", "0.408"},
{"Treynor Ratio", "-9.544"},
{"Information Ratio", "5.17"},
{"Tracking Error", "0.409"},
{"Treynor Ratio", "-9.071"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$44000000.00"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
@@ -202,7 +202,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "3cccf8c2409ee8a9020ba79a6c45742a"}
{"OrderListHash", "bd96db56c80107572e8fc13c8794279b"}
};
}
}

View File

@@ -190,7 +190,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Annual Variance", "0"},
{"Information Ratio", "-0.334"},
{"Tracking Error", "0.138"},
{"Treynor Ratio", "-3.273"},
{"Treynor Ratio", "-9.47"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$22000.00"},
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
@@ -213,7 +213,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "177477b78d9264384a09f1607e8c7d11"}
{"OrderListHash", "e971949fb0d1cc8d034ad7cba97d09cc"}
};
}
}

View File

@@ -199,13 +199,13 @@ namespace QuantConnect.Algorithm.CSharp
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.682"},
{"Beta", "0.204"},
{"Alpha", "-0.683"},
{"Beta", "0.218"},
{"Annual Standard Deviation", "0.356"},
{"Annual Variance", "0.126"},
{"Information Ratio", "-1.936"},
{"Tracking Error", "0.371"},
{"Treynor Ratio", "-3.293"},
{"Information Ratio", "-1.94"},
{"Tracking Error", "0.37"},
{"Treynor Ratio", "-3.083"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX 31KC0UJHC75TA|SPX 31"},
@@ -228,7 +228,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "f2d98f952cc0b54fb620795018682105"}
{"OrderListHash", "6df8b200489a2f217cd514592ee98663"}
};
}
}

View File

@@ -189,7 +189,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Annual Variance", "0"},
{"Information Ratio", "-0.595"},
{"Tracking Error", "0.137"},
{"Treynor Ratio", "-5.196"},
{"Treynor Ratio", "-5.349"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
@@ -212,7 +212,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "6faffe52c64c2148458af1d2deb68a6f"}
{"OrderListHash", "b0c50080f0229facd065721f1f5d715e"}
};
}
}

View File

@@ -185,13 +185,13 @@ namespace QuantConnect.Algorithm.CSharp
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.67"},
{"Beta", "0.197"},
{"Alpha", "-0.671"},
{"Beta", "0.211"},
{"Annual Standard Deviation", "0.344"},
{"Annual Variance", "0.118"},
{"Information Ratio", "-1.96"},
{"Tracking Error", "0.361"},
{"Treynor Ratio", "-3.349"},
{"Information Ratio", "-1.963"},
{"Tracking Error", "0.36"},
{"Treynor Ratio", "-3.133"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX XL80P3GHDZXQ|SPX 31"},
@@ -214,7 +214,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "439042b39981ea246e50728cc57c31c7"}
{"OrderListHash", "856448f4cbba4fc39af8dba369c054df"}
};
}
}

View File

@@ -183,7 +183,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Annual Variance", "0"},
{"Information Ratio", "-0.32"},
{"Tracking Error", "0.138"},
{"Treynor Ratio", "-3.277"},
{"Treynor Ratio", "-9.479"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$22000.00"},
{"Lowest Capacity Asset", "SPX XL80P59H5E6M|SPX 31"},
@@ -206,7 +206,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "b55e2b2bd35bc3200e228b4e6e77dd90"}
{"OrderListHash", "76ffdfc100ba7778009e35966bd92cfc"}
};
}
}

View File

@@ -190,12 +190,12 @@ namespace QuantConnect.Algorithm.CSharp
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "1.938"},
{"Beta", "-0.224"},
{"Beta", "-0.235"},
{"Annual Standard Deviation", "0.356"},
{"Annual Variance", "0.127"},
{"Information Ratio", "4.793"},
{"Information Ratio", "4.787"},
{"Tracking Error", "0.393"},
{"Treynor Ratio", "-8.593"},
{"Treynor Ratio", "-8.187"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX 31KC0UJHC75TA|SPX 31"},
@@ -218,7 +218,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "f243341674cb1486d7cf009d74d4e6ff"}
{"OrderListHash", "77d9040316634cb6b9e8cd2e4e192fd5"}
};
}
}

View File

@@ -182,7 +182,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Annual Variance", "0"},
{"Information Ratio", "-0.066"},
{"Tracking Error", "0.139"},
{"Treynor Ratio", "-4.611"},
{"Treynor Ratio", "-4.733"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "SPX 31KC0UJFONTBI|SPX 31"},
@@ -205,7 +205,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "636b79bb5bf3db20eeda02ccf1064d07"}
{"OrderListHash", "12861ef440f68994997aeb24c8027748"}
};
}
}

View File

@@ -42,7 +42,7 @@ namespace QuantConnect.Algorithm.CSharp
public override void Initialize()
{
SetStartDate(2015, 12, 23);
SetEndDate(2015, 12, 24);
SetEndDate(2015, 12, 28);
SetCash(100000);
Stock = AddEquity("GOOG", Resolution.Minute);
@@ -78,33 +78,33 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "24"},
{"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"},
{"Average Win", "9.60%"},
{"Average Loss", "-16.86%"},
{"Compounding Annual Return", "-75.533%"},
{"Drawdown", "2.300%"},
{"Expectancy", "0.046"},
{"Net Profit", "-2.162%"},
{"Sharpe Ratio", "-6.761"},
{"Probabilistic Sharpe Ratio", "1.125%"},
{"Loss Rate", "33%"},
{"Win Rate", "67%"},
{"Profit-Loss Ratio", "0.57"},
{"Alpha", "-0.01"},
{"Beta", "0.455"},
{"Annual Standard Deviation", "0.014"},
{"Annual Variance", "0"},
{"Information Ratio", "0"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Information Ratio", "6.047"},
{"Tracking Error", "0.015"},
{"Treynor Ratio", "-0.207"},
{"Total Fees", "$12.00"},
{"Estimated Strategy Capacity", "$310000.00"},
{"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0.5"},
{"Estimated Strategy Capacity", "$1100000.00"},
{"Lowest Capacity Asset", "GOOCV 305RBQ20WHPNQ|GOOCV VP83T1ZUHROL"},
{"Fitness Score", "0.057"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "-50.725"},
{"Portfolio Turnover", "8.14"},
{"Sortino Ratio", "-3.876"},
{"Return Over Maximum Drawdown", "-35.706"},
{"Portfolio Turnover", "3.258"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "58557574cf0489dd38fb37768f509ca1"}
{"OrderListHash", "a0e8eeee1c31968b773ebdf47bb996df"}
};
}
}

View File

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

View File

@@ -124,16 +124,16 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "4"},
{"Average Win", "0.30%"},
{"Average Loss", "-0.33%"},
{"Average Loss", "-0.32%"},
{"Compounding Annual Return", "-24.104%"},
{"Drawdown", "0.400%"},
{"Expectancy", "-0.358"},
{"Expectancy", "-0.359"},
{"Net Profit", "-0.352%"},
{"Sharpe Ratio", "0"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "67%"},
{"Win Rate", "33%"},
{"Profit-Loss Ratio", "0.93"},
{"Profit-Loss Ratio", "0.92"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
@@ -163,7 +163,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "091c92055026a8323accb4508a68bf3f"}
{"OrderListHash", "c764f59736091ece264bd2f959eae97c"}
};
}
}

View File

@@ -0,0 +1,202 @@
/*
* 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;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This is an option split regression algorithm
/// </summary>
/// <meta name="tag" content="options" />
/// <meta name="tag" content="regression test" />
public class OptionRenameDailyRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _optionSymbol;
private Symbol _contractSymbol;
private Symbol _underlyingSymbol;
public override void Initialize()
{
// this test opens position in the first day of trading, lives through stock rename (NWSA->FOXA), dividends, and closes adjusted position on the third day
SetStartDate(2013, 06, 27);
SetEndDate(2013, 07, 02);
SetCash(1000000);
var option = AddOption("NWSA", Resolution.Daily);
_optionSymbol = option.Symbol;
// set our strike/expiry filter for this option chain
option.SetFilter(-1, +1, TimeSpan.Zero, TimeSpan.MaxValue);
// use the underlying equity as the benchmark
SetBenchmark("NWSA");
}
/// <summary>
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
/// </summary>
/// <param name="slice">The current slice of data keyed by symbol string</param>
public override void OnData(Slice slice)
{
foreach (var dividend in slice.Dividends.Values)
{
if (dividend.ReferencePrice != 32.6m || dividend.Distribution != 3.82m)
{
throw new Exception($"{Time} - Invalid dividend {dividend}");
}
}
if (!Portfolio.Invested)
{
OptionChain chain;
if (slice.OptionChains.TryGetValue(_optionSymbol, out chain))
{
var contract =
chain.OrderBy(x => x.Expiry)
.Where(x => x.Right == OptionRight.Call && x.Strike == 33 && x.Expiry.Date == new DateTime(2013, 08, 17))
.FirstOrDefault();
if (contract != null)
{
// Buying option
_contractSymbol = contract.Symbol;
Buy(_contractSymbol, 1);
// Buying the underlying stock
_underlyingSymbol = contract.Symbol.Underlying;
Buy(_underlyingSymbol, 100);
// Check
if (slice.Time != new DateTime(2013, 6, 28))
{
throw new Exception(@"Received first contract at {slice.Time}; Expected at 6/28/2013 12AM.");
}
if (contract.AskPrice != 1.15m)
{
throw new Exception("Current ask price was not loaded from NWSA backtest file and is not $1.1");
}
if (contract.UnderlyingSymbol.Value != "NWSA")
{
throw new Exception("Contract underlying symbol was not NWSA as expected");
}
}
}
}
else if (slice.Time.Day == 3) // Final day
{
// selling positions
Liquidate();
// checks
OptionChain chain;
if (slice.OptionChains.TryGetValue(_optionSymbol, out chain))
{
if (chain.Underlying.Symbol.Value != "FOXA")
{
throw new Exception("Chain underlying symbol was not FOXA as expected");
}
var contract =
chain.OrderBy(x => x.Expiry)
.Where(x => x.Right == OptionRight.Call && x.Strike == 33 && x.Expiry.Date == new DateTime(2013, 08, 17))
.FirstOrDefault();
if (contract.BidPrice != 0.05m)
{
throw new Exception("Current bid price was not loaded from FOXA file and is not $0.05");
}
}
}
}
/// <summary>
/// Order fill event handler. On an order fill update the resulting information is passed to this method.
/// </summary>
/// <param name="orderEvent">Order event details containing details of the evemts</param>
/// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>
public override void OnOrderEvent(OrderEvent orderEvent)
{
Log(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 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>
/// 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.273%"},
{"Drawdown", "0.000%"},
{"Expectancy", "0"},
{"Net Profit", "-0.004%"},
{"Sharpe Ratio", "-2.264"},
{"Probabilistic Sharpe Ratio", "32.662%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.001"},
{"Annual Variance", "0"},
{"Information Ratio", "-2.264"},
{"Tracking Error", "0.001"},
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$0"},
{"Lowest Capacity Asset", "NWSA VJ5IKAXU7WBQ|NWSA T3MO1488O0H1"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.168"},
{"Return Over Maximum Drawdown", "-6.338"},
{"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", "8b89135535d842f6df7b2849d6604fbd"}
};
}
}

View File

@@ -19,6 +19,7 @@ using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using System.Linq;
namespace QuantConnect.Algorithm.CSharp
{
@@ -473,6 +474,62 @@ namespace QuantConnect.Algorithm.CSharp
return Time.Day == day && Time.Hour == hour && Time.Minute == minute;
}
public override void OnEndOfAlgorithm()
{
Func<OrderTicket, bool> basicOrderTicketFilter = x => x.Symbol == symbol;
var filledOrders = Transactions.GetOrders(x => x.Status == OrderStatus.Filled);
var orderTickets = Transactions.GetOrderTickets(basicOrderTicketFilter);
var openOrders = Transactions.GetOpenOrders(x => x.Symbol == symbol);
var openOrderTickets = Transactions.GetOpenOrderTickets(basicOrderTicketFilter);
var remainingOpenOrders = Transactions.GetOpenOrdersRemainingQuantity(basicOrderTicketFilter);
if (filledOrders.Count() != 8 || orderTickets.Count() != 10)
{
throw new Exception($"There were expected 8 filled orders and 10 order tickets");
}
if (openOrders.Count != 0 || openOrderTickets.Any())
{
throw new Exception($"No open orders or tickets were expected");
}
if (remainingOpenOrders != 0m)
{
throw new Exception($"No remaining quantiy to be filled from open orders was expected");
}
var symbolOpenOrders = Transactions.GetOpenOrders(symbol).Count;
var symbolOpenOrdersTickets = Transactions.GetOpenOrderTickets(symbol).Count();
var symbolOpenOrdersRemainingQuantity = Transactions.GetOpenOrdersRemainingQuantity(symbol);
if (symbolOpenOrders != 0 || symbolOpenOrdersTickets != 0)
{
throw new Exception($"No open orders or tickets were expected");
}
if (symbolOpenOrdersRemainingQuantity != 0)
{
throw new Exception($"No remaining quantiy to be filled from open orders was expected");
}
var defaultOrders = Transactions.GetOrders();
var defaultOrderTickets = Transactions.GetOrderTickets();
var defaultOpenOrders = Transactions.GetOpenOrders();
var defaultOpenOrderTickets = Transactions.GetOpenOrderTickets();
var defaultOpenOrdersRemaining = Transactions.GetOpenOrdersRemainingQuantity();
if (defaultOrders.Count() != 10 || defaultOrderTickets.Count() != 10)
{
throw new Exception($"There were expected 10 orders and 10 order tickets");
}
if (defaultOpenOrders.Count != 0 || defaultOpenOrderTickets.Any())
{
throw new Exception($"No open orders or tickets were expected");
}
if (defaultOpenOrdersRemaining != 0m)
{
throw new Exception($"No remaining quantiy 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>

View File

@@ -35,7 +35,7 @@
<DebugType>portable</DebugType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.8" />
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.10" />
<PackageReference Include="Accord" Version="3.6.0" />
<PackageReference Include="Accord.Fuzzy" Version="3.6.0" />
<PackageReference Include="Accord.MachineLearning" Version="3.6.0" />

View File

@@ -32,7 +32,7 @@ namespace QuantConnect.Algorithm.CSharp
public class RawDataRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private const string Ticker = "GOOGL";
private FactorFile _factorFile;
private CorporateFactorProvider _factorFile;
private readonly IEnumerator<decimal> _expectedRawPrices = new List<decimal> { 1157.93m, 1158.72m,
1131.97m, 1114.28m, 1120.15m, 1114.51m, 1134.89m, 567.55m, 571.50m, 545.25m, 540.63m }.GetEnumerator();
private Symbol _googl;
@@ -56,7 +56,7 @@ namespace QuantConnect.Algorithm.CSharp
mapFileProvider.Initialize(dataProvider);
var factorFileProvider = new LocalDiskFactorFileProvider();
factorFileProvider.Initialize(mapFileProvider, dataProvider);
_factorFile = factorFileProvider.Get(_googl);
_factorFile = factorFileProvider.Get(_googl) as CorporateFactorProvider;
// Prime our expected values
_expectedRawPrices.MoveNext();
@@ -81,7 +81,7 @@ namespace QuantConnect.Algorithm.CSharp
if (_expectedRawPrices.Current != googlData.Close)
{
// Our values don't match lets try and give a reason why
var dayFactor = _factorFile.GetPriceScaleFactor(googlData.Time);
var dayFactor = _factorFile.GetPriceFactor(googlData.Time, DataNormalizationMode.Adjusted);
var probableRawPrice = googlData.Close / dayFactor; // Undo adjustment
if (_expectedRawPrices.Current == probableRawPrice)

View File

@@ -69,16 +69,6 @@ namespace QuantConnect.Algorithm.CSharp
throw new Exception("Was expecting resolution to be set to Hour");
}
try
{
AddOption("AAPL", Resolution.Daily);
throw new Exception("Was expecting an ArgumentException to be thrown");
}
catch (ArgumentException)
{
// expected, options only support minute resolution
}
var option = AddOption("AAPL");
if (SubscriptionManager.SubscriptionDataConfigService.GetSubscriptionDataConfigs(option.Symbol)
.Any(config => config.Resolution != Resolution.Minute))

View File

@@ -173,32 +173,32 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "4"},
{"Average Win", "0.64%"},
{"Average Win", "0.71%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "-56.617%"},
{"Drawdown", "3.800%"},
{"Compounding Annual Return", "-55.953%"},
{"Drawdown", "3.700%"},
{"Expectancy", "0"},
{"Net Profit", "-3.815%"},
{"Sharpe Ratio", "-2.708"},
{"Probabilistic Sharpe Ratio", "13.091%"},
{"Net Profit", "-3.747%"},
{"Sharpe Ratio", "-2.668"},
{"Probabilistic Sharpe Ratio", "13.421%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "-0.275"},
{"Beta", "1.237"},
{"Alpha", "-0.268"},
{"Beta", "1.241"},
{"Annual Standard Deviation", "0.167"},
{"Annual Variance", "0.028"},
{"Information Ratio", "-2.491"},
{"Information Ratio", "-2.443"},
{"Tracking Error", "0.124"},
{"Treynor Ratio", "-0.365"},
{"Total Fees", "$4.00"},
{"Treynor Ratio", "-0.358"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$870000.00"},
{"Lowest Capacity Asset", "GOOAV VP83T1ZUHROL"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-3.836"},
{"Return Over Maximum Drawdown", "-14.841"},
{"Sortino Ratio", "-3.793"},
{"Return Over Maximum Drawdown", "-14.933"},
{"Portfolio Turnover", "0.135"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -213,7 +213,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "bbc9f982183f74b34be4529acaa33fe8"}
{"OrderListHash", "afde32cdef5e61707f85d62f62eece17"}
};
}
}

View File

@@ -0,0 +1,120 @@
/*
* 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 System.Collections.Generic;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Data.Custom.AlphaStreams;
namespace QuantConnect.Algorithm.Framework.Alphas
{
/// <summary>
/// Alpha model that will handle adding and removing securities from the algorithm based on the current portfolio of the different alphas
/// </summary>
public sealed class AlphaStreamAlphaModule : AlphaModel
{
private Dictionary<Symbol, HashSet<Symbol>> _symbolsPerAlpha = new Dictionary<Symbol, HashSet<Symbol>>();
/// <summary>
/// Initialize new <see cref="AlphaStreamAlphaModule"/>
/// </summary>
public AlphaStreamAlphaModule(string name = null)
{
Name = name ?? "AlphaStreamAlphaModule";
}
/// <summary>
/// Updates this alpha model with the latest data from the algorithm.
/// This is called each time the algorithm receives data for subscribed securities
/// </summary>
/// <param name="algorithm">The algorithm instance</param>
/// <param name="data">The new data available</param>
/// <returns>The new insights generated</returns>
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
{
foreach (var portfolioState in data.Get<AlphaStreamsPortfolioState>().Values)
{
ProcessPortfolioState(algorithm, portfolioState);
}
return Enumerable.Empty<Insight>();
}
/// <summary>
/// Event fired each time the we add/remove securities from the data feed
/// </summary>
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
/// <param name="changes">The security additions and removals from the algorithm</param>
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
{
changes.FilterCustomSecurities = false;
foreach (var addedSecurity in changes.AddedSecurities)
{
if (addedSecurity.Symbol.IsCustomDataType<AlphaStreamsPortfolioState>())
{
if (!_symbolsPerAlpha.ContainsKey(addedSecurity.Symbol))
{
_symbolsPerAlpha[addedSecurity.Symbol] = new HashSet<Symbol>();
}
// warmup alpha state, adding target securities
ProcessPortfolioState(algorithm, addedSecurity.Cache.GetData<AlphaStreamsPortfolioState>());
}
}
algorithm.Log($"OnSecuritiesChanged: {changes}");
}
/// <summary>
/// Will handle adding and removing securities from the algorithm based on the current portfolio of the different alphas
/// </summary>
private void ProcessPortfolioState(QCAlgorithm algorithm, AlphaStreamsPortfolioState portfolioState)
{
if (portfolioState == null)
{
return;
}
var alphaId = portfolioState.Symbol;
if (!_symbolsPerAlpha.TryGetValue(alphaId, out var currentSymbols))
{
_symbolsPerAlpha[alphaId] = currentSymbols = new HashSet<Symbol>();
}
var newSymbols = new HashSet<Symbol>(currentSymbols.Count);
foreach (var symbol in portfolioState.PositionGroups?.SelectMany(positionGroup => positionGroup.Positions).Select(state => state.Symbol) ?? Enumerable.Empty<Symbol>())
{
// only add it if it's not used by any alpha (already added check)
if (newSymbols.Add(symbol) && !UsedBySomeAlpha(symbol))
{
algorithm.AddSecurity(symbol,
resolution: algorithm.UniverseSettings.Resolution,
extendedMarketHours: algorithm.UniverseSettings.ExtendedMarketHours);
}
}
_symbolsPerAlpha[alphaId] = newSymbols;
foreach (var symbol in currentSymbols.Where(symbol => !UsedBySomeAlpha(symbol)))
{
algorithm.RemoveSecurity(symbol);
}
}
private bool UsedBySomeAlpha(Symbol asset)
{
return _symbolsPerAlpha.Any(pair => pair.Value.Contains(asset));
}
}
}

View File

@@ -1,4 +1,4 @@
/*
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
@@ -35,7 +35,7 @@ namespace QuantConnect.Algorithm.Framework.Alphas
private readonly MovingAverageType _movingAverageType;
private readonly Resolution _resolution;
private const decimal BounceThresholdPercent = 0.01m;
private readonly Dictionary<Symbol, SymbolData> _symbolData;
protected readonly Dictionary<Symbol, SymbolData> _symbolData;
/// <summary>
/// Initializes a new instance of the <see cref="MacdAlphaModel"/> class
@@ -130,7 +130,7 @@ namespace QuantConnect.Algorithm.Framework.Alphas
}
}
class SymbolData
public class SymbolData
{
public InsightDirection? PreviousDirection { get; set; }
@@ -147,6 +147,7 @@ namespace QuantConnect.Algorithm.Framework.Alphas
MACD = new MovingAverageConvergenceDivergence(fastPeriod, slowPeriod, signalPeriod, movingAverageType);
algorithm.RegisterIndicator(security.Symbol, MACD, Consolidator);
algorithm.WarmUpIndicator(security.Symbol, MACD, resolution);
}
}
}

View File

@@ -1,4 +1,4 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# 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");
@@ -98,5 +98,6 @@ class SymbolData:
self.Consolidator = algorithm.ResolveConsolidator(security.Symbol, resolution)
algorithm.RegisterIndicator(security.Symbol, self.MACD, self.Consolidator)
algorithm.WarmUpIndicator(security.Symbol, self.MACD, resolution)
self.PreviousDirection = None

View File

@@ -0,0 +1,51 @@
/*
* 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.Logging;
using System.Collections.Generic;
using QuantConnect.Algorithm.Framework.Portfolio;
namespace QuantConnect.Algorithm.Framework
{
/// <summary>
/// Custom weighting alpha streams portfolio construction model that will generate aggregated security targets taking into account all the alphas positions
/// and a custom weighting factor for each alpha, which is also factored by the relation of the alphas portfolio value and the current algorithms portfolio value
/// </summary>
public class CustomWeightingAlphaStreamsPortfolioConstructionModel : EqualWeightingAlphaStreamsPortfolioConstructionModel
{
private Dictionary<string, decimal> _alphaWeights;
/// <summary>
/// Specify a custom set of alpha portfolio weights to use
/// </summary>
/// <param name="alphaWeights">The alpha portfolio weights</param>
public void SetAlphaWeights(Dictionary<string, decimal> alphaWeights)
{
Log.Trace($"CustomWeightingAlphaStreamsPortfolioConstructionModel.SetAlphaWeights(): new weights: [{string.Join(",", alphaWeights.Select(pair => $"{pair.Key}:{pair.Value}"))}]");
_alphaWeights = alphaWeights;
}
/// <summary>
/// Get's the weight for an alpha
/// </summary>
/// <param name="alphaId">The algorithm instance that experienced the change in securities</param>
/// <returns>The alphas weight</returns>
public override decimal GetAlphaWeight(string alphaId)
{
return !_alphaWeights.TryGetValue(alphaId, out var alphaWeight) ? 0 : alphaWeight;
}
}
}

View File

@@ -109,7 +109,6 @@ namespace QuantConnect.Algorithm.Framework
/// <summary>
/// Invokes the provided <paramref name="add"/> and <paramref name="remove"/> functions for each
/// <seealso cref="SecurityChanges.Added"/> and <seealso cref="SecurityChanges.Removed"/>, respectively
/// </summary>
/// <param name="changes">The security changes to process</param>
/// <param name="add">Function called for each added security</param>
@@ -126,4 +125,4 @@ namespace QuantConnect.Algorithm.Framework
}
}
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.UniverseSelection;
using QuantConnect.Algorithm.Framework.Alphas;
namespace QuantConnect.Algorithm.Framework.Portfolio
{
/// <summary>
/// Base alpha streams portfolio construction model
/// </summary>
public class AlphaStreamsPortfolioConstructionModel : IPortfolioConstructionModel
{
/// <summary>
/// Get's the weight for an alpha
/// </summary>
/// <param name="alphaId">The algorithm instance that experienced the change in securities</param>
/// <returns>The alphas weight</returns>
public virtual decimal GetAlphaWeight(string alphaId)
{
throw new System.NotImplementedException();
}
/// <summary>
/// Event fired each time the we add/remove securities from the data feed
/// </summary>
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
/// <param name="changes">The security additions and removals from the algorithm</param>
public virtual void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
{
throw new System.NotImplementedException();
}
/// <summary>
/// Create portfolio targets from the specified insights
/// </summary>
/// <param name="algorithm">The algorithm instance</param>
/// <param name="insights">The insights to create portfolio targets from</param>
/// <returns>An enumerable of portfolio targets to be sent to the execution model</returns>
public virtual IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
{
throw new System.NotImplementedException();
}
}
}

View File

@@ -29,7 +29,7 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
/// and an equal weighting factor for each alpha, which is also factored by the relation of the alphas portfolio value and the current algorithms portfolio value,
/// overriding <see cref="GetAlphaWeight"/> allows custom weighting implementations
/// </summary>
public class EqualWeightingAlphaStreamsPortfolioConstructionModel : IPortfolioConstructionModel
public class EqualWeightingAlphaStreamsPortfolioConstructionModel : AlphaStreamsPortfolioConstructionModel
{
private bool _rebalance;
private Dictionary<Symbol, PortfolioTarget> _targetsPerSymbol;
@@ -48,7 +48,7 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
/// <param name="algorithm">The algorithm instance</param>
/// <param name="insights">The insights to create portfolio targets from</param>
/// <returns>An enumerable of portfolio targets to be sent to the execution model</returns>
public IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
public override IEnumerable<IPortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights)
{
if (_targetsPerSymbol == null)
{
@@ -104,12 +104,22 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
}
}
/// <summary>
/// Get's the weight for an alpha
/// </summary>
/// <param name="alphaId">The algorithm instance that experienced the change in securities</param>
/// <returns>The alphas weight</returns>
public override decimal GetAlphaWeight(string alphaId)
{
return 1m / _targetsPerSymbolPerAlpha.Count;
}
/// <summary>
/// Event fired each time the we add/remove securities from the data feed
/// </summary>
/// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
/// <param name="changes">The security additions and removals from the algorithm</param>
public void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
{
changes.FilterCustomSecurities = false;
@@ -153,10 +163,10 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
/// Determines the portfolio weight to give a specific alpha. Default implementation just returns equal weighting
/// </summary>
/// <param name="portfolioState">The alphas portfolio state to get the weight for</param>
/// <param name="totalUsablePortfolioValue">This algorithms usable total portfolio value</param>
/// <param name="totalUsablePortfolioValue">This algorithms usable total portfolio value, removing the free portfolio value</param>
/// <param name="cashBook">This algorithms cash book</param>
/// <returns>The weight to use on this alphas positions</returns>
protected virtual decimal GetAlphaWeight(AlphaStreamsPortfolioState portfolioState,
private decimal GetAlphaWeight(AlphaStreamsPortfolioState portfolioState,
decimal totalUsablePortfolioValue,
CashBook cashBook)
{
@@ -168,8 +178,7 @@ namespace QuantConnect.Algorithm.Framework.Portfolio
return 0;
}
var equalWeightFactor = 1m / _targetsPerSymbolPerAlpha.Count;
return totalUsablePortfolioValue * equalWeightFactor / alphaPortfolioValueInOurAccountCurrency;
return totalUsablePortfolioValue * GetAlphaWeight(portfolioState.AlphaId) / alphaPortfolioValueInOurAccountCurrency;
}
private bool ProcessPortfolioState(AlphaStreamsPortfolioState portfolioState, QCAlgorithm algorithm)

View File

@@ -30,7 +30,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.8" />
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.10" />
<PackageReference Include="Accord" Version="3.6.0" />
<PackageReference Include="Accord.Math" Version="3.6.0" />
<PackageReference Include="Accord.Statistics" Version="3.6.0" />

View File

@@ -35,7 +35,7 @@ class BasicTemplateAtreyuAlgorithm(QCAlgorithm):
self.DefaultOrderProperties = AtreyuOrderProperties()
# Can specify the default exchange to execute an order on.
# If not specified will default to the primary exchange
self.DefaultOrderProperties.Exchange = Exchange.NASDAQ
self.DefaultOrderProperties.Exchange = Exchange.BATS
# Currently only support order for the day
self.DefaultOrderProperties.TimeInForce = TimeInForce.Day
@@ -46,7 +46,7 @@ class BasicTemplateAtreyuAlgorithm(QCAlgorithm):
data: Slice object keyed by symbol containing the stock data
'''
if not self.Portfolio.Invested:
# will set 25% of our buying power with a market order that will be routed to exchange set in the default order properties (NASDAQ)
# will set 25% of our buying power with a market order that will be routed to exchange set in the default order properties (BATS)
self.SetHoldings("SPY", 0.25)
# will increase our SPY holdings to 50% of our buying power with a market order that will be routed to ARCA

View File

@@ -0,0 +1,66 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
### <summary>
### Basic Continuous Futures Template Algorithm
### </summary>
class BasicTemplateContinuousFutureAlgorithm(QCAlgorithm):
'''Basic template algorithm simply initializes the date range and cash'''
def Initialize(self):
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
self.SetStartDate(2013, 7, 1)
self.SetEndDate(2014, 1, 1)
self._continuousContract = self.AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
dataMappingMode = DataMappingMode.LastTradingDay,
contractDepthOffset= 0)
self._fast = self.SMA(self._continuousContract.Symbol, 3, Resolution.Daily)
self._slow = self.SMA(self._continuousContract.Symbol, 10, Resolution.Daily)
self._currentContract = None
def OnData(self, data):
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
Arguments:
data: Slice object keyed by symbol containing the stock data
'''
for changedEvent in data.SymbolChangedEvents.Values:
if changedEvent.Symbol == self._continuousContract.Symbol:
self.Log(f"SymbolChanged event: {changedEvent}")
if not self.Portfolio.Invested:
if self._fast.Current.Value > self._slow.Current.Value:
self._currentContract = self.Securities[self._continuousContract.Mapped]
self.Buy(self._currentContract.Symbol, 1)
elif self._fast.Current.Value < self._slow.Current.Value:
self.Liquidate()
if self._currentContract is not None and self._currentContract.Symbol != self._continuousContract.Mapped:
self.Log(f"{Time} - rolling position from {self._currentContract.Symbol} to {self._continuousContract.Mapped}")
currentPositionSize = self._currentContract.Holdings.Quantity
self.Liquidate(self._currentContract.Symbol)
self.Buy(self._continuousContract.Mapped, currentPositionSize)
self._currentContract = self.Securities[self._continuousContract.Mapped]
def OnOrderEvent(self, orderEvent):
self.Debug("Purchased Stock: {0}".format(orderEvent.Symbol))
def OnSecuritiesChanged(self, changes):
self.Debug(f"{self.Time}-{changes}")

View File

@@ -0,0 +1,55 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
### <summary>
### This example demonstrates how to add futures with daily resolution.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="benchmarks" />
### <meta name="tag" content="futures" />
class BasicTemplateFuturesDailyAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 10, 8)
self.SetEndDate(2013, 10, 10)
self.SetCash(1000000)
self.contractSymbol = None
# Subscribe and set our expiry filter for the futures chain
futureSP500 = self.AddFuture(Futures.Indices.SP500EMini, Resolution.Daily)
futureGold = self.AddFuture(Futures.Metals.Gold, Resolution.Daily)
# set our expiry filter for this futures chain
# SetFilter method accepts timedelta objects or integer for days.
# The following statements yield the same filtering criteria
futureSP500.SetFilter(timedelta(0), timedelta(182))
futureGold.SetFilter(0, 182)
def OnData(self,slice):
if not self.Portfolio.Invested:
for chain in slice.FutureChains:
# Get contracts expiring no earlier than in 90 days
contracts = list(filter(lambda x: x.Expiry > self.Time + timedelta(90), chain.Value))
# if there is any contract, trade the front contract
if len(contracts) == 0: continue
front = sorted(contracts, key = lambda x: x.Expiry, reverse=True)[0]
self.contractSymbol = front.Symbol
self.MarketOrder(front.Symbol , 1)
else:
self.Liquidate()

View File

@@ -0,0 +1,55 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
### <summary>
### This example demonstrates how to add futures with hourly resolution.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="benchmarks" />
### <meta name="tag" content="futures" />
class BasicTemplateFuturesHourlyAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 10, 8)
self.SetEndDate(2013, 10, 10)
self.SetCash(1000000)
self.contractSymbol = None
# Subscribe and set our expiry filter for the futures chain
futureSP500 = self.AddFuture(Futures.Indices.SP500EMini, Resolution.Hour)
futureGold = self.AddFuture(Futures.Metals.Gold, Resolution.Hour)
# set our expiry filter for this futures chain
# SetFilter method accepts timedelta objects or integer for days.
# The following statements yield the same filtering criteria
futureSP500.SetFilter(timedelta(0), timedelta(182))
futureGold.SetFilter(0, 182)
def OnData(self,slice):
if not self.Portfolio.Invested:
for chain in slice.FutureChains:
# Get contracts expiring no earlier than in 90 days
contracts = list(filter(lambda x: x.Expiry > self.Time + timedelta(90), chain.Value))
# if there is any contract, trade the front contract
if len(contracts) == 0: continue
front = sorted(contracts, key = lambda x: x.Expiry, reverse=True)[0]
self.contractSymbol = front.Symbol
self.MarketOrder(front.Symbol , 1)
else:
self.Liquidate()

View File

@@ -16,7 +16,7 @@ from AlgorithmImports import *
class BasicTemplateIndexAlgorithm(QCAlgorithm):
def Initialize(self) -> None:
self.SetStartDate(2021, 1, 4)
self.SetEndDate(2021, 1, 15)
self.SetEndDate(2021, 1, 18)
self.SetCash(1000000)
# Use indicator for signal; but it cannot be traded

View File

@@ -0,0 +1,73 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
### <summary>
### This example demonstrates how to add options for a given underlying equity security.
### It also shows how you can prefilter contracts easily based on strikes and expirations, and how you
### can inspect the option chain to pick a specific option contract to trade.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="options" />
### <meta name="tag" content="filter selection" />
class BasicTemplateOptionsDailyAlgorithm(QCAlgorithm):
UnderlyingTicker = "GOOG"
def Initialize(self):
self.SetStartDate(2015, 12, 23)
self.SetEndDate(2016, 1, 20)
self.SetCash(100000)
self.optionExpired = False
equity = self.AddEquity(self.UnderlyingTicker, Resolution.Daily)
option = self.AddOption(self.UnderlyingTicker, Resolution.Daily)
self.option_symbol = option.Symbol
# set our strike/expiry filter for this option chain
option.SetFilter(lambda u: (u.Strikes(0, 1).Expiration(0, 30)))
# use the underlying equity as the benchmark
self.SetBenchmark(equity.Symbol)
def OnData(self,slice):
if self.Portfolio.Invested: return
chain = slice.OptionChains.GetValue(self.option_symbol)
if chain is None:
return
# Grab us the contract nearest expiry
contracts = sorted(chain, key = lambda x: x.Expiry)
# if found, trade it
if len(contracts) == 0: return
symbol = contracts[0].Symbol
self.MarketOrder(symbol, 1)
def OnOrderEvent(self, orderEvent):
self.Log(str(orderEvent))
# Check for our expected OTM option expiry
if orderEvent.Message == "OTM":
# Assert it is at midnight 1/16 (5AM UTC)
if orderEvent.UtcTime.month != 1 and orderEvent.UtcTime.day != 16 and orderEvent.UtcTime.hour != 5:
raise AssertionError(f"Expiry event was not at the correct time, {orderEvent.UtcTime}")
self.optionExpired = True
def OnEndOfAlgorithm(self):
# Assert we had our option expire and fill a liquidation order
if not self.optionExpired:
raise AssertionError("Algorithm did not process the option expiration like expected")

View File

@@ -26,7 +26,7 @@ class BasicTemplateOptionsFilterUniverseAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2015, 12, 24)
self.SetEndDate(2015, 12, 24)
self.SetEndDate(2015, 12, 28)
self.SetCash(100000)
equity = self.AddEquity(self.UnderlyingTicker)

View File

@@ -29,7 +29,7 @@ class BasicTemplateOptionsFrameworkAlgorithm(QCAlgorithm):
self.UniverseSettings.Resolution = Resolution.Minute
self.SetStartDate(2014, 6, 5)
self.SetEndDate(2014, 6, 6)
self.SetEndDate(2014, 6, 9)
self.SetCash(100000)
# set framework models

View File

@@ -0,0 +1,66 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
### <summary>
### This example demonstrates how to add options for a given underlying equity security.
### It also shows how you can prefilter contracts easily based on strikes and expirations, and how you
### can inspect the option chain to pick a specific option contract to trade.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="options" />
### <meta name="tag" content="filter selection" />
class BasicTemplateOptionsHourlyAlgorithm(QCAlgorithm):
UnderlyingTicker = "AAPL"
def Initialize(self):
self.SetStartDate(2014, 6, 6)
self.SetEndDate(2014, 6, 9)
self.SetCash(100000)
equity = self.AddEquity(self.UnderlyingTicker, Resolution.Hour)
option = self.AddOption(self.UnderlyingTicker, Resolution.Hour)
self.option_symbol = option.Symbol
# set our strike/expiry filter for this option chain
option.SetFilter(lambda u: (u.Strikes(-2, +2)
# Expiration method accepts TimeSpan objects or integer for days.
# The following statements yield the same filtering criteria
.Expiration(0, 180)))
#.Expiration(TimeSpan.Zero, TimeSpan.FromDays(180))))
# use the underlying equity as the benchmark
self.SetBenchmark(equity.Symbol)
def OnData(self,slice):
if self.Portfolio.Invested or not self.IsMarketOpen(self.option_symbol): return
chain = slice.OptionChains.GetValue(self.option_symbol)
if chain is None:
return
# we sort the contracts to find at the money (ATM) contract with farthest expiration
contracts = sorted(sorted(sorted(chain, \
key = lambda x: abs(chain.Underlying.Price - x.Strike)), \
key = lambda x: x.Expiry, reverse=True), \
key = lambda x: x.Right, reverse=True)
# if found, trade it
if len(contracts) == 0: return
symbol = contracts[0].Symbol
self.MarketOrder(symbol, 1)
self.MarketOnCloseOrder(symbol, -1)
def OnOrderEvent(self, orderEvent):
self.Log(str(orderEvent))

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.
from AlgorithmImports import *
### <summary>
### Continuous Futures Regression algorithm. Asserting and showcasing the behavior of adding a continuous future
### </summary>
class ContinuousFutureRegressionAlgorithm(QCAlgorithm):
'''Basic template algorithm simply initializes the date range and cash'''
def Initialize(self):
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
self.SetStartDate(2013, 7, 1)
self.SetEndDate(2014, 1, 1)
self._mappings = []
self._lastDateLog = -1
self._continuousContract = self.AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
dataMappingMode = DataMappingMode.LastTradingDay,
contractDepthOffset= 0)
self._currentMappedSymbol = self._continuousContract.Symbol;
def OnData(self, data):
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
Arguments:
data: Slice object keyed by symbol containing the stock data
'''
currentlyMappedSecurity = self.Securities[self._continuousContract.Mapped]
if len(data.Keys) != 1:
raise ValueError(f"We are getting data for more than one symbols! {','.join(data.Keys)}")
for changedEvent in data.SymbolChangedEvents.Values:
if changedEvent.Symbol == self._continuousContract.Symbol:
self._mappings.append(changedEvent)
self.Log(f"SymbolChanged event: {changedEvent}")
if self._currentMappedSymbol == self._continuousContract.Mapped:
raise ValueError(f"Continuous contract current symbol did not change! {self._continuousContract.Mapped}")
if self._lastDateLog != self.Time.month and currentlyMappedSecurity.HasData:
self._lastDateLog = self.Time.month
self.Log(f"{self.Time}- {currentlyMappedSecurity.GetLastData()}")
if self.Portfolio.Invested:
self.Liquidate()
else:
# This works because we set this contract as tradable, even if it's a canonical security
self.Buy(currentlyMappedSecurity.Symbol, 1)
if self.Time.month == 1 and self.Time.year == 2013:
response = self.History( [ self._continuousContract.Symbol ], 60 * 24 * 90)
if response.empty:
raise ValueError("Unexpected empty history response")
self._currentMappedSymbol = self._continuousContract.Mapped
def OnOrderEvent(self, orderEvent):
if orderEvent.Status == OrderStatus.Filled:
self.Debug("Purchased Stock: {0}".format(orderEvent.Symbol))
def OnSecuritiesChanged(self, changes):
self.Debug(f"{self.Time}-{changes}")
def OnEndOfAlgorithm(self):
expectedMappingCounts = 2
if len(self._mappings) != expectedMappingCounts:
raise ValueError(f"Unexpected symbol changed events: {self._mappings.count()}, was expecting {expectedMappingCounts}")

View File

@@ -0,0 +1,137 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
from collections import deque
### <summary>
### Regression test to check python indicator is keeping backwards compatibility
### with indicators that do not set WarmUpPeriod or do not inherit from PythonIndicator class.
### </summary>
### <meta name="tag" content="indicators" />
### <meta name="tag" content="indicator classes" />
### <meta name="tag" content="custom indicator" />
### <meta name="tag" content="regression test" />
class CustomWarmUpPeriodIndicatorAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013,10,7)
self.SetEndDate(2013,10,11)
self.AddEquity("SPY", Resolution.Second)
# Create three python indicators
# - customNotWarmUp does not define WarmUpPeriod parameter
# - customWarmUp defines WarmUpPeriod parameter
# - customNotInherit defines WarmUpPeriod parameter but does not inherit from PythonIndicator class
# - csharpIndicator defines WarmUpPeriod parameter and represents the traditional LEAN C# indicator
self.customNotWarmUp = CSMANotWarmUp('customNotWarmUp', 60)
self.customWarmUp = CSMAWithWarmUp('customWarmUp', 60)
self.customNotInherit = CustomSMA('customNotInherit', 60)
self.csharpIndicator = SimpleMovingAverage('csharpIndicator', 60)
# Register the daily data of "SPY" to automatically update the indicators
self.RegisterIndicator("SPY", self.customWarmUp, Resolution.Minute)
self.RegisterIndicator("SPY", self.customNotWarmUp, Resolution.Minute)
self.RegisterIndicator("SPY", self.customNotInherit, Resolution.Minute)
self.RegisterIndicator("SPY", self.csharpIndicator, Resolution.Minute)
# Warm up customWarmUp indicator
self.WarmUpIndicator("SPY", self.customWarmUp, Resolution.Minute)
# Check customWarmUp indicator has already been warmed up with the requested data
assert(self.customWarmUp.IsReady), "customWarmUp indicator was expected to be ready"
assert(self.customWarmUp.Samples == 60), "customWarmUp indicator was expected to have processed 60 datapoints already"
# Try to warm up customNotWarmUp indicator. It's expected from LEAN to skip the warm up process
# because this indicator doesn't define WarmUpPeriod parameter
self.WarmUpIndicator("SPY", self.customNotWarmUp, Resolution.Minute)
# Check customNotWarmUp indicator is not ready and is using the default WarmUpPeriod value
assert(not self.customNotWarmUp.IsReady), "customNotWarmUp indicator wasn't expected to be warmed up"
assert(self.customNotWarmUp.WarmUpPeriod == 0), "customNotWarmUp indicator WarmUpPeriod parameter was expected to be 0"
# Warm up customNotInherit indicator. Though it does not inherit from PythonIndicator class,
# it defines WarmUpPeriod parameter so it's expected to be warmed up from LEAN
self.WarmUpIndicator("SPY", self.customNotInherit, Resolution.Minute)
# Check customNotInherit indicator has already been warmed up with the requested data
assert(self.customNotInherit.IsReady), "customNotInherit indicator was expected to be ready"
assert(self.customNotInherit.Samples == 60), "customNotInherit indicator was expected to have processed 60 datapoints already"
# Warm up csharpIndicator
self.WarmUpIndicator("SPY", self.csharpIndicator, Resolution.Minute)
# Check csharpIndicator indicator has already been warmed up with the requested data
assert(self.csharpIndicator.IsReady), "csharpIndicator indicator was expected to be ready"
assert(self.csharpIndicator.Samples == 60), "csharpIndicator indicator was expected to have processed 60 datapoints already"
def OnData(self, data):
if not self.Portfolio.Invested:
self.SetHoldings("SPY", 1)
if self.Time.second == 0:
# Compute the difference between indicators values
diff = abs(self.customNotWarmUp.Current.Value - self.customWarmUp.Current.Value)
diff += abs(self.customNotInherit.Value - self.customNotWarmUp.Current.Value)
diff += abs(self.customNotInherit.Value - self.customWarmUp.Current.Value)
diff += abs(self.csharpIndicator.Current.Value - self.customWarmUp.Current.Value)
diff += abs(self.csharpIndicator.Current.Value - self.customNotWarmUp.Current.Value)
diff += abs(self.csharpIndicator.Current.Value - self.customNotInherit.Value)
# Check customNotWarmUp indicator is ready when the number of samples is bigger than its WarmUpPeriod parameter
assert(self.customNotWarmUp.IsReady == (self.customNotWarmUp.Samples >= 60)), "customNotWarmUp indicator was expected to be ready when the number of samples were bigger that its WarmUpPeriod parameter"
# Check their values are the same. We only need to check if customNotWarmUp indicator is ready because the other ones has already been asserted to be ready
assert(diff <= 1e-10 or (not self.customNotWarmUp.IsReady)), f"The values of the indicators are not the same. Indicators difference is {diff}"
# Python implementation of SimpleMovingAverage.
# Represents the traditional simple moving average indicator (SMA) without Warm Up Period parameter defined
class CSMANotWarmUp(PythonIndicator):
def __init__(self, name, period):
self.Name = name
self.Value = 0
self.queue = deque(maxlen=period)
# Update method is mandatory
def Update(self, input):
self.queue.appendleft(input.Value)
count = len(self.queue)
self.Value = np.sum(self.queue) / count
return count == self.queue.maxlen
# Python implementation of SimpleMovingAverage.
# Represents the traditional simple moving average indicator (SMA) With Warm Up Period parameter defined
class CSMAWithWarmUp(CSMANotWarmUp):
def __init__(self, name, period):
super().__init__(name, period)
self.WarmUpPeriod = period
# Custom python implementation of SimpleMovingAverage.
# Represents the traditional simple moving average indicator (SMA)
class CustomSMA():
def __init__(self, name, period):
self.Name = name
self.Value = 0
self.queue = deque(maxlen=period)
self.WarmUpPeriod = period
self.IsReady = False
self.Samples = 0
# Update method is mandatory
def Update(self, input):
self.Samples += 1
self.queue.appendleft(input.Value)
count = len(self.queue)
self.Value = np.sum(self.queue) / count
if count == self.queue.maxlen:
self.IsReady = True
return self.IsReady

View File

@@ -25,7 +25,7 @@ class FilterUniverseRegressionAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2015, 12, 24)
self.SetEndDate(2015, 12, 24)
self.SetEndDate(2015, 12, 28)
self.SetCash(100000)
equity = self.AddEquity(self.UnderlyingTicker)

View File

@@ -84,7 +84,7 @@ class FutureOptionCallITMExpiryRegressionAlgorithm(QCAlgorithm):
self.Log(f"{self.Time} -- {orderEvent.Symbol} :: Price: {self.Securities[orderEvent.Symbol].Holdings.Price} Qty: {self.Securities[orderEvent.Symbol].Holdings.Quantity} Direction: {orderEvent.Direction} Msg: {orderEvent.Message}")
def AssertFutureOptionOrderExercise(self, orderEvent: OrderEvent, future: Security, optionContract: Security):
expectedLiquidationTimeUtc = datetime(2020, 6, 19, 20, 0, 0)
expectedLiquidationTimeUtc = datetime(2020, 6, 20, 4, 0, 0)
if orderEvent.Direction == OrderDirection.Sell and future.Holdings.Quantity != 0:
# We expect the contract to have been liquidated immediately

View File

@@ -0,0 +1,65 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License
from AlgorithmImports import *
### <summary>
### This regression algorithm tests using FutureOptions daily resolution
### </summary>
class FutureOptionDailyRegressionAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2012, 1, 3)
self.SetEndDate(2012, 1, 4)
resolution = Resolution.Daily
# Add our underlying future contract
self.dc = self.AddFutureContract(
Symbol.CreateFuture(
Futures.Dairy.ClassIIIMilk,
Market.CME,
datetime(2012, 4, 1)
),
resolution).Symbol
# Attempt to fetch a specific ITM future option contract
dcOptions = [
self.AddFutureOptionContract(x, resolution).Symbol for x in (self.OptionChainProvider.GetOptionContractList(self.dc, self.Time)) if x.ID.StrikePrice == 17 and x.ID.OptionRight == OptionRight.Call
]
self.dcOption = dcOptions[0]
# Validate it is the expected contract
expectedContract = Symbol.CreateOption(self.dc, Market.CME, OptionStyle.American, OptionRight.Call, 17, datetime(2012, 4, 1))
if self.dcOption != expectedContract:
raise AssertionError(f"Contract {self.dcOption} was not the expected contract {expectedContract}")
# Schedule a purchase of this contract tomorrow at 1AM
self.Schedule.On(self.DateRules.Tomorrow, self.TimeRules.At(1,0,0), self.ScheduleCallbackBuy)
# Schedule liquidation at 6pm tomorrow
self.Schedule.On(self.DateRules.Tomorrow, self.TimeRules.At(18,0,0), self.ScheduleCallbackLiquidate)
def ScheduleCallbackBuy(self):
self.MarketOrder(self.dcOption, 1)
def OnData(self, slice):
# Assert we are only getting data at 7PM (12AM UTC)
if slice.Time.hour != 19:
raise AssertionError(f"Expected data at 7PM each day; instead was {slice.Time}")
def ScheduleCallbackLiquidate(self):
self.Liquidate()
def OnEndOfAlgorithm(self):
if self.Portfolio.Invested:
raise AssertionError(f"Expected no holdings at end of algorithm, but are invested in: {', '.join([str(i.ID) for i in self.Portfolio.Keys])}")

View File

@@ -0,0 +1,68 @@
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License
from AlgorithmImports import *
### <summary>
### This regression algorithm tests using FutureOptions daily resolution
### </summary>
class FutureOptionHourlyRegressionAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2012, 1, 3)
self.SetEndDate(2012, 1, 4)
resolution = Resolution.Hour
# Add our underlying future contract
self.dc = self.AddFutureContract(
Symbol.CreateFuture(
Futures.Dairy.ClassIIIMilk,
Market.CME,
datetime(2012, 4, 1)
),
resolution).Symbol
# Attempt to fetch a specific ITM future option contract
dcOptions = [
self.AddFutureOptionContract(x, resolution).Symbol for x in (self.OptionChainProvider.GetOptionContractList(self.dc, self.Time)) if x.ID.StrikePrice == 17 and x.ID.OptionRight == OptionRight.Call
]
self.dcOption = dcOptions[0]
# Validate it is the expected contract
expectedContract = Symbol.CreateOption(self.dc, Market.CME, OptionStyle.American, OptionRight.Call, 17, datetime(2012, 4, 1))
if self.dcOption != expectedContract:
raise AssertionError(f"Contract {self.dcOption} was not the expected contract {expectedContract}")
# Schedule a purchase of this contract at noon
self.Schedule.On(self.DateRules.Today, self.TimeRules.Noon, self.ScheduleCallbackBuy)
# Schedule liquidation at 6pm
self.Schedule.On(self.DateRules.Today, self.TimeRules.At(18,0,0), self.ScheduleCallbackLiquidate)
def ScheduleCallbackBuy(self):
self.ticket = self.MarketOrder(self.dcOption, 1)
def OnData(self, slice):
# Assert we are only getting data at 7PM (12AM UTC)
if slice.Time.minute != 0:
raise AssertionError(f"Expected data only on hourly intervals; instead was {slice.Time}")
def ScheduleCallbackLiquidate(self):
self.Liquidate()
def OnEndOfAlgorithm(self):
if self.Portfolio.Invested:
raise AssertionError(f"Expected no holdings at end of algorithm, but are invested in: {', '.join([str(i.ID) for i in self.Portfolio.Keys])}")
if self.ticket.Status != OrderStatus.Filled:
raise AssertionError("Future option order failed to fill correctly")

View File

@@ -83,7 +83,7 @@ class FutureOptionPutITMExpiryRegressionAlgorithm(QCAlgorithm):
self.Log(f"{self.Time} -- {orderEvent.Symbol} :: Price: {self.Securities[orderEvent.Symbol].Holdings.Price} Qty: {self.Securities[orderEvent.Symbol].Holdings.Quantity} Direction: {orderEvent.Direction} Msg: {orderEvent.Message}")
def AssertFutureOptionOrderExercise(self, orderEvent: OrderEvent, future: Security, optionContract: Security):
expectedLiquidationTimeUtc = datetime(2020, 6, 19, 20, 0, 0)
expectedLiquidationTimeUtc = datetime(2020, 6, 20, 4, 0, 0)
if orderEvent.Direction == OrderDirection.Buy and future.Holdings.Quantity != 0:
# We expect the contract to have been liquidated immediately

View File

@@ -24,7 +24,7 @@ class FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm(QCAlgo
self.expectedExpiryWarningTime = datetime(2020, 6, 19)
self.expectedExpiryDelistingTime = datetime(2020, 6, 20)
self.expectedLiquidationTime = datetime(2020, 6, 19, 16, 0, 0)
self.expectedLiquidationTime = datetime(2020, 6, 20)
self.SetStartDate(2020, 1, 5)
self.SetEndDate(2020, 12, 1)

View File

@@ -341,3 +341,44 @@ class OrderTicketDemoAlgorithm(QCAlgorithm):
def TimeIs(self, day, hour, minute):
return self.Time.day == day and self.Time.hour == hour and self.Time.minute == minute
def OnEndOfAlgorithm(self):
basicOrderTicketFilter = lambda x: x.Symbol == self.spy;
filledOrders = self.Transactions.GetOrders(lambda x: x.Status == OrderStatus.Filled);
orderTickets = self.Transactions.GetOrderTickets(basicOrderTicketFilter);
openOrders = self.Transactions.GetOpenOrders(lambda x: x.Symbol == self.spy);
openOrderTickets = self.Transactions.GetOpenOrderTickets(basicOrderTicketFilter);
remainingOpenOrders = self.Transactions.GetOpenOrdersRemainingQuantity(basicOrderTicketFilter);
# The type returned by self.Transactions.GetOrders() is iterable and not a list
# that's why we use sum() to get the size of the iterable object type
filledOrdersSize = sum(1 for order in filledOrders)
orderTicketsSize = sum(1 for ticket in orderTickets)
openOrderTicketsSize = sum(1 for ticket in openOrderTickets)
assert(filledOrdersSize == 8 and orderTicketsSize == 10), "There were expected 8 filled orders and 10 order tickets"
assert(not (len(openOrders) or openOrderTicketsSize)), "No open orders or tickets were expected"
assert(not remainingOpenOrders), "No remaining quantiy to be filled from open orders was expected"
spyOpenOrders = self.Transactions.GetOpenOrders(self.spy)
spyOpenOrderTickets = self.Transactions.GetOpenOrderTickets(self.spy)
spyOpenOrderTicketsSize = sum(1 for tickets in spyOpenOrderTickets)
spyOpenOrdersRemainingQuantity = self.Transactions.GetOpenOrdersRemainingQuantity(self.spy)
assert(not (len(spyOpenOrders) or spyOpenOrderTicketsSize)), "No open orders or tickets were expected"
assert(not spyOpenOrdersRemainingQuantity), "No remaining quantiy to be filled from open orders was expected"
defaultOrders = self.Transactions.GetOrders();
defaultOrderTickets = self.Transactions.GetOrderTickets();
defaultOpenOrders = self.Transactions.GetOpenOrders();
defaultOpenOrderTickets = self.Transactions.GetOpenOrderTickets();
defaultOpenOrdersRemaining = self.Transactions.GetOpenOrdersRemainingQuantity();
defaultOrdersSize = sum(1 for order in defaultOrders)
defaultOrderTicketsSize = sum(1 for ticket in defaultOrderTickets)
defaultOpenOrderTicketsSize = sum(1 for ticket in defaultOpenOrderTickets)
assert(defaultOrdersSize == 10 and defaultOrderTicketsSize == 10), "There were expected 10 orders and 10 order tickets"
assert(not (len(defaultOpenOrders) or defaultOpenOrderTicketsSize)), "No open orders or tickets were expected"
assert(not defaultOpenOrdersRemaining), "No remaining quantiy to be filled from open orders was expected"

View File

@@ -37,7 +37,7 @@
<Compile Include="..\Common\Properties\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.8" />
<PackageReference Include="QuantConnect.pythonnet" Version="2.0.10" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -1,4 +1,4 @@
/*
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
@@ -28,6 +28,7 @@ namespace QuantConnect.Algorithm
/// Sets the alpha model
/// </summary>
/// <param name="alpha">Model that generates alpha</param>
[DocumentationAttribute(AlgorithmFramework)]
public void SetAlpha(PyObject alpha)
{
IAlphaModel model;
@@ -45,6 +46,7 @@ namespace QuantConnect.Algorithm
/// Adds a new alpha model
/// </summary>
/// <param name="alpha">Model that generates alpha to add</param>
[DocumentationAttribute(AlgorithmFramework)]
public void AddAlpha(PyObject alpha)
{
IAlphaModel model;
@@ -62,6 +64,8 @@ namespace QuantConnect.Algorithm
/// Sets the execution model
/// </summary>
/// <param name="execution">Model defining how to execute trades to reach a portfolio target</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(TradingAndOrders)]
public void SetExecution(PyObject execution)
{
IExecutionModel model;
@@ -79,6 +83,8 @@ namespace QuantConnect.Algorithm
/// Sets the portfolio construction model
/// </summary>
/// <param name="portfolioConstruction">Model defining how to build a portfolio from alphas</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(TradingAndOrders)]
public void SetPortfolioConstruction(PyObject portfolioConstruction)
{
IPortfolioConstructionModel model;
@@ -96,6 +102,8 @@ namespace QuantConnect.Algorithm
/// Sets the universe selection model
/// </summary>
/// <param name="universeSelection">Model defining universes for the algorithm</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(Universes)]
public void SetUniverseSelection(PyObject universeSelection)
{
IUniverseSelectionModel model;
@@ -110,6 +118,8 @@ namespace QuantConnect.Algorithm
/// Adds a new universe selection model
/// </summary>
/// <param name="universeSelection">Model defining universes for the algorithm to add</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(Universes)]
public void AddUniverseSelection(PyObject universeSelection)
{
IUniverseSelectionModel model;
@@ -124,6 +134,8 @@ namespace QuantConnect.Algorithm
/// Sets the risk management model
/// </summary>
/// <param name="riskManagement">Model defining how risk is managed</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(TradingAndOrders)]
public void SetRiskManagement(PyObject riskManagement)
{
IRiskManagementModel model;
@@ -141,6 +153,8 @@ namespace QuantConnect.Algorithm
/// Adds a new risk management model
/// </summary>
/// <param name="riskManagement">Model defining how risk is managed to add</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(TradingAndOrders)]
public void AddRiskManagement(PyObject riskManagement)
{
IRiskManagementModel model;
@@ -151,4 +165,4 @@ namespace QuantConnect.Algorithm
AddRiskManagement(model);
}
}
}
}

View File

@@ -1,4 +1,4 @@
/*
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
@@ -38,37 +38,44 @@ namespace QuantConnect.Algorithm
/// Enables additional logging of framework models including:
/// All insights, portfolio targets, order events, and any risk management altered targets
/// </summary>
[DocumentationAttribute(Logging)]
public bool DebugMode { get; set; }
/// <summary>
/// Gets or sets the universe selection model.
/// </summary>
[DocumentationAttribute(AlgorithmFramework)]
public IUniverseSelectionModel UniverseSelection { get; set; }
/// <summary>
/// Gets or sets the alpha model
/// </summary>
[DocumentationAttribute(AlgorithmFramework)]
public IAlphaModel Alpha { get; set; }
/// <summary>
/// Gets or sets the portfolio construction model
/// </summary>
[DocumentationAttribute(AlgorithmFramework)]
public IPortfolioConstructionModel PortfolioConstruction { get; set; }
/// <summary>
/// Gets or sets the execution model
/// </summary>
[DocumentationAttribute(AlgorithmFramework)]
public IExecutionModel Execution { get; set; }
/// <summary>
/// Gets or sets the risk management model
/// </summary>
[DocumentationAttribute(AlgorithmFramework)]
public IRiskManagementModel RiskManagement { get; set; }
/// <summary>
/// Called by setup handlers after Initialize and allows the algorithm a chance to organize
/// the data gather in the Initialize method
/// </summary>
[DocumentationAttribute(AlgorithmFramework)]
public void FrameworkPostInitialize()
{
//Prevents execution in the case of cash brokerage with IExecutionModel and IPortfolioConstructionModel
@@ -97,6 +104,8 @@ namespace QuantConnect.Algorithm
/// Used to send data updates to algorithm framework models
/// </summary>
/// <param name="slice">The current data slice</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(HandlingData)]
public void OnFrameworkData(Slice slice)
{
if (UtcTime >= UniverseSelection.GetNextRefreshTimeUtc())
@@ -170,6 +179,7 @@ namespace QuantConnect.Algorithm
/// and the <see cref="IExecutionModel"/> will execute the <see cref="IPortfolioTarget"/>
/// </summary>
/// <param name="insights">The insight to process</param>
[DocumentationAttribute(AlgorithmFramework)]
private void ProcessInsights(Insight[] insights)
{
// construct portfolio targets from insights
@@ -244,6 +254,8 @@ namespace QuantConnect.Algorithm
/// Used to send security changes to algorithm framework models
/// </summary>
/// <param name="changes">Security additions/removals for this time step</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(Universes)]
public void OnFrameworkSecuritiesChanged(SecurityChanges changes)
{
if (DebugMode)
@@ -261,6 +273,8 @@ namespace QuantConnect.Algorithm
/// Sets the universe selection model
/// </summary>
/// <param name="universeSelection">Model defining universes for the algorithm</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(Universes)]
public void SetUniverseSelection(IUniverseSelectionModel universeSelection)
{
UniverseSelection = universeSelection;
@@ -270,6 +284,8 @@ namespace QuantConnect.Algorithm
/// Adds a new universe selection model
/// </summary>
/// <param name="universeSelection">Model defining universes for the algorithm to add</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(Universes)]
public void AddUniverseSelection(IUniverseSelectionModel universeSelection)
{
if (UniverseSelection.GetType() != typeof(NullUniverseSelectionModel))
@@ -294,6 +310,7 @@ namespace QuantConnect.Algorithm
/// Sets the alpha model
/// </summary>
/// <param name="alpha">Model that generates alpha</param>
[DocumentationAttribute(AlgorithmFramework)]
public void SetAlpha(IAlphaModel alpha)
{
Alpha = alpha;
@@ -303,6 +320,7 @@ namespace QuantConnect.Algorithm
/// Adds a new alpha model
/// </summary>
/// <param name="alpha">Model that generates alpha to add</param>
[DocumentationAttribute(AlgorithmFramework)]
public void AddAlpha(IAlphaModel alpha)
{
if (Alpha.GetType() != typeof(NullAlphaModel))
@@ -327,6 +345,8 @@ namespace QuantConnect.Algorithm
/// Sets the portfolio construction model
/// </summary>
/// <param name="portfolioConstruction">Model defining how to build a portfolio from insights</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(TradingAndOrders)]
public void SetPortfolioConstruction(IPortfolioConstructionModel portfolioConstruction)
{
PortfolioConstruction = portfolioConstruction;
@@ -336,6 +356,8 @@ namespace QuantConnect.Algorithm
/// Sets the execution model
/// </summary>
/// <param name="execution">Model defining how to execute trades to reach a portfolio target</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(TradingAndOrders)]
public void SetExecution(IExecutionModel execution)
{
Execution = execution;
@@ -345,6 +367,8 @@ namespace QuantConnect.Algorithm
/// Sets the risk management model
/// </summary>
/// <param name="riskManagement">Model defining how risk is managed</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(TradingAndOrders)]
public void SetRiskManagement(IRiskManagementModel riskManagement)
{
RiskManagement = riskManagement;
@@ -354,6 +378,8 @@ namespace QuantConnect.Algorithm
/// Adds a new risk management model
/// </summary>
/// <param name="riskManagement">Model defining how risk is managed to add</param>
[DocumentationAttribute(AlgorithmFramework)]
[DocumentationAttribute(TradingAndOrders)]
public void AddRiskManagement(IRiskManagementModel riskManagement)
{
if (RiskManagement.GetType() != typeof(NullRiskManagementModel))
@@ -380,6 +406,7 @@ namespace QuantConnect.Algorithm
/// QCAlgorithm that have been ported into the algorithm framework.
/// </summary>
/// <param name="insights">The array of insights to be emitted</param>
[DocumentationAttribute(AlgorithmFramework)]
public void EmitInsights(params Insight[] insights)
{
if (IsWarmingUp)
@@ -403,6 +430,7 @@ namespace QuantConnect.Algorithm
/// QCAlgorithm that have been ported into the algorithm framework.
/// </summary>
/// <param name="insight">The insight to be emitted</param>
[DocumentationAttribute(AlgorithmFramework)]
public void EmitInsights(Insight insight)
{
EmitInsights(new[] { insight });

View File

@@ -39,6 +39,7 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Gets whether or not this algorithm is still warming up
/// </summary>
[DocumentationAttribute(HistoricalData)]
public bool IsWarmingUp
{
get;
@@ -49,6 +50,7 @@ namespace QuantConnect.Algorithm
/// Sets the warm up period to the specified value
/// </summary>
/// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
[DocumentationAttribute(HistoricalData)]
public void SetWarmup(TimeSpan timeSpan)
{
SetWarmUp(timeSpan, null);
@@ -58,6 +60,7 @@ namespace QuantConnect.Algorithm
/// Sets the warm up period to the specified value
/// </summary>
/// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
[DocumentationAttribute(HistoricalData)]
public void SetWarmUp(TimeSpan timeSpan)
{
SetWarmup(timeSpan);
@@ -68,6 +71,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
/// <param name="resolution">The resolution to request</param>
[DocumentationAttribute(HistoricalData)]
public void SetWarmup(TimeSpan timeSpan, Resolution? resolution)
{
if (_locked)
@@ -85,6 +89,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
/// <param name="resolution">The resolution to request</param>
[DocumentationAttribute(HistoricalData)]
public void SetWarmUp(TimeSpan timeSpan, Resolution? resolution)
{
SetWarmup(timeSpan, resolution);
@@ -97,6 +102,7 @@ namespace QuantConnect.Algorithm
/// use 200 minute bars.
/// </summary>
/// <param name="barCount">The number of data points requested for warm up</param>
[DocumentationAttribute(HistoricalData)]
public void SetWarmup(int barCount)
{
SetWarmUp(barCount, null);
@@ -109,6 +115,7 @@ namespace QuantConnect.Algorithm
/// use 200 minute bars.
/// </summary>
/// <param name="barCount">The number of data points requested for warm up</param>
[DocumentationAttribute(HistoricalData)]
public void SetWarmUp(int barCount)
{
SetWarmup(barCount);
@@ -120,6 +127,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="barCount">The number of data points requested for warm up</param>
/// <param name="resolution">The resolution to request</param>
[DocumentationAttribute(HistoricalData)]
public void SetWarmup(int barCount, Resolution? resolution)
{
if (_locked)
@@ -138,6 +146,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="barCount">The number of data points requested for warm up</param>
/// <param name="resolution">The resolution to request</param>
[DocumentationAttribute(HistoricalData)]
public void SetWarmUp(int barCount, Resolution? resolution)
{
SetWarmup(barCount, resolution);
@@ -146,6 +155,7 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Sets <see cref="IAlgorithm.IsWarmingUp"/> to false to indicate this algorithm has finished its warm up
/// </summary>
[DocumentationAttribute(HistoricalData)]
public void SetFinishedWarmingUp()
{
IsWarmingUp = false;
@@ -165,6 +175,7 @@ namespace QuantConnect.Algorithm
/// Gets the history requests required for provide warm up data for the algorithm
/// </summary>
/// <returns></returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<HistoryRequest> GetWarmupHistoryRequests()
{
if (_warmupBarCount.HasValue)
@@ -189,6 +200,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to request data. This is a calendar span, so take into consideration weekends and such</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing data over the most recent span for all configured securities</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<Slice> History(TimeSpan span, Resolution? resolution = null)
{
return History(Securities.Keys, Time - span, Time, resolution).Memoize();
@@ -202,6 +214,7 @@ namespace QuantConnect.Algorithm
/// <param name="periods">The number of bars to request</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing data over the most recent span for all configured securities</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<Slice> History(int periods, Resolution? resolution = null)
{
return History(Securities.Keys, periods, resolution).Memoize();
@@ -215,6 +228,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to retrieve recent historical data</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<DataDictionary<T>> History<T>(TimeSpan span, Resolution? resolution = null)
where T : IBaseData
{
@@ -230,6 +244,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to retrieve recent historical data</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, TimeSpan span, Resolution? resolution = null)
where T : IBaseData
{
@@ -246,6 +261,7 @@ namespace QuantConnect.Algorithm
/// <param name="periods">The number of bars to request</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null)
where T : IBaseData
{
@@ -272,6 +288,7 @@ namespace QuantConnect.Algorithm
/// <param name="end">The end time in the algorithm's time zone</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null)
where T : IBaseData
{
@@ -294,6 +311,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to retrieve recent historical data</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<T> History<T>(Symbol symbol, TimeSpan span, Resolution? resolution = null)
where T : IBaseData
{
@@ -308,6 +326,7 @@ namespace QuantConnect.Algorithm
/// <param name="periods">The number of bars to request</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<TradeBar> History(Symbol symbol, int periods, Resolution? resolution = null)
{
if (symbol == null) throw new ArgumentException(_symbolEmptyErrorMessage);
@@ -328,6 +347,7 @@ namespace QuantConnect.Algorithm
/// <param name="periods">The number of bars to request</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<T> History<T>(Symbol symbol, int periods, Resolution? resolution = null)
where T : IBaseData
{
@@ -347,6 +367,7 @@ namespace QuantConnect.Algorithm
/// <param name="end">The end time in the algorithm's time zone</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<T> History<T>(Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null)
where T : IBaseData
{
@@ -363,6 +384,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to retrieve recent historical data</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<TradeBar> History(Symbol symbol, TimeSpan span, Resolution? resolution = null)
{
return History(symbol, Time - span, Time, resolution);
@@ -376,6 +398,7 @@ namespace QuantConnect.Algorithm
/// <param name="end">The end time in the algorithm's time zone</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<TradeBar> History(Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null)
{
var securityType = symbol.ID.SecurityType;
@@ -403,6 +426,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to retrieve recent historical data</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, TimeSpan span, Resolution? resolution = null)
{
return History(symbols, Time - span, Time, resolution).Memoize();
@@ -417,6 +441,7 @@ namespace QuantConnect.Algorithm
/// <param name="periods">The number of bars to request</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null)
{
if (resolution == Resolution.Tick) throw new ArgumentException("History functions that accept a 'periods' parameter can not be used with Resolution.Tick");
@@ -433,6 +458,7 @@ namespace QuantConnect.Algorithm
/// <param name="fillForward">True to fill forward missing data, false otherwise</param>
/// <param name="extendedMarket">True to include extended market hours data, false otherwise</param>
/// <returns>An enumerable of slice containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null, bool? fillForward = null, bool? extendedMarket = null)
{
return History(CreateDateRangeHistoryRequests(symbols, start, end, resolution, fillForward, extendedMarket)).Memoize();
@@ -443,6 +469,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="request">the history request to execute</param>
/// <returns>An enumerable of slice satisfying the specified history request</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<Slice> History(HistoryRequest request)
{
return History(new[] { request }).Memoize();
@@ -453,6 +480,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="requests">the history requests to execute</param>
/// <returns>An enumerable of slice satisfying the specified history request</returns>
[DocumentationAttribute(HistoricalData)]
public IEnumerable<Slice> History(IEnumerable<HistoryRequest> requests)
{
return History(requests, TimeZone).Memoize();
@@ -463,6 +491,8 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="security"><see cref="Security"/> object for which to retrieve historical data</param>
/// <returns>Securities historical data</returns>
[DocumentationAttribute(AddingData)]
[DocumentationAttribute(HistoricalData)]
public IEnumerable<BaseData> GetLastKnownPrices(Security security)
{
return GetLastKnownPrices(security.Symbol);
@@ -473,9 +503,11 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="symbol">The symbol we want to get seed data for</param>
/// <returns>Securities historical data</returns>
[DocumentationAttribute(AddingData)]
[DocumentationAttribute(HistoricalData)]
public IEnumerable<BaseData> GetLastKnownPrices(Symbol symbol)
{
if (symbol.IsCanonical() || HistoryProvider == null)
if (!HistoryRequestValid(symbol) || HistoryProvider == null)
{
return Enumerable.Empty<BaseData>();
}
@@ -534,6 +566,8 @@ namespace QuantConnect.Algorithm
/// <returns>A single <see cref="BaseData"/> object with the last known price</returns>
[Obsolete("This method is obsolete please use 'GetLastKnownPrices' which will return the last data point" +
" for each type associated with the requested security")]
[DocumentationAttribute(AddingData)]
[DocumentationAttribute(HistoricalData)]
public BaseData GetLastKnownPrice(Security security)
{
return GetLastKnownPrices(security.Symbol)
@@ -563,12 +597,13 @@ namespace QuantConnect.Algorithm
}
return config;
}
[DocumentationAttribute(HistoricalData)]
private IEnumerable<Slice> History(IEnumerable<HistoryRequest> requests, DateTimeZone timeZone)
{
var sentMessage = false;
// filter out any universe securities that may have made it this far
var filteredRequests = requests.Where(hr => !UniverseManager.ContainsKey(hr.Symbol)).ToList();
var filteredRequests = requests.Where(hr => HistoryRequestValid(hr.Symbol)).ToList();
for (var i = 0; i < filteredRequests.Count; i++)
{
var request = filteredRequests[i];
@@ -604,7 +639,7 @@ namespace QuantConnect.Algorithm
/// </summary>
private IEnumerable<HistoryRequest> CreateDateRangeHistoryRequests(IEnumerable<Symbol> symbols, DateTime startAlgoTz, DateTime endAlgoTz, Resolution? resolution = null, bool? fillForward = null, bool? extendedMarket = null)
{
return symbols.Where(x => !x.IsCanonical()).SelectMany(x =>
return symbols.Where(HistoryRequestValid).SelectMany(x =>
{
var requests = new List<HistoryRequest>();
@@ -629,7 +664,7 @@ namespace QuantConnect.Algorithm
/// </summary>
private IEnumerable<HistoryRequest> CreateBarCountHistoryRequests(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null)
{
return symbols.Where(x => !x.IsCanonical()).SelectMany(x =>
return symbols.Where(HistoryRequestValid).SelectMany(x =>
{
var res = GetResolution(x, resolution);
var exchange = GetExchangeHours(x);
@@ -729,7 +764,7 @@ namespace QuantConnect.Algorithm
false,
x.Item2,
true,
UniverseSettings.DataNormalizationMode));
UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType)));
}
}
@@ -778,5 +813,14 @@ namespace QuantConnect.Algorithm
return resolution ?? UniverseSettings.Resolution;
}
}
/// <summary>
/// Validate a symbol for a history request.
/// Universe and canonical symbols are only valid for future security types
/// </summary>
private bool HistoryRequestValid(Symbol symbol)
{
return symbol.SecurityType == SecurityType.Future || !UniverseManager.ContainsKey(symbol) && !symbol.IsCanonical();
}
}
}

View File

@@ -30,6 +30,7 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Gets whether or not WarmUpIndicator is allowed to warm up indicators/>
/// </summary>
[DocumentationAttribute(Indicators)]
public bool EnableAutomaticIndicatorWarmUp { get; set; } = false;
/// <summary>
@@ -42,6 +43,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar.</param>
/// <returns></returns>
[DocumentationAttribute(Indicators)]
public AccelerationBands ABANDS(Symbol symbol, int period, decimal width = 4, MovingAverageType movingAverageType = MovingAverageType.Simple,
Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
@@ -64,6 +66,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The AccumulationDistribution indicator for the requested symbol over the speified period</returns>
[DocumentationAttribute(Indicators)]
public AccumulationDistribution AD(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, "AD", resolution);
@@ -87,6 +90,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The AccumulationDistributionOscillator indicator for the requested symbol over the speified period</returns>
[DocumentationAttribute(Indicators)]
public AccumulationDistributionOscillator ADOSC(Symbol symbol, int fastPeriod, int slowPeriod, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"ADOSC({fastPeriod},{slowPeriod})", resolution);
@@ -111,6 +115,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">Size of the rolling series to fit onto</param>
/// <param name="resolution">The resolution</param>
/// <returns>The ARIMA indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public AutoRegressiveIntegratedMovingAverage ARIMA(Symbol symbol, int arOrder, int diffOrder, int maOrder, int period, Resolution? resolution = null)
{
var name = CreateIndicatorName(symbol, $"ARIMA({arOrder},{diffOrder},{maOrder},{period})", resolution);
@@ -134,6 +139,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">The period over which to compute the Average Directional Index</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The Average Directional Index indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public AverageDirectionalIndex ADX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"ADX({period})", resolution);
@@ -157,6 +163,7 @@ namespace QuantConnect.Algorithm
/// <param name="slowPeriod">The period of the slow moving average associated with the AO</param>
/// <param name="type">The type of moving average used when computing the fast and slow term. Defaults to simple moving average.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
[DocumentationAttribute(Indicators)]
public AwesomeOscillator AO(Symbol symbol, int slowPeriod, int fastPeriod, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"AO({fastPeriod},{slowPeriod},{type})", resolution);
@@ -179,6 +186,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The AverageDirectionalMovementIndexRating indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public AverageDirectionalMovementIndexRating ADXR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"ADXR({period})", resolution);
@@ -207,6 +215,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The ArnaudLegouxMovingAverage indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public ArnaudLegouxMovingAverage ALMA(Symbol symbol, int period, int sigma = 6, decimal offset = 0.85m, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"ALMA({period},{sigma},{offset})", resolution);
@@ -231,6 +240,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The AbsolutePriceOscillator indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public AbsolutePriceOscillator APO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"APO({fastPeriod},{slowPeriod})", resolution);
@@ -253,6 +263,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>An AroonOscillator configured with the specied periods</returns>
[DocumentationAttribute(Indicators)]
public AroonOscillator AROON(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
return AROON(symbol, period, period, resolution, selector);
@@ -267,6 +278,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>An AroonOscillator configured with the specified periods</returns>
[DocumentationAttribute(Indicators)]
public AroonOscillator AROON(Symbol symbol, int upPeriod, int downPeriod, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"AROON({upPeriod},{downPeriod})", resolution);
@@ -291,6 +303,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>A new AverageTrueRange indicator with the specified smoothing type and period</returns>
[DocumentationAttribute(Indicators)]
public AverageTrueRange ATR(Symbol symbol, int period, MovingAverageType type = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"ATR({period})", resolution);
@@ -314,6 +327,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The AugenPriceSpike indicator for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public AugenPriceSpike APS(Symbol symbol, int period = 3, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"APS({period})", resolution);
@@ -338,6 +352,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>A BollingerBands configured with the specified period</returns>
[DocumentationAttribute(Indicators)]
public BollingerBands BB(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"BB({period},{k})", resolution);
@@ -352,6 +367,32 @@ namespace QuantConnect.Algorithm
return bollingerBands;
}
/// <summary>
/// Creates a Beta indicator for the given target symbol in relation with the reference used.
/// The indicator will be automatically updated on the given resolution.
/// </summary>
/// <param name="target">The target symbol whose Beta value we want</param>
/// <param name="reference">The reference symbol to compare with the target symbol</param>
/// <param name="period">The period of the Beta indicator</param>
/// <param name="resolution">The resolution</param>
/// <returns>The Beta indicator for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public Beta B(Symbol target, Symbol reference, int period, Resolution? resolution = null)
{
var name = CreateIndicatorName(QuantConnect.Symbol.None, "B", resolution);
var beta = new Beta(name, period, target, reference);
RegisterIndicator(target, beta, resolution);
RegisterIndicator(reference, beta, resolution);
if (EnableAutomaticIndicatorWarmUp)
{
WarmUpIndicator(target, beta, resolution);
WarmUpIndicator(reference, beta, resolution);
}
return beta;
}
/// <summary>
/// Creates a new Balance Of Power indicator.
/// The indicator will be automatically updated on the given resolution.
@@ -360,6 +401,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The Balance Of Power indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public BalanceOfPower BOP(Symbol symbol, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, "BOP", resolution);
@@ -384,6 +426,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The Coppock Curve indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public CoppockCurve CC(Symbol symbol, int shortRocPeriod = 11, int longRocPeriod = 14, int lwmaPeriod = 10, Resolution? resolution = null,
Func<IBaseData, decimal> selector = null)
{
@@ -409,6 +452,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The CommodityChannelIndex indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public CommodityChannelIndex CCI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"CCI({period})", resolution);
@@ -431,6 +475,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The ChaikinMoneyFlow indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public ChaikinMoneyFlow CMF(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"CMF({period})", resolution);
@@ -453,6 +498,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The ChandeMomentumOscillator indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public ChandeMomentumOscillator CMO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"CMO({period})", resolution);
@@ -477,6 +523,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The DeMarker indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public DeMarkerIndicator DEM(Symbol symbol, int period, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"DEM({period},{type})", resolution);
@@ -501,6 +548,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The Donchian Channel indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public DonchianChannel DCH(Symbol symbol, int upperPeriod, int lowerPeriod, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"DCH({upperPeriod},{lowerPeriod})", resolution);
@@ -524,6 +572,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The Donchian Channel indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public DonchianChannel DCH(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
return DCH(symbol, period, period, resolution, selector);
@@ -537,6 +586,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The DoubleExponentialMovingAverage indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public DoubleExponentialMovingAverage DEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"DEMA({period})", resolution);
@@ -559,6 +609,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>A new registered DetrendedPriceOscillator indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public DetrendedPriceOscillator DPO(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"DPO({period})", resolution);
@@ -582,6 +633,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The ExponentialMovingAverage for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public ExponentialMovingAverage EMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
return EMA(symbol, period, ExponentialMovingAverage.SmoothingFactorDefault(period), resolution, selector);
@@ -597,6 +649,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The ExponentialMovingAverage for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public ExponentialMovingAverage EMA(Symbol symbol, int period, decimal smoothingFactor, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"EMA({period})", resolution);
@@ -621,6 +674,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The EaseOfMovementValue indicator for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public EaseOfMovementValue EMV(Symbol symbol, int period = 1, int scale = 10000, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"EMV({period}, {scale})", resolution);
@@ -644,6 +698,7 @@ namespace QuantConnect.Algorithm
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public FilteredIdentity FilteredIdentity(Symbol symbol, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
{
var resolution = GetSubscription(symbol).Resolution;
@@ -660,6 +715,7 @@ namespace QuantConnect.Algorithm
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public FilteredIdentity FilteredIdentity(Symbol symbol, Resolution resolution, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
{
var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
@@ -678,6 +734,7 @@ namespace QuantConnect.Algorithm
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public FilteredIdentity FilteredIdentity(Symbol symbol, TimeSpan resolution, Func<IBaseData, IBaseDataBar> selector = null, Func<IBaseData, bool> filter = null, string fieldName = null)
{
var name = Invariant($"{symbol}({fieldName ?? "close"}_{resolution})");
@@ -695,6 +752,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The FisherTransform for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public FisherTransform FISH(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"FISH({period})", resolution);
@@ -719,6 +777,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The FRAMA for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public FractalAdaptiveMovingAverage FRAMA(Symbol symbol, int period, int longPeriod = 198, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"FRAMA({period},{longPeriod})", resolution);
@@ -740,6 +799,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Heikin-Ashi indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public HeikinAshi HeikinAshi(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, "HA", resolution);
@@ -762,6 +822,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns></returns>
[DocumentationAttribute(Indicators)]
public HullMovingAverage HMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"HMA({period})", resolution);
@@ -789,6 +850,7 @@ namespace QuantConnect.Algorithm
/// <param name="senkouBDelayPeriod">The period to calculate the Tenkan-sen period</param>
/// <param name="resolution">The resolution</param>
/// <returns>A new IchimokuKinkoHyo indicator with the specified periods and delays</returns>
[DocumentationAttribute(Indicators)]
public IchimokuKinkoHyo ICHIMOKU(Symbol symbol, int tenkanPeriod, int kijunPeriod, int senkouAPeriod, int senkouBPeriod, int senkouADelayPeriod, int senkouBDelayPeriod, Resolution? resolution = null)
{
var name = CreateIndicatorName(symbol, $"ICHIMOKU({tenkanPeriod},{kijunPeriod},{senkouAPeriod},{senkouBPeriod},{senkouADelayPeriod},{senkouBDelayPeriod})", resolution);
@@ -811,6 +873,7 @@ namespace QuantConnect.Algorithm
/// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new Identity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public Identity Identity(Symbol symbol, Func<IBaseData, decimal> selector = null, string fieldName = null)
{
var resolution = GetSubscription(symbol).Resolution;
@@ -826,6 +889,7 @@ namespace QuantConnect.Algorithm
/// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new Identity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public Identity Identity(Symbol symbol, Resolution resolution, Func<IBaseData, decimal> selector = null, string fieldName = null)
{
var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
@@ -843,6 +907,7 @@ namespace QuantConnect.Algorithm
/// <param name="selector">Selects a value from the BaseData, if null defaults to the .Value property (x => x.Value)</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new Identity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public Identity Identity(Symbol symbol, TimeSpan resolution, Func<IBaseData, decimal> selector = null, string fieldName = null)
{
var name = Invariant($"{symbol}({fieldName ?? "close"},{resolution})");
@@ -859,6 +924,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
return KAMA(symbol, period, 2, 30, resolution, selector);
@@ -874,6 +940,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The KaufmanAdaptiveMovingAverage indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public KaufmanAdaptiveMovingAverage KAMA(Symbol symbol, int period, int fastEmaPeriod, int slowEmaPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"KAMA({period},{fastEmaPeriod},{slowEmaPeriod})", resolution);
@@ -888,6 +955,28 @@ namespace QuantConnect.Algorithm
return kaufmanAdaptiveMovingAverage;
}
/// <summary>
/// Creates an KaufmanEfficiencyRatio indicator for the symbol. The indicator will be automatically
/// updated on the given resolution.
/// </summary>
/// <param name="symbol">The symbol whose EF we want</param>
/// <param name="period">The period of the EF</param>
/// <param name="resolution">The resolution</param>
/// <returns>The KaufmanEfficiencyRatio indicator for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public KaufmanEfficiencyRatio KER(Symbol symbol, int period = 2, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"KER({period})", resolution);
var kaufmanEfficiencyRatio = new KaufmanEfficiencyRatio(name, period);
RegisterIndicator(symbol, kaufmanEfficiencyRatio, resolution, selector);
if (EnableAutomaticIndicatorWarmUp)
{
WarmUpIndicator(symbol, kaufmanEfficiencyRatio, resolution);
}
return kaufmanEfficiencyRatio;
}
/// <summary>
/// Creates a new Keltner Channels indicator.
/// The indicator will be automatically updated on the given resolution.
@@ -899,6 +988,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The Keltner Channel indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public KeltnerChannels KCH(Symbol symbol, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"KCH({period},{k})", resolution);
@@ -921,6 +1011,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar.</param>
/// <returns>log return indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public LogReturn LOGR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"LOGR({period})", resolution);
@@ -943,6 +1034,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar.</param>
/// <returns>A LeastSquaredMovingAverage configured with the specified period</returns>
[DocumentationAttribute(Indicators)]
public LeastSquaresMovingAverage LSMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"LSMA({period})", resolution);
@@ -966,6 +1058,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns></returns>
[DocumentationAttribute(Indicators)]
public LinearWeightedMovingAverage LWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"LWMA({period})", resolution);
@@ -991,6 +1084,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The moving average convergence divergence between the fast and slow averages</returns>
[DocumentationAttribute(Indicators)]
public MovingAverageConvergenceDivergence MACD(Symbol symbol, int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType type = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"MACD({fastPeriod},{slowPeriod},{signalPeriod})", resolution);
@@ -1013,6 +1107,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The MeanAbsoluteDeviation indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public MeanAbsoluteDeviation MAD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"MAD({period})", resolution);
@@ -1038,6 +1133,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Volume Profile indicator for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public VolumeProfile VP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"VP({period})", resolution);
@@ -1063,6 +1159,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Time Profile indicator for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public TimeProfile TP(Symbol symbol, int period = 2, decimal valueAreaVolumePercentage = 0.70m, decimal priceRangeRoundOff = 0.05m, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"TP({period})", resolution);
@@ -1086,6 +1183,7 @@ namespace QuantConnect.Algorithm
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null and the symbol is of type TradeBar defaults to the High property,
/// otherwise it defaults to Value property of BaseData (x => x.Value)</param>
/// <returns>A Maximum indicator that compute the max value and the periods since the max value</returns>
[DocumentationAttribute(Indicators)]
public Maximum MAX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"MAX({period})", resolution);
@@ -1121,6 +1219,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The MoneyFlowIndex indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public MoneyFlowIndex MFI(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"MFI({period})", resolution);
@@ -1145,6 +1244,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Mass Index indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public MassIndex MASS(Symbol symbol, int emaPeriod = 9, int sumPeriod = 25, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"MASS({emaPeriod},{sumPeriod})", resolution);
@@ -1167,6 +1267,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The MidPoint indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public MidPoint MIDPOINT(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"MIDPOINT({period})", resolution);
@@ -1189,6 +1290,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The MidPrice indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public MidPrice MIDPRICE(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"MIDPRICE({period})", resolution);
@@ -1212,6 +1314,7 @@ namespace QuantConnect.Algorithm
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null and the symbol is of type TradeBar defaults to the Low property,
/// otherwise it defaults to Value property of BaseData (x => x.Value)</param>
/// <returns>A Minimum indicator that compute the in value and the periods since the min value</returns>
[DocumentationAttribute(Indicators)]
public Minimum MIN(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"MIN({period})", resolution);
@@ -1247,6 +1350,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The momentum indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public Momentum MOM(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"MOM({period})", resolution);
@@ -1270,6 +1374,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Momersion indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public MomersionIndicator MOMERSION(Symbol symbol, int? minPeriod, int fullPeriod, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"MOMERSION({minPeriod},{fullPeriod})", resolution);
@@ -1293,6 +1398,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The momentum indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public MomentumPercent MOMP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"MOMP({period})", resolution);
@@ -1315,6 +1421,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The NormalizedAverageTrueRange indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public NormalizedAverageTrueRange NATR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"NATR({period})", resolution);
@@ -1338,6 +1445,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The On Balance Volume indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public OnBalanceVolume OBV(Symbol symbol, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, "OBV", resolution);
@@ -1362,6 +1470,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The PivotPointsHighLow indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public PivotPointsHighLow PPHL(Symbol symbol, int lengthHigh, int lengthLow, int lastStoredValues = 100, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"PPHL({lengthHigh},{lengthLow})", resolution);
@@ -1386,6 +1495,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The PercentagePriceOscillator indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public PercentagePriceOscillator PPO(Symbol symbol, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"PPO({fastPeriod},{slowPeriod})", resolution);
@@ -1410,6 +1520,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>A ParabolicStopAndReverse configured with the specified periods</returns>
[DocumentationAttribute(Indicators)]
public ParabolicStopAndReverse PSAR(Symbol symbol, decimal afStart = 0.02m, decimal afIncrement = 0.02m, decimal afMax = 0.2m, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"PSAR({afStart},{afIncrement},{afMax})", resolution);
@@ -1433,6 +1544,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>A Regression Channel configured with the specified period and number of standard deviation</returns>
[DocumentationAttribute(Indicators)]
public RegressionChannel RC(Symbol symbol, int period, decimal k, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"RC({period},{k})", resolution);
@@ -1456,6 +1568,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The RateOfChange indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public RateOfChange ROC(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"ROC({period})", resolution);
@@ -1479,6 +1592,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The RateOfChangePercent indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public RateOfChangePercent ROCP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"ROCP({period})", resolution);
@@ -1501,6 +1615,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The RateOfChangeRatio indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public RateOfChangeRatio ROCR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"ROCR({period})", resolution);
@@ -1525,6 +1640,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The RelativeStrengthIndex indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public RelativeStrengthIndex RSI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"RSI({period},{movingAverageType})", resolution);
@@ -1547,6 +1663,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The RelativeVigorIndex indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public RelativeVigorIndex RVI(Symbol symbol, int period, MovingAverageType movingAverageType = MovingAverageType.Simple, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"RVI({period},{movingAverageType})", resolution);
@@ -1570,6 +1687,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Relative Volume indicator for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public RelativeDailyVolume RDV(Symbol symbol, int period = 2, Resolution resolution = Resolution.Daily, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"RDV({period})", resolution);
@@ -1584,6 +1702,29 @@ namespace QuantConnect.Algorithm
return relativeDailyVolume;
}
/// <summary>
/// Creates a new SuperTrend indicator.
/// </summary>
/// <param name="symbol">The symbol whose SuperTrend indicator we want.</param>
/// <param name="period">The smoothing period for average true range.</param>
/// <param name="multiplier">Multiplier to calculate basic upper and lower bands width.</param>
/// <param name="movingAverageType">Smoother type for average true range, defaults to Wilders.</param>
/// <param name="resolution">The resolution.</param>
[DocumentationAttribute(Indicators)]
public SuperTrend STR(Symbol symbol, int period, decimal multiplier, MovingAverageType movingAverageType = MovingAverageType.Wilders, Resolution? resolution = null)
{
var name = CreateIndicatorName(symbol, $"STR({period},{multiplier})", resolution);
var strend = new SuperTrend(name, period, multiplier, movingAverageType);
RegisterIndicator(symbol, strend, resolution);
if (EnableAutomaticIndicatorWarmUp)
{
WarmUpIndicator(symbol, strend, resolution);
}
return strend;
}
/// <summary>
/// Creates a new RollingSharpeRatio indicator.
/// </summary>
@@ -1593,6 +1734,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The RollingSharpeRatio indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public SharpeRatio SR(Symbol symbol, int sharpePeriod, decimal riskFreeRate = 0.0m, Resolution ? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"SR({sharpePeriod},{riskFreeRate})", resolution);
@@ -1617,6 +1759,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The SimpleMovingAverage for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public SimpleMovingAverage SMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"SMA({period})", resolution);
@@ -1642,6 +1785,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The SchaffTrendCycle indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public SchaffTrendCycle STC(Symbol symbol, int cyclePeriod, int fastPeriod, int slowPeriod, MovingAverageType movingAverageType = MovingAverageType.Exponential, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"STC({cyclePeriod},{fastPeriod},{slowPeriod})", resolution);
@@ -1664,6 +1808,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The StandardDeviation indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public StandardDeviation STD(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"STD({period})", resolution);
@@ -1686,6 +1831,7 @@ namespace QuantConnect.Algorithm
/// <param name="kPeriod">The sum period of the stochastic. Normally 14</param>
/// <param name="dPeriod">The sum period of the stochastic. Normally 3</param>
/// <returns>Stochastic indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public Stochastic STO(Symbol symbol, int period, int kPeriod, int dPeriod, Resolution? resolution = null)
{
var name = CreateIndicatorName(symbol, $"STO({period},{kPeriod},{dPeriod})", resolution);
@@ -1707,6 +1853,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution.</param>
/// <param name="period">The period of the stochastic. Normally 14</param>
/// <returns>Stochastic indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public Stochastic STO(Symbol symbol, int period, Resolution? resolution = null)
{
return STO(symbol, period, period, 3, resolution);
@@ -1720,6 +1867,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Sum indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public Sum SUM(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"SUM({period})", resolution);
@@ -1745,6 +1893,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">elects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The calculation using the given tool</returns>
[DocumentationAttribute(Indicators)]
public SwissArmyKnife SWISS(Symbol symbol, int period, double delta, SwissArmyKnifeTool tool, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"SWISS({period},{delta},{tool})", resolution);
@@ -1768,6 +1917,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The T3MovingAverage indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public T3MovingAverage T3(Symbol symbol, int period, decimal volumeFactor = 0.7m, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"T3({period},{volumeFactor})", resolution);
@@ -1790,6 +1940,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The TripleExponentialMovingAverage indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public TripleExponentialMovingAverage TEMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"TEMA({period})", resolution);
@@ -1811,6 +1962,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The TrueRange indicator for the requested symbol.</returns>
[DocumentationAttribute(Indicators)]
public TrueRange TR(Symbol symbol, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, "TR", resolution);
@@ -1833,6 +1985,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The TriangularMovingAverage indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public TriangularMovingAverage TRIMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"TRIMA({period})", resolution);
@@ -1855,6 +2008,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Trix indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public Trix TRIX(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"TRIX({period})", resolution);
@@ -1879,6 +2033,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The UltimateOscillator indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public UltimateOscillator ULTOSC(Symbol symbol, int period1, int period2, int period3, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"ULTOSC({period1},{period2},{period3})", resolution);
@@ -1901,6 +2056,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Variance indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public Variance VAR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"VAR({period})", resolution);
@@ -1924,6 +2080,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The VolumeWeightedAveragePrice for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public VolumeWeightedAveragePriceIndicator VWAP(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"VWAP({period})", resolution);
@@ -1944,6 +2101,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="symbol">The symbol whose VWAP we want</param>
/// <returns>The IntradayVWAP for the specified symbol</returns>
[DocumentationAttribute(Indicators)]
public IntradayVwap VWAP(Symbol symbol)
{
var name = CreateIndicatorName(symbol, "VWAP", null);
@@ -1962,6 +2120,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The Williams %R indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public WilliamsPercentR WILR(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"WILR({period})", resolution);
@@ -1986,6 +2145,7 @@ namespace QuantConnect.Algorithm
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The WilderMovingAverage for the given parameters</returns>
/// <remarks>WWMA for Welles Wilder Moving Average</remarks>
[DocumentationAttribute(Indicators)]
public WilderMovingAverage WWMA(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
var name = CreateIndicatorName(symbol, $"WWMA({period})", resolution);
@@ -2009,6 +2169,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <returns>The WilderSwingIndex for the given parameters</returns>
/// <remarks>SI for Wilder Swing Index</remarks>
[DocumentationAttribute(Indicators)]
public WilderSwingIndex SI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily)
{
var name = CreateIndicatorName(symbol, "SI", resolution);
@@ -2032,6 +2193,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <returns>The WilderAccumulativeSwingIndex for the given parameters</returns>
/// <remarks>ASI for Wilder Accumulative Swing Index</remarks>
[DocumentationAttribute(Indicators)]
public WilderAccumulativeSwingIndex ASI(Symbol symbol, decimal limitMove, Resolution? resolution = Resolution.Daily)
{
var name = CreateIndicatorName(symbol, "ASI", resolution);
@@ -2052,6 +2214,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbols">The symbols whose Arms Index we want</param>
/// <param name="resolution">The resolution</param>
/// <returns>The Arms Index indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public ArmsIndex TRIN(IEnumerable<Symbol> symbols, Resolution? resolution = null)
{
return TRIN(symbols.ToArray(), resolution);
@@ -2063,6 +2226,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbols">The symbols whose Arms Index we want</param>
/// <param name="resolution">The resolution</param>
/// <returns>The Arms Index indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public ArmsIndex TRIN(Symbol[] symbols, Resolution? resolution = null)
{
var name = CreateIndicatorName(QuantConnect.Symbol.None, "TRIN", resolution ?? GetSubscription(symbols.First()).Resolution);
@@ -2087,6 +2251,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbols">The symbols whose A/D Ratio we want</param>
/// <param name="resolution">The resolution</param>
/// <returns>The Advance/Decline Ratio indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public AdvanceDeclineRatio ADR(IEnumerable<Symbol> symbols, Resolution? resolution = null)
{
var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Ratio", resolution ?? GetSubscription(symbols.First()).Resolution);
@@ -2111,6 +2276,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbols">The symbol whose A/D Volume Rate we want</param>
/// <param name="resolution">The resolution</param>
/// <returns>The Advance/Decline Volume Ratio indicator for the requested symbol over the specified period</returns>
[DocumentationAttribute(Indicators)]
public AdvanceDeclineVolumeRatio ADVR(IEnumerable<Symbol> symbols, Resolution? resolution = null)
{
var name = CreateIndicatorName(QuantConnect.Symbol.None, "A/D Volume Rate", resolution ?? GetSubscription(symbols.First()).Resolution);
@@ -2136,6 +2302,7 @@ namespace QuantConnect.Algorithm
/// <param name="type">The indicator type, for example, 'SMA(5)'</param>
/// <param name="resolution">The resolution requested</param>
/// <returns>A unique for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public string CreateIndicatorName(Symbol symbol, FormattableString type, Resolution? resolution)
{
return CreateIndicatorName(symbol, Invariant(type), resolution);
@@ -2148,6 +2315,7 @@ namespace QuantConnect.Algorithm
/// <param name="type">The indicator type, for example, 'SMA(5)'</param>
/// <param name="resolution">The resolution requested</param>
/// <returns>A unique for the given parameters</returns>
[DocumentationAttribute(Indicators)]
public string CreateIndicatorName(Symbol symbol, string type, Resolution? resolution)
{
if (!resolution.HasValue)
@@ -2238,6 +2406,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value));
@@ -2251,6 +2421,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan? resolution = null, Func<IBaseData, decimal> selector = null)
{
RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector ?? (x => x.Value));
@@ -2264,6 +2436,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="consolidator">The consolidator to receive raw subscription data</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public void RegisterIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, IDataConsolidator consolidator, Func<IBaseData, decimal> selector = null)
{
// default our selector to the Value property on BaseData
@@ -2287,6 +2461,8 @@ namespace QuantConnect.Algorithm
/// <param name="symbol">The symbol to register against</param>
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null)
where T : IBaseData
{
@@ -2301,6 +2477,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution, Func<IBaseData, T> selector)
where T : IBaseData
{
@@ -2315,6 +2493,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, TimeSpan? resolution, Func<IBaseData, T> selector = null)
where T : IBaseData
{
@@ -2329,6 +2509,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="consolidator">The consolidator to receive raw subscription data</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public void RegisterIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, IDataConsolidator consolidator, Func<IBaseData, T> selector = null)
where T : IBaseData
{
@@ -2372,6 +2554,8 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The given indicator</returns>
[DocumentationAttribute(HistoricalData)]
[DocumentationAttribute(Indicators)]
public IndicatorBase<IndicatorDataPoint> WarmUpIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, Resolution? resolution = null, Func<IBaseData, decimal> selector = null)
{
resolution = GetResolution(symbol, resolution);
@@ -2387,6 +2571,8 @@ namespace QuantConnect.Algorithm
/// <param name="period">The necessary period to warm up the indicator</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The given indicator</returns>
[DocumentationAttribute(HistoricalData)]
[DocumentationAttribute(Indicators)]
public IndicatorBase<IndicatorDataPoint> WarmUpIndicator(Symbol symbol, IndicatorBase<IndicatorDataPoint> indicator, TimeSpan period, Func<IBaseData, decimal> selector = null)
{
var history = GetIndicatorWarmUpHistory(symbol, indicator, period);
@@ -2413,6 +2599,8 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to the Value property of BaseData (x => x.Value)</param>
/// <returns>The given indicator</returns>
[DocumentationAttribute(HistoricalData)]
[DocumentationAttribute(Indicators)]
public IndicatorBase<T> WarmUpIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, Resolution? resolution = null, Func<IBaseData, T> selector = null)
where T : class, IBaseData
{
@@ -2429,6 +2617,8 @@ namespace QuantConnect.Algorithm
/// <param name="period">The necessary period to warm up the indicator</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
/// <returns>The given indicator</returns>
[DocumentationAttribute(HistoricalData)]
[DocumentationAttribute(Indicators)]
public IndicatorBase<T> WarmUpIndicator<T>(Symbol symbol, IndicatorBase<T> indicator, TimeSpan period, Func<IBaseData, T> selector = null)
where T : class, IBaseData
{
@@ -2452,7 +2642,7 @@ namespace QuantConnect.Algorithm
{
var periods = (indicator as IIndicatorWarmUpPeriodProvider)?.WarmUpPeriod;
if (periods.HasValue)
if (periods.HasValue && periods != 0)
{
var resolution = timeSpan.ToHigherResolutionEquivalent(false);
var resolutionTicks = resolution.ToTimeSpan().Ticks;
@@ -2472,7 +2662,8 @@ namespace QuantConnect.Algorithm
}
else if (!_isEmitWarmupInsightWarningSent)
{
Debug($"Warning: the 'WarmUpIndicator' feature only works with indicators which inherit from '{nameof(IIndicatorWarmUpPeriodProvider)}' and define a warm up period." +
Debug($"Warning: the 'WarmUpIndicator' feature only works with indicators which inherit from '{nameof(IIndicatorWarmUpPeriodProvider)}'" +
$" and define a warm up period, setting property 'WarmUpPeriod' with a value > 0." +
$" The provided indicator of type '{indicator.GetType().Name}' will not be warmed up.");
_isEmitWarmupInsightWarningSent = true;
}
@@ -2538,6 +2729,8 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The resolution for the consolidator, if null, uses the resolution from subscription</param>
/// <param name="dataType">The data type for this consolidator, if null, uses TradeBar over QuoteBar if present</param>
/// <returns>The new default consolidator</returns>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public IDataConsolidator ResolveConsolidator(Symbol symbol, Resolution? resolution, Type dataType = null)
{
TimeSpan? timeSpan = null;
@@ -2555,6 +2748,8 @@ namespace QuantConnect.Algorithm
/// <param name="timeSpan">The requested time span for the consolidator, if null, uses the resolution from subscription</param>
/// <param name="dataType">The data type for this consolidator, if null, uses TradeBar over QuoteBar if present</param>
/// <returns>The new default consolidator</returns>
[DocumentationAttribute(ConsolidatingData)]
[DocumentationAttribute(Indicators)]
public IDataConsolidator ResolveConsolidator(Symbol symbol, TimeSpan? timeSpan, Type dataType = null)
{
var tickType = dataType != null ? LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType) : (TickType?)null;
@@ -2585,6 +2780,7 @@ namespace QuantConnect.Algorithm
/// <param name="consolidatorInputType">The desired input type of the consolidator, such as TradeBar or QuoteBar</param>
/// <param name="tickType">Trade or Quote. Optional, defaults to trade</param>
/// <returns>A new consolidator matching the requested parameters</returns>
[DocumentationAttribute(ConsolidatingData)]
public static IDataConsolidator CreateConsolidator(TimeSpan period, Type consolidatorInputType, TickType? tickType = null)
{
// if our type can be used as a trade bar, then let's just make one of those
@@ -2641,6 +2837,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">The consolidation period</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action<TradeBar> handler)
{
return Consolidate(symbol, period.ToTimeSpan(), TickType.Trade, handler);
@@ -2653,6 +2850,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">The consolidation period</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action<TradeBar> handler)
{
return Consolidate(symbol, period, TickType.Trade, handler);
@@ -2665,6 +2863,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">The consolidation period</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, Resolution period, Action<QuoteBar> handler)
{
return Consolidate(symbol, period.ToTimeSpan(), TickType.Quote, handler);
@@ -2677,6 +2876,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">The consolidation period</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, Action<QuoteBar> handler)
{
return Consolidate(symbol, period, TickType.Quote, handler);
@@ -2690,6 +2890,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">The consolidation period</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate<T>(Symbol symbol, TimeSpan period, Action<T> handler)
where T : class, IBaseData
{
@@ -2709,6 +2910,7 @@ namespace QuantConnect.Algorithm
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate<T>(Symbol symbol, Resolution period, TickType? tickType, Action<T> handler)
where T : class, IBaseData
{
@@ -2724,6 +2926,7 @@ namespace QuantConnect.Algorithm
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate<T>(Symbol symbol, TimeSpan period, TickType? tickType, Action<T> handler)
where T : class, IBaseData
{
@@ -2744,6 +2947,7 @@ namespace QuantConnect.Algorithm
/// <param name="calendar">The consolidation calendar</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<QuoteBar> handler)
{
return Consolidate(symbol, calendar, TickType.Quote, handler);
@@ -2756,6 +2960,7 @@ namespace QuantConnect.Algorithm
/// <param name="calendar">The consolidation calendar</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<TradeBar> handler)
{
return Consolidate(symbol, calendar, TickType.Trade, handler);
@@ -2769,6 +2974,7 @@ namespace QuantConnect.Algorithm
/// <param name="calendar">The consolidation calendar</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, Action<T> handler)
where T : class, IBaseData
{
@@ -2788,6 +2994,7 @@ namespace QuantConnect.Algorithm
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
private IDataConsolidator Consolidate<T>(Symbol symbol, Func<DateTime, CalendarInfo> calendar, TickType? tickType, Action<T> handler)
where T : class, IBaseData
{
@@ -2805,6 +3012,7 @@ namespace QuantConnect.Algorithm
/// Adds the provided consolidator and asserts the handler T type is assignable from the consolidator output,
/// if not will throw <see cref="ArgumentException"/>
/// </summary>
[DocumentationAttribute(ConsolidatingData)]
private void AddConsolidator<T>(Symbol symbol, IDataConsolidator consolidator, Action<T> handler)
{
if (!typeof(T).IsAssignableFrom(consolidator.OutputType))
@@ -2828,6 +3036,7 @@ namespace QuantConnect.Algorithm
SubscriptionManager.AddConsolidator(symbol, consolidator);
}
[DocumentationAttribute(ConsolidatingData)]
private IDataConsolidator CreateConsolidator(Func<DateTime, CalendarInfo> calendar, Type consolidatorInputType, TickType tickType)
{
// if our type can be used as a trade bar, then let's just make one of those

View File

@@ -45,6 +45,7 @@ namespace QuantConnect.Algorithm
/// Access to the runtime statistics property. User provided statistics.
/// </summary>
/// <remarks> RuntimeStatistics are displayed in the head banner in live trading</remarks>
[DocumentationAttribute(Charting)]
public ConcurrentDictionary<string, string> RuntimeStatistics { get; } = new ConcurrentDictionary<string, string>();
/// <summary>
@@ -52,6 +53,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="chart">Chart object to add to collection.</param>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void AddChart(Chart chart)
{
_charts.TryAdd(chart.Name, chart);
@@ -63,6 +65,7 @@ namespace QuantConnect.Algorithm
/// <param name="series">Name of the plot series</param>
/// <param name="value">Value to plot</param>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string series, decimal value)
{
//By default plot to the primary chart:
@@ -74,6 +77,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <remarks> Record(string series, int value)</remarks>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Record(string series, int value)
{
Plot(series, value);
@@ -83,6 +87,7 @@ namespace QuantConnect.Algorithm
/// Plot a chart using string series name, with double value. Alias of Plot();
/// </summary>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Record(string series, double value)
{
Plot(series, value);
@@ -94,6 +99,7 @@ namespace QuantConnect.Algorithm
/// <param name="series"></param>
/// <param name="value"></param>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Record(string series, decimal value)
{
//By default plot to the primary chart:
@@ -104,6 +110,7 @@ namespace QuantConnect.Algorithm
/// Plot a chart using string series name, with double value.
/// </summary>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string series, double value) {
Plot(series, value.SafeDecimalCast());
}
@@ -112,6 +119,7 @@ namespace QuantConnect.Algorithm
/// Plot a chart using string series name, with int value.
/// </summary>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string series, int value)
{
Plot(series, (decimal)value);
@@ -121,6 +129,7 @@ namespace QuantConnect.Algorithm
///Plot a chart using string series name, with float value.
/// </summary>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string series, float value)
{
Plot(series, (decimal)value);
@@ -130,6 +139,7 @@ namespace QuantConnect.Algorithm
/// Plot a chart to string chart name, using string series name, with double value.
/// </summary>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string chart, string series, double value)
{
Plot(chart, series, value.SafeDecimalCast());
@@ -139,6 +149,7 @@ namespace QuantConnect.Algorithm
/// Plot a chart to string chart name, using string series name, with int value
/// </summary>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string chart, string series, int value)
{
Plot(chart, series, (decimal)value);
@@ -148,6 +159,7 @@ namespace QuantConnect.Algorithm
/// Plot a chart to string chart name, using string series name, with float value
/// </summary>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string chart, string series, float value)
{
Plot(chart, series, (decimal)value);
@@ -159,6 +171,7 @@ namespace QuantConnect.Algorithm
/// <param name="chart">Chart name</param>
/// <param name="series">Series name</param>
/// <param name="value">Value of the point</param>
[DocumentationAttribute(Charting)]
public void Plot(string chart, string series, decimal value)
{
// Check if chart/series names are reserved
@@ -209,6 +222,7 @@ namespace QuantConnect.Algorithm
/// <param name="series">The series name</param>
/// <param name="seriesType">The type of series, i.e, Scatter</param>
/// <param name="unit">The unit of the y axis, usually $</param>
[DocumentationAttribute(Charting)]
public void AddSeries(string chart, string series, SeriesType seriesType, string unit = "$")
{
Chart c;
@@ -226,6 +240,7 @@ namespace QuantConnect.Algorithm
/// <param name="chart">The chart's name</param>
/// <param name="indicators">The indicatorsto plot</param>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot<T>(string chart, params IndicatorBase<T>[] indicators)
where T : IBaseData
{
@@ -238,6 +253,8 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Automatically plots each indicator when a new value is available
/// </summary>
[DocumentationAttribute(Charting)]
[DocumentationAttribute(Indicators)]
public void PlotIndicator<T>(string chart, params IndicatorBase<T>[] indicators)
where T : IBaseData
{
@@ -257,6 +274,8 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Automatically plots each indicator when a new value is available, optionally waiting for indicator.IsReady to return true
/// </summary>
[DocumentationAttribute(Charting)]
[DocumentationAttribute(Indicators)]
public void PlotIndicator<T>(string chart, bool waitForReady, params IndicatorBase<T>[] indicators)
where T : IBaseData
{
@@ -282,6 +301,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">Name of your runtime statistic</param>
/// <param name="value">String value of your runtime statistic</param>
/// <seealso cref="LiveMode"/>
[DocumentationAttribute(Charting)]
public void SetRuntimeStatistic(string name, string value)
{
RuntimeStatistics.AddOrUpdate(name, value);
@@ -292,6 +312,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="name">Name of your runtime statistic</param>
/// <param name="value">Decimal value of your runtime statistic</param>
[DocumentationAttribute(Charting)]
public void SetRuntimeStatistic(string name, decimal value)
{
SetRuntimeStatistic(name, value.ToString(CultureInfo.InvariantCulture));
@@ -302,6 +323,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="name">Name of your runtime statistic</param>
/// <param name="value">Int value of your runtime statistic</param>
[DocumentationAttribute(Charting)]
public void SetRuntimeStatistic(string name, int value)
{
SetRuntimeStatistic(name, value.ToStringInvariant());
@@ -312,17 +334,19 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="name">Name of your runtime statistic</param>
/// <param name="value">Double value of your runtime statistic</param>
[DocumentationAttribute(Charting)]
public void SetRuntimeStatistic(string name, double value)
{
SetRuntimeStatistic(name, value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Get the chart updates by fetch the recent points added and return for dynamic plotting.
/// Get the chart updates by fetch the recent points added and return for dynamic Charting.
/// </summary>
/// <param name="clearChartData"></param>
/// <returns>List of chart updates since the last request</returns>
/// <remarks>GetChartUpdates returns the latest updates since previous request.</remarks>
[DocumentationAttribute(Charting)]
public List<Chart> GetChartUpdates(bool clearChartData = false)
{
var updates = _charts.Select(x => x.Value).Select(chart => chart.GetUpdates()).ToList();

View File

@@ -1,4 +1,4 @@
/*
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
@@ -59,6 +59,7 @@ namespace QuantConnect.Algorithm
/// <param name="ticker">Key/Ticker for data</param>
/// <param name="resolution">Resolution of the data</param>
/// <returns>The new <see cref="Security"/></returns>
[DocumentationAttribute(AddingData)]
public Security AddData(PyObject type, string ticker, Resolution? resolution = null)
{
return AddData(type, ticker, resolution, null, false, 1m);
@@ -82,6 +83,7 @@ namespace QuantConnect.Algorithm
/// Adding the three unused parameters makes it choose the correct method when using a string or Symbol. This is
/// due to pythonnet's method precedence, as viewable here: https://github.com/QuantConnect/pythonnet/blob/9e29755c54e6008cb016e3dd9d75fbd8cd19fcf7/src/runtime/methodbinder.cs#L215
/// </remarks>
[DocumentationAttribute(AddingData)]
public Security AddData(PyObject type, Symbol underlying, Resolution? resolution = null)
{
return AddData(type, underlying, resolution, null, false, 1m);
@@ -99,6 +101,7 @@ namespace QuantConnect.Algorithm
/// <param name="fillDataForward">When no data available on a tradebar, return the last data that was generated</param>
/// <param name="leverage">Custom leverage per security</param>
/// <returns>The new <see cref="Security"/></returns>
[DocumentationAttribute(AddingData)]
public Security AddData(PyObject type, string ticker, Resolution? resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m)
{
return AddData(type.CreateType(), ticker, resolution, timeZone, fillDataForward, leverage);
@@ -124,6 +127,7 @@ namespace QuantConnect.Algorithm
/// Adding the three unused parameters makes it choose the correct method when using a string or Symbol. This is
/// due to pythonnet's method precedence, as viewable here: https://github.com/QuantConnect/pythonnet/blob/9e29755c54e6008cb016e3dd9d75fbd8cd19fcf7/src/runtime/methodbinder.cs#L215
/// </remarks>
[DocumentationAttribute(AddingData)]
public Security AddData(PyObject type, Symbol underlying, Resolution? resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m)
{
return AddData(type.CreateType(), underlying, resolution, timeZone, fillDataForward, leverage);
@@ -141,6 +145,7 @@ namespace QuantConnect.Algorithm
/// <param name="fillDataForward">When no data available on a tradebar, return the last data that was generated</param>
/// <param name="leverage">Custom leverage per security</param>
/// <returns>The new <see cref="Security"/></returns>
[DocumentationAttribute(AddingData)]
public Security AddData(Type dataType, string ticker, Resolution? resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m)
{
// NOTE: Invoking methods on BaseData w/out setting the symbol may provide unexpected behavior
@@ -185,6 +190,7 @@ namespace QuantConnect.Algorithm
/// Adding the three unused parameters makes it choose the correct method when using a string or Symbol. This is
/// due to pythonnet's method precedence, as viewable here: https://github.com/QuantConnect/pythonnet/blob/9e29755c54e6008cb016e3dd9d75fbd8cd19fcf7/src/runtime/methodbinder.cs#L215
/// </remarks>
[DocumentationAttribute(AddingData)]
public Security AddData(Type dataType, Symbol underlying, Resolution? resolution = null, DateTimeZone timeZone = null, bool fillDataForward = false, decimal leverage = 1.0m)
{
var symbol = QuantConnect.Symbol.CreateBase(dataType, underlying, Market.USA);
@@ -204,6 +210,7 @@ namespace QuantConnect.Algorithm
/// <param name="fillDataForward">When no data available on a tradebar, return the last data that was generated</param>
/// <param name="leverage">Custom leverage per security</param>
/// <returns>The new <see cref="Security"/></returns>
[DocumentationAttribute(AddingData)]
public Security AddData(PyObject type, string ticker, SymbolProperties properties, SecurityExchangeHours exchangeHours, Resolution? resolution = null, bool fillDataForward = false, decimal leverage = 1.0m)
{
// Get the right key for storage of base type symbols
@@ -224,6 +231,7 @@ namespace QuantConnect.Algorithm
/// <param name="optionFilter">Filter to apply to option contracts loaded as part of the universe</param>
/// <returns>The new Option security, containing a Future as its underlying.</returns>
/// <exception cref="ArgumentException">The symbol provided is not canonical.</exception>
[DocumentationAttribute(AddingData)]
public void AddFutureOption(Symbol futureSymbol, PyObject optionFilter)
{
Func<OptionFilterUniverse, OptionFilterUniverse> optionFilterUniverse;
@@ -276,11 +284,13 @@ namespace QuantConnect.Algorithm
/// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>
/// </summary>
/// <param name="pyObject">Defines an initial coarse selection</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(PyObject pyObject)
{
Func<IEnumerable<CoarseFundamental>, object> coarseFunc;
Universe universe;
// TODO: to be removed when https://github.com/QuantConnect/pythonnet/issues/62 is solved
if (pyObject.TryConvert(out universe))
{
return AddUniverse(universe);
@@ -308,6 +318,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="pyObject">Defines an initial coarse selection or a universe</param>
/// <param name="pyfine">Defines a more detailed selection with access to more data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(PyObject pyObject, PyObject pyfine)
{
Func<IEnumerable<CoarseFundamental>, object> coarseFunc;
@@ -339,6 +350,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">A unique name for this universe</param>
/// <param name="resolution">The resolution this universe should be triggered on</param>
/// <param name="pySelector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(string name, Resolution resolution, PyObject pySelector)
{
var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
@@ -351,6 +363,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="name">A unique name for this universe</param>
/// <param name="pySelector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(string name, PyObject pySelector)
{
var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
@@ -366,6 +379,7 @@ namespace QuantConnect.Algorithm
/// <param name="market">The market of the universe</param>
/// <param name="universeSettings">The subscription settings used for securities added from this universe</param>
/// <param name="pySelector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, PyObject pySelector)
{
var selector = pySelector.ConvertToDelegate<Func<DateTime, object>>();
@@ -380,6 +394,7 @@ namespace QuantConnect.Algorithm
/// <param name="T">The data type</param>
/// <param name="name">A unique name for this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(PyObject T, string name, PyObject selector)
{
return AddUniverse(T.CreateType(), SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
@@ -394,6 +409,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">A unique name for this universe</param>
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(PyObject T, string name, Resolution resolution, PyObject selector)
{
return AddUniverse(T.CreateType(), SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
@@ -409,6 +425,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="universeSettings">The settings used for securities added by this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(PyObject T, string name, Resolution resolution, UniverseSettings universeSettings, PyObject selector)
{
return AddUniverse(T.CreateType(), SecurityType.Equity, name, resolution, Market.USA, universeSettings, selector);
@@ -423,6 +440,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">A unique name for this universe</param>
/// <param name="universeSettings">The settings used for securities added by this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(PyObject T, string name, UniverseSettings universeSettings, PyObject selector)
{
return AddUniverse(T.CreateType(), SecurityType.Equity, name, Resolution.Daily, Market.USA, universeSettings, selector);
@@ -438,6 +456,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="market">The market for selected symbols</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(PyObject T, SecurityType securityType, string name, Resolution resolution, string market, PyObject selector)
{
return AddUniverse(T.CreateType(), securityType, name, resolution, market, UniverseSettings, selector);
@@ -453,6 +472,7 @@ namespace QuantConnect.Algorithm
/// <param name="market">The market for selected symbols</param>
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(PyObject T, SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, PyObject selector)
{
return AddUniverse(T.CreateType(), securityType, name, resolution, market, universeSettings, selector);
@@ -468,6 +488,7 @@ namespace QuantConnect.Algorithm
/// <param name="market">The market for selected symbols</param>
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
/// <param name="pySelector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(Type dataType, SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, PyObject pySelector)
{
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
@@ -494,6 +515,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="universe">The universe we want to chain an option universe selection model too</param>
/// <param name="optionFilter">The option filter universe to use</param>
[DocumentationAttribute(Universes)]
public void AddUniverseOptions(PyObject universe, PyObject optionFilter)
{
Func<OptionFilterUniverse, OptionFilterUniverse> convertedOptionChain;
@@ -520,6 +542,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
[DocumentationAttribute(Indicators)]
[DocumentationAttribute(ConsolidatingData)]
public void RegisterIndicator(Symbol symbol, PyObject indicator, Resolution? resolution = null, PyObject selector = null)
{
RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector);
@@ -533,6 +557,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="resolution">The resolution at which to send data to the indicator, null to use the same resolution as the subscription</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
[DocumentationAttribute(Indicators)]
[DocumentationAttribute(ConsolidatingData)]
public void RegisterIndicator(Symbol symbol, PyObject indicator, TimeSpan? resolution = null, PyObject selector = null)
{
RegisterIndicator(symbol, indicator, ResolveConsolidator(symbol, resolution), selector);
@@ -546,6 +572,8 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="pyObject">The python object that it is trying to register with, could be consolidator or a timespan</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
[DocumentationAttribute(Indicators)]
[DocumentationAttribute(ConsolidatingData)]
public void RegisterIndicator(Symbol symbol, PyObject indicator, PyObject pyObject, PyObject selector = null)
{
try
@@ -593,8 +621,11 @@ namespace QuantConnect.Algorithm
/// <param name="indicator">The indicator to receive data from the consolidator</param>
/// <param name="consolidator">The consolidator to receive raw subscription data</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
[DocumentationAttribute(Indicators)]
[DocumentationAttribute(ConsolidatingData)]
public void RegisterIndicator(Symbol symbol, PyObject indicator, IDataConsolidator consolidator, PyObject selector = null)
{
// TODO: to be removed when https://github.com/QuantConnect/pythonnet/issues/62 is solved
IndicatorBase<IndicatorDataPoint> indicatorDataPoint;
IndicatorBase<IBaseDataBar> indicatorDataBar;
IndicatorBase<TradeBar> indicatorTradeBar;
@@ -618,12 +649,48 @@ namespace QuantConnect.Algorithm
RegisterIndicator(symbol, WrapPythonIndicator(indicator), consolidator, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
}
/// <summary>
/// Warms up a given indicator with historical data
/// </summary>
/// <param name="symbol">The symbol whose indicator we want</param>
/// <param name="indicator">The indicator we want to warm up</param>
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData send into the indicator, if null defaults to a cast (x => (T)x)</param>
[DocumentationAttribute(Indicators)]
[DocumentationAttribute(HistoricalData)]
public void WarmUpIndicator(Symbol symbol, PyObject indicator, Resolution? resolution = null, PyObject selector = null)
{
// TODO: to be removed when https://github.com/QuantConnect/pythonnet/issues/62 is solved
IndicatorBase<IndicatorDataPoint> indicatorDataPoint;
IndicatorBase<IBaseDataBar> indicatorDataBar;
IndicatorBase<TradeBar> indicatorTradeBar;
if (indicator.TryConvert(out indicatorDataPoint))
{
WarmUpIndicator(symbol, indicatorDataPoint, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
return;
}
else if (indicator.TryConvert(out indicatorDataBar))
{
WarmUpIndicator(symbol, indicatorDataBar, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
return;
}
else if (indicator.TryConvert(out indicatorTradeBar))
{
WarmUpIndicator(symbol, indicatorTradeBar, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
return;
}
WarmUpIndicator(symbol, WrapPythonIndicator(indicator), resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
}
/// <summary>
/// Plot a chart using string series name, with value.
/// </summary>
/// <param name="series">Name of the plot series</param>
/// <param name="pyObject">PyObject with the value to plot</param>
/// <seealso cref="Plot(string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string series, PyObject pyObject)
{
using (Py.GIL())
@@ -650,6 +717,7 @@ namespace QuantConnect.Algorithm
/// <param name="third">The third indicator to plot</param>
/// <param name="fourth">The fourth indicator to plot</param>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string chart, Indicator first, Indicator second = null, Indicator third = null, Indicator fourth = null)
{
Plot(chart, new[] { first, second, third, fourth }.Where(x => x != null).ToArray());
@@ -664,6 +732,7 @@ namespace QuantConnect.Algorithm
/// <param name="third">The third indicator to plot</param>
/// <param name="fourth">The fourth indicator to plot</param>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string chart, BarIndicator first, BarIndicator second = null, BarIndicator third = null, BarIndicator fourth = null)
{
Plot(chart, new[] { first, second, third, fourth }.Where(x => x != null).ToArray());
@@ -678,6 +747,7 @@ namespace QuantConnect.Algorithm
/// <param name="third">The third indicator to plot</param>
/// <param name="fourth">The fourth indicator to plot</param>
/// <seealso cref="Plot(string,string,decimal)"/>
[DocumentationAttribute(Charting)]
public void Plot(string chart, TradeBarIndicator first, TradeBarIndicator second = null, TradeBarIndicator third = null, TradeBarIndicator fourth = null)
{
Plot(chart, new[] { first, second, third, fourth }.Where(x => x != null).ToArray());
@@ -686,6 +756,8 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Automatically plots each indicator when a new value is available
/// </summary>
[DocumentationAttribute(Charting)]
[DocumentationAttribute(Indicators)]
public void PlotIndicator(string chart, PyObject first, PyObject second = null, PyObject third = null, PyObject fourth = null)
{
var array = GetIndicatorArray(first, second, third, fourth);
@@ -695,6 +767,8 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Automatically plots each indicator when a new value is available
/// </summary>
[DocumentationAttribute(Charting)]
[DocumentationAttribute(Indicators)]
public void PlotIndicator(string chart, bool waitForReady, PyObject first, PyObject second = null, PyObject third = null, PyObject fourth = null)
{
var array = GetIndicatorArray(first, second, third, fourth);
@@ -710,6 +784,7 @@ namespace QuantConnect.Algorithm
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public FilteredIdentity FilteredIdentity(Symbol symbol, PyObject selector = null, PyObject filter = null, string fieldName = null)
{
var resolution = GetSubscription(symbol).Resolution;
@@ -726,6 +801,7 @@ namespace QuantConnect.Algorithm
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public FilteredIdentity FilteredIdentity(Symbol symbol, Resolution resolution, PyObject selector = null, PyObject filter = null, string fieldName = null)
{
var name = CreateIndicatorName(symbol, fieldName ?? "close", resolution);
@@ -746,6 +822,7 @@ namespace QuantConnect.Algorithm
/// <param name="filter">Filters the IBaseData send into the indicator, if null defaults to true (x => true) which means no filter</param>
/// <param name="fieldName">The name of the field being selected</param>
/// <returns>A new FilteredIdentity indicator for the specified symbol and selector</returns>
[DocumentationAttribute(Indicators)]
public FilteredIdentity FilteredIdentity(Symbol symbol, TimeSpan resolution, PyObject selector = null, PyObject filter = null, string fieldName = null)
{
var name = $"{symbol}({fieldName ?? "close"}_{resolution.ToStringInvariant(null)})";
@@ -764,6 +841,7 @@ namespace QuantConnect.Algorithm
/// <param name="periods">The number of bars to request</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>A python dictionary with pandas DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject tickers, int periods, Resolution? resolution = null)
{
var symbols = tickers.ConvertToSymbolEnumerable();
@@ -778,6 +856,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to retrieve recent historical data</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>A python dictionary with pandas DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject tickers, TimeSpan span, Resolution? resolution = null)
{
var symbols = tickers.ConvertToSymbolEnumerable();
@@ -792,6 +871,7 @@ namespace QuantConnect.Algorithm
/// <param name="end">The end time in the algorithm's time zone</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>A python dictionary with pandas DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject tickers, DateTime start, DateTime end, Resolution? resolution = null)
{
var symbols = tickers.ConvertToSymbolEnumerable();
@@ -807,6 +887,7 @@ namespace QuantConnect.Algorithm
/// <param name="end">The end time in the algorithm's time zone</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>pandas.DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject type, PyObject tickers, DateTime start, DateTime end, Resolution? resolution = null)
{
var symbols = tickers.ConvertToSymbolEnumerable();
@@ -835,6 +916,7 @@ namespace QuantConnect.Algorithm
/// <param name="periods">The number of bars to request</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>pandas.DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject type, PyObject tickers, int periods, Resolution? resolution = null)
{
var symbols = tickers.ConvertToSymbolEnumerable();
@@ -865,6 +947,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to retrieve recent historical data</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>pandas.DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject type, PyObject tickers, TimeSpan span, Resolution? resolution = null)
{
return History(type, tickers, Time - span, Time, resolution);
@@ -879,6 +962,7 @@ namespace QuantConnect.Algorithm
/// <param name="end">The end time in the algorithm's time zone</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>pandas.DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject type, Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null)
{
var security = Securities[symbol];
@@ -906,6 +990,7 @@ namespace QuantConnect.Algorithm
/// <param name="periods">The number of bars to request</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>pandas.DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject type, Symbol symbol, int periods, Resolution? resolution = null)
{
if (resolution == Resolution.Tick) throw new ArgumentException("History functions that accept a 'periods' parameter can not be used with Resolution.Tick");
@@ -925,6 +1010,7 @@ namespace QuantConnect.Algorithm
/// <param name="span">The span over which to retrieve recent historical data</param>
/// <param name="resolution">The resolution to request</param>
/// <returns>pandas.DataFrame containing the requested historical data</returns>
[DocumentationAttribute(HistoricalData)]
public PyObject History(PyObject type, Symbol symbol, TimeSpan span, Resolution? resolution = null)
{
return History(type, symbol, Time - span, Time, resolution);
@@ -935,6 +1021,9 @@ namespace QuantConnect.Algorithm
/// the benchmark at each date/time requested
/// </summary>
/// <param name="benchmark">The benchmark producing function</param>
[DocumentationAttribute(TradingAndOrders)]
[DocumentationAttribute(SecuritiesAndPortfolio)]
[DocumentationAttribute(Indicators)]
public void SetBenchmark(PyObject benchmark)
{
using (Py.GIL())
@@ -954,6 +1043,7 @@ namespace QuantConnect.Algorithm
/// This can be used to set a custom brokerage model.
/// </summary>
/// <param name="model">The brokerage model to use</param>
[DocumentationAttribute(Modeling)]
public void SetBrokerageModel(PyObject model)
{
IBrokerageModel brokerageModel;
@@ -969,6 +1059,8 @@ namespace QuantConnect.Algorithm
/// Sets the security initializer function, used to initialize/configure securities after creation
/// </summary>
/// <param name="securityInitializer">The security initializer function or class</param>
[DocumentationAttribute(AddingData)]
[DocumentationAttribute(Modeling)]
public void SetSecurityInitializer(PyObject securityInitializer)
{
var securityInitializer1 = PythonUtil.ToAction<Security>(securityInitializer);
@@ -988,6 +1080,8 @@ namespace QuantConnect.Algorithm
/// <param name="address">A string containing the URI to download</param>
/// <param name="headers">Defines header values to add to the request</param>
/// <returns>The requested resource as a <see cref="string"/></returns>
[DocumentationAttribute(AddingData)]
[DocumentationAttribute(MachineLearning)]
public string Download(string address, PyObject headers) => Download(address, headers, null, null);
/// <summary>
@@ -999,6 +1093,8 @@ namespace QuantConnect.Algorithm
/// <param name="userName">The user name associated with the credentials</param>
/// <param name="password">The password for the user name associated with the credentials</param>
/// <returns>The requested resource as a <see cref="string"/></returns>
[DocumentationAttribute(AddingData)]
[DocumentationAttribute(MachineLearning)]
public string Download(string address, PyObject headers, string userName, string password)
{
var dict = new Dictionary<string, string>();
@@ -1033,6 +1129,7 @@ namespace QuantConnect.Algorithm
/// <param name="message">Message to send to debug console</param>
/// <seealso cref="Log(PyObject)"/>
/// <seealso cref="Error(PyObject)"/>
[DocumentationAttribute(Logging)]
public void Debug(PyObject message)
{
Debug(message.ToSafeString());
@@ -1044,6 +1141,7 @@ namespace QuantConnect.Algorithm
/// <param name="message">Message to display in errors grid</param>
/// <seealso cref="Debug(PyObject)"/>
/// <seealso cref="Log(PyObject)"/>
[DocumentationAttribute(Logging)]
public void Error(PyObject message)
{
Error(message.ToSafeString());
@@ -1055,6 +1153,7 @@ namespace QuantConnect.Algorithm
/// <param name="message">String message to log.</param>
/// <seealso cref="Debug(PyObject)"/>
/// <seealso cref="Error(PyObject)"/>
[DocumentationAttribute(Logging)]
public void Log(PyObject message)
{
Log(message.ToSafeString());
@@ -1064,6 +1163,7 @@ namespace QuantConnect.Algorithm
/// Terminate the algorithm after processing the current event handler.
/// </summary>
/// <param name="message">Exit message to display on quitting</param>
[DocumentationAttribute(Logging)]
public void Quit(PyObject message)
{
Quit(message.ToSafeString());
@@ -1076,6 +1176,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">The consolidation period</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, Resolution period, PyObject handler)
{
return Consolidate(symbol, period.ToTimeSpan(), null, handler);
@@ -1089,6 +1190,7 @@ namespace QuantConnect.Algorithm
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, Resolution period, TickType? tickType, PyObject handler)
{
return Consolidate(symbol, period.ToTimeSpan(), tickType, handler);
@@ -1101,6 +1203,7 @@ namespace QuantConnect.Algorithm
/// <param name="period">The consolidation period</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, PyObject handler)
{
return Consolidate(symbol, period, null, handler);
@@ -1114,6 +1217,7 @@ namespace QuantConnect.Algorithm
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, TimeSpan period, TickType? tickType, PyObject handler)
{
// resolve consolidator input subscription
@@ -1139,6 +1243,7 @@ namespace QuantConnect.Algorithm
/// <param name="calendar">The consolidation calendar</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, PyObject handler)
{
return Consolidate(symbol, calendar, null, handler);
@@ -1148,6 +1253,8 @@ namespace QuantConnect.Algorithm
/// Schedules the provided training code to execute immediately
/// </summary>
/// <param name="trainingCode">The training code to be invoked</param>
[DocumentationAttribute(MachineLearning)]
[DocumentationAttribute(ScheduledEvents)]
public ScheduledEvent Train(PyObject trainingCode)
{
return Schedule.TrainingNow(trainingCode);
@@ -1159,6 +1266,8 @@ namespace QuantConnect.Algorithm
/// <param name="dateRule">Specifies what dates the event should run</param>
/// <param name="timeRule">Specifies the times on those dates the event should run</param>
/// <param name="trainingCode">The training code to be invoked</param>
[DocumentationAttribute(MachineLearning)]
[DocumentationAttribute(ScheduledEvents)]
public ScheduledEvent Train(IDateRule dateRule, ITimeRule timeRule, PyObject trainingCode)
{
return Schedule.Training(dateRule, timeRule, trainingCode);
@@ -1172,6 +1281,7 @@ namespace QuantConnect.Algorithm
/// <param name="tickType">The tick type of subscription used as data source for consolidator. Specify null to use first subscription found.</param>
/// <param name="handler">Data handler receives new consolidated data when generated</param>
/// <returns>A new consolidator matching the requested parameters with the handler already registered</returns>
[DocumentationAttribute(ConsolidatingData)]
private IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo> calendar, TickType? tickType, PyObject handler)
{
// resolve consolidator input subscription

View File

@@ -1,4 +1,4 @@
/*
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
@@ -33,6 +33,7 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Transaction Manager - Process transaction fills and order management.
/// </summary>
[DocumentationAttribute(TradingAndOrders)]
public SecurityTransactionManager Transactions { get; set; }
/// <summary>
@@ -42,6 +43,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">int Quantity of the asset to trade</param>
/// <seealso cref="Buy(Symbol, double)"/>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Buy(Symbol symbol, int quantity)
{
return Order(symbol, (decimal)Math.Abs(quantity));
@@ -54,6 +56,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">double Quantity of the asset to trade</param>
/// <seealso cref="Buy(Symbol, decimal)"/>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Buy(Symbol symbol, double quantity)
{
return Order(symbol, Math.Abs(quantity).SafeDecimalCast());
@@ -66,6 +69,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">decimal Quantity of the asset to trade</param>
/// <seealso cref="Order(Symbol, int)"/>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Buy(Symbol symbol, decimal quantity)
{
return Order(symbol, Math.Abs(quantity));
@@ -78,6 +82,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">float Quantity of the asset to trade</param>
/// <seealso cref="Buy(Symbol, decimal)"/>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Buy(Symbol symbol, float quantity)
{
return Order(symbol, (decimal)Math.Abs(quantity));
@@ -91,6 +96,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">int Quantity of the asset to trade</param>
/// <seealso cref="Sell(Symbol, decimal)"/>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Sell(Symbol symbol, int quantity)
{
return Order(symbol, (decimal)Math.Abs(quantity) * -1);
@@ -102,6 +108,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbol">String symbol to sell</param>
/// <param name="quantity">Quantity to order</param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Sell(Symbol symbol, double quantity)
{
return Order(symbol, Math.Abs(quantity).SafeDecimalCast() * -1m);
@@ -113,6 +120,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbol">String symbol</param>
/// <param name="quantity">Quantity to sell</param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Sell(Symbol symbol, float quantity)
{
return Order(symbol, (decimal)Math.Abs(quantity) * -1m);
@@ -124,6 +132,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbol">String symbol to sell</param>
/// <param name="quantity">Quantity to sell</param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Sell(Symbol symbol, decimal quantity)
{
return Order(symbol, Math.Abs(quantity) * -1);
@@ -136,6 +145,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">Quantity to order</param>
/// <seealso cref="Order(Symbol, decimal)"/>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Order(Symbol symbol, double quantity)
{
return Order(symbol, quantity.SafeDecimalCast());
@@ -147,6 +157,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbol">Symbol to order</param>
/// <param name="quantity">Quantity to order</param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Order(Symbol symbol, int quantity)
{
return MarketOrder(symbol, (decimal)quantity);
@@ -158,6 +169,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbol">Symbol to order</param>
/// <param name="quantity">Quantity to order</param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Order(Symbol symbol, decimal quantity)
{
return MarketOrder(symbol, quantity);
@@ -173,6 +185,7 @@ namespace QuantConnect.Algorithm
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
/// <seealso cref="MarketOrder(Symbol, decimal, bool, string)"/>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Order(Symbol symbol, decimal quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
{
return MarketOrder(symbol, quantity, asynchronous, tag, orderProperties);
@@ -187,6 +200,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOrder(Symbol symbol, int quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
{
return MarketOrder(symbol, (decimal)quantity, asynchronous, tag, orderProperties);
@@ -201,6 +215,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOrder(Symbol symbol, double quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
{
return MarketOrder(symbol, quantity.SafeDecimalCast(), asynchronous, tag, orderProperties);
@@ -215,6 +230,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOrder(Symbol symbol, decimal quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
{
var security = Securities[symbol];
@@ -230,6 +246,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOrder(Security security, decimal quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
{
// check the exchange is open before sending a market order, if it's not open
@@ -284,6 +301,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOnOpenOrder(Symbol symbol, double quantity, string tag = "", IOrderProperties orderProperties = null)
{
return MarketOnOpenOrder(symbol, quantity.SafeDecimalCast(), tag, orderProperties);
@@ -297,6 +315,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOnOpenOrder(Symbol symbol, int quantity, string tag = "", IOrderProperties orderProperties = null)
{
return MarketOnOpenOrder(symbol, (decimal)quantity, tag, orderProperties);
@@ -310,6 +329,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOnOpenOrder(Symbol symbol, decimal quantity, string tag = "", IOrderProperties orderProperties = null)
{
var security = Securities[symbol];
@@ -331,6 +351,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOnCloseOrder(Symbol symbol, int quantity, string tag = "", IOrderProperties orderProperties = null)
{
return MarketOnCloseOrder(symbol, (decimal)quantity, tag, orderProperties);
@@ -344,6 +365,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOnCloseOrder(Symbol symbol, double quantity, string tag = "", IOrderProperties orderProperties = null)
{
return MarketOnCloseOrder(symbol, quantity.SafeDecimalCast(), tag, orderProperties);
@@ -357,6 +379,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Place a custom order property or tag (e.g. indicator data).</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket MarketOnCloseOrder(Symbol symbol, decimal quantity, string tag = "", IOrderProperties orderProperties = null)
{
var security = Securities[symbol];
@@ -379,6 +402,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket LimitOrder(Symbol symbol, int quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
return LimitOrder(symbol, (decimal)quantity, limitPrice, tag, orderProperties);
@@ -393,6 +417,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket LimitOrder(Symbol symbol, double quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
return LimitOrder(symbol, quantity.SafeDecimalCast(), limitPrice, tag, orderProperties);
@@ -407,6 +432,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket LimitOrder(Symbol symbol, decimal quantity, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
var security = Securities[symbol];
@@ -429,6 +455,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Optional string data tag for the order</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket StopMarketOrder(Symbol symbol, int quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
{
return StopMarketOrder(symbol, (decimal)quantity, stopPrice, tag, orderProperties);
@@ -443,6 +470,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Optional string data tag for the order</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket StopMarketOrder(Symbol symbol, double quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
{
return StopMarketOrder(symbol, quantity.SafeDecimalCast(), stopPrice, tag, orderProperties);
@@ -457,6 +485,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Optional string data tag for the order</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket StopMarketOrder(Symbol symbol, decimal quantity, decimal stopPrice, string tag = "", IOrderProperties orderProperties = null)
{
var security = Securities[symbol];
@@ -480,6 +509,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket StopLimitOrder(Symbol symbol, int quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
return StopLimitOrder(symbol, (decimal)quantity, stopPrice, limitPrice, tag, orderProperties);
@@ -495,6 +525,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket StopLimitOrder(Symbol symbol, double quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
return StopLimitOrder(symbol, quantity.SafeDecimalCast(), stopPrice, limitPrice, tag, orderProperties);
@@ -510,6 +541,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket StopLimitOrder(Symbol symbol, decimal quantity, decimal stopPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
var security = Securities[symbol];
@@ -534,6 +566,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket LimitIfTouchedOrder(Symbol symbol, int quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
return LimitIfTouchedOrder(symbol, (decimal)quantity, triggerPrice, limitPrice, tag, orderProperties);
@@ -549,6 +582,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket LimitIfTouchedOrder(Symbol symbol, double quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
return LimitIfTouchedOrder(symbol, quantity.SafeDecimalCast(), triggerPrice, limitPrice, tag, orderProperties);
@@ -564,6 +598,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket LimitIfTouchedOrder(Symbol symbol, decimal quantity, decimal triggerPrice, decimal limitPrice, string tag = "", IOrderProperties orderProperties = null)
{
var security = Securities[symbol];
@@ -587,6 +622,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">String tag for the order (optional)</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket ExerciseOption(Symbol optionSymbol, int quantity, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
{
var option = (Option) Securities[optionSymbol];
@@ -629,6 +665,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">Quantity of the strategy to trade</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>Sequence of order tickets</returns>
[DocumentationAttribute(TradingAndOrders)]
public IEnumerable<OrderTicket> Buy(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
{
return Order(strategy, Math.Abs(quantity), orderProperties);
@@ -641,6 +678,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">Quantity of the strategy to trade</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>Sequence of order tickets</returns>
[DocumentationAttribute(TradingAndOrders)]
public IEnumerable<OrderTicket> Sell(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
{
return Order(strategy, Math.Abs(quantity) * -1, orderProperties);
@@ -653,6 +691,7 @@ namespace QuantConnect.Algorithm
/// <param name="quantity">Quantity of the strategy to trade</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>Sequence of order tickets</returns>
[DocumentationAttribute(TradingAndOrders)]
public IEnumerable<OrderTicket> Order(OptionStrategy strategy, int quantity, IOrderProperties orderProperties = null)
{
return GenerateOrders(strategy, quantity, orderProperties);
@@ -925,6 +964,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Custom tag to know who is calling this.</param>
/// <returns>Array of order ids for liquidated symbols</returns>
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
[DocumentationAttribute(TradingAndOrders)]
public List<int> Liquidate(Symbol symbolToLiquidate = null, string tag = "Liquidated")
{
var orderIdList = new List<int>();
@@ -997,6 +1037,7 @@ namespace QuantConnect.Algorithm
/// Maximum number of orders for the algorithm
/// </summary>
/// <param name="max"></param>
[DocumentationAttribute(TradingAndOrders)]
public void SetMaximumOrders(int max)
{
if (!_locked)
@@ -1015,6 +1056,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Tag the order with a short string.</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
[DocumentationAttribute(TradingAndOrders)]
public void SetHoldings(List<PortfolioTarget> targets, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
{
foreach (var portfolioTarget in targets
@@ -1035,6 +1077,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Tag the order with a short string.</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
[DocumentationAttribute(TradingAndOrders)]
public void SetHoldings(Symbol symbol, double percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
{
SetHoldings(symbol, percentage.SafeDecimalCast(), liquidateExistingHoldings, tag, orderProperties);
@@ -1049,6 +1092,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Tag the order with a short string.</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
[DocumentationAttribute(TradingAndOrders)]
public void SetHoldings(Symbol symbol, float percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
{
SetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag, orderProperties);
@@ -1063,6 +1107,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Tag the order with a short string.</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
[DocumentationAttribute(TradingAndOrders)]
public void SetHoldings(Symbol symbol, int percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
{
SetHoldings(symbol, (decimal)percentage, liquidateExistingHoldings, tag, orderProperties);
@@ -1080,6 +1125,7 @@ namespace QuantConnect.Algorithm
/// <param name="tag">Tag the order with a short string.</param>
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <seealso cref="MarketOrder(QuantConnect.Symbol,decimal,bool,string)"/>
[DocumentationAttribute(TradingAndOrders)]
public void SetHoldings(Symbol symbol, decimal percentage, bool liquidateExistingHoldings = false, string tag = "", IOrderProperties orderProperties = null)
{
SetHoldingsImpl(symbol, CalculateOrderQuantity(symbol, percentage), liquidateExistingHoldings, tag, orderProperties);
@@ -1142,6 +1188,7 @@ namespace QuantConnect.Algorithm
/// <param name="symbol">Security object we're asking for</param>
/// <param name="target">Target percentage holdings</param>
/// <returns>Order quantity to achieve this percentage</returns>
[DocumentationAttribute(TradingAndOrders)]
public decimal CalculateOrderQuantity(Symbol symbol, double target)
{
return CalculateOrderQuantity(symbol, target.SafeDecimalCast());
@@ -1155,6 +1202,7 @@ namespace QuantConnect.Algorithm
/// if you have 2x leverage and request 100% holdings, it will utilize half of the
/// available margin</param>
/// <returns>Order quantity to achieve this percentage</returns>
[DocumentationAttribute(TradingAndOrders)]
public decimal CalculateOrderQuantity(Symbol symbol, decimal target)
{
var percent = PortfolioTarget.Percent(this, symbol, target, true);
@@ -1178,6 +1226,7 @@ namespace QuantConnect.Algorithm
/// <param name="orderProperties">The order properties to use. Defaults to <see cref="DefaultOrderProperties"/></param>
/// <returns>The order ticket instance.</returns>
[Obsolete("This Order method has been made obsolete, use Order(string, int, bool, string) method instead. Calls to the obsolete method will only generate market orders.")]
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Order(Symbol symbol, int quantity, OrderType type, bool asynchronous = false, string tag = "", IOrderProperties orderProperties = null)
{
return Order(symbol, quantity, asynchronous, tag, orderProperties);
@@ -1191,6 +1240,7 @@ namespace QuantConnect.Algorithm
/// <param name="type">The order type</param>
/// <returns>The order ticket instance.</returns>
[Obsolete("This Order method has been made obsolete, use the specialized Order helper methods instead. Calls to the obsolete method will only generate market orders.")]
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Order(Symbol symbol, decimal quantity, OrderType type)
{
return Order(symbol, quantity);
@@ -1204,6 +1254,7 @@ namespace QuantConnect.Algorithm
/// <param name="type">The order type</param>
/// <returns>The order ticket instance.</returns>
[Obsolete("This Order method has been made obsolete, use the specialized Order helper methods instead. Calls to the obsolete method will only generate market orders.")]
[DocumentationAttribute(TradingAndOrders)]
public OrderTicket Order(Symbol symbol, int quantity, OrderType type)
{
return Order(symbol, (decimal)quantity);
@@ -1214,6 +1265,8 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="symbol">The symbol</param>
/// <returns>True if the exchange is considered open at the current time, false otherwise</returns>
[DocumentationAttribute(TradingAndOrders)]
[DocumentationAttribute(SecuritiesAndPortfolio)]
public bool IsMarketOpen(Symbol symbol)
{
var exchangeHours = MarketHoursDatabase

View File

@@ -16,13 +16,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NodaTime;
using QuantConnect.Algorithm.Selection;
using QuantConnect.Data;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Securities;
using QuantConnect.Securities.Future;
using QuantConnect.Util;
namespace QuantConnect.Algorithm
@@ -43,6 +44,7 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Gets universe manager which holds universes keyed by their symbol
/// </summary>
[DocumentationAttribute(Universes)]
public UniverseManager UniverseManager
{
get;
@@ -52,6 +54,7 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Gets the universe settings to be used when adding securities via universe selection
/// </summary>
[DocumentationAttribute(Universes)]
public UniverseSettings UniverseSettings
{
get;
@@ -62,6 +65,7 @@ namespace QuantConnect.Algorithm
/// Invoked at the end of every time step. This allows the algorithm
/// to process events before advancing to the next time step.
/// </summary>
[DocumentationAttribute(HandlingData)]
public void OnEndOfTimeStep()
{
if (_pendingUniverseAdditions.Count + _pendingUserDefinedUniverseSecurityAdditions.Count == 0)
@@ -186,6 +190,7 @@ namespace QuantConnect.Algorithm
/// <summary>
/// Gets a helper that provides pre-defined universe definitions, such as top dollar volume
/// </summary>
[DocumentationAttribute(Universes)]
public UniverseDefinitions Universe
{
get;
@@ -196,6 +201,7 @@ namespace QuantConnect.Algorithm
/// Adds the universe to the algorithm
/// </summary>
/// <param name="universe">The universe to be added</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(Universe universe)
{
// The universe will be added at the end of time step, same as the AddData user defined universes.
@@ -213,6 +219,7 @@ namespace QuantConnect.Algorithm
/// <typeparam name="T">The data type</typeparam>
/// <param name="name">A unique name for this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(string name, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
{
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
@@ -226,6 +233,7 @@ namespace QuantConnect.Algorithm
/// <typeparam name="T">The data type</typeparam>
/// <param name="name">A unique name for this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(string name, Func<IEnumerable<T>, IEnumerable<string>> selector)
{
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
@@ -240,6 +248,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">A unique name for this universe</param>
/// <param name="universeSettings">The settings used for securities added by this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(string name, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
{
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, universeSettings, selector);
@@ -254,6 +263,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">A unique name for this universe</param>
/// <param name="universeSettings">The settings used for securities added by this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(string name, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<string>> selector)
{
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, universeSettings, selector);
@@ -268,6 +278,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">A unique name for this universe</param>
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(string name, Resolution resolution, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
{
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
@@ -282,6 +293,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">A unique name for this universe</param>
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(string name, Resolution resolution, Func<IEnumerable<T>, IEnumerable<string>> selector)
{
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
@@ -297,6 +309,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="universeSettings">The settings used for securities added by this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(string name, Resolution resolution, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
{
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, universeSettings, selector);
@@ -312,6 +325,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="universeSettings">The settings used for securities added by this universe</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(string name, Resolution resolution, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<string>> selector)
{
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, universeSettings, selector);
@@ -327,6 +341,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="market">The market for selected symbols</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
{
return AddUniverse(securityType, name, resolution, market, UniverseSettings, selector);
@@ -342,6 +357,7 @@ namespace QuantConnect.Algorithm
/// <param name="resolution">The epected resolution of the universe data</param>
/// <param name="market">The market for selected symbols</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, Func<IEnumerable<T>, IEnumerable<string>> selector)
{
return AddUniverse(securityType, name, resolution, market, UniverseSettings, selector);
@@ -357,6 +373,7 @@ namespace QuantConnect.Algorithm
/// <param name="market">The market for selected symbols</param>
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<Symbol>> selector)
{
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
@@ -377,6 +394,7 @@ namespace QuantConnect.Algorithm
/// <param name="market">The market for selected symbols</param>
/// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
/// <param name="selector">Function delegate that performs selection on the universe data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<IEnumerable<T>, IEnumerable<string>> selector)
{
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
@@ -394,6 +412,7 @@ namespace QuantConnect.Algorithm
/// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>
/// </summary>
/// <param name="selector">Defines an initial coarse selection</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> selector)
{
return AddUniverse(new CoarseFundamentalUniverse(UniverseSettings, selector));
@@ -405,6 +424,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="coarseSelector">Defines an initial coarse selection</param>
/// <param name="fineSelector">Defines a more detailed selection with access to more data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> coarseSelector, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
{
var coarse = new CoarseFundamentalUniverse(UniverseSettings, coarseSelector);
@@ -418,6 +438,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="universe">The universe to be filtered with fine fundamental selection</param>
/// <param name="fineSelector">Defines a more detailed selection with access to more data</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(Universe universe, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
{
return AddUniverse(new FineFundamentalFilteredUniverse(universe, fineSelector));
@@ -429,6 +450,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="name">A unique name for this universe</param>
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(string name, Func<DateTime, IEnumerable<string>> selector)
{
return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
@@ -441,6 +463,7 @@ namespace QuantConnect.Algorithm
/// <param name="name">A unique name for this universe</param>
/// <param name="resolution">The resolution this universe should be triggered on</param>
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(string name, Resolution resolution, Func<DateTime, IEnumerable<string>> selector)
{
return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
@@ -455,6 +478,7 @@ namespace QuantConnect.Algorithm
/// <param name="market">The market of the universe</param>
/// <param name="universeSettings">The subscription settings used for securities added from this universe</param>
/// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
[DocumentationAttribute(Universes)]
public Universe AddUniverse(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<DateTime, IEnumerable<string>> selector)
{
var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
@@ -472,6 +496,7 @@ namespace QuantConnect.Algorithm
/// <param name="underlyingSymbol">Underlying Symbol to add as an option. For Futures, the option chain constructed will be per-contract, as long as a canonical Symbol is provided.</param>
/// <param name="optionFilter">User-defined filter used to select the options we want out of the option chain provided.</param>
/// <exception cref="InvalidOperationException">The underlying Symbol's universe is not found.</exception>
[DocumentationAttribute(Universes)]
public void AddUniverseOptions(Symbol underlyingSymbol, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter)
{
// We need to load the universe associated with the provided Symbol and provide that universe to the option filter universe.
@@ -507,6 +532,7 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="universe">The universe we want to chain an option universe selection model too</param>
/// <param name="optionFilter">The option filter universe to use</param>
[DocumentationAttribute(Universes)]
public void AddUniverseOptions(Universe universe, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter)
{
AddUniverseSelection(new OptionChainedUniverseSelectionModel(universe, optionFilter));
@@ -557,14 +583,15 @@ namespace QuantConnect.Algorithm
{
// create a new universe, these subscription settings don't currently get used
// since universe selection proper is never invoked on this type of universe
var uconfig = new SubscriptionDataConfig(subscription, symbol: universeSymbol, isInternalFeed: true, fillForward: false);
var uconfig = new SubscriptionDataConfig(subscription, symbol: universeSymbol, isInternalFeed: true, fillForward: false,
exchangeTimeZone: DateTimeZone.Utc,
dataTimeZone: DateTimeZone.Utc);
if (security.Type == SecurityType.Base)
{
// set entry in market hours database for the universe subscription to match the custom data
var symbolString = MarketHoursDatabase.GetDatabaseSymbolKey(uconfig.Symbol);
MarketHoursDatabase.SetEntry(uconfig.Market, symbolString, uconfig.SecurityType, security.Exchange.Hours, uconfig.DataTimeZone);
}
// this is the universe symbol, has no real entry in the mhdb, will default to market and security type
// set entry in market hours database for the universe subscription to match the config
var symbolString = MarketHoursDatabase.GetDatabaseSymbolKey(uconfig.Symbol);
MarketHoursDatabase.SetEntry(uconfig.Market, symbolString, uconfig.SecurityType,
SecurityExchangeHours.AlwaysOpen(uconfig.ExchangeTimeZone), uconfig.DataTimeZone);
universe = new UserDefinedUniverse(uconfig,
new UniverseSettings(
@@ -593,7 +620,7 @@ namespace QuantConnect.Algorithm
else
{
// should never happen, someone would need to add a non-user defined universe with this symbol
throw new Exception("Expected universe with symbol '" + universeSymbol.Value + "' to be of type UserDefinedUniverse.");
throw new Exception($"Expected universe with symbol '{universeSymbol.Value}' to be of type {nameof(UserDefinedUniverse)} but was {universe.GetType().Name}.");
}
return security;

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