Compare commits

...

50 Commits
11079 ... 11346

Author SHA1 Message Date
Martin-Molinero
d94a1d09a4 Remove unrequired references 2021-04-12 16:05:01 -03:00
Martin-Molinero
2c843cae9e Fix rebase
- Fix ambiguous Index
- Remove StrategyCapacity.cs
- Update System.Threading.Tasks.Extensionsy
2021-04-12 15:09:34 -03:00
Stefano Raggi
039fdf7e4a Upgrade IBAutomater to v1.0.51
ignored, and an empty message aborts the commit.
2021-04-12 15:09:33 -03:00
Martin Molinero
2c63546c37 Remove FXCM 2021-04-12 15:09:33 -03:00
Martin Molinero
58682e1bbd Fix ambiguous errors. Add IBAutomator net5 2021-04-12 15:09:33 -03:00
Gerardo Salazar
d11a375fdb Update projects to use .NET 5.0, the successor to .NET Core 2021-04-12 15:09:33 -03:00
Martin-Molinero
6ab91a13e1 Add note for TimeZoneOffsetProvider StartTime (#5469) 2021-04-08 18:00:17 -03:00
Colton Sellers
beaa705646 Loader Support Full Algorithm Name (#5467)
* Apply fix

* Address possible mismatching subset of name
2021-04-08 17:59:08 -03:00
Colton Sellers
4c830c8235 Fix Breaking Unit Test (#5466)
* Adjust Timeout; Reduce time advance

* Move logging of EndTime above asserts
2021-04-07 21:09:56 -03:00
Colton Sellers
395c1123da Remove Obsolete QCAlgorithm.OnEndOfDay() (#5441)
* Remove and replace OnEndOfDay() ref

* Restore functionality of obsolete EOD, waiting for deprecation in August 2021

* Cleanup

* Adjustments to only post message when using obsolete EOD

* nit, extra space

* Address review

* Adjust test to reflect new behaviour

* Move GetPythonArgCount to an extension method

* Add unit test

* nit accidental import

* Refactor broken test

* Use Py.GIL() state for extension
2021-04-07 13:39:49 -03:00
Martin-Molinero
8e50645640 Update System.Threading.Tasks.Extensions (#5340) 2021-04-07 12:36:22 -03:00
Colton Sellers
68ca504d3a Apply fixes (#5464) 2021-04-07 11:46:31 -03:00
Jasper van Merle
12df1c9a31 Fix drawdown plotting failing on single equity point (#5461) 2021-04-06 16:30:23 -07:00
Aaron Janeiro Stone
4de25b6cd4 _lastLow and _lastHigh are given resets under DeM's Reset method (#5449) 2021-04-06 10:15:16 -03:00
dependabot[bot]
cdef9e709a Bump System.Net.Security from 4.3.0 to 4.3.1 in /Tests (#5453)
Bumps System.Net.Security from 4.3.0 to 4.3.1.

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-06 10:11:43 -03:00
Colton Sellers
3579fecc58 Live Consolidator Bug Fix (#5429)
* Set _lastEmit before emitting, otherwise _workingBar is always null

* Aggregate bars if the data endTime is past lastEmit

* Add unit test

* Address Review

* Clean up unit tests

* Refactor solution to set consistent _lastEmit behaviour

* Add another unit test

* Make fixture non-parallelizable

* Undo last change, and adjust breaking test directly
2021-04-05 17:05:53 -07:00
Stefano Raggi
3a390cfa9f Add IB brokerage message event filtering (#5452) 2021-04-05 17:17:14 -03:00
Stefano Raggi
58dae061e7 Add REST API exception logging in Tradier brokerage (#5454) 2021-04-05 17:14:52 -03:00
Martin-Molinero
3f2479393f Update clr-loader and remove workaround (#5451) 2021-04-05 14:25:19 -03:00
Jasper van Merle
4849588c3b Fix flipped operator in random data generator (#5446) 2021-04-05 11:07:51 -03:00
Martin-Molinero
3d84c76abb Add missing timedelta import in python custom data regression algorithms. Relate to https://github.com/QuantConnect/Lean/pull/5426/files (#5450) 2021-04-05 10:26:51 -03:00
Colton Sellers
1c3d849ad5 Fix Warnings V2 (#5436)
* Reconcile duplicated code

* Add License header

* CS0219 Fixes: Value assigned, but never used

* CA1507: Use nameof in place of string literals

* CS0108 : Hides Inherited Member; Use new keyword to overwrite formally

* CS0114: Hides inherited member; use override keyword

* CS0168: Variable is declared but never used

* Tests CS1062; using obsolete implicit Symbol -> String; fix via .ToString()

* CS0472: Non Nullable Obj getting Null Checked

* CS0067 Member not used; ignore all cases for future use

* CS00162 : Unreachable code; either removed or ignored for debugging and test cases

* CS0169 Remove non-used fields; ignore those that may be used in future

* CS0414; Field is assigned but never used.

* CS0618; Obsolete properties and members; Only fixes simple ones, rest will have to broken up

* CS0649; Field never assigned too

* CS0659 & CS0661 ; Overwrite operators and equals but not hashcode; I don't really override it but just call base

* Small comment fix

* Cleanup pragma statement
2021-04-02 11:20:01 -07:00
Jasper van Merle
271220083b Fix various map file generation issues (#5443) 2021-04-02 11:08:02 -07:00
Stefano Raggi
b29d0cbfaf Tradier Brokerage Updates (#5445)
* Tradier brokerage updates

- Add missing status check after REST API calls
- Initialize DataQueueHandler on-demand (on first subscribe call)

* Trigger build
2021-04-02 10:58:27 -07:00
Tomas Rampas
27a25cd663 The null value parameter removed from call of OandaBrokerage c'tor from OandaDownloader class (#5430)
Co-authored-by: rampasto <tomas.rampas@outlook.com>
2021-03-30 15:25:54 -07:00
Derek Melchin
5ed61db2bb Fix timestamps in custom data algorithms (#5426)
* Correct custom data timestamp and match performance across languages

* Add EndTime property

* Add comment for crypto SetHoldings
2021-03-30 14:48:59 -07:00
Colton Sellers
4a1485a291 QB Fundamental Test Fix (#5437)
* Use only 1 QB instance for fundamental tests, (want to see github workflow result)

* Fix small bug in test
2021-03-30 06:42:39 -07:00
Alexandre Catarino
d6072c88a5 Fixes LiveOptionChainProvider.FindOptionContracts (#5434)
`LiveOptionChainProvider.FindOptionContracts` handles the following data format:
`SPY  2021 03 26 190 000 C P  0 612 360000000`
where both existing `OptionRight.Call` and `OptionRight.Put` are declared in the same line.
2021-03-29 13:39:41 -07:00
Colton Sellers
20910ca2dc Broken Regressions Fixes (#5421)
* Remove regression references to non-existant Python versions

* Adjust regressions estimated capacity not adjusted by #5389

* Adjusts regression algorithms so that they pass (Index/Index Options)

  * Changes start/end date on BasicTemplateIndexAlgorithm
  * Changes option pricing model to BlackScholes in
    IndexOptionCallITMGreeksExpiryRegressionAlgorithm

    - The root cause of why there are no greeks at times for these
      options was identified. It is most likely due to the underlying's
      VolatilityModel not having had enough data to be "warmed up",
      which means it will return a standard deviation of zero to the
      option pricing model, rendering most metrics as NaN.

* Adds missing index/index options regression algorithms

  - Regression algorithms are now 1-1 between C# and Python for
    Indexes/Index options. All regression tests are now passing

* Fixes broken BasicTemplateIndex regression algorithm

  * Previously traded SPY, but because we have no SPY data in Lean
    master, I instead opted for index options, since data for those
    dates is already included

* Deal with weekend for breaking test case

* Adjust DefaultEndDate test to always pass

* Check todays date for open

Co-authored-by: Gerardo Salazar <gsalaz9800@gmail.com>
2021-03-29 13:35:03 -07:00
Jasper van Merle
c333ccdc4a Check whether storage directory exists before enumerating it (#5432) 2021-03-29 13:32:28 -07:00
Christian Korn
88c4a332bc Update PearsonCorrelationPairsTradingAlphaModel.cs (#5428)
Fix index of out bounds (#5427)
2021-03-26 10:55:19 -07:00
Colton Sellers
5d762d16b2 GetFundamental Default End Date (#5401)
* Change default end date for GetFundamental

* Add DefaultEndDate test
2021-03-23 14:18:07 -07:00
Colton Sellers
e2a0873b7c Fix Lean Warnings V1 (#5408)
Cleanup all non-breaking warnings
2021-03-22 11:08:48 -07:00
Gerardo Salazar
31ebaaeaa9 Fixes live BTC futures contract crashing in IB brokerage (#5409) 2021-03-22 08:48:58 -07:00
Jared
7625e232f4 Update readme.md 2021-03-19 14:53:46 -07:00
Alexandre Catarino
63f3af7afe Remove decimal.py (#5406)
* Removes decimal.py

* Removes References to Decimal in Examples
2021-03-19 14:17:05 -07:00
Colton Sellers
87b42f6fb5 Named Args Unit Tests (#5381)
Add regression and unit test
2021-03-16 16:53:02 -07:00
Gerardo Salazar
f9dc38efab Use trades per period instead of days for capacity calculation (#5389)
Use trades per period instead of days for capacity calculation
Updates regression algorithms
2021-03-16 16:30:49 -07:00
Colton Sellers
5587efaadd Update Python Runtime dll location (#5398) 2021-03-16 15:56:56 -07:00
Colton Sellers
a642d53bf9 Specify clr-loader version (#5400) 2021-03-16 14:50:47 -07:00
Colton Sellers
002151eab2 PythonNet 2.0.1 (#5390)
* Trigger rebuild

* Add Package QC PythonNet 2.0.1

* Update project files

* Push latest package

* Remove test package for shipping
2021-03-12 22:26:28 -03:00
Gerardo Salazar
4c085ff853 Adds Indexes and Index Options asset types (Backtesting/Live, IB only) (#5379)
* Add support for Index SecurityType  🚀 (#5364)

* Add Index SecurityType  🚀

* Extend SecurityIdentifier & Lean Data classes with Index support

* Add Index SecurityType  🚀

* Extend SecurityIdentifier & Lean Data classes with Index support

* Fixes

* Added index cross basic template demonstration

* WIP: Prototype index security type for LEAN as non tradable asset

* Re-adds Index entries to MHDB after rebase

* First steps to getting Index Options running

  * Looks at any instance where we pattern match for an option type
    and replaces it with a generic call to `.IsOption()` for easier
    extensibility in the future for additional option security types

  * Adds IndexOption security and misc. classes

  * Misc. changes, mainly related to any sort of special casing of
    equity options and made index options take the same path

* Enables index options data for backtesting

  * Adds new index options market hours to MHDB
  * Misc. bug fixes for index options
  * WIP: add live support for index options and indexes
  * Use OptionMarginModel for Index Options because they both use the
    same calculation for margin requirements

* Fixes contract not found errors on SPX index options and SPX index in IB

  * Turns out index options' last trading day is the day before expiry,
    which IB was expecting the last trading day.

* Add index option test cases (temp)

* LiveOptionChainProvider fix, use Symbol vs. ticker

  * Description updates to regression algorithms

* Fixes bug in live trading for indexes and index options

  * Adds overridable minimum price variation symbol property
  * Adds variable sized minimum price variation for index options
  * Adjusts symbol properties for index options
  * Misc. bug fixes

* Fixes option assignment simulation for European options

  * Updates index options regression algorithms (WIP)

* Fixes bug where index option exercise would trade index underlying

  * Fixes bugs where SecurityType.Index was getting flagged as tradable

* Regression algorithms updates and addresses review

  * Misc. style fixes and refactoring + a few bug fixes
  * Updates regression algorithms to run without runtime errors
  * Adds data for regression algos

* Sets DefaultOptionStyle on Canonical and support index options

* Update regression algos statistics

* Removes bad line in regression algorithm causing build to fail

* Minor tweaks

* Address review add comment about quoteBar parse scale

Co-authored-by: Balamurali Pandranki <balamurali@live.com>
Co-authored-by: Jared Broad <jaredbroad@gmail.com>
Co-authored-by: Martin-Molinero <martin@quantconnect.com>
2021-03-12 20:46:23 -03:00
Jasper van Merle
3aa76d4289 Add report creator to Docker image (#5386) 2021-03-11 14:42:26 -08:00
Martin-Molinero
5236fc202d Adding Symbol.Canonical (#5383)
- Adding Symbol.Canonical property which will be cached. Adding unit and
  regression tests
2021-03-11 18:38:20 -03:00
quantify-cflynn
1ca4389ed2 Adds SharpeRatio indicator (#5348)
* RollingSharpeRatio Submission

Creation of RollingSharpeRatio indicator, utilizing LEAN engine. Tests were created and successfully passed by the indicator, using spy_rsr.txt as outside data file which was created during a prior running of the program.

* Fixed Test Case Loading and Added Indicator Function

Added the RSR() function to auto load the indicator in Algorithm\QCAlgorithm.Indicators.cs. Also added a reference for the test file ("spy_rsr.txt") in Tests\QuantConnect.Tests.csproj.

* Fixed SharpeRatio Indicator

Updated the base formula, indicator structure/call, and the testing data for the SharpeRatio indicator.

* Minor Fixes

- Removed dividend yield from calculation
- Fixed typos in code/documentation

* Minor Style Fix and Error Confirmation

- Changed style to match style guide better.
- Checking for confirmation that QuantConnect.Tests.Engine.DataFeeds.LinveTradingDataFeedTests.DelistedEventEmmited_Equity() is server side, as it runs locally and should not have been affected by prior changes

* Simplification and fixing of SR calculation

- Updates calculation to proper SR formula
- Utilizes IndicatorExtensions for SR calculation rather than manual calculation
- Defines counter for 1 extra period offset on warmup (otherwise first datapoint is inaccurate if warmup period is SharpePeriod length)

* Minor Fixes

- Removal of SharpePeriod and RiskFreeRate variables
- Substitution of (SharpePeriod + 1) for WarmUpPeriod
- Outdated comment fixes

* Resubmission for Mono Confirmation Error

Error detected on Git for this version of the program. An error should not occur as only comments and minor variables were edited. Resubmitting to see if it is a false positive mono error.

* Notation Fixes

Fixed notation regarding spacing and outdated comments.

* Removal of Counter Logic

- Replaces counter for warmup with improved IsReady logic

* Fixed Syntax

- Removed unused imports
- Fixed variable readability
- Fixed comments
- Replaced Tabs with spacing

Co-authored-by: quantify-cflynn <quantify-cflynn>
2021-03-11 13:35:08 -08:00
Jared
b8397db0b7 Usability buffer on allocation (#5385) 2021-03-11 11:44:54 -08:00
Martin-Molinero
d4ea5f7b04 Simplify cash limit allocation (#5382) 2021-03-10 14:47:39 -08:00
Martin-Molinero
458272b2ea Fix mono running in research (#5380) 2021-03-10 17:34:59 -03:00
Colton Sellers
6c7353d09a Trigger rebuild (#5377) 2021-03-09 18:44:18 -03:00
Colton Sellers
834d4a4d58 QC PythonNet 2.0 (#5376)
* Update to new QC PythonNet

* Update readme

* Remove Python.Runtime config, replaced by env var

* Allow local packages testing in repo

* Address Review

* Add the LocalPackages readme

* Update Jupyter Image

* Update Research ReadMe
2021-03-09 18:25:31 -03:00
508 changed files with 7954 additions and 5638 deletions

2
.gitignore vendored
View File

@@ -196,6 +196,7 @@ publish/
# NuGet Packages
*.nupkg
!LocalPackages/*
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
@@ -204,6 +205,7 @@ publish/
#!**/packages/repositories.config
# ignore sln level nuget
.nuget/
!.nuget/NuGet.config
# Windows Azure Build Output
csx/

10
.nuget/NuGet.config Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="enabled" value="true" />
<add key="automatic" value="true" />
</packageRestore>
<packageSources>
<add key="LocalPackages" value="../LocalPackages" />
</packageSources>
</configuration>

View File

@@ -6,6 +6,7 @@ mono:
solution: QuantConnect.Lean.sln
before_install:
- export PATH="$HOME/miniconda3/bin:$PATH"
- export PYTHONNET_PYDLL="$HOME/miniconda3/lib/libpython3.6m.so"
- wget -q https://cdn.quantconnect.com/miniconda/Miniconda3-4.5.12-Linux-x86_64.sh
- bash Miniconda3-4.5.12-Linux-x86_64.sh -b
- rm -rf Miniconda3-4.5.12-Linux-x86_64.sh
@@ -20,6 +21,7 @@ before_install:
install:
- nuget install NUnit.Runners -Version 3.11.1 -OutputDirectory testrunner
script:
- dotnet nuget add source $TRAVIS_BUILD_DIR/LocalPackages
- dotnet build /p:Configuration=Release /p:VbcToolExe=vbnc.exe /v:quiet /p:WarningLevel=1 QuantConnect.Lean.sln
- mono ./testrunner/NUnit.ConsoleRunner.3.11.1/tools/nunit3-console.exe ./Tests/bin/Release/QuantConnect.Tests.dll --where "cat != TravisExclude" --labels=Off --params:log-handler=ConsoleErrorLogHandler
- chmod +x ci_build_stubs.sh

View File

@@ -94,7 +94,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.212"},
{"Treynor Ratio", "-2.13"},
{"Total Fees", "$199.00"},
{"Estimated Strategy Capacity", "$280000000.00"},
{"Estimated Strategy Capacity", "$23000000.00"},
{"Fitness Score", "0.002"},
{"Kelly Criterion Estimate", "38.64"},
{"Kelly Criterion Probability Value", "0.229"},

View File

@@ -130,7 +130,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.367"},
{"Treynor Ratio", "-4.079"},
{"Total Fees", "$14.33"},
{"Estimated Strategy Capacity", "$29000000.00"},
{"Estimated Strategy Capacity", "$38000000.00"},
{"Fitness Score", "0.408"},
{"Kelly Criterion Estimate", "16.447"},
{"Kelly Criterion Probability Value", "0.315"},

View File

@@ -139,7 +139,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.058"},
{"Treynor Ratio", "2.133"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$6400000.00"},
{"Estimated Strategy Capacity", "$45000000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -191,7 +191,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.042"},
{"Treynor Ratio", "0.286"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$1400000.00"},
{"Estimated Strategy Capacity", "$2800000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -79,19 +79,19 @@ namespace QuantConnect.Algorithm.CSharp
// things like manually added, auto added, internal, and any other boolean state we need to track against a single security)
throw new Exception("The underlying equity data should NEVER be removed in this algorithm because it was manually added");
}
if (_expectedSecurities.AreDifferent(LinqExtensions.ToHashSet(Securities.Keys)))
if (_expectedSecurities.AreDifferent(Securities.Keys.ToHashSet()))
{
var expected = string.Join(Environment.NewLine, _expectedSecurities.OrderBy(s => s.ToString()));
var actual = string.Join(Environment.NewLine, Securities.Keys.OrderBy(s => s.ToString()));
throw new Exception($"{Time}:: Detected differences in expected and actual securities{Environment.NewLine}Expected:{Environment.NewLine}{expected}{Environment.NewLine}Actual:{Environment.NewLine}{actual}");
}
if (_expectedUniverses.AreDifferent(LinqExtensions.ToHashSet(UniverseManager.Keys)))
if (_expectedUniverses.AreDifferent(Securities.Keys.ToHashSet()))
{
var expected = string.Join(Environment.NewLine, _expectedUniverses.OrderBy(s => s.ToString()));
var actual = string.Join(Environment.NewLine, UniverseManager.Keys.OrderBy(s => s.ToString()));
throw new Exception($"{Time}:: Detected differences in expected and actual universes{Environment.NewLine}Expected:{Environment.NewLine}{expected}{Environment.NewLine}Actual:{Environment.NewLine}{actual}");
}
if (_expectedData.AreDifferent(LinqExtensions.ToHashSet(data.Keys)))
if (_expectedData.AreDifferent(Securities.Keys.ToHashSet()))
{
var expected = string.Join(Environment.NewLine, _expectedData.OrderBy(s => s.ToString()));
var actual = string.Join(Environment.NewLine, data.Keys.OrderBy(s => s.ToString()));
@@ -183,7 +183,7 @@ namespace QuantConnect.Algorithm.CSharp
if (changes.RemovedSecurities
.Where(x => x.Symbol.SecurityType == SecurityType.Option)
.ToHashSet(s => s.Symbol)
.AreDifferent(LinqExtensions.ToHashSet(_expectedContracts)))
.AreDifferent(_expectedContracts.ToHashSet()))
{
throw new Exception("Expected removed securities to equal expected contracts added");
}
@@ -230,7 +230,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$6.00"},
{"Estimated Strategy Capacity", "$3000.00"},
{"Estimated Strategy Capacity", "$1500.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -131,7 +131,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.072"},
{"Treynor Ratio", "2.933"},
{"Total Fees", "$26.39"},
{"Estimated Strategy Capacity", "$2200000.00"},
{"Estimated Strategy Capacity", "$4400000.00"},
{"Fitness Score", "0.374"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -84,7 +84,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.006"},
{"Treynor Ratio", "2.029"},
{"Total Fees", "$9.77"},
{"Estimated Strategy Capacity", "$28000000.00"},
{"Estimated Strategy Capacity", "$37000000.00"},
{"Fitness Score", "0.747"},
{"Kelly Criterion Estimate", "38.64"},
{"Kelly Criterion Probability Value", "0.229"},

View File

@@ -103,7 +103,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.376"},
{"Treynor Ratio", "-0.084"},
{"Total Fees", "$13.98"},
{"Estimated Strategy Capacity", "$31000000.00"},
{"Estimated Strategy Capacity", "$61000000.00"},
{"Fitness Score", "0.146"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "1"},

View File

@@ -110,7 +110,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.194"},
{"Treynor Ratio", "-0.962"},
{"Total Fees", "$25.92"},
{"Estimated Strategy Capacity", "$16000000.00"},
{"Estimated Strategy Capacity", "$69000000.00"},
{"Fitness Score", "0.004"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "1"},

View File

@@ -211,7 +211,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.068"},
{"Treynor Ratio", "1.722"},
{"Total Fees", "$307.50"},
{"Estimated Strategy Capacity", "$710000.00"},
{"Estimated Strategy Capacity", "$2800000.00"},
{"Fitness Score", "0.173"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -98,7 +98,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.099"},
{"Treynor Ratio", "-5.187"},
{"Total Fees", "$65.00"},
{"Estimated Strategy Capacity", "$2300000000.00"},
{"Estimated Strategy Capacity", "$16000000000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -130,7 +130,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.001"},
{"Treynor Ratio", "1.922"},
{"Total Fees", "$3.26"},
{"Estimated Strategy Capacity", "$15000000.00"},
{"Estimated Strategy Capacity", "$58000000.00"},
{"Fitness Score", "0.248"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -97,7 +97,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.001"},
{"Treynor Ratio", "1.922"},
{"Total Fees", "$3.26"},
{"Estimated Strategy Capacity", "$15000000.00"},
{"Estimated Strategy Capacity", "$58000000.00"},
{"Fitness Score", "0.248"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -88,7 +88,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.221"},
{"Treynor Ratio", "-13.568"},
{"Total Fees", "$3.26"},
{"Estimated Strategy Capacity", "$130000000.00"},
{"Estimated Strategy Capacity", "$890000000.00"},
{"Fitness Score", "0.111"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -109,7 +109,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.002"},
{"Treynor Ratio", "1.839"},
{"Total Fees", "$9.77"},
{"Estimated Strategy Capacity", "$20000000.00"},
{"Estimated Strategy Capacity", "$27000000.00"},
{"Fitness Score", "0.747"},
{"Kelly Criterion Estimate", "38.64"},
{"Kelly Criterion Probability Value", "0.229"},

View File

@@ -147,7 +147,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.504"},
{"Treynor Ratio", "1.011"},
{"Total Fees", "$15207.00"},
{"Estimated Strategy Capacity", "$8800000.00"},
{"Estimated Strategy Capacity", "$7700.00"},
{"Fitness Score", "0.033"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -155,7 +155,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.188"},
{"Treynor Ratio", "-3.318"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$13000000.00"},
{"Estimated Strategy Capacity", "$52000000.00"},
{"Fitness Score", "0.009"},
{"Kelly Criterion Estimate", "-112.972"},
{"Kelly Criterion Probability Value", "0.671"},

View File

@@ -0,0 +1,157 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data;
using System.Collections.Generic;
using QuantConnect.Indicators;
using QuantConnect.Interfaces;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This example demonstrates how to add index asset types.
/// </summary>
/// <meta name="tag" content="using data" />
/// <meta name="tag" content="benchmarks" />
/// <meta name="tag" content="indexes" />
public class BasicTemplateIndexAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
private ExponentialMovingAverage _emaSlow;
private ExponentialMovingAverage _emaFast;
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 15);
SetCash(1000000);
// Use indicator for signal; but it cannot be traded
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Trade on SPX ITM calls
_spxOption = QuantConnect.Symbol.CreateOption(
_spx,
Market.USA,
OptionStyle.European,
OptionRight.Call,
3200m,
new DateTime(2021, 1, 15));
AddIndexOptionContract(_spxOption, Resolution.Minute);
_emaSlow = EMA(_spx, 80);
_emaFast = EMA(_spx, 200);
}
/// <summary>
/// Index EMA Cross trading underlying.
/// </summary>
public override void OnData(Slice slice)
{
if (!slice.Bars.ContainsKey(_spx) || !slice.Bars.ContainsKey(_spxOption))
{
return;
}
// Warm up indicators
if (!_emaSlow.IsReady)
{
return;
}
if (_emaFast > _emaSlow)
{
SetHoldings(_spxOption, 1);
}
else
{
Liquidate();
}
}
public override void OnEndOfAlgorithm()
{
if (Portfolio[_spx].TotalSaleVolume > 0)
{
throw new Exception("Index is not tradable.");
}
}
/// <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", "-53.10%"},
{"Compounding Annual Return", "-96.172%"},
{"Drawdown", "10.100%"},
{"Expectancy", "-1"},
{"Net Profit", "-9.915%"},
{"Sharpe Ratio", "-4.217"},
{"Probabilistic Sharpe Ratio", "0.052%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.139"},
{"Annual Variance", "0.019"},
{"Information Ratio", "-4.217"},
{"Tracking Error", "0.139"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$14000000.00"},
{"Fitness Score", "0.044"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.96"},
{"Return Over Maximum Drawdown", "-10.171"},
{"Portfolio Turnover", "0.34"},
{"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", "52521ab779446daf4d38a7c9bbbdd893"}
};
}
}

View File

@@ -0,0 +1,180 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using QuantConnect.Data;
using System.Collections.Generic;
using QuantConnect.Indicators;
using QuantConnect.Interfaces;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This example demonstrates how to add index asset types and trade index options on SPX.
/// </summary>
public class BasicTemplateIndexOptionsAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private ExponentialMovingAverage _emaSlow;
private ExponentialMovingAverage _emaFast;
/// <summary>
/// Initialize your algorithm and add desired assets.
/// </summary>
public override void Initialize()
{
SetStartDate(2021, 1, 4);
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);
spxOptions.SetFilter(filterFunc => filterFunc.CallsOnly());
_emaSlow = EMA(_spx, 80);
_emaFast = EMA(_spx, 200);
}
/// <summary>
/// Index EMA Cross trading index options of the index.
/// </summary>
public override void OnData(Slice slice)
{
if (!slice.Bars.ContainsKey(_spx))
{
Debug($"No SPX on {Time}");
return;
}
// Warm up indicators
if (!_emaSlow.IsReady)
{
Debug($"EMA slow not ready on {Time}");
return;
}
foreach (var chain in slice.OptionChains.Values)
{
foreach (var contract in chain.Contracts.Values)
{
if (contract.Expiry.Month == 3 && contract.Symbol.ID.StrikePrice == 3700m && contract.Right == OptionRight.Call && slice.QuoteBars.ContainsKey(contract.Symbol))
{
Log($"{Time} {contract.Strike}{(contract.Right == OptionRight.Call ? 'C' : 'P')} -- {slice.QuoteBars[contract.Symbol]}");
}
if (Portfolio.Invested)
{
continue;
}
if (_emaFast > _emaSlow && contract.Right == OptionRight.Call)
{
Liquidate(InvertOption(contract.Symbol));
MarketOrder(contract.Symbol, 1);
}
else if (_emaFast < _emaSlow && contract.Right == OptionRight.Put)
{
Liquidate(InvertOption(contract.Symbol));
MarketOrder(contract.Symbol, 1);
}
}
}
}
public override void OnEndOfAlgorithm()
{
if (Portfolio[_spx].TotalSaleVolume > 0)
{
throw new Exception("Index is not tradable.");
}
if (Portfolio.TotalSaleVolume == 0)
{
throw new Exception("Trade volume should be greater than zero by the end of this algorithm");
}
}
public Symbol InvertOption(Symbol symbol)
{
return QuantConnect.Symbol.CreateOption(
symbol.Underlying,
symbol.ID.Market,
symbol.ID.OptionStyle,
symbol.ID.OptionRight == OptionRight.Call ? OptionRight.Put : OptionRight.Call,
symbol.ID.StrikePrice,
symbol.ID.Date);
}
/// <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;
/// <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", "8220"},
{"Average Win", "0.00%"},
{"Average Loss", "0.00%"},
{"Compounding Annual Return", "-100.000%"},
{"Drawdown", "13.500%"},
{"Expectancy", "-0.818"},
{"Net Profit", "-13.517%"},
{"Sharpe Ratio", "-2.678"},
{"Probabilistic Sharpe Ratio", "0%"},
{"Loss Rate", "89%"},
{"Win Rate", "11%"},
{"Profit-Loss Ratio", "0.69"},
{"Alpha", "4.398"},
{"Beta", "-0.989"},
{"Annual Standard Deviation", "0.373"},
{"Annual Variance", "0.139"},
{"Information Ratio", "-12.816"},
{"Tracking Error", "0.504"},
{"Treynor Ratio", "1.011"},
{"Total Fees", "$15207.00"},
{"Estimated Strategy Capacity", "$8800000.00"},
{"Fitness Score", "0.033"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-8.62"},
{"Return Over Maximum Drawdown", "-7.81"},
{"Portfolio Turnover", "302.321"},
{"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", "35b3f4b7a225468d42ca085386a2383e"}
};
}
}

View File

@@ -134,7 +134,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$778.00"},
{"Estimated Strategy Capacity", "$180000.00"},
{"Estimated Strategy Capacity", "$720.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -131,7 +131,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$2600000.00"},
{"Estimated Strategy Capacity", "$1300000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -28,11 +28,11 @@ namespace QuantConnect.Algorithm.CSharp.Benchmarks
_symbol = AddEquity("SPY").Symbol;
}
public override void OnEndOfDay()
public override void OnEndOfDay(Symbol symbol)
{
var minuteHistory = History(_symbol, 60, Resolution.Minute);
var minuteHistory = History(symbol, 60, Resolution.Minute);
var lastHourHigh = minuteHistory.Select(minuteBar => minuteBar.High).DefaultIfEmpty(0).Max();
var dailyHistory = History(_symbol, 1, Resolution.Daily).First();
var dailyHistory = History(symbol, 1, Resolution.Daily).First();
var dailyHigh = dailyHistory.High;
var dailyLow = dailyHistory.Low;
var dailyOpen = dailyHistory.Open;

View File

@@ -94,7 +94,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.09"},
{"Treynor Ratio", "0.82"},
{"Total Fees", "$41.70"},
{"Estimated Strategy Capacity", "$2000000.00"},
{"Estimated Strategy Capacity", "$3000000.00"},
{"Fitness Score", "0.634"},
{"Kelly Criterion Estimate", "13.656"},
{"Kelly Criterion Probability Value", "0.228"},

View File

@@ -181,7 +181,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.149"},
{"Treynor Ratio", "-1.405"},
{"Total Fees", "$2.00"},
{"Estimated Strategy Capacity", "$6000000.00"},
{"Estimated Strategy Capacity", "$42000000.00"},
{"Fitness Score", "0.076"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -136,7 +136,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.126"},
{"Treynor Ratio", "-0.607"},
{"Total Fees", "$11.63"},
{"Estimated Strategy Capacity", "$13000000.00"},
{"Estimated Strategy Capacity", "$46000000.00"},
{"Fitness Score", "0.013"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -120,7 +120,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.105"},
{"Treynor Ratio", "1.667"},
{"Total Fees", "$2.91"},
{"Estimated Strategy Capacity", "$96000000.00"},
{"Estimated Strategy Capacity", "$670000000.00"},
{"Fitness Score", "0.141"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -91,7 +91,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.101"},
{"Treynor Ratio", "5.409"},
{"Total Fees", "$67.00"},
{"Estimated Strategy Capacity", "$2400000.00"},
{"Estimated Strategy Capacity", "$3200000.00"},
{"Fitness Score", "0.501"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -85,7 +85,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.009"},
{"Treynor Ratio", "1.575"},
{"Total Fees", "$22.77"},
{"Estimated Strategy Capacity", "$19000000.00"},
{"Estimated Strategy Capacity", "$22000000.00"},
{"Fitness Score", "0.999"},
{"Kelly Criterion Estimate", "38.64"},
{"Kelly Criterion Probability Value", "0.229"},

View File

@@ -94,7 +94,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.165"},
{"Treynor Ratio", "1.212"},
{"Total Fees", "$6.00"},
{"Estimated Strategy Capacity", "$32000000.00"},
{"Estimated Strategy Capacity", "$42000000.00"},
{"Fitness Score", "0.063"},
{"Kelly Criterion Estimate", "38.64"},
{"Kelly Criterion Probability Value", "0.229"},

View File

@@ -190,7 +190,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.176"},
{"Treynor Ratio", "-1.46"},
{"Total Fees", "$7.82"},
{"Estimated Strategy Capacity", "$6000000.00"},
{"Estimated Strategy Capacity", "$12000000.00"},
{"Fitness Score", "0.1"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -146,7 +146,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.239"},
{"Treynor Ratio", "-1.435"},
{"Total Fees", "$755.29"},
{"Estimated Strategy Capacity", "$150000000.00"},
{"Estimated Strategy Capacity", "$1100000000.00"},
{"Fitness Score", "0.024"},
{"Kelly Criterion Estimate", "-0.84"},
{"Kelly Criterion Probability Value", "0.53"},

View File

@@ -99,7 +99,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.168"},
{"Treynor Ratio", "2.38"},
{"Total Fees", "$3.26"},
{"Estimated Strategy Capacity", "$75000000.00"},
{"Estimated Strategy Capacity", "$300000000.00"},
{"Fitness Score", "0.245"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -96,7 +96,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0"},
{"Treynor Ratio", "0.988"},
{"Total Fees", "$7.78"},
{"Estimated Strategy Capacity", "$2200000.00"},
{"Estimated Strategy Capacity", "$8700000.00"},
{"Fitness Score", "0.031"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -43,7 +43,7 @@ namespace QuantConnect.Algorithm.CSharp
security.SetBuyingPowerModel(new CustomBuyingPowerModel());
}
public void OnData(Slice slice)
public override void OnData(Slice slice)
{
if (Portfolio.Invested)
{
@@ -113,7 +113,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "1.04"},
{"Treynor Ratio", "5.073"},
{"Total Fees", "$30.00"},
{"Estimated Strategy Capacity", "$2800000.00"},
{"Estimated Strategy Capacity", "$20000000.00"},
{"Fitness Score", "0.418"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -80,7 +80,7 @@ namespace QuantConnect.Algorithm.CSharp
/// OnEndOfDay Event Handler - At the end of each trading day we fire this code.
/// To avoid flooding, we recommend running your plotting at the end of each day.
/// </summary>
public override void OnEndOfDay()
public override void OnEndOfDay(Symbol symbol)
{
//Log the end of day prices:
Plot("Trade Plot", "Price", _lastPrice);

View File

@@ -119,7 +119,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.112"},
{"Treynor Ratio", "-6.121"},
{"Total Fees", "$3.50"},
{"Estimated Strategy Capacity", "$6900000.00"},
{"Estimated Strategy Capacity", "$48000000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -124,7 +124,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.112"},
{"Treynor Ratio", "-6.121"},
{"Total Fees", "$3.50"},
{"Estimated Strategy Capacity", "$6900000.00"},
{"Estimated Strategy Capacity", "$48000000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -131,7 +131,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.19"},
{"Treynor Ratio", "2.159"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$14000000.00"},
{"Estimated Strategy Capacity", "$58000000.00"},
{"Fitness Score", "0.1"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -58,7 +58,9 @@ namespace QuantConnect.Algorithm.CSharp
//Weather used as a tradable asset, like stocks, futures etc.
if (data.Close != 0)
{
Order("BTC", (Portfolio.MarginRemaining / Math.Abs(data.Close + 1)));
// It's only OK to use SetHoldings with crypto when using custom data. When trading with built-in crypto data,
// use the cashbook. Reference https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/BasicTemplateCryptoAlgorithm.py
SetHoldings("BTC", 1);
}
Console.WriteLine("Buying BTC 'Shares': BTC: " + data.Close);
}
@@ -117,7 +119,7 @@ namespace QuantConnect.Algorithm.CSharp
//return "http://my-ftp-server.com/futures-data-" + date.ToString("Ymd") + ".zip";
// OR simply return a fixed small data file. Large files will slow down your backtest
return new SubscriptionDataSource("https://www.quandl.com/api/v3/datasets/BCHARTS/BITSTAMPUSD.csv?order=asc", SubscriptionTransportMedium.RemoteFile);
return new SubscriptionDataSource("https://www.quantconnect.com/api/v2/proxy/quandl/api/v3/datasets/BCHARTS/BITSTAMPUSD.csv?order=asc&api_key=WyAazVXnq7ATy_fefTqm", SubscriptionTransportMedium.RemoteFile);
}
/// <summary>
@@ -154,6 +156,7 @@ namespace QuantConnect.Algorithm.CSharp
{
string[] data = line.Split(',');
coin.Time = DateTime.Parse(data[0], CultureInfo.InvariantCulture);
coin.EndTime = coin.Time.AddDays(1);
coin.Open = Convert.ToDecimal(data[1], CultureInfo.InvariantCulture);
coin.High = Convert.ToDecimal(data[2], CultureInfo.InvariantCulture);
coin.Low = Convert.ToDecimal(data[3], CultureInfo.InvariantCulture);

View File

@@ -61,7 +61,7 @@ namespace QuantConnect.Algorithm.CSharp
/// "Nifty" type below and fired into this event handler.
/// </summary>
/// <param name="data">One(1) Nifty Object, streamed into our algorithm synchronised in time with our other data streams</param>
public void OnData(Slice data)
public override void OnData(Slice data)
{
if (data.ContainsKey("USDINR"))
{
@@ -77,7 +77,7 @@ namespace QuantConnect.Algorithm.CSharp
{
_today.NiftyPrice = Convert.ToDouble(data["NIFTY"].Close);
if (_today.Date == data["NIFTY"].EndTime)
if (_today.Date == data["NIFTY"].Time)
{
_prices.Add(_today);
@@ -91,7 +91,7 @@ namespace QuantConnect.Algorithm.CSharp
var quantity = (int)(Portfolio.MarginRemaining * 0.9m / data["NIFTY"].Close);
var highestNifty = (from pair in _prices select pair.NiftyPrice).Max();
var lowestNifty = (from pair in _prices select pair.NiftyPrice).Min();
if (Time.DayOfWeek == DayOfWeek.Wednesday) //prices.Count >= minimumCorrelationHistory &&
{
//List<double> niftyPrices = (from pair in prices select pair.NiftyPrice).ToList();
@@ -121,7 +121,7 @@ namespace QuantConnect.Algorithm.CSharp
/// End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets).
/// </summary>
/// <remarks>Method is called 10 minutes before closing to allow user to close out position.</remarks>
public override void OnEndOfDay()
public override void OnEndOfDay(Symbol symbol)
{
Plot("Nifty Closing Price", _today.NiftyPrice);
}
@@ -181,6 +181,7 @@ namespace QuantConnect.Algorithm.CSharp
//2011-09-13 7792.9 7799.9 7722.65 7748.7 116534670 6107.78
var data = line.Split(',');
index.Time = DateTime.Parse(data[0], CultureInfo.InvariantCulture);
index.EndTime = index.Time.AddDays(1);
index.Open = Convert.ToDecimal(data[1], CultureInfo.InvariantCulture);
index.High = Convert.ToDecimal(data[2], CultureInfo.InvariantCulture);
index.Low = Convert.ToDecimal(data[3], CultureInfo.InvariantCulture);
@@ -247,6 +248,7 @@ namespace QuantConnect.Algorithm.CSharp
{
var data = line.Split(',');
currency.Time = DateTime.Parse(data[0], CultureInfo.InvariantCulture);
currency.EndTime = currency.Time.AddDays(1);
currency.Close = Convert.ToDecimal(data[1], CultureInfo.InvariantCulture);
currency.Symbol = "USDINR";
currency.Value = currency.Close;

View File

@@ -114,29 +114,29 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "1"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "155.262%"},
{"Compounding Annual Return", "157.498%"},
{"Drawdown", "84.800%"},
{"Expectancy", "0"},
{"Net Profit", "5123.242%"},
{"Sharpe Ratio", "2.067"},
{"Probabilistic Sharpe Ratio", "68.833%"},
{"Net Profit", "5319.081%"},
{"Sharpe Ratio", "2.086"},
{"Probabilistic Sharpe Ratio", "69.456%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "1.732"},
{"Beta", "0.037"},
{"Annual Standard Deviation", "0.841"},
{"Annual Variance", "0.707"},
{"Information Ratio", "1.902"},
{"Tracking Error", "0.848"},
{"Treynor Ratio", "46.992"},
{"Alpha", "1.736"},
{"Beta", "0.136"},
{"Annual Standard Deviation", "0.84"},
{"Annual Variance", "0.706"},
{"Information Ratio", "1.925"},
{"Tracking Error", "0.846"},
{"Treynor Ratio", "12.904"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "2.238"},
{"Return Over Maximum Drawdown", "1.832"},
{"Sortino Ratio", "2.269"},
{"Return Over Maximum Drawdown", "1.858"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -151,7 +151,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "1f54fb75ebcc0daafa5d45bfbaa4fbcb"}
{"OrderListHash", "0d80bb47bd16b5bc6989a4c1c7aa8349"}
};
/// <summary>
@@ -243,6 +243,7 @@ namespace QuantConnect.Algorithm.CSharp
{
string[] data = line.Split(',');
coin.Time = DateTime.Parse(data[0], CultureInfo.InvariantCulture);
coin.EndTime = coin.Time.AddDays(1);
coin.Open = Convert.ToDecimal(data[1], CultureInfo.InvariantCulture);
coin.High = Convert.ToDecimal(data[2], CultureInfo.InvariantCulture);
coin.Low = Convert.ToDecimal(data[3], CultureInfo.InvariantCulture);
@@ -258,4 +259,4 @@ namespace QuantConnect.Algorithm.CSharp
}
}
}
}
}

View File

@@ -84,29 +84,29 @@ namespace QuantConnect.Algorithm.CSharp
{"Total Trades", "1"},
{"Average Win", "0%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "155.262%"},
{"Compounding Annual Return", "157.497%"},
{"Drawdown", "84.800%"},
{"Expectancy", "0"},
{"Net Profit", "5123.170%"},
{"Sharpe Ratio", "2.066"},
{"Probabilistic Sharpe Ratio", "68.832%"},
{"Net Profit", "5319.007%"},
{"Sharpe Ratio", "2.086"},
{"Probabilistic Sharpe Ratio", "69.456%"},
{"Loss Rate", "0%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "1.732"},
{"Beta", "0.037"},
{"Annual Standard Deviation", "0.841"},
{"Annual Variance", "0.707"},
{"Information Ratio", "1.902"},
{"Tracking Error", "0.848"},
{"Treynor Ratio", "46.996"},
{"Alpha", "1.736"},
{"Beta", "0.136"},
{"Annual Standard Deviation", "0.84"},
{"Annual Variance", "0.706"},
{"Information Ratio", "1.925"},
{"Tracking Error", "0.846"},
{"Treynor Ratio", "12.903"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "2.238"},
{"Return Over Maximum Drawdown", "1.832"},
{"Sortino Ratio", "2.269"},
{"Return Over Maximum Drawdown", "1.858"},
{"Portfolio Turnover", "0"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -121,7 +121,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "0e7d560d0db2829adb19d3e403c30d97"}
{"OrderListHash", "50faa37f15732bf5c24ad1eeaa335bc7"}
};
/// <summary>
@@ -213,6 +213,7 @@ namespace QuantConnect.Algorithm.CSharp
{
string[] data = line.Split(',');
coin.Time = DateTime.Parse(data[0], CultureInfo.InvariantCulture);
coin.EndTime = coin.Time.AddDays(1);
coin.Open = Convert.ToDecimal(data[1], CultureInfo.InvariantCulture);
coin.High = Convert.ToDecimal(data[2], CultureInfo.InvariantCulture);
coin.Low = Convert.ToDecimal(data[3], CultureInfo.InvariantCulture);
@@ -228,4 +229,4 @@ namespace QuantConnect.Algorithm.CSharp
}
}
}
}
}

View File

@@ -212,7 +212,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.118"},
{"Treynor Ratio", "-0.591"},
{"Total Fees", "$62.24"},
{"Estimated Strategy Capacity", "$100000000.00"},
{"Estimated Strategy Capacity", "$49000000.00"},
{"Fitness Score", "0.147"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -103,7 +103,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.251"},
{"Treynor Ratio", "9.323"},
{"Total Fees", "$3.26"},
{"Estimated Strategy Capacity", "$220000000.00"},
{"Estimated Strategy Capacity", "$890000000.00"},
{"Fitness Score", "0.201"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -113,7 +113,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.08"},
{"Treynor Ratio", "0.517"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$38000000.00"},
{"Estimated Strategy Capacity", "$270000000.00"},
{"Fitness Score", "0.019"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -123,7 +123,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.115"},
{"Treynor Ratio", "1.545"},
{"Total Fees", "$37.00"},
{"Estimated Strategy Capacity", "$58000.00"},
{"Estimated Strategy Capacity", "$400000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -186,7 +186,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.204"},
{"Treynor Ratio", "-8.165"},
{"Total Fees", "$46.75"},
{"Estimated Strategy Capacity", "$96000000.00"},
{"Estimated Strategy Capacity", "$670000000.00"},
{"Fitness Score", "0.002"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -204,7 +204,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.171"},
{"Treynor Ratio", "-1.761"},
{"Total Fees", "$8669.41"},
{"Estimated Strategy Capacity", "$170000.00"},
{"Estimated Strategy Capacity", "$320000.00"},
{"Fitness Score", "0.675"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -177,7 +177,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.171"},
{"Treynor Ratio", "-1.971"},
{"Total Fees", "$6806.67"},
{"Estimated Strategy Capacity", "$150000.00"},
{"Estimated Strategy Capacity", "$320000.00"},
{"Fitness Score", "0.694"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -131,7 +131,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.29"},
{"Treynor Ratio", "4.005"},
{"Total Fees", "$18.28"},
{"Estimated Strategy Capacity", "$200000000.00"},
{"Estimated Strategy Capacity", "$500000000.00"},
{"Fitness Score", "0.052"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -127,7 +127,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.204"},
{"Treynor Ratio", "-1.424"},
{"Total Fees", "$16.26"},
{"Estimated Strategy Capacity", "$250000000.00"},
{"Estimated Strategy Capacity", "$590000000.00"},
{"Fitness Score", "0.003"},
{"Kelly Criterion Estimate", "12.539"},
{"Kelly Criterion Probability Value", "0.367"},

View File

@@ -148,7 +148,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "1.441"},
{"Treynor Ratio", "-0.15"},
{"Total Fees", "$33.30"},
{"Estimated Strategy Capacity", "$4200000.00"},
{"Estimated Strategy Capacity", "$17000000.00"},
{"Fitness Score", "0.079"},
{"Kelly Criterion Estimate", "-9.366"},
{"Kelly Criterion Probability Value", "0.607"},

View File

@@ -184,7 +184,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.123"},
{"Treynor Ratio", "-1.288"},
{"Total Fees", "$669.76"},
{"Estimated Strategy Capacity", "$8100000.00"},
{"Estimated Strategy Capacity", "$210000.00"},
{"Fitness Score", "0.021"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -147,7 +147,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.049"},
{"Treynor Ratio", "-0.934"},
{"Total Fees", "$22.26"},
{"Estimated Strategy Capacity", "$3600000.00"},
{"Estimated Strategy Capacity", "$360000.00"},
{"Fitness Score", "0.002"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -122,7 +122,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.186"},
{"Treynor Ratio", "1.557"},
{"Total Fees", "$4.00"},
{"Estimated Strategy Capacity", "$1400000.00"},
{"Estimated Strategy Capacity", "$5200000.00"},
{"Fitness Score", "0.012"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -174,7 +174,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$804.33"},
{"Estimated Strategy Capacity", "$21000.00"},
{"Estimated Strategy Capacity", "$11000.00"},
{"Fitness Score", "0.504"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -98,7 +98,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$5.93"},
{"Estimated Strategy Capacity", "$200000.00"},
{"Estimated Strategy Capacity", "$590000.00"},
{"Fitness Score", "0.499"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -105,7 +105,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.394"},
{"Treynor Ratio", "-5.313"},
{"Total Fees", "$5.40"},
{"Estimated Strategy Capacity", "$59000000.00"},
{"Estimated Strategy Capacity", "$230000000.00"},
{"Fitness Score", "0.244"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.507"},
{"Treynor Ratio", "0"},
{"Total Fees", "$2651.01"},
{"Estimated Strategy Capacity", "$9800.00"},
{"Estimated Strategy Capacity", "$30000.00"},
{"Fitness Score", "0.467"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -99,7 +99,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.267"},
{"Treynor Ratio", "-0.847"},
{"Total Fees", "$41.17"},
{"Estimated Strategy Capacity", "$98000000.00"},
{"Estimated Strategy Capacity", "$340000000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "38.884"},
{"Kelly Criterion Probability Value", "0.009"},

View File

@@ -138,7 +138,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.195"},
{"Treynor Ratio", "55.977"},
{"Total Fees", "$14.80"},
{"Estimated Strategy Capacity", "$2100000.00"},
{"Estimated Strategy Capacity", "$15000000.00"},
{"Fitness Score", "0.018"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -222,7 +222,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.191"},
{"Treynor Ratio", "33.18"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$1300000.00"},
{"Estimated Strategy Capacity", "$9000000.00"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -180,7 +180,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.718"},
{"Treynor Ratio", "18.473"},
{"Total Fees", "$66.60"},
{"Estimated Strategy Capacity", "$1200000.00"},
{"Estimated Strategy Capacity", "$8300000.00"},
{"Fitness Score", "0.162"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -197,7 +197,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.182"},
{"Treynor Ratio", "28.46"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$830000.00"},
{"Estimated Strategy Capacity", "$5800000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -223,7 +223,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.183"},
{"Treynor Ratio", "37.798"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$1400000.00"},
{"Estimated Strategy Capacity", "$9900000.00"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -196,7 +196,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.187"},
{"Treynor Ratio", "28.078"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$1200000.00"},
{"Estimated Strategy Capacity", "$8700000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -207,7 +207,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.183"},
{"Treynor Ratio", "22.266"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$1900000.00"},
{"Estimated Strategy Capacity", "$13000000.00"},
{"Fitness Score", "0.021"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -190,7 +190,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.176"},
{"Treynor Ratio", "27.339"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$460000.00"},
{"Estimated Strategy Capacity", "$3200000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -204,7 +204,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.176"},
{"Treynor Ratio", "14.729"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$1900000.00"},
{"Estimated Strategy Capacity", "$14000000.00"},
{"Fitness Score", "0.022"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -189,7 +189,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.179"},
{"Treynor Ratio", "28.253"},
{"Total Fees", "$3.70"},
{"Estimated Strategy Capacity", "$770000.00"},
{"Estimated Strategy Capacity", "$5400000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -102,7 +102,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.332"},
{"Treynor Ratio", "2.021"},
{"Total Fees", "$1.85"},
{"Estimated Strategy Capacity", "$47000000.00"},
{"Estimated Strategy Capacity", "$93000000.00"},
{"Fitness Score", "0.005"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -173,7 +173,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.176"},
{"Treynor Ratio", "29.128"},
{"Total Fees", "$7.40"},
{"Estimated Strategy Capacity", "$10000000.00"},
{"Estimated Strategy Capacity", "$71000000.00"},
{"Fitness Score", "0.007"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -92,7 +92,7 @@ namespace QuantConnect.Algorithm.CSharp
}
}
public override void OnEndOfDay()
public override void OnEndOfDay(Symbol symbol)
{
Plot("Indicator Signal", "EOD", IsDownTrend ? -1 : IsUpTrend ? 1 : 0);
}

View File

@@ -41,7 +41,9 @@ namespace QuantConnect.Algorithm.CSharp
// Without this, consuming projects would need to hard reference the Accord dlls,
// which is less than perfect. This seems to be the better of two evils
//
#pragma warning disable 0414
Accord.Math.Matrix3x3 _matrix = new Accord.Math.Matrix3x3();
#pragma warning restore 0414
//Fuzzy Engine
private FuzzyEngine _engine;

View File

@@ -317,7 +317,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.264"},
{"Treynor Ratio", "26.924"},
{"Total Fees", "$3.26"},
{"Estimated Strategy Capacity", "$300000000.00"},
{"Estimated Strategy Capacity", "$890000000.00"},
{"Fitness Score", "0.251"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -106,7 +106,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.866"},
{"Treynor Ratio", "-0.286"},
{"Total Fees", "$5.40"},
{"Estimated Strategy Capacity", "$350000.00"},
{"Estimated Strategy Capacity", "$2400000.00"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -128,7 +128,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$12000000000.00"},
{"Estimated Strategy Capacity", "$36000000000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -116,7 +116,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.073"},
{"Treynor Ratio", "0.573"},
{"Total Fees", "$14.75"},
{"Estimated Strategy Capacity", "$1300000.00"},
{"Estimated Strategy Capacity", "$6300000.00"},
{"Fitness Score", "0.2"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -0,0 +1,167 @@
/*
* 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.Interfaces;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests In The Money (ITM) index option calls across different strike prices.
/// We expect 4* orders from the algorithm, which are:
///
/// * (1) Initial entry, buy SPX Call Option (SPXF21 expiring ITM)
/// * (2) Initial entry, sell SPX Call Option at different strike (SPXF21 expiring ITM)
/// * [2] Option assignment, settle into cash
/// * [1] Option exercise, settle into cash
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
///
/// * Assignments are counted as orders
/// </summary>
public class IndexOptionBuySellCallIntradayRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
var spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select a index option expiring ITM, and adds it to the algorithm.
var spxOptions = OptionChainProvider.GetOptionContractList(spx, Time)
.Where(x => (x.ID.StrikePrice == 3700m || x.ID.StrikePrice == 3800m) && x.ID.OptionRight == OptionRight.Call && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.Select(x => AddIndexOptionContract(x, Resolution.Minute).Symbol)
.OrderBy(x => x.ID.StrikePrice)
.ToList();
var expectedContract3700 = QuantConnect.Symbol.CreateOption(
spx,
Market.USA,
OptionStyle.European,
OptionRight.Call,
3700m,
new DateTime(2021, 1, 15));
var expectedContract3800 = QuantConnect.Symbol.CreateOption(
spx,
Market.USA,
OptionStyle.European,
OptionRight.Call,
3800m,
new DateTime(2021, 1, 15));
if (spxOptions.Count != 2)
{
throw new Exception($"Expected 2 index options symbols from chain provider, found {spxOptions.Count}");
}
if (spxOptions[0] != expectedContract3700)
{
throw new Exception($"Contract {expectedContract3700} was not found in the chain, found instead: {spxOptions[0]}");
}
if (spxOptions[1] != expectedContract3800)
{
throw new Exception($"Contract {expectedContract3800} was not found in the chain, found instead: {spxOptions[1]}");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(spx, 1), () =>
{
MarketOrder(spxOptions[0], 1);
MarketOrder(spxOptions[1], -1);
});
Schedule.On(DateRules.Tomorrow, TimeRules.Noon, () =>
{
Liquidate();
});
}
/// <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)}");
}
}
/// <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.06%"},
{"Compounding Annual Return", "-1.552%"},
{"Drawdown", "0.100%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.110%"},
{"Sharpe Ratio", "-3.525"},
{"Probabilistic Sharpe Ratio", "0.518%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.004"},
{"Annual Variance", "0"},
{"Information Ratio", "-3.525"},
{"Tracking Error", "0.004"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-4619.237"},
{"Return Over Maximum Drawdown", "-14.266"},
{"Portfolio Turnover", "0.005"},
{"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", "7d15f56731d38768ea81afac627f0657"}
};
}
}

View File

@@ -0,0 +1,229 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests In The Money (ITM) index option expiry for calls.
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, buy SPX Call Option (expiring ITM)
/// * Option exercise, settles into cash
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
public class IndexOptionCallITMExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
private Symbol _expectedOptionContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
SetCash(100000);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select an index option expiring ITM, and adds it to the algorithm.
_spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice <= 3200m && x.ID.OptionRight == OptionRight.Call && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderByDescending(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute).Symbol;
_expectedOptionContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Call, 3200m, new DateTime(2021, 1, 15));
if (_spxOption != _expectedOptionContract)
{
throw new Exception($"Contract {_expectedOptionContract} was not found in the chain");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(_spx, 1), () =>
{
MarketOrder(_spxOption, 1);
});
}
public override void OnData(Slice data)
{
// Assert delistings, so that we can make sure that we receive the delisting warnings at
// the expected time. These assertions detect bug #4872
foreach (var delisting in data.Delistings.Values)
{
if (delisting.Type == DelistingType.Warning)
{
if (delisting.Time != new DateTime(2021, 1, 15))
{
throw new Exception($"Delisting warning issued at unexpected date: {delisting.Time}");
}
}
if (delisting.Type == DelistingType.Delisted)
{
if (delisting.Time != new DateTime(2021, 1, 16))
{
throw new Exception($"Delisting happened at unexpected date: {delisting.Time}");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status != OrderStatus.Filled)
{
// There's lots of noise with OnOrderEvent, but we're only interested in fills.
return;
}
if (!Securities.ContainsKey(orderEvent.Symbol))
{
throw new Exception($"Order event Symbol not found in Securities collection: {orderEvent.Symbol}");
}
var security = Securities[orderEvent.Symbol];
if (security.Symbol == _spx)
{
AssertIndexOptionOrderExercise(orderEvent, security, Securities[_expectedOptionContract]);
}
else if (security.Symbol == _expectedOptionContract)
{
AssertIndexOptionContractOrder(orderEvent, security);
}
else
{
throw new Exception($"Received order event for unknown Symbol: {orderEvent.Symbol}");
}
Log($"{Time:yyyy-MM-dd HH:mm:ss} -- {orderEvent.Symbol} :: Price: {Securities[orderEvent.Symbol].Holdings.Price} Qty: {Securities[orderEvent.Symbol].Holdings.Quantity} Direction: {orderEvent.Direction} Msg: {orderEvent.Message}");
}
private void AssertIndexOptionOrderExercise(OrderEvent orderEvent, Security index, Security optionContract)
{
var expectedLiquidationTimeUtc = new DateTime(2021, 1, 16, 3, 0, 0);
// No way to detect option exercise orders or any other kind of special orders
// other than matching strings, for now.
if (orderEvent.Message.Contains("Option Exercise"))
{
if (orderEvent.FillPrice != 3200m)
{
throw new Exception("Option did not exercise at expected strike price (3200)");
}
if (optionContract.Holdings.Quantity != 0)
{
throw new Exception($"Exercised option contract, but we have holdings for Option contract {optionContract.Symbol}");
}
}
}
private void AssertIndexOptionContractOrder(OrderEvent orderEvent, Security option)
{
if (orderEvent.Direction == OrderDirection.Buy && option.Holdings.Quantity != 1)
{
throw new Exception($"No holdings were created for option contract {option.Symbol}");
}
if (orderEvent.Direction == OrderDirection.Sell && option.Holdings.Quantity != 0)
{
throw new Exception($"Holdings were found after a filled option exercise");
}
if (orderEvent.Message.Contains("Exercise") && option.Holdings.Quantity != 0)
{
throw new Exception($"Holdings were found after exercising option contract {option.Symbol}");
}
}
/// <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)}");
}
}
/// <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", "-49.28%"},
{"Compounding Annual Return", "301.490%"},
{"Drawdown", "2.300%"},
{"Expectancy", "-1"},
{"Net Profit", "10.274%"},
{"Sharpe Ratio", "6.904"},
{"Probabilistic Sharpe Ratio", "89.741%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.386"},
{"Annual Variance", "0.149"},
{"Information Ratio", "6.904"},
{"Tracking Error", "0.386"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0.024"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "649.537"},
{"Return Over Maximum Drawdown", "1130.655"},
{"Portfolio Turnover", "0.024"},
{"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", "6dda4f153b0be9fdf55026da439f90f6"}
};
}
}

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 System.Reflection;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests In The Money (ITM) index option expiry for calls.
/// We test to make sure that index options have greeks enabled, same as equity options.
/// </summary>
public class IndexOptionCallITMGreeksExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private bool _invested;
private int _onDataCalls;
private Symbol _spx;
private Option _spxOption;
private Symbol _expectedOptionContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select an index option expiring ITM, and adds it to the algorithm.
_spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice <= 3200m && x.ID.OptionRight == OptionRight.Call && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderByDescending(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute);
_spxOption.PriceModel = OptionPriceModels.BlackScholes();
_expectedOptionContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Call, 3200m, new DateTime(2021, 1, 15));
if (_spxOption.Symbol != _expectedOptionContract)
{
throw new Exception($"Contract {_expectedOptionContract} was not found in the chain");
}
}
public override void OnData(Slice data)
{
// Let the algo warmup, but without using SetWarmup. Otherwise, we get
// no contracts in the option chain
if (_invested || _onDataCalls++ < 40)
{
return;
}
if (data.OptionChains.Count == 0)
{
return;
}
if (data.OptionChains.Values.All(o => o.Contracts.Values.Any(c => !data.ContainsKey(c.Symbol))))
{
return;
}
if (data.OptionChains.Values.First().Contracts.Count == 0)
{
throw new Exception($"No contracts found in the option {data.OptionChains.Keys.First()}");
}
var deltas = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Delta).ToList();
var gammas = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Gamma).ToList();
var lambda = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Lambda).ToList();
var rho = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Rho).ToList();
var theta = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Theta).ToList();
var vega = data.OptionChains.Values.OrderByDescending(y => y.Contracts.Values.Sum(x => x.Volume)).First().Contracts.Values.Select(x => x.Greeks.Vega).ToList();
// The commented out test cases all return zero.
// This is because of failure to evaluate the greeks in the option pricing model, most likely
// due to us not clearing the default 30 day requirement for the volatility model to start being updated.
if (deltas.Any(d => d == 0))
{
throw new AggregateException("Option contract Delta was equal to zero");
}
//if (gammas.Any(g => g == 0))
//{
// throw new AggregateException("Option contract Gamma was equal to zero");
//}
//if (lambda.Any(l => l == 0))
//{
// throw new AggregateException("Option contract Lambda was equal to zero");
//}
if (rho.Any(r => r == 0))
{
throw new AggregateException("Option contract Rho was equal to zero");
}
if (theta.Any(t => t == 0))
{
throw new AggregateException("Option contract Theta was equal to zero");
}
//if (vega.Any(v => v == 0))
//{
// throw new AggregateException("Option contract Vega was equal to zero");
//}
if (!_invested)
{
SetHoldings(data.OptionChains.Values.First().Contracts.Values.First().Symbol, 1);
_invested = true;
}
}
/// <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 (!_invested)
{
throw new Exception($"Never checked greeks, maybe we have no option data?");
}
}
/// <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", "-56.91%"},
{"Compounding Annual Return", "44.906%"},
{"Drawdown", "9.800%"},
{"Expectancy", "-1"},
{"Net Profit", "2.644%"},
{"Sharpe Ratio", "7.691"},
{"Probabilistic Sharpe Ratio", "91.027%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.417"},
{"Annual Variance", "0.174"},
{"Information Ratio", "7.691"},
{"Tracking Error", "0.417"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$46000000.00"},
{"Fitness Score", "0.023"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "0.535"},
{"Return Over Maximum Drawdown", "5.789"},
{"Portfolio Turnover", "0.03"},
{"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", "3cccf8c2409ee8a9020ba79a6c45742a"}
};
}
}

View File

@@ -0,0 +1,219 @@
/*
* 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 Out of The Money (OTM) index option expiry for calls.
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, buy SPX Call Option (expiring OTM)
/// - contract expires worthless, not exercised, so never opened a position in the underlying
///
/// * Liquidation of worthless SPX call option (expiring OTM)
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
/// <remarks>
/// Total Trades in regression algorithm should be 1, but expiration is counted as a trade.
/// See related issue: https://github.com/QuantConnect/Lean/issues/4854
/// </remarks>
public class IndexOptionCallOTMExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
private Symbol _expectedContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select a index option call expiring OTM, and adds it to the algorithm.
_spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice >= 4250m && x.ID.OptionRight == OptionRight.Call && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderBy(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute).Symbol;
_expectedContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Call, 4250m, new DateTime(2021, 1, 15));
if (_spxOption != _expectedContract)
{
throw new Exception($"Contract {_expectedContract} was not found in the chain");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(_spx, 1), () =>
{
MarketOrder(_spxOption, 1);
});
}
public override void OnData(Slice data)
{
// Assert delistings, so that we can make sure that we receive the delisting warnings at
// the expected time. These assertions detect bug #4872
foreach (var delisting in data.Delistings.Values)
{
if (delisting.Type == DelistingType.Warning)
{
if (delisting.Time != new DateTime(2021, 1, 15))
{
throw new Exception($"Delisting warning issued at unexpected date: {delisting.Time}");
}
}
if (delisting.Type == DelistingType.Delisted)
{
if (delisting.Time != new DateTime(2021, 1, 16))
{
throw new Exception($"Delisting happened at unexpected date: {delisting.Time}");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status != OrderStatus.Filled)
{
// There's lots of noise with OnOrderEvent, but we're only interested in fills.
return;
}
if (!Securities.ContainsKey(orderEvent.Symbol))
{
throw new Exception($"Order event Symbol not found in Securities collection: {orderEvent.Symbol}");
}
var security = Securities[orderEvent.Symbol];
if (security.Symbol == _spx)
{
throw new Exception("Invalid state: did not expect a position for the underlying to be opened, since this contract expires OTM");
}
if (security.Symbol == _expectedContract)
{
AssertIndexOptionContractOrder(orderEvent, security);
}
else
{
throw new Exception($"Received order event for unknown Symbol: {orderEvent.Symbol}");
}
Log($"{orderEvent}");
}
private void AssertIndexOptionContractOrder(OrderEvent orderEvent, Security option)
{
if (orderEvent.Direction == OrderDirection.Buy && option.Holdings.Quantity != 1)
{
throw new Exception($"No holdings were created for option contract {option.Symbol}");
}
if (orderEvent.Direction == OrderDirection.Sell && option.Holdings.Quantity != 0)
{
throw new Exception("Holdings were found after a filled option exercise");
}
if (orderEvent.Direction == OrderDirection.Sell && !orderEvent.Message.Contains("OTM"))
{
throw new Exception("Contract did not expire OTM");
}
if (orderEvent.Message.Contains("Exercise"))
{
throw new Exception("Exercised option, even though it expires OTM");
}
}
/// <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)}");
}
}
/// <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.01%"},
{"Compounding Annual Return", "-0.142%"},
{"Drawdown", "0.000%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.010%"},
{"Sharpe Ratio", "-5.154"},
{"Probabilistic Sharpe Ratio", "0.016%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "-5.154"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$23000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-51177.748"},
{"Return Over Maximum Drawdown", "-14.362"},
{"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", "177477b78d9264384a09f1607e8c7d11"}
};
}
}

View File

@@ -0,0 +1,234 @@
/*
* 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 In The Money (ITM) index option expiry for puts.
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, buy ES Put Option (expiring ITM) (buy, qty 1)
/// * Option exercise, receiving cash (sell, qty -1)
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
public class IndexOptionPutITMExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
private Symbol _expectedContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select a index option expiring ITM, and adds it to the algorithm.
_spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice >= 4200m && x.ID.OptionRight == OptionRight.Put && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderBy(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute).Symbol;
_expectedContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Put, 4200m, new DateTime(2021, 1, 15));
if (_spxOption != _expectedContract)
{
throw new Exception($"Contract {_expectedContract} was not found in the chain");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(_spx, 1), () =>
{
MarketOrder(_spxOption, 1);
});
}
public override void OnData(Slice data)
{
// Assert delistings, so that we can make sure that we receive the delisting warnings at
// the expected time. These assertions detect bug #4872
foreach (var delisting in data.Delistings.Values)
{
if (delisting.Type == DelistingType.Warning)
{
if (delisting.Time != new DateTime(2021, 1, 15))
{
throw new Exception($"Delisting warning issued at unexpected date: {delisting.Time}");
}
}
if (delisting.Type == DelistingType.Delisted)
{
if (delisting.Time != new DateTime(2021, 1, 16))
{
throw new Exception($"Delisting happened at unexpected date: {delisting.Time}");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status != OrderStatus.Filled)
{
// There's lots of noise with OnOrderEvent, but we're only interested in fills.
return;
}
if (!Securities.ContainsKey(orderEvent.Symbol))
{
throw new Exception($"Order event Symbol not found in Securities collection: {orderEvent.Symbol}");
}
var security = Securities[orderEvent.Symbol];
if (security.Symbol == _spx)
{
AssertIndexOptionOrderExercise(orderEvent, security, Securities[_expectedContract]);
}
else if (security.Symbol == _expectedContract)
{
AssertIndexOptionContractOrder(orderEvent, security);
}
else
{
throw new Exception($"Received order event for unknown Symbol: {orderEvent.Symbol}");
}
Log($"{Time:yyyy-MM-dd HH:mm:ss} -- {orderEvent.Symbol} :: Price: {Securities[orderEvent.Symbol].Holdings.Price} Qty: {Securities[orderEvent.Symbol].Holdings.Quantity} Direction: {orderEvent.Direction} Msg: {orderEvent.Message}");
}
private void AssertIndexOptionOrderExercise(OrderEvent orderEvent, Security index, Security optionContract)
{
var expectedLiquidationTimeUtc = new DateTime(2021, 1, 15);
if (orderEvent.Direction == OrderDirection.Buy && orderEvent.UtcTime != expectedLiquidationTimeUtc)
{
throw new Exception($"Liquidated index option contract, but not at the expected time. Expected: {expectedLiquidationTimeUtc:yyyy-MM-dd HH:mm:ss} - found {orderEvent.UtcTime:yyyy-MM-dd HH:mm:ss}");
}
// No way to detect option exercise orders or any other kind of special orders
// other than matching strings, for now.
if (orderEvent.Message.Contains("Option Exercise"))
{
if (orderEvent.FillPrice != 3300m)
{
throw new Exception("Option did not exercise at expected strike price (3300)");
}
if (optionContract.Holdings.Quantity != 0)
{
throw new Exception($"Exercised option contract, but we have holdings for Option contract {optionContract.Symbol}");
}
}
}
private void AssertIndexOptionContractOrder(OrderEvent orderEvent, Security option)
{
if (orderEvent.Direction == OrderDirection.Buy && option.Holdings.Quantity != 1)
{
throw new Exception($"No holdings were created for option contract {option.Symbol}");
}
if (orderEvent.Direction == OrderDirection.Sell && option.Holdings.Quantity != 0)
{
throw new Exception($"Holdings were found after a filled option exercise");
}
if (orderEvent.Message.Contains("Exercise") && option.Holdings.Quantity != 0)
{
throw new Exception($"Holdings were found after exercising option contract {option.Symbol}");
}
}
/// <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)}");
}
}
/// <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", "-51.53%"},
{"Compounding Annual Return", "-81.170%"},
{"Drawdown", "13.800%"},
{"Expectancy", "-1"},
{"Net Profit", "-11.084%"},
{"Sharpe Ratio", "-1.894"},
{"Probabilistic Sharpe Ratio", "0.621%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.398"},
{"Annual Variance", "0.158"},
{"Information Ratio", "-1.894"},
{"Tracking Error", "0.398"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0.005"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.662"},
{"Return Over Maximum Drawdown", "-7.157"},
{"Portfolio Turnover", "0.025"},
{"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", "f2d98f952cc0b54fb620795018682105"}
};
}
}

View File

@@ -0,0 +1,218 @@
/*
* 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 Out of The Money (OTM) index option expiry for puts.
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, buy SPX Put Option (expiring OTM)
/// - contract expires worthless, not exercised, so never opened a position in the underlying
///
/// * Liquidation of worthless SPX Put OTM contract
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
/// <remarks>
/// Total Trades in regression algorithm should be 1, but expiration is counted as a trade.
/// </remarks>
public class IndexOptionPutOTMExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
private Symbol _expectedContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select a index option expiring ITM, and adds it to the algorithm.
_spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice <= 3200m && x.ID.OptionRight == OptionRight.Put && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderByDescending(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute).Symbol;
_expectedContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Put, 3200m, new DateTime(2021, 1, 15));
if (_spxOption != _expectedContract)
{
throw new Exception($"Contract {_expectedContract} was not found in the chain");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(_spx, 1), () =>
{
MarketOrder(_spxOption, 1);
});
}
public override void OnData(Slice data)
{
// Assert delistings, so that we can make sure that we receive the delisting warnings at
// the expected time. These assertions detect bug #4872
foreach (var delisting in data.Delistings.Values)
{
if (delisting.Type == DelistingType.Warning)
{
if (delisting.Time != new DateTime(2021, 1, 15))
{
throw new Exception($"Delisting warning issued at unexpected date: {delisting.Time}");
}
}
if (delisting.Type == DelistingType.Delisted)
{
if (delisting.Time != new DateTime(2021, 1, 16))
{
throw new Exception($"Delisting happened at unexpected date: {delisting.Time}");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status != OrderStatus.Filled)
{
// There's lots of noise with OnOrderEvent, but we're only interested in fills.
return;
}
if (!Securities.ContainsKey(orderEvent.Symbol))
{
throw new Exception($"Order event Symbol not found in Securities collection: {orderEvent.Symbol}");
}
var security = Securities[orderEvent.Symbol];
if (security.Symbol == _spx)
{
throw new Exception("Invalid state: did not expect a position for the underlying to be opened, since this contract expires OTM and is not tradable");
}
if (security.Symbol == _expectedContract)
{
AssertIndexOptionContractOrder(orderEvent, security);
}
else
{
throw new Exception($"Received order event for unknown Symbol: {orderEvent.Symbol}");
}
Log($"{orderEvent}");
}
private void AssertIndexOptionContractOrder(OrderEvent orderEvent, Security option)
{
if (orderEvent.Direction == OrderDirection.Buy && option.Holdings.Quantity != 1)
{
throw new Exception($"No holdings were created for option contract {option.Symbol}");
}
if (orderEvent.Direction == OrderDirection.Sell && option.Holdings.Quantity != 0)
{
throw new Exception("Holdings were found after a filled option exercise");
}
if (orderEvent.Direction == OrderDirection.Sell && !orderEvent.Message.Contains("OTM"))
{
throw new Exception("Contract did not expire OTM");
}
if (orderEvent.Message.Contains("Exercise"))
{
throw new Exception("Exercised option, even though it expires OTM");
}
}
/// <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)}");
}
}
/// <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.37%"},
{"Compounding Annual Return", "-5.132%"},
{"Drawdown", "0.400%"},
{"Expectancy", "-1"},
{"Net Profit", "-0.370%"},
{"Sharpe Ratio", "-3.622"},
{"Probabilistic Sharpe Ratio", "0.270%"},
{"Loss Rate", "100%"},
{"Win Rate", "0%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.013"},
{"Annual Variance", "0"},
{"Information Ratio", "-3.622"},
{"Tracking Error", "0.013"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-1.628"},
{"Return Over Maximum Drawdown", "-14.021"},
{"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", "6faffe52c64c2148458af1d2deb68a6f"}
};
}
}

View File

@@ -0,0 +1,220 @@
/*
* 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 In The Money (ITM) index option expiry for short calls.
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, sell SPX Call Option (expiring ITM)
/// * Option assignment
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
public class IndexOptionShortCallITMExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _esOption;
private Symbol _expectedContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select a index option expiring ITM, and adds it to the algorithm.
_esOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice <= 3200m && x.ID.OptionRight == OptionRight.Call && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderByDescending(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute).Symbol;
_expectedContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Call, 3200m, new DateTime(2021, 1, 15));
if (_esOption != _expectedContract)
{
throw new Exception($"Contract {_expectedContract} was not found in the chain");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(_spx, 1), () =>
{
MarketOrder(_esOption, -1);
});
}
public override void OnData(Slice data)
{
// Assert delistings, so that we can make sure that we receive the delisting warnings at
// the expected time. These assertions detect bug #4872
foreach (var delisting in data.Delistings.Values)
{
if (delisting.Type == DelistingType.Warning)
{
if (delisting.Time != new DateTime(2021, 1, 15))
{
throw new Exception($"Delisting warning issued at unexpected date: {delisting.Time}");
}
}
if (delisting.Type == DelistingType.Delisted)
{
if (delisting.Time != new DateTime(2021, 1, 16))
{
throw new Exception($"Delisting happened at unexpected date: {delisting.Time}");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status != OrderStatus.Filled)
{
// There's lots of noise with OnOrderEvent, but we're only interested in fills.
return;
}
if (!Securities.ContainsKey(orderEvent.Symbol))
{
throw new Exception($"Order event Symbol not found in Securities collection: {orderEvent.Symbol}");
}
var security = Securities[orderEvent.Symbol];
if (security.Symbol == _spx)
{
AssertIndexOptionOrderExercise(orderEvent, security, Securities[_expectedContract]);
}
else if (security.Symbol == _expectedContract)
{
AssertIndexOptionContractOrder(orderEvent, security);
}
else
{
throw new Exception($"Received order event for unknown Symbol: {orderEvent.Symbol}");
}
Log($"{orderEvent}");
}
private void AssertIndexOptionOrderExercise(OrderEvent orderEvent, Security index, Security optionContract)
{
if (orderEvent.Message.Contains("Assignment"))
{
if (orderEvent.FillPrice != 3200m)
{
throw new Exception("Option was not assigned at expected strike price (3200)");
}
if (orderEvent.Direction != OrderDirection.Sell || index.Holdings.Quantity != 0)
{
throw new Exception($"Expected Qty: 0 index holdings for assigned index option {index.Symbol}, found {index.Holdings.Quantity}");
}
}
}
private void AssertIndexOptionContractOrder(OrderEvent orderEvent, Security option)
{
if (orderEvent.Direction == OrderDirection.Sell && option.Holdings.Quantity != -1)
{
throw new Exception($"No holdings were created for option contract {option.Symbol}");
}
if (orderEvent.IsAssignment && option.Holdings.Quantity != 0)
{
throw new Exception($"Holdings were found after option contract was assigned: {option.Symbol}");
}
}
/// <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)}");
}
}
/// <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", "48.82%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "-80.089%"},
{"Drawdown", "13.400%"},
{"Expectancy", "0"},
{"Net Profit", "-10.734%"},
{"Sharpe Ratio", "-1.928"},
{"Probabilistic Sharpe Ratio", "0.619%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.385"},
{"Annual Variance", "0.148"},
{"Information Ratio", "-1.928"},
{"Tracking Error", "0.385"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0.005"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.676"},
{"Return Over Maximum Drawdown", "-7.289"},
{"Portfolio Turnover", "0.024"},
{"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", "439042b39981ea246e50728cc57c31c7"}
};
}
}

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.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 Out of The Money (OTM) index option expiry for short calls.
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, sell SPX Call Option (expiring OTM)
/// - Profit the option premium, since the option was not assigned.
///
/// * Liquidation of SPX call OTM contract on the last trade date
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
public class IndexOptionShortCallOTMExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
private Symbol _expectedContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select a index option expiring ITM, and adds it to the algorithm.
_spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice >= 4250m && x.ID.OptionRight == OptionRight.Call && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderBy(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute).Symbol;
_expectedContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Call, 4250m, new DateTime(2021, 1, 15));
if (_spxOption != _expectedContract)
{
throw new Exception($"Contract {_expectedContract} was not found in the chain");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(_spx, 1), () =>
{
MarketOrder(_spxOption, -1);
});
}
public override void OnData(Slice data)
{
// Assert delistings, so that we can make sure that we receive the delisting warnings at
// the expected time. These assertions detect bug #4872
foreach (var delisting in data.Delistings.Values)
{
if (delisting.Type == DelistingType.Warning)
{
if (delisting.Time != new DateTime(2021, 1, 15))
{
throw new Exception($"Delisting warning issued at unexpected date: {delisting.Time}");
}
}
if (delisting.Type == DelistingType.Delisted)
{
if (delisting.Time != new DateTime(2021, 1, 16))
{
throw new Exception($"Delisting happened at unexpected date: {delisting.Time}");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status != OrderStatus.Filled)
{
// There's lots of noise with OnOrderEvent, but we're only interested in fills.
return;
}
if (!Securities.ContainsKey(orderEvent.Symbol))
{
throw new Exception($"Order event Symbol not found in Securities collection: {orderEvent.Symbol}");
}
var security = Securities[orderEvent.Symbol];
if (security.Symbol == _spx)
{
throw new Exception($"Expected no order events for underlying Symbol {security.Symbol}");
}
if (security.Symbol == _expectedContract)
{
AssertIndexOptionContractOrder(orderEvent, security);
}
else
{
throw new Exception($"Received order event for unknown Symbol: {orderEvent.Symbol}");
}
Log($"{orderEvent}");
}
private void AssertIndexOptionContractOrder(OrderEvent orderEvent, Security optionContract)
{
if (orderEvent.Direction == OrderDirection.Sell && optionContract.Holdings.Quantity != -1)
{
throw new Exception($"No holdings were created for option contract {optionContract.Symbol}");
}
if (orderEvent.Direction == OrderDirection.Buy && optionContract.Holdings.Quantity != 0)
{
throw new Exception("Expected no options holdings after closing position");
}
if (orderEvent.IsAssignment)
{
throw new Exception($"Assignment was not expected for {orderEvent.Symbol}");
}
}
/// <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)}");
}
}
/// <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.01%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "0.142%"},
{"Drawdown", "0%"},
{"Expectancy", "0"},
{"Net Profit", "0.010%"},
{"Sharpe Ratio", "5.161"},
{"Probabilistic Sharpe Ratio", "99.241%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0"},
{"Annual Variance", "0"},
{"Information Ratio", "5.161"},
{"Tracking Error", "0"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$23000.00"},
{"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", "b55e2b2bd35bc3200e228b4e6e77dd90"}
};
}
}

View File

@@ -0,0 +1,224 @@
/*
* 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 In The Money (ITM) index option expiry for short puts.
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, sell SPX Put Option (expiring ITM)
/// * Option assignment
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
public class IndexOptionShortPutITMExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
private Symbol _expectedContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select a index option expiring ITM, and adds it to the algorithm.
_spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice <= 4200m && x.ID.OptionRight == OptionRight.Put && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderByDescending(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute).Symbol;
_expectedContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Put, 4200m, new DateTime(2021, 1, 15));
if (_spxOption != _expectedContract)
{
throw new Exception($"Contract {_expectedContract} was not found in the chain");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(_spx, 1), () =>
{
MarketOrder(_spxOption, -1);
});
}
public override void OnData(Slice data)
{
// Assert delistings, so that we can make sure that we receive the delisting warnings at
// the expected time. These assertions detect bug #4872
foreach (var delisting in data.Delistings.Values)
{
if (delisting.Type == DelistingType.Warning)
{
if (delisting.Time != new DateTime(2021, 1, 15))
{
throw new Exception($"Delisting warning issued at unexpected date: {delisting.Time}");
}
}
if (delisting.Type == DelistingType.Delisted)
{
if (delisting.Time != new DateTime(2021, 1, 16))
{
throw new Exception($"Delisting happened at unexpected date: {delisting.Time}");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status != OrderStatus.Filled)
{
// There's lots of noise with OnOrderEvent, but we're only interested in fills.
return;
}
if (!Securities.ContainsKey(orderEvent.Symbol))
{
throw new Exception($"Order event Symbol not found in Securities collection: {orderEvent.Symbol}");
}
var security = Securities[orderEvent.Symbol];
if (security.Symbol == _spx)
{
AssertIndexOptionOrderExercise(orderEvent, security, Securities[_expectedContract]);
}
else if (security.Symbol == _expectedContract)
{
AssertIndexOptionContractOrder(orderEvent, security);
}
else
{
throw new Exception($"Received order event for unknown Symbol: {orderEvent.Symbol}");
}
Log($"{orderEvent}");
}
private void AssertIndexOptionOrderExercise(OrderEvent orderEvent, Security index, Security optionContract)
{
if (orderEvent.Message.Contains("Assignment"))
{
if (orderEvent.FillPrice != 4200)
{
throw new Exception("Option was not assigned at expected strike price (4200)");
}
if (orderEvent.Direction != OrderDirection.Buy || index.Holdings.Quantity != 0)
{
throw new Exception($"Expected Qty: 0 index holdings for assigned index option {index.Symbol}, found {index.Holdings.Quantity}");
}
}
else if (index.Holdings.Quantity != 0)
{
throw new Exception($"Expected no holdings in index: {index.Symbol}");
}
}
private void AssertIndexOptionContractOrder(OrderEvent orderEvent, Security option)
{
if (orderEvent.Direction == OrderDirection.Sell && option.Holdings.Quantity != -1)
{
throw new Exception($"No holdings were created for option contract {option.Symbol}");
}
if (orderEvent.IsAssignment && option.Holdings.Quantity != 0)
{
throw new Exception($"Holdings were found after option contract was assigned: {option.Symbol}");
}
}
/// <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)}");
}
}
/// <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", "51.07%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "319.986%"},
{"Drawdown", "2.400%"},
{"Expectancy", "0"},
{"Net Profit", "10.624%"},
{"Sharpe Ratio", "7.1"},
{"Probabilistic Sharpe Ratio", "89.813%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.398"},
{"Annual Variance", "0.159"},
{"Information Ratio", "7.1"},
{"Tracking Error", "0.398"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0.025"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "634.943"},
{"Return Over Maximum Drawdown", "1184.633"},
{"Portfolio Turnover", "0.025"},
{"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", "f243341674cb1486d7cf009d74d4e6ff"}
};
}
}

View File

@@ -0,0 +1,211 @@
/*
* 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 Out of The Money (OTM) index option expiry for short puts.
/// We expect 2 order from the algorithm, which are:
///
/// * Initial entry, sell SPX Put Option (expiring OTM)
/// - Profit the option premium, since the option was not assigned.
///
/// * Liquidation of SPX put OTM contract on the last trade date
///
/// Additionally, we test delistings for index options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
public class IndexOptionShortPutOTMExpiryRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private Symbol _spx;
private Symbol _spxOption;
private Symbol _expectedContract;
public override void Initialize()
{
SetStartDate(2021, 1, 4);
SetEndDate(2021, 1, 31);
_spx = AddIndex("SPX", Resolution.Minute).Symbol;
// Select a index option expiring ITM, and adds it to the algorithm.
_spxOption = AddIndexOptionContract(OptionChainProvider.GetOptionContractList(_spx, Time)
.Where(x => x.ID.StrikePrice <= 3200m && x.ID.OptionRight == OptionRight.Put && x.ID.Date.Year == 2021 && x.ID.Date.Month == 1)
.OrderByDescending(x => x.ID.StrikePrice)
.Take(1)
.Single(), Resolution.Minute).Symbol;
_expectedContract = QuantConnect.Symbol.CreateOption(_spx, Market.USA, OptionStyle.European, OptionRight.Put, 3200m, new DateTime(2021, 1, 15));
if (_spxOption != _expectedContract)
{
throw new Exception($"Contract {_expectedContract} was not found in the chain");
}
Schedule.On(DateRules.Tomorrow, TimeRules.AfterMarketOpen(_spx, 1), () =>
{
MarketOrder(_spxOption, -1);
});
}
public override void OnData(Slice data)
{
// Assert delistings, so that we can make sure that we receive the delisting warnings at
// the expected time. These assertions detect bug #4872
foreach (var delisting in data.Delistings.Values)
{
if (delisting.Type == DelistingType.Warning)
{
if (delisting.Time != new DateTime(2021, 1, 15))
{
throw new Exception($"Delisting warning issued at unexpected date: {delisting.Time}");
}
}
if (delisting.Type == DelistingType.Delisted)
{
if (delisting.Time != new DateTime(2021, 1, 16))
{
throw new Exception($"Delisting happened at unexpected date: {delisting.Time}");
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Status != OrderStatus.Filled)
{
// There's lots of noise with OnOrderEvent, but we're only interested in fills.
return;
}
if (!Securities.ContainsKey(orderEvent.Symbol))
{
throw new Exception($"Order event Symbol not found in Securities collection: {orderEvent.Symbol}");
}
var security = Securities[orderEvent.Symbol];
if (security.Symbol == _spx)
{
throw new Exception($"Expected no order events for underlying Symbol {security.Symbol}");
}
if (security.Symbol == _expectedContract)
{
AssertIndexOptionContractOrder(orderEvent, security);
}
else
{
throw new Exception($"Received order event for unknown Symbol: {orderEvent.Symbol}");
}
Log($"{orderEvent}");
}
private void AssertIndexOptionContractOrder(OrderEvent orderEvent, Security option)
{
if (orderEvent.Direction == OrderDirection.Sell && option.Holdings.Quantity != -1)
{
throw new Exception($"No holdings were created for option contract {option.Symbol}");
}
if (orderEvent.Direction == OrderDirection.Buy && option.Holdings.Quantity != 0)
{
throw new Exception("Expected no options holdings after closing position");
}
if (orderEvent.IsAssignment)
{
throw new Exception($"Assignment was not expected for {orderEvent.Symbol}");
}
}
/// <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)}");
}
}
/// <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.35%"},
{"Average Loss", "0%"},
{"Compounding Annual Return", "5.091%"},
{"Drawdown", "0.000%"},
{"Expectancy", "0"},
{"Net Profit", "0.350%"},
{"Sharpe Ratio", "3.573"},
{"Probabilistic Sharpe Ratio", "91.608%"},
{"Loss Rate", "0%"},
{"Win Rate", "100%"},
{"Profit-Loss Ratio", "0"},
{"Alpha", "0"},
{"Beta", "0"},
{"Annual Standard Deviation", "0.013"},
{"Annual Variance", "0"},
{"Information Ratio", "3.573"},
{"Tracking Error", "0.013"},
{"Treynor Ratio", "0"},
{"Total Fees", "$0.00"},
{"Estimated Strategy Capacity", "$0"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "514.964"},
{"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", "636b79bb5bf3db20eeda02ccf1064d07"}
};
}
}

View File

@@ -158,8 +158,10 @@ namespace QuantConnect.Algorithm.CSharp
/// <summary>
/// Fire plotting events once per day.
/// </summary>
public override void OnEndOfDay()
public override void OnEndOfDay(Symbol symbol)
{
if (symbol != _symbol) return;
if (!_indicators.BB.IsReady) return;
Plot("BB", "Price", _price);
@@ -261,7 +263,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.146"},
{"Treynor Ratio", "-2.677"},
{"Total Fees", "$1.00"},
{"Estimated Strategy Capacity", "$75000000.00"},
{"Estimated Strategy Capacity", "$530000000.00"},
{"Fitness Score", "0.001"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -94,7 +94,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.165"},
{"Treynor Ratio", "1.212"},
{"Total Fees", "$6.00"},
{"Estimated Strategy Capacity", "$32000000.00"},
{"Estimated Strategy Capacity", "$42000000.00"},
{"Fitness Score", "0.063"},
{"Kelly Criterion Estimate", "38.64"},
{"Kelly Criterion Probability Value", "0.229"},

View File

@@ -102,7 +102,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0"},
{"Treynor Ratio", "1.925"},
{"Total Fees", "$61.90"},
{"Estimated Strategy Capacity", "$2900000.00"},
{"Estimated Strategy Capacity", "$5800000.00"},
{"Fitness Score", "0.979"},
{"Kelly Criterion Estimate", "38.64"},
{"Kelly Criterion Probability Value", "0.229"},

View File

@@ -100,7 +100,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.196"},
{"Treynor Ratio", "-0.169"},
{"Total Fees", "$34.00"},
{"Estimated Strategy Capacity", "$460000000.00"},
{"Estimated Strategy Capacity", "$180000000.00"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -145,7 +145,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.22"},
{"Treynor Ratio", "3.431"},
{"Total Fees", "$3.00"},
{"Estimated Strategy Capacity", "$480000000.00"},
{"Estimated Strategy Capacity", "$1900000000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.004"},
{"Treynor Ratio", "1.577"},
{"Total Fees", "$293.06"},
{"Estimated Strategy Capacity", "$19000000.00"},
{"Estimated Strategy Capacity", "$14000000.00"},
{"Fitness Score", "0.999"},
{"Kelly Criterion Estimate", "-6.994"},
{"Kelly Criterion Probability Value", "0.593"},

View File

@@ -118,7 +118,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.214"},
{"Treynor Ratio", "-0.774"},
{"Total Fees", "$443.74"},
{"Estimated Strategy Capacity", "$110000000.00"},
{"Estimated Strategy Capacity", "$750000000.00"},
{"Fitness Score", "0.013"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -135,7 +135,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.224"},
{"Treynor Ratio", "3.851"},
{"Total Fees", "$26.01"},
{"Estimated Strategy Capacity", "$11000000.00"},
{"Estimated Strategy Capacity", "$22000000.00"},
{"Fitness Score", "0.999"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

View File

@@ -105,7 +105,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Tracking Error", "0.346"},
{"Treynor Ratio", "-0.863"},
{"Total Fees", "$13.69"},
{"Estimated Strategy Capacity", "$1800000.00"},
{"Estimated Strategy Capacity", "$13000000.00"},
{"Fitness Score", "0"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},

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