Compare commits

...

26 Commits

Author SHA1 Message Date
Colton Sellers
4006ba01e4 Reduce Travis Log (#5039)
* Reduce Travis setup verbosity

* Introduce ConsoleErrorLogHandler

* Change Console.WriteLine to Log statements

* Quiet wget

* Route build stubs stdout to null

* Fix Quantbook history test

* Silence stub packages directly

* Use parameterized log-handler for testing

* Rename AssemblyInitialize Setup

* Fix AlgorithmRunner file logging

* Drop all overriden LogHandlers in tests

* Change to OneTimeSetup to maintain LogHandlers

* Permit any ILogHandler to be defined in params

* Fix for AlgorithmRunner Handlers V2
2020-12-17 12:59:13 -03:00
Martin-Molinero
6d824b40a6 Add handling for custom host name (#5043)
* Add handling for custom host name

* Credit cost as decimal
2020-12-16 21:54:00 -03:00
Colton Sellers
8e410fcaf1 Update old Hourly/Daily data for ApiDataProvider (#5034)
* Update old Hourly/Daily data for ApiDataProvider

* Add unit test for IsOutOfDate

* Address review

* Fix reference to static function in test
2020-12-16 19:04:06 -03:00
Adalyat Nazirov
d136428556 ignore *.DotSettings files (#5035)
This layer is designated for common settings that enforce your team preferences for the current solution.
Since we don't have specific resharper settings we want to share within the team we ignore this file
2020-12-16 12:38:01 -03:00
Gerardo Salazar
40d81965be Adds debug logging for MapSymbol(...) method in IB Brokerage (#5040) 2020-12-15 17:44:00 -08:00
Aaron Janeiro Stone
c650eb6c1c Adds DeM indicator (#5002)
* Adds DeM indicator

* Added reference to param movingaverage type

* Fixed variable declarations

* Added nameless initialize

* Missing DeM "type" args added

* Missing DeM "type" args added

* refactor

* Undid _previousInput → protected

* Demarker symbol: DeM →DEM

* Symbol change: DeM → DEM

* Updated symbols

TestDivByZero originally had dem as cmf.

* Symbol: DeM →DEM

Co-authored-by: Alexandre Catarino <AlexCatarino@users.noreply.github.com>
2020-12-15 08:29:55 -03:00
Charles Naccio
aa2f9f927a Fixed QuantBook import path for CSharp example (#5028)
Now requires a relative path for loading QuantBook.csx
2020-12-14 21:22:22 -03:00
Charles Naccio
c698a65a84 Replaced obsolete Gitter badge with Slack (#5031) 2020-12-14 12:55:35 -03:00
Charles Naccio
181283a4cd Noted Polygon downloaded in Readme (#5025) 2020-12-11 16:55:58 -08:00
Martin-Molinero
b247724a34 Improve Optimizer runtime statistics (#5024)
- Adding optimization Id to backtests packets
- SeriesSampler will allow truncating the samples
- Removing OptimizationEstimate, simplifying getting estimate and
  runtime stats separatly
2020-12-11 16:39:13 -08:00
Gerardo Salazar
dde3576161 Fixes intraday delistings not occurring before contract expiry for Futures and FOPs (#5007)
* Fixes intraday delistings not occurring for Futures and FOPs

  * Previously, we would wait until the next market open to
    liquidate futures and futures options contracts. Since these
    contracts can not be traded at the next market open and require
    intraday delisting, changes were made to liquidate at the first
    available place where we know the market is open. This means
    we now liquidate futures and FOPs intraday as a market order.

  * Maintains backwards compatability with equities and equity options
    delisting behavior

* Addresses review: adds additional protections for ProcessDelistedSymbols

  * We choose to adjust the delisting date to the next market open only
    if the market is not open at the current time, otherwise the time
    would have been adjusted to the market open of the next trading day

* Addresses review: reverts changes and fixes error message in regression algo
2020-12-11 20:46:56 -03:00
Gerardo Salazar
e8734a0797 Adds/Fixes Futures Options History Research Support (#5013)
* Adds Futures Options History Research Support

* Address review: make canonical future throw when calling GetOptionHistory

* Improve error message, recommending users to user FutureChainProvider
2020-12-11 20:46:41 -03:00
Aaron Janeiro Stone
7f5d69bbec Adds the Awesome Oscillator (#5005)
* Adds the awesome oscillator.

* added missing type hint for AO

* cleaned initializations

* refactor in call for AO(fast,slow,type)

* added missing type parameter for AO

* Changes AO sub-indicators to public.

Co-authored-by: Alexandre Catarino <AlexCatarino@users.noreply.github.com>
2020-12-11 20:46:07 -03:00
Colton Sellers
f6be7a41a5 Bug python runtime issue with local report generation (#5014)
* Fixed Python runtime issue that was occurring when trying to generate reports locally on OSX/mono, but assume the issue impacts all configurations.

* Move Python.Runtime config to common

* Remove duplicate files

* Update readme

* Typo

* Change destination in build directory

Co-authored-by: Charles Naccio <cnaccio@gmail.com>
2020-12-11 20:45:26 -03:00
Stefano Raggi
7f30c0cd00 Downgrade IB error codes from Warning to Information (#5015) 2020-12-11 18:53:25 -03:00
Colton Sellers
6694fe01f8 Api Chart Hotfix (#5023)
* Api Chart Hotfix

* Use IsNullOrEmpty
2020-12-11 18:43:18 -03:00
Aaron Janeiro Stone
32ab4fdea1 Adds ChaikinMoneyFlow indicator (#4986)
* Added CMF indicator

CMF is a volume-weighted average of accumulation and distribution over a period.

* Added initializer for CMF

Registration for ChaikinMoneyFlow implemented.

* Added CMF tests.

* Added CMF tests.

* spy_cmf.txt changed to external indicator data.

* Implement suggestions of @AlexCatarino

* added sum terms as subindicators.

* added sum terms as subindicators.

* Removal of vestigial rolling window

* Minor nit changes

Co-authored-by: Martin Molinero <martin.molinero1@gmail.com>
2020-12-11 18:04:17 -03:00
Colton Sellers
fc81f606e4 Reserve Names for Pandas Mapper (#4978)
* Fix for #4886 and unit test

* Fix test function

* Address review

* Clarify comments
2020-12-11 16:39:13 -03:00
Stefano Raggi
ec74abd4d0 Fix Bitfinex brokerage currency mapping (#5011) 2020-12-11 16:12:57 -03:00
Colton Sellers
bd3ead3480 ApiDataProvider Zip Download Fixes (#5020)
* Stop non zip responses from being saved as a zip

* Capture and log message

* Log as Error
2020-12-11 16:01:57 -03:00
Colton Sellers
45849962a3 Readme expansion and additional VS build tasks (#5018) 2020-12-11 14:49:29 -03:00
Gerardo Salazar
8279cf7eac Improve exception message for indicators using Update(DateTime, decimal) (#5019) 2020-12-11 14:36:42 -03:00
Colton Sellers
4c4a699cb0 Stop Emitting Insights on Delisted Securities (#4997)
* Verify insights are valid before emitting

* nit

* Address review

* Address review and unit tests

* nit - remove extra lines

* Address review

* Initialize insight fields
2020-12-10 11:44:37 -03:00
Colton Sellers
31a2c31c0a Api Update November 2020 (#4981)
* WIP Backtest adjustments

* Workaround awaiting changes

* Adjustments to API Changes

* Nit fix

* Custom Newtonsoft Deserializer for AlphaRuntimeStatistics

* Workaround Travis build error

* Drop AlphaRuntimeStatistics converter; use Decimal converter

* Use StringDecimalJsonConverter

* Undo set properties

* Add more members to de-serializer class
2020-12-09 16:51:58 -03:00
Jared
877a123276 Update readme.md 2020-12-08 12:26:21 -08:00
Gerardo Salazar
4134b05bfd Fixes options order crash in ReportGenerator/PortfolioLooper (#4992) 2020-12-07 12:39:53 -03:00
126 changed files with 6564 additions and 464 deletions

1
.gitignore vendored
View File

@@ -144,6 +144,7 @@ $tf/
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings
*.DotSettings.user
# JustCode is a .NET coding addin-in

View File

@@ -5,7 +5,7 @@ mono:
solution: QuantConnect.Lean.sln
before_install:
- export PATH="$HOME/miniconda3/bin:$PATH"
- wget https://cdn.quantconnect.com/miniconda/Miniconda3-4.5.12-Linux-x86_64.sh
- 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
- sudo ln -s $HOME/miniconda3/lib/libpython3.6m.so /usr/lib/libpython3.6m.so
@@ -17,10 +17,10 @@ before_install:
- conda install -y scipy=1.4.1
- conda install -y wrapt=1.12.1
install:
- nuget restore QuantConnect.Lean.sln
- nuget restore QuantConnect.Lean.sln -v quiet
- nuget install NUnit.Runners -Version 3.11.1 -OutputDirectory testrunner
script:
- msbuild /p:Configuration=Release /p:VbcToolExe=vbnc.exe 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
- msbuild /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
- sudo -E ./ci_build_stubs.sh -d -t -g -p

15
.vscode/readme.md vendored
View File

@@ -13,7 +13,7 @@ Before anything we need to ensure a few things have been done:
1. Get [Visual Studio Code](https://code.visualstudio.com/download)
* Get the Extension [Mono Debug](https://marketplace.visualstudio.com/items?itemName=ms-vscode.mono-debug) for C# Debugging
* Get the Extension [Mono Debug **15.8**](https://marketplace.visualstudio.com/items?itemName=ms-vscode.mono-debug) for C# Debugging
* Get the Extension [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) for Python Debugging
2. Get [Docker](https://docs.docker.com/get-docker/):
@@ -35,7 +35,8 @@ Before anything we need to ensure a few things have been done:
* Download the repo or clone it using: _git clone[ https://github.com/QuantConnect/Lean](https://github.com/QuantConnect/Lean)_
* Open the folder using VS Code
**NOTES**:
- Mono Extension Version 16 and greater fails to debug the docker container remotely, please install **Version 15.8**. To install an older version from within VS Code go to the extensions tab, search "Mono Debug", and select "Install Another Version...".
<br />
<h1>Develop Algorithms Locally, Run in Container</h1>
@@ -112,6 +113,12 @@ In VS Code click on the debug/run icon on the left toolbar, at the top you shoul
As defaults these are all great! Feel free to change them as needed for your setup.
**NOTE:** VSCode may try and throw errors when launching this way regarding build on `QuantConnect.csx` and `Config.json` these errors can be ignored by selecting "*Debug Anyway*". To stop this error message in the future select "*Remember my choice in user settings*".
If using C# algorithms ensure that msbuild can build them successfully.
<br />
<h3>Option 2</h3>
@@ -194,4 +201,6 @@ _Figure 2: Python Debugger Messages_
<h1>Common Issues</h1>
Here we will cover some common issues with setting this up. This section will expand as we get user feedback!
* Error messages about build in VSCode points to comments in JSON. Either select **ignore** or follow steps described [here](https://stackoverflow.com/questions/47834825/in-vs-code-disable-error-comments-are-not-permitted-in-json) to remove the errors entirely.
* Any error messages about building in VSCode that point to comments in JSON. Either select **ignore** or follow steps described [here](https://stackoverflow.com/questions/47834825/in-vs-code-disable-error-comments-are-not-permitted-in-json) to remove the errors entirely.
* `Errors exist after running preLaunchTask 'run-docker'`This VSCode error appears to warn you of CSharp errors when trying to use `Debug in Container` select "Debug Anyway" as the errors are false flags for JSON comments as well as `QuantConnect.csx` not finding references. Neither of these will impact your debugging.
* `The container name "/LeanEngine" is already in use by container "****"` This Docker error implies that another instance of lean is already running under the container name /LeanEngine. If this error appears either use Docker Desktop to delete the container or use `docker kill LeanEngine` from the command line.

28
.vscode/tasks.json vendored
View File

@@ -20,6 +20,34 @@
},
"problemMatcher": "$msCompile"
},
{
"label": "rebuild",
"type": "shell",
"command": "msbuild",
"args": [
"/p:Configuration=Debug",
"/p:DebugType=portable",
"/t:rebuild",
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "clean",
"type": "shell",
"command": "msbuild",
"args": [
"/t:clean",
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "force build linux",
"type": "shell",

View File

@@ -132,7 +132,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "-1252326142"}
{"OrderListHash", "490786648"}
};
}
}

View File

@@ -124,30 +124,30 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "6"},
{"Average Win", "2.94%"},
{"Average Win", "2.93%"},
{"Average Loss", "-4.15%"},
{"Compounding Annual Return", "-5.601%"},
{"Drawdown", "5.600%"},
{"Expectancy", "-0.146"},
{"Net Profit", "-2.771%"},
{"Sharpe Ratio", "-0.49"},
{"Probabilistic Sharpe Ratio", "10.583%"},
{"Compounding Annual Return", "-5.663%"},
{"Drawdown", "5.700%"},
{"Expectancy", "-0.148"},
{"Net Profit", "-2.802%"},
{"Sharpe Ratio", "-0.495"},
{"Probabilistic Sharpe Ratio", "10.470%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.71"},
{"Profit-Loss Ratio", "0.70"},
{"Alpha", "-0.043"},
{"Beta", "-0.001"},
{"Annual Standard Deviation", "0.087"},
{"Annual Variance", "0.008"},
{"Information Ratio", "0.96"},
{"Information Ratio", "0.957"},
{"Tracking Error", "0.192"},
{"Treynor Ratio", "58.394"},
{"Treynor Ratio", "57.633"},
{"Total Fees", "$14.80"},
{"Fitness Score", "0.018"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.096"},
{"Return Over Maximum Drawdown", "-0.993"},
{"Sortino Ratio", "-0.097"},
{"Return Over Maximum Drawdown", "-0.999"},
{"Portfolio Turnover", "0.043"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -162,7 +162,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "-290004562"}
{"OrderListHash", "-1863159170"}
};
}
}

View File

@@ -132,12 +132,10 @@ namespace QuantConnect.Algorithm.CSharp
private void AssertFutureOptionOrderExercise(OrderEvent orderEvent, Security future, Security optionContract)
{
// We expect the liquidation to occur on the day of the delisting (while the market is open),
// but currently we liquidate at the next market open (AAPL open) which happens to be
// at 9:30:00 Eastern Time. For unknown reasons, the delisting happens two minutes after the
// market open.
// Read more about the issue affecting this test here: https://github.com/QuantConnect/Lean/issues/4980
var expectedLiquidationTimeUtc = new DateTime(2020, 6, 22, 13, 32, 0);
// For unknown reasons, the delisting happens two minutes after the market open. Most likely
// stems from the placement of the ProcessDelistedSymbols and HandleDelistedSymbols methods in relation
// to the algorithm time update and the brokerage ProcessSynchronousEvents.
var expectedLiquidationTimeUtc = new DateTime(2020, 6, 19, 13, 32, 0);
if (orderEvent.Direction == OrderDirection.Sell && future.Holdings.Quantity != 0)
{
@@ -214,13 +212,13 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"Average Win", "1.25%"},
{"Average Win", "1.22%"},
{"Average Loss", "-7.42%"},
{"Compounding Annual Return", "-12.413%"},
{"Compounding Annual Return", "-12.461%"},
{"Drawdown", "6.300%"},
{"Expectancy", "-0.416"},
{"Net Profit", "-6.257%"},
{"Sharpe Ratio", "-1.325"},
{"Expectancy", "-0.417"},
{"Net Profit", "-6.282%"},
{"Sharpe Ratio", "-1.324"},
{"Probabilistic Sharpe Ratio", "0.004%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
@@ -229,14 +227,14 @@ namespace QuantConnect.Algorithm.CSharp
{"Beta", "-0.003"},
{"Annual Standard Deviation", "0.076"},
{"Annual Variance", "0.006"},
{"Information Ratio", "0.673"},
{"Information Ratio", "0.671"},
{"Tracking Error", "0.188"},
{"Treynor Ratio", "33.559"},
{"Treynor Ratio", "33.52"},
{"Total Fees", "$7.40"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.205"},
{"Sortino Ratio", "-0.204"},
{"Return Over Maximum Drawdown", "-1.983"},
{"Portfolio Turnover", "0.023"},
{"Total Insights Generated", "0"},
@@ -252,7 +250,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "23301049"}
{"OrderListHash", "1442219241"}
};
}
}

View File

@@ -166,31 +166,31 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"Average Win", "28.04%"},
{"Average Win", "27.44%"},
{"Average Loss", "-62.81%"},
{"Compounding Annual Return", "-78.165%"},
{"Drawdown", "52.400%"},
{"Expectancy", "-0.277"},
{"Net Profit", "-52.379%"},
{"Sharpe Ratio", "-0.865"},
{"Compounding Annual Return", "-78.376%"},
{"Drawdown", "52.600%"},
{"Expectancy", "-0.282"},
{"Net Profit", "-52.604%"},
{"Sharpe Ratio", "-0.864"},
{"Probabilistic Sharpe Ratio", "0.019%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.45"},
{"Alpha", "-0.596"},
{"Beta", "-0.031"},
{"Annual Standard Deviation", "0.681"},
{"Annual Variance", "0.463"},
{"Profit-Loss Ratio", "0.44"},
{"Alpha", "-0.598"},
{"Beta", "-0.032"},
{"Annual Standard Deviation", "0.684"},
{"Annual Variance", "0.467"},
{"Information Ratio", "-0.514"},
{"Tracking Error", "0.703"},
{"Treynor Ratio", "18.748"},
{"Tracking Error", "0.706"},
{"Treynor Ratio", "18.718"},
{"Total Fees", "$66.60"},
{"Fitness Score", "0.157"},
{"Fitness Score", "0.158"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.133"},
{"Return Over Maximum Drawdown", "-1.492"},
{"Portfolio Turnover", "0.411"},
{"Return Over Maximum Drawdown", "-1.489"},
{"Portfolio Turnover", "0.413"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
{"Total Insights Analysis Completed", "0"},
@@ -204,7 +204,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "151392833"}
{"OrderListHash", "891799117"}
};
}
}

View File

@@ -26,11 +26,13 @@ namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests Out of The Money (OTM) future option expiry for calls.
/// We expect 1 order from the algorithm, which are:
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, buy ES Call Option (expiring OTM)
/// - contract expires worthless, not exercised, so never opened a position in the underlying
///
/// * Liquidation of worthless ES call option (expiring OTM)
///
/// Additionally, we test delistings for future options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
@@ -219,7 +221,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "-1116221764"}
{"OrderListHash", "1061918870"}
};
}
}

View File

@@ -132,12 +132,10 @@ namespace QuantConnect.Algorithm.CSharp
private void AssertFutureOptionOrderExercise(OrderEvent orderEvent, Security future, Security optionContract)
{
// We expect the liquidation to occur on the day of the delisting (while the market is open),
// but currently we liquidate at the next market open (AAPL open) which happens to be
// at 9:30:00 Eastern Time. For unknown reasons, the delisting happens two minutes after the
// market open.
// Read more about the issue affecting this test here: https://github.com/QuantConnect/Lean/issues/4980
var expectedLiquidationTimeUtc = new DateTime(2020, 6, 22, 13, 32, 0);
// For unknown reasons, the delisting happens two minutes after the market open. Most likely
// stems from the placement of the ProcessDelistedSymbols and HandleDelistedSymbols methods in relation
// to the algorithm time update and the brokerage ProcessSynchronousEvents.
var expectedLiquidationTimeUtc = new DateTime(2020, 6, 19, 13, 32, 0);
if (orderEvent.Direction == OrderDirection.Buy && future.Holdings.Quantity != 0)
{
@@ -214,24 +212,24 @@ namespace QuantConnect.Algorithm.CSharp
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
{
{"Total Trades", "3"},
{"Average Win", "4.18%"},
{"Average Win", "4.15%"},
{"Average Loss", "-8.27%"},
{"Compounding Annual Return", "-8.879%"},
{"Drawdown", "4.400%"},
{"Expectancy", "-0.247"},
{"Net Profit", "-4.432%"},
{"Sharpe Ratio", "-1.391"},
{"Compounding Annual Return", "-8.928%"},
{"Drawdown", "4.500%"},
{"Expectancy", "-0.249"},
{"Net Profit", "-4.457%"},
{"Sharpe Ratio", "-1.389"},
{"Probabilistic Sharpe Ratio", "0.002%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.51"},
{"Profit-Loss Ratio", "0.50"},
{"Alpha", "-0.073"},
{"Beta", "-0.002"},
{"Annual Standard Deviation", "0.052"},
{"Annual Variance", "0.003"},
{"Information Ratio", "0.863"},
{"Information Ratio", "0.861"},
{"Tracking Error", "0.179"},
{"Treynor Ratio", "38.46"},
{"Treynor Ratio", "38.365"},
{"Total Fees", "$7.40"},
{"Fitness Score", "0.008"},
{"Kelly Criterion Estimate", "0"},
@@ -252,7 +250,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "-675079082"}
{"OrderListHash", "-1705374528"}
};
}
}

View File

@@ -26,11 +26,13 @@ namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests Out of The Money (OTM) future option expiry for puts.
/// We expect 1 order from the algorithm, which are:
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, buy ES Put Option (expiring OTM)
/// - contract expires worthless, not exercised, so never opened a position in the underlying
///
/// * Liquidation of worthless ES Put OTM contract
///
/// Additionally, we test delistings for future options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
@@ -218,7 +220,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "515984318"}
{"OrderListHash", "-312857564"}
};
}
}

View File

@@ -194,29 +194,29 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "3"},
{"Average Win", "10.05%"},
{"Average Loss", "-5.60%"},
{"Compounding Annual Return", "8.121%"},
{"Average Loss", "-5.63%"},
{"Compounding Annual Return", "8.067%"},
{"Drawdown", "0.500%"},
{"Expectancy", "0.396"},
{"Net Profit", "3.880%"},
{"Sharpe Ratio", "1.192"},
{"Probabilistic Sharpe Ratio", "58.203%"},
{"Expectancy", "0.393"},
{"Net Profit", "3.855%"},
{"Sharpe Ratio", "1.191"},
{"Probabilistic Sharpe Ratio", "58.149%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "1.79"},
{"Alpha", "0.069"},
{"Alpha", "0.068"},
{"Beta", "0.003"},
{"Annual Standard Deviation", "0.057"},
{"Annual Variance", "0.003"},
{"Information Ratio", "1.641"},
{"Information Ratio", "1.64"},
{"Tracking Error", "0.18"},
{"Treynor Ratio", "22.101"},
{"Treynor Ratio", "22.061"},
{"Total Fees", "$7.40"},
{"Fitness Score", "0.021"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "17.255"},
{"Return Over Maximum Drawdown", "17.142"},
{"Portfolio Turnover", "0.021"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -231,7 +231,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "1118389718"}
{"OrderListHash", "-991138464"}
};
}
}

View File

@@ -26,11 +26,13 @@ namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests Out of The Money (OTM) future option expiry for short calls.
/// We expect 1 order from the algorithm, which are:
/// We expect 2 orders from the algorithm, which are:
///
/// * Initial entry, sell ES Call Option (expiring OTM)
/// - Profit the option premium, since the option was not assigned.
///
/// * Liquidation of ES call OTM contract on the last trade date
///
/// Additionally, we test delistings for future options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
@@ -212,7 +214,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "1364902860"}
{"OrderListHash", "1847291350"}
};
}
}

View File

@@ -191,29 +191,29 @@ namespace QuantConnect.Algorithm.CSharp
{
{"Total Trades", "3"},
{"Average Win", "10.18%"},
{"Average Loss", "-8.02%"},
{"Compounding Annual Return", "2.773%"},
{"Average Loss", "-8.05%"},
{"Compounding Annual Return", "2.721%"},
{"Drawdown", "0.500%"},
{"Expectancy", "0.135"},
{"Net Profit", "1.343%"},
{"Sharpe Ratio", "0.939"},
{"Probabilistic Sharpe Ratio", "46.842%"},
{"Expectancy", "0.133"},
{"Net Profit", "1.318%"},
{"Sharpe Ratio", "0.934"},
{"Probabilistic Sharpe Ratio", "46.618%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "1.27"},
{"Alpha", "0.023"},
{"Beta", "0.002"},
{"Annual Standard Deviation", "0.025"},
{"Annual Standard Deviation", "0.024"},
{"Annual Variance", "0.001"},
{"Information Ratio", "1.45"},
{"Information Ratio", "1.448"},
{"Tracking Error", "0.173"},
{"Treynor Ratio", "14.62"},
{"Treynor Ratio", "14.482"},
{"Total Fees", "$7.40"},
{"Fitness Score", "0.021"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "79228162514264337593543950335"},
{"Return Over Maximum Drawdown", "5.815"},
{"Return Over Maximum Drawdown", "5.706"},
{"Portfolio Turnover", "0.022"},
{"Total Insights Generated", "0"},
{"Total Insights Closed", "0"},
@@ -228,7 +228,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "980293281"}
{"OrderListHash", "777632049"}
};
}
}

View File

@@ -26,11 +26,13 @@ namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// This regression algorithm tests Out of The Money (OTM) future option expiry for short puts.
/// We expect 1 order from the algorithm, which are:
/// We expect 2 order from the algorithm, which are:
///
/// * Initial entry, sell ES Put Option (expiring OTM)
/// - Profit the option premium, since the option was not assigned.
///
/// * Liquidation of ES put OTM contract on the last trade date
///
/// Additionally, we test delistings for future options and assert that our
/// portfolio holdings reflect the orders the algorithm has submitted.
/// </summary>
@@ -211,7 +213,7 @@ namespace QuantConnect.Algorithm.CSharp
{"Mean Population Magnitude", "0%"},
{"Rolling Averaged Population Direction", "0%"},
{"Rolling Averaged Population Magnitude", "0%"},
{"OrderListHash", "-418839052"}
{"OrderListHash", "1003680014"}
};
}
}

View File

@@ -0,0 +1,202 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Orders;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.CSharp
{
/// <summary>
/// Tests delistings for Futures and Futures Options to ensure that they are delisted at the expected times.
/// </summary>
public class FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
{
private bool _invested;
private int _liquidated;
private int _delistingsReceived;
private Symbol _esFuture;
private Symbol _esFutureOption;
private readonly DateTime _expectedExpiryWarningTime = new DateTime(2020, 6, 19);
private readonly DateTime _expectedExpiryDelistingTime = new DateTime(2020, 6, 20);
private readonly DateTime _expectedLiquidationTime = new DateTime(2020, 6, 19, 9, 32, 0);
public override void Initialize()
{
SetStartDate(2020, 1, 5);
SetEndDate(2020, 12, 1);
SetCash(100000);
// To ensure that the expiry liquidations are ran for the Futures and FOPs, we
// add AAPL to pump a data point through on liquidation date so that the liquidation goes through
// at AAPL market open. See issue for more details: https://github.com/QuantConnect/Lean/issues/4872
AddEquity("AAPL", Resolution.Daily);
var es = QuantConnect.Symbol.CreateFuture(
Futures.Indices.SP500EMini,
Market.CME,
new DateTime(2020, 6, 19));
var esOption = QuantConnect.Symbol.CreateOption(
es,
Market.CME,
OptionStyle.American,
OptionRight.Put,
3400m,
new DateTime(2020, 6, 19));
_esFuture = AddFutureContract(es, Resolution.Minute).Symbol;
_esFutureOption = AddFutureOptionContract(esOption, Resolution.Minute).Symbol;
}
public override void OnData(Slice data)
{
foreach (var delisting in data.Delistings.Values)
{
// Two warnings and two delisted events should be received for a grand total of 4 events.
_delistingsReceived++;
if (delisting.Type == DelistingType.Warning &&
delisting.Time != _expectedExpiryWarningTime)
{
throw new Exception($"Expiry warning with time {delisting.Time} but is expected to be {_expectedExpiryWarningTime}");
}
if (delisting.Type == DelistingType.Warning && delisting.Time != Time.Date)
{
throw new Exception($"Delisting warning received at an unexpected date: {Time} - expected {delisting.Time}");
}
if (delisting.Type == DelistingType.Delisted &&
delisting.Time != _expectedExpiryDelistingTime)
{
throw new Exception($"Delisting occurred at unexpected time: {delisting.Time} - expected: {_expectedExpiryDelistingTime}");
}
if (delisting.Type == DelistingType.Delisted &&
delisting.Time != Time.Date)
{
throw new Exception($"Delisting notice received at an unexpected date: {Time} - expected {delisting.Time}");
}
}
if (!_invested &&
(data.Bars.ContainsKey(_esFuture) || data.QuoteBars.ContainsKey(_esFuture)) &&
(data.Bars.ContainsKey(_esFutureOption) || data.QuoteBars.ContainsKey(_esFutureOption)))
{
_invested = true;
MarketOrder(_esFuture, 1);
MarketOrder(_esFutureOption, 1);
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Direction != OrderDirection.Sell || orderEvent.Status != OrderStatus.Filled)
{
return;
}
// * Future Liquidation
// * Future Option Exercise
// * Underlying Future Liquidation
_liquidated++;
if (orderEvent.Symbol.SecurityType == SecurityType.FutureOption && _expectedLiquidationTime != Time)
{
throw new Exception($"Expected to liquidate option {orderEvent.Symbol} at {_expectedLiquidationTime}, instead liquidated at {Time}");
}
if (orderEvent.Symbol.SecurityType == SecurityType.Future && _expectedLiquidationTime.AddMinutes(-1) != Time && _expectedLiquidationTime != Time)
{
throw new Exception($"Expected to liquidate future {orderEvent.Symbol} at {_expectedLiquidationTime} (+1 minute), instead liquidated at {Time}");
}
}
public override void OnEndOfAlgorithm()
{
if (!_invested)
{
throw new Exception("Never invested in ES futures and FOPs");
}
if (_delistingsReceived != 4)
{
throw new Exception($"Expected 4 delisting events received, found: {_delistingsReceived}");
}
if (_liquidated != 3)
{
throw new Exception($"Expected 3 liquidation events, found {_liquidated}");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public 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.13%"},
{"Average Loss", "-11.33%"},
{"Compounding Annual Return", "-2.634%"},
{"Drawdown", "2.400%"},
{"Expectancy", "-0.494"},
{"Net Profit", "-2.399%"},
{"Sharpe Ratio", "-0.933"},
{"Probabilistic Sharpe Ratio", "0.003%"},
{"Loss Rate", "50%"},
{"Win Rate", "50%"},
{"Profit-Loss Ratio", "0.01"},
{"Alpha", "-0.017"},
{"Beta", "-0.001"},
{"Annual Standard Deviation", "0.018"},
{"Annual Variance", "0"},
{"Information Ratio", "0.886"},
{"Tracking Error", "0.127"},
{"Treynor Ratio", "30.534"},
{"Total Fees", "$9.25"},
{"Fitness Score", "0.007"},
{"Kelly Criterion Estimate", "0"},
{"Kelly Criterion Probability Value", "0"},
{"Sortino Ratio", "-0.177"},
{"Return Over Maximum Drawdown", "-1.098"},
{"Portfolio Turnover", "0.018"},
{"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", "542517089"}
};
}
}

View File

@@ -148,6 +148,7 @@
<Compile Include="AddOptionContractExpiresRegressionAlgorithm.cs" />
<Compile Include="AltData\QuiverWallStreetBetsDataAlgorithm.cs" />
<Compile Include="FutureOptionCallITMGreeksExpiryRegressionAlgorithm.cs" />
<Compile Include="FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm.cs" />
<Compile Include="OnOrderEventExceptionRegression.cs" />
<Compile Include="FutureOptionCallITMExpiryRegressionAlgorithm.cs" />
<Compile Include="FutureOptionCallOTMExpiryRegressionAlgorithm.cs" />

View File

@@ -107,7 +107,7 @@ class FutureOptionCallITMExpiryRegressionAlgorithm(QCAlgorithm):
# at 9:30:00 Eastern Time. For unknown reasons, the delisting happens two minutes after the
# market open.
# Read more about the issue affecting this test here: https://github.com/QuantConnect/Lean/issues/4980
expectedLiquidationTimeUtc = datetime(2020, 6, 22, 13, 32, 0)
expectedLiquidationTimeUtc = datetime(2020, 6, 19, 13, 32, 0)
if orderEvent.Direction == OrderDirection.Sell and future.Holdings.Quantity != 0:
# We expect the contract to have been liquidated immediately

View File

@@ -28,11 +28,13 @@ from QuantConnect import Market
### <summary>
### This regression algorithm tests Out of The Money (OTM) future option expiry for calls.
### We expect 1 order from the algorithm, which are:
### We expect 2 orders from the algorithm, which are:
###
### * Initial entry, buy ES Call Option (expiring OTM)
### - contract expires worthless, not exercised, so never opened a position in the underlying
###
### * Liquidation of worthless ES call option (expiring OTM)
###
### Additionally, we test delistings for future options and assert that our
### portfolio holdings reflect the orders the algorithm has submitted.
### </summary>

View File

@@ -106,7 +106,7 @@ class FutureOptionPutITMExpiryRegressionAlgorithm(QCAlgorithm):
# at 9:30:00 Eastern Time. For unknown reasons, the delisting happens two minutes after the
# market open.
# Read more about the issue affecting this test here: https://github.com/QuantConnect/Lean/issues/4980
expectedLiquidationTimeUtc = datetime(2020, 6, 22, 13, 32, 0)
expectedLiquidationTimeUtc = datetime(2020, 6, 19, 13, 32, 0)
if orderEvent.Direction == OrderDirection.Buy and future.Holdings.Quantity != 0:
# We expect the contract to have been liquidated immediately

View File

@@ -28,10 +28,12 @@ from QuantConnect import Market
### <summary>
### This regression algorithm tests Out of The Money (OTM) future option expiry for puts.
### We expect 1 order from the algorithm, which are:
### We expect 2 orders from the algorithm, which are:
###
### * Initial entry, buy ES Put Option (expiring OTM)
### - contract expires worthless, not exercised, so never opened a position in the underlying
###
### * Liquidation of worthless ES Put OTM contract
###
### Additionally, we test delistings for future options and assert that our
### portfolio holdings reflect the orders the algorithm has submitted.

View File

@@ -28,11 +28,13 @@ from QuantConnect import Market
### <summary>
### This regression algorithm tests Out of The Money (OTM) future option expiry for short calls.
### We expect 1 order from the algorithm, which are:
### We expect 2 orders from the algorithm, which are:
###
### * Initial entry, sell ES Call Option (expiring OTM)
### - Profit the option premium, since the option was not assigned.
###
### * Liquidation of ES call OTM contract on the last trade date
###
### Additionally, we test delistings for future options and assert that our
### portfolio holdings reflect the orders the algorithm has submitted.
### </summary>

View File

@@ -28,11 +28,13 @@ from QuantConnect import Market
### <summary>
### This regression algorithm tests Out of The Money (OTM) future option expiry for short puts.
### We expect 1 order from the algorithm, which are:
### We expect 2 orders from the algorithm, which are:
###
### * Initial entry, sell ES Put Option (expiring OTM)
### - Profit the option premium, since the option was not assigned.
###
### * Liquidation of ES put OTM contract on the last trade date
###
### Additionally, we test delistings for future options and assert that our
### portfolio holdings reflect the orders the algorithm has submitted.
### </summary>

View File

@@ -0,0 +1,100 @@
from datetime import datetime, timedelta
from QuantConnect.Algorithm import *
from QuantConnect.Data import *
from QuantConnect.Data.Market import *
from QuantConnect.Orders import *
from QuantConnect import *
### <summary>
### Tests delistings for Futures and Futures Options to ensure that they are delisted at the expected times.
### </summary>
class FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm(QCAlgorithm):
def Initialize(self):
self.invested = False
self.liquidated = 0
self.delistingsReceived = 0
self.expectedExpiryWarningTime = datetime(2020, 6, 19)
self.expectedExpiryDelistingTime = datetime(2020, 6, 20)
self.expectedLiquidationTime = datetime(2020, 6, 19, 9, 32, 0)
self.SetStartDate(2020, 1, 5)
self.SetEndDate(2020, 12, 1)
self.SetCash(100000)
# To ensure that the expiry liquidations are ran for the Futures and FOPs, we
# add AAPL to pump a data point through on liquidation date so that the liquidation goes through
# at AAPL market open. See issue for more details: https://github.com/QuantConnect/Lean/issues/4872
self.AddEquity("AAPL", Resolution.Daily)
es = Symbol.CreateFuture(
"ES",
Market.CME,
datetime(2020, 6, 19)
)
esOption = Symbol.CreateOption(
es,
Market.CME,
OptionStyle.American,
OptionRight.Put,
3400.0,
datetime(2020, 6, 19)
)
self.esFuture = self.AddFutureContract(es, Resolution.Minute).Symbol
self.esFutureOption = self.AddFutureOptionContract(esOption, Resolution.Minute).Symbol
def OnData(self, data: Slice):
for delisting in data.Delistings.Values:
self.delistingsReceived += 1
if delisting.Type == DelistingType.Warning and delisting.Time != self.expectedExpiryWarningTime:
raise AssertionError(f"Expiry warning with time {delisting.Time} but is expected to be {self.expectedExpiryWarningTime}")
if delisting.Type == DelistingType.Warning and delisting.Time != datetime(self.Time.year, self.Time.month, self.Time.day):
raise AssertionError(f"Delisting warning received at an unexpected date: {self.Time} - expected {delisting.Time}")
if delisting.Type == DelistingType.Delisted and delisting.Time != self.expectedExpiryDelistingTime:
raise AssertionError(f"Delisting occurred at unexpected time: {delisting.Time} - expected: {self.expectedExpiryDelistingTime}")
if delisting.Type == DelistingType.Delisted and delisting.Time != datetime(self.Time.year, self.Time.month, self.Time.day):
raise AssertionError(f"Delisting notice received at an unexpected date: {self.Time} - expected {delisting.Time}")
if not self.invested and \
(self.esFuture in data.Bars or self.esFuture in data.QuoteBars) and \
(self.esFutureOption in data.Bars or self.esFutureOption in data.QuoteBars):
self.invested = True
self.MarketOrder(self.esFuture, 1)
self.MarketOrder(self.esFutureOption, 1)
def OnOrderEvent(self, orderEvent: OrderEvent):
if orderEvent.Direction != OrderDirection.Sell or orderEvent.Status != OrderStatus.Filled:
return
# * Future Liquidation
# * Future Option Exercise
# * Underlying Future Liquidation
self.liquidated += 1
if orderEvent.Symbol.SecurityType == SecurityType.FutureOption and self.expectedLiquidationTime != self.Time:
raise AssertionError(f"Expected to liquidate option {orderEvent.Symbol} at {self.expectedLiquidationTime}, instead liquidated at {self.Time}")
if orderEvent.Symbol.SecurityType == SecurityType.Future and \
(self.expectedLiquidationTime - timedelta(minutes=1)) != self.Time and \
self.expectedLiquidationTime != self.Time:
raise AssertionError(f"Expected to liquidate future {orderEvent.Symbol} at {self.expectedLiquidationTime} (+1 minute), instead liquidated at {self.Time}")
def OnEndOfAlgorithm(self):
if not self.invested:
raise AssertionError("Never invested in ES futures and FOPs")
if self.delistingsReceived != 4:
raise AssertionError(f"Expected 4 delisting events received, found: {self.delistingsReceived}")
if self.liquidated != 3:
raise AssertionError(f"Expected 3 liquidation events, found {self.liquidated}")

View File

@@ -109,6 +109,7 @@
<Content Include="FutureOptionShortCallOTMExpiryRegressionAlgorithm.py" />
<Content Include="FutureOptionShortPutITMExpiryRegressionAlgorithm.py" />
<Content Include="FutureOptionShortPutOTMExpiryRegressionAlgorithm.py" />
<Content Include="FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm.py" />
<Content Include="KerasNeuralNetworkAlgorithm.py" />
<Content Include="CustomDataUsingMapFileRegressionAlgorithm.py" />
<Content Include="LiquidETFUniverseFrameworkAlgorithm.py" />

View File

@@ -41,12 +41,12 @@ Before we enable python support, follow the [installation instructions](https://
2. Install [pandas=0.25.3](https://pandas.pydata.org/) and its [dependencies](https://pandas.pydata.org/pandas-docs/stable/install.html#dependencies).
3. Install [wrapt=1.11.2](https://pypi.org/project/wrapt/) module.
*Note:* If you encounter the "System.DllNotFoundException: python3.6m" runtime error when running Python algorithms on macOS:
*Note:* If you encounter the "System.DllNotFoundException: python3.6m" runtime error when running Python algorithms, or generating reports, on macOS:
1. Find `libpython3.6m.dylib` in your Python installation folder. If you installed Python with Anaconda, it may be found at
```
/Users/{your_user_name}/anaconda3/lib/libpython3.6m.dylib
```
2. Open `Lean/Launcher/bin/Debug/Python.Runtime.dll.config`, add the following text under `<configuration> ... </configuration>` and save:
2. Open `Lean/Common/Python/Python.Runtime.dll.config`, add the following text under `<configuration> ... </configuration>` and save:
```
<dllmap dll="python3.6m" target="{the path in step 1 including libpython3.6m.dylib}" os="osx"/>
```
@@ -81,7 +81,7 @@ conda install -y wrapt=1.11.2
conda create -n qc_environment python=3.6.8 cython=0.29.11 pandas=0.25.3 wrapt=1.11.2
```
2. Open `Lean/Launcher/bin/Debug/Python.Runtime.dll.config`, add the following text under `<configuration> ... </configuration>` and save:
2. Open `Lean/Common/Python/Python.Runtime.dll.config`, add the following text under `<configuration> ... </configuration>` and save:
```
<dllmap dll="python3.6m" target="{the path in step 1 including libpython3.6m.so}" os="linux"/>
```

View File

@@ -14,6 +14,7 @@
*/
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Alphas.Analysis;
@@ -31,6 +32,7 @@ namespace QuantConnect.Algorithm
{
private readonly ISecurityValuesProvider _securityValuesProvider;
private bool _isEmitWarmupInsightWarningSent;
private bool _isEmitDelistedInsightWarningSent;
/// <summary>
/// Enables additional logging of framework models including:
@@ -147,7 +149,8 @@ namespace QuantConnect.Algorithm
// only fire insights generated event if we actually have insights
if (insights.Length != 0)
{
OnInsightsGenerated(insights.Select(InitializeInsightFields));
insights = InitializeInsights(insights);
OnInsightsGenerated(insights);
}
ProcessInsights(insights);
@@ -226,7 +229,7 @@ namespace QuantConnect.Algorithm
Log($"{Time}: RISK ADJUSTED TARGETS: {string.Join(" | ", riskAdjustedTargets.Select(t => t.ToString()).OrderBy(t => t))}");
}
}
Execution.Execute(this, riskAdjustedTargets);
}
@@ -382,7 +385,8 @@ namespace QuantConnect.Algorithm
return;
}
OnInsightsGenerated(insights.Select(InitializeInsightFields));
insights = InitializeInsights(insights);
OnInsightsGenerated(insights);
ProcessInsights(insights);
}
@@ -394,7 +398,52 @@ namespace QuantConnect.Algorithm
/// <param name="insight">The insight to be emitted</param>
public void EmitInsights(Insight insight)
{
EmitInsights(new []{insight});
EmitInsights(new[] { insight });
}
/// <summary>
/// Helper method used to validate insights and prepare them to be emitted
/// </summary>
/// <param name="insights">insights preparing to be emitted</param>
/// <returns>Validated insights</returns>
private Insight[] InitializeInsights(Insight[] insights)
{
List<Insight> validInsights = null;
for (var i = 0; i < insights.Length; i++)
{
if (Securities[insights[i].Symbol].IsDelisted)
{
if (!_isEmitDelistedInsightWarningSent)
{
Error($"QCAlgorithm.EmitInsights(): Warning: cannot emit insights for delisted securities, these will be discarded");
_isEmitDelistedInsightWarningSent = true;
}
// If this is our first invalid insight, create the list and fill it with previous values
if (validInsights == null)
{
validInsights = new List<Insight>() {};
for (var j = 0; j < i; j++)
{
validInsights.Add(insights[j]);
}
}
}
else
{
// Initialize the insight fields
insights[i] = InitializeInsightFields(insights[i]);
// If we already had an invalid insight, this will have been initialized storing the valid ones.
if (validInsights != null)
{
validInsights.Add(insights[i]);
}
}
}
return validInsights == null ? insights : validInsights.ToArray();
}
/// <summary>

View File

@@ -126,6 +126,28 @@ namespace QuantConnect.Algorithm
return averageDirectionalIndex;
}
/// <summary>
/// Creates a new Awesome Oscillator from the specified periods.
/// </summary>
/// <param name="symbol">The symbol whose Awesome Oscillator we seek</param>
/// <param name="resolution">The resolution.</param>
/// <param name="fastPeriod">The period of the fast moving average associated with the AO</param>
/// <param name="slowPeriod">The period of the slow moving average associated with the AO</param>
/// <param name="type">The type of moving average used when computing the fast and slow term. Defaults to simple moving average.</param>
public AwesomeOscillator AO(Symbol symbol, int slowPeriod, int fastPeriod, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, IBaseDataBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"AO({fastPeriod},{slowPeriod},{type})", resolution);
var awesomeOscillator = new AwesomeOscillator(name, fastPeriod, slowPeriod, type);
RegisterIndicator(symbol, awesomeOscillator, resolution, selector);
if (EnableAutomaticIndicatorWarmUp)
{
WarmUpIndicator(symbol, awesomeOscillator, resolution);
}
return awesomeOscillator;
}
/// <summary>
/// Creates a new AverageDirectionalMovementIndexRating indicator.
/// </summary>
@@ -354,6 +376,28 @@ namespace QuantConnect.Algorithm
return commodityChannelIndex;
}
/// <summary>
/// Creates a new ChaikinMoneyFlow indicator.
/// </summary>
/// <param name="symbol">The symbol whose CMF we want</param>
/// <param name="period">The period over which to compute the CMF</param>
/// <param name="resolution">The resolution</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The ChaikinMoneyFlow indicator for the requested symbol over the specified period</returns>
public ChaikinMoneyFlow CMF(Symbol symbol, int period, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"CMF({period})", resolution);
var chaikinMoneyFlow = new ChaikinMoneyFlow(name, period);
RegisterIndicator(symbol, chaikinMoneyFlow, resolution, selector);
if (EnableAutomaticIndicatorWarmUp)
{
WarmUpIndicator(symbol, chaikinMoneyFlow, resolution);
}
return chaikinMoneyFlow;
}
/// <summary>
/// Creates a new ChandeMomentumOscillator indicator.
@@ -376,7 +420,31 @@ namespace QuantConnect.Algorithm
return chandeMomentumOscillator;
}
///<summary>
/// Creates a new DeMarker Indicator (DEM), an oscillator-type indicator measuring changes in terms of an asset's
/// High and Low tradebar values.
///</summary>
/// <param name="symbol">The symbol whose DEM we seek.</param>
/// <param name="period">The period of the moving average implemented</param>
/// <param name="movingAverageType">Specifies the type of moving average to be used</param>
/// <param name="resolution">The resolution.</param>
/// <param name="selector">Selects a value from the BaseData to send into the indicator, if null defaults to casting the input value to a TradeBar</param>
/// <returns>The DeMarker indicator for the requested symbol.</returns>
public DeMarkerIndicator DEM(Symbol symbol, int period, MovingAverageType type, Resolution? resolution = null, Func<IBaseData, TradeBar> selector = null)
{
var name = CreateIndicatorName(symbol, $"DEM({period},{type})", resolution);
var deMarkerIndicator = new DeMarkerIndicator(name, period, type);
RegisterIndicator(symbol, deMarkerIndicator, resolution, selector);
if (EnableAutomaticIndicatorWarmUp)
{
WarmUpIndicator(symbol, deMarkerIndicator, resolution);
}
return deMarkerIndicator;
}
/// <summary>
/// Creates a new Donchian Channel indicator which will compute the Upper Band and Lower Band.
/// The indicator will be automatically updated on the given resolution.
@@ -2543,4 +2611,4 @@ namespace QuantConnect.Algorithm
return new BaseDataConsolidator(calendar);
}
}
}
}

View File

@@ -2286,17 +2286,15 @@ namespace QuantConnect.Algorithm
/// </summary>
/// <param name="insights">The collection of insights generaed at the current time step</param>
/// <param name="clone">Will emit a clone of the generated insights</param>
private void OnInsightsGenerated(IEnumerable<Insight> insights, bool clone = true)
private void OnInsightsGenerated(Insight[] insights, bool clone = true)
{
var insightCollection = insights.ToArray();
// debug printing of generated insights
if (DebugMode)
{
Log($"{Time}: ALPHA: {string.Join(" | ", insightCollection.Select(i => i.ToString()).OrderBy(i => i))}");
Log($"{Time}: ALPHA: {string.Join(" | ", insights.Select(i => i.ToString()).OrderBy(i => i))}");
}
InsightsGenerated?.Invoke(this, new GeneratedInsightsCollection(UtcTime, insightCollection, clone: clone));
InsightsGenerated?.Invoke(this, new GeneratedInsightsCollection(UtcTime, insights, clone: clone));
}
/// <summary>

View File

@@ -20,6 +20,7 @@ using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using QuantConnect.Interfaces;
using QuantConnect.Logging;
using QuantConnect.Orders;
using RestSharp;
using RestSharp.Extensions;
@@ -383,9 +384,15 @@ namespace QuantConnect.Api
backtestName
}), ParameterType.RequestBody);
Backtest result;
BacktestResponseWrapper result;
ApiConnection.TryRequest(request, out result);
return result;
// Use API Response values for Backtest Values
result.Backtest.Success = result.Success;
result.Backtest.Errors = result.Errors;
// Return only the backtest object
return result.Backtest;
}
/// <summary>
@@ -408,9 +415,58 @@ namespace QuantConnect.Api
backtestId
}), ParameterType.RequestBody);
Backtest result;
BacktestResponseWrapper result;
ApiConnection.TryRequest(request, out result);
return result;
// Go fetch the charts if the backtest is completed
if (result.Backtest.Completed)
{
// For storing our collected charts
var updatedCharts = new Dictionary<string, Chart>();
// Create backtest requests for each chart that is empty
foreach (var chart in result.Backtest.Charts)
{
if (!chart.Value.Series.IsNullOrEmpty())
{
continue;
}
var chartRequest = new RestRequest("backtests/read", Method.POST)
{
RequestFormat = DataFormat.Json
};
chartRequest.AddParameter("application/json", JsonConvert.SerializeObject(new
{
projectId,
backtestId,
chart = chart.Key.Replace(' ', '+')
}), ParameterType.RequestBody);
BacktestResponseWrapper chartResponse;
ApiConnection.TryRequest(chartRequest, out chartResponse);
// Add this chart to our updated collection
if (chartResponse.Success)
{
updatedCharts.Add(chart.Key, chartResponse.Backtest.Charts[chart.Key]);
}
}
// Update our result
foreach(var updatedChart in updatedCharts)
{
result.Backtest.Charts[updatedChart.Key] = updatedChart.Value;
}
}
// Use API Response values for Backtest Values
result.Backtest.Success = result.Success;
result.Backtest.Errors = result.Errors;
// Return only the backtest object
return result.Backtest;
}
/// <summary>
@@ -761,8 +817,17 @@ namespace QuantConnect.Api
var uri = new Uri(link.DataLink);
var client = new RestClient(uri.Scheme + "://" + uri.Host);
var request = new RestRequest(uri.PathAndQuery, Method.GET);
client.DownloadData(request).SaveAs(path);
// If the response is not a zip then it is not data, don't write it.
var response = client.Execute(request);
if (response.ContentType != "application/zip")
{
var message = JObject.Parse(response.Content)["message"].Value<string>();
Log.Error($"Api.DownloadData(): Failed to download zip for {symbol} {resolution} data for date {date}, Api response: {message}");
return false;
}
response.RawBytes.SaveAs(path);
return true;
}

View File

@@ -28,6 +28,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using QuantConnect.Brokerages.Bitfinex.Messages;
using Order = QuantConnect.Orders.Order;
@@ -53,6 +54,9 @@ namespace QuantConnect.Brokerages.Bitfinex
private readonly object _clientOrderIdLocker = new object();
private long _nextClientOrderId;
// map Bitfinex currency to LEAN currency
private readonly Dictionary<string, string> _currencyMap;
/// <summary>
/// Locking object for the Ticks list in the data queue handler
/// </summary>
@@ -89,6 +93,15 @@ namespace QuantConnect.Brokerages.Bitfinex
_algorithm = algorithm;
_aggregator = aggregator;
// load currency map
using (var wc = new WebClient())
{
var json = wc.DownloadString("https://api-pub.bitfinex.com/v2/conf/pub:map:currency:sym");
var rows = JsonConvert.DeserializeObject<List<List<List<string>>>>(json)[0];
_currencyMap = rows
.ToDictionary(row => row[0], row => row[1].ToUpperInvariant());
}
WebSocket.Open += (sender, args) =>
{
SubscribeAuth();
@@ -384,7 +397,7 @@ namespace QuantConnect.Brokerages.Bitfinex
var fillQuantity = update.ExecAmount;
var direction = fillQuantity < 0 ? OrderDirection.Sell : OrderDirection.Buy;
var updTime = Time.UnixMillisecondTimeStampToDateTime(update.MtsCreate);
var orderFee = new OrderFee(new CashAmount(Math.Abs(update.Fee), update.FeeCurrency));
var orderFee = new OrderFee(new CashAmount(Math.Abs(update.Fee), GetLeanCurrency(update.FeeCurrency)));
var status = OrderStatus.Filled;
if (fillQuantity != order.Quantity)
@@ -440,6 +453,17 @@ namespace QuantConnect.Brokerages.Bitfinex
}
}
private string GetLeanCurrency(string brokerageCurrency)
{
string currency;
if (!_currencyMap.TryGetValue(brokerageCurrency.ToUpperInvariant(), out currency))
{
currency = brokerageCurrency.ToUpperInvariant();
}
return currency;
}
/// <summary>
/// Emit stream tick
/// </summary>

View File

@@ -280,7 +280,7 @@ namespace QuantConnect.Brokerages.Bitfinex
{
if (item.Balance > 0)
{
list.Add(new CashAmount(item.Balance, item.Currency.ToUpperInvariant()));
list.Add(new CashAmount(item.Balance, GetLeanCurrency(item.Currency)));
}
}

View File

@@ -2250,6 +2250,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
var market = InteractiveBrokersBrokerageModel.DefaultMarketMap[securityType];
var isFutureOption = contract.SecType == IB.SecurityType.FutureOption;
// Handle future options as a Future, up until we actually return the future.
if (isFutureOption || securityType == SecurityType.Future)
{
@@ -2260,6 +2261,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
market = defaultMarket;
}
Log.Trace($"Mapping contract {contract} with ticker `{leanSymbol}` and SecurityType `{securityType.ToString()}` with expiry: {contract.LastTradeDateOrContractMonth} to Symbol");
var contractExpiryDate = DateTime.ParseExact(contract.LastTradeDateOrContractMonth, DateFormat.EightCharacter, CultureInfo.InvariantCulture);
if (!isFutureOption)
@@ -2281,6 +2283,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
}
if (securityType == SecurityType.Option)
{
Log.Trace($"Mapping contract {contract} with ticker `{ibSymbol}` and SecurityType `{securityType.ToString()}` with expiry: {contract.LastTradeDateOrContractMonth} to Symbol");
var expiryDate = DateTime.ParseExact(contract.LastTradeDateOrContractMonth, DateFormat.EightCharacter, CultureInfo.InvariantCulture);
var right = contract.Right == IB.RightType.Call ? OptionRight.Call : OptionRight.Put;
var strike = Convert.ToDecimal(contract.Strike);
@@ -3220,7 +3223,7 @@ namespace QuantConnect.Brokerages.InteractiveBrokers
// these are warning messages from IB
private static readonly HashSet<int> WarningCodes = new HashSet<int>
{
102, 104, 105, 106, 107, 109, 110, 111, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 129, 131, 132, 133, 134, 135, 136, 137, 140, 141, 146, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 201, 303,313,314,315,319,325,328,329,334,335,336,337,338,339,340,341,342,343,345,347,348,349,350,352,353,355,356,358,359,360,361,362,363,364,367,368,369,370,371,372,373,374,375,376,377,378,379,380,382,383,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,402,403,404,405,406,407,408,409,410,411,412,413,417,418,419,420,421,422,423,424,425,426,427,428,429,430,433,434,435,436,437,439,440,441,442,443,444,445,446,447,448,449,450,1100,10002,10003,10006,10007,10008,10009,10010,10011,10012,10014,10018,10019,10020,10052,10147,10148,10149,1101,1102,2100,2101,2102,2103,2105,2109,2110,2148
102, 104, 105, 106, 107, 109, 110, 111, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 129, 131, 132, 133, 134, 135, 136, 137, 140, 141, 146, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 201, 303,313,314,315,319,325,328,329,334,335,336,337,338,339,340,341,342,343,345,347,348,349,350,352,353,355,356,358,359,360,361,362,363,364,367,368,369,370,371,372,373,374,375,376,377,378,379,380,382,383,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,402,403,404,405,406,407,408,409,410,411,412,413,417,418,419,420,421,422,423,424,425,426,427,428,429,430,433,434,435,436,437,439,440,441,442,443,444,445,446,447,448,449,450,10002,10003,10006,10007,10008,10009,10010,10011,10012,10014,10018,10019,10020,10052,10147,10148,10149,2100,2101,2102,2109,2148
};
// these require us to issue invalidated order events

View File

@@ -19,6 +19,7 @@ using System.Collections.Generic;
using Newtonsoft.Json;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Interfaces;
using QuantConnect.Util;
namespace QuantConnect
{
@@ -183,7 +184,7 @@ namespace QuantConnect
/// It is calculated by taking a portfolio's annualized rate of return and subtracting the risk free rate of return.
/// </summary>
/// <remarks>For performance we only truncate when the value is gotten</remarks>
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore), JsonConverter(typeof(StringDecimalJsonConverter), true)]
public decimal SortinoRatio
{
get

View File

@@ -16,7 +16,7 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using QuantConnect.Packets;
using QuantConnect.Statistics;
namespace QuantConnect.Api
{
@@ -55,12 +55,6 @@ namespace QuantConnect.Api
[JsonProperty(PropertyName = "progress")]
public decimal Progress;
/// <summary>
/// Result packet for the backtest
/// </summary>
[JsonProperty(PropertyName = "result")]
public BacktestResult Result;
/// <summary>
/// Backtest error message
/// </summary>
@@ -78,6 +72,56 @@ namespace QuantConnect.Api
/// </summary>
[JsonProperty(PropertyName = "created")]
public DateTime Created;
/// <summary>
/// Rolling window detailed statistics.
/// </summary>
[JsonProperty(PropertyName = "rollingWindow", NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string, AlgorithmPerformance> RollingWindow;
/// <summary>
/// Rolling window detailed statistics.
/// </summary>
[JsonProperty(PropertyName = "totalPerformance", NullValueHandling = NullValueHandling.Ignore)]
public AlgorithmPerformance TotalPerformance;
/// <summary>
/// Contains population averages scores over the life of the algorithm
/// </summary>
[JsonProperty(PropertyName = "alphaRuntimeStatistics", NullValueHandling = NullValueHandling.Ignore)]
public AlphaRuntimeStatistics AlphaRuntimeStatistics;
/// <summary>
/// Charts updates for the live algorithm since the last result packet
/// </summary>
[JsonProperty(PropertyName = "charts", NullValueHandling = NullValueHandling.Ignore)]
public IDictionary<string, Chart> Charts;
/// <summary>
/// Statistics information sent during the algorithm operations.
/// </summary>
/// <remarks>Intended for update mode -- send updates to the existing statistics in the result GUI. If statistic key does not exist in GUI, create it</remarks>
[JsonProperty(PropertyName = "statistics", NullValueHandling = NullValueHandling.Ignore)]
public IDictionary<string, string> Statistics;
/// <summary>
/// Runtime banner/updating statistics in the title banner of the live algorithm GUI.
/// </summary>
[JsonProperty(PropertyName = "runtimeStatistics", NullValueHandling = NullValueHandling.Ignore)]
public IDictionary<string, string> RuntimeStatistics;
}
/// <summary>
/// Wrapper class for Backtest/* endpoints JSON response
/// Currently used by Backtest/Read and Backtest/Create
/// </summary>
public class BacktestResponseWrapper : RestResponse
{
/// <summary>
/// Backtest Object
/// </summary>
[JsonProperty(PropertyName = "backtest")]
public Backtest Backtest;
}
/// <summary>

View File

@@ -33,6 +33,12 @@ namespace QuantConnect.Packets
: base(type)
{ }
/// <summary>
/// The host name to use if any
/// </summary>
[JsonProperty(PropertyName = "sHostName")]
public string HostName;
/// <summary>
/// User Id placing request
/// </summary>

View File

@@ -49,6 +49,12 @@ namespace QuantConnect.Packets
[JsonProperty(PropertyName = "sAlgorithmID")]
public string AlgorithmId;
/// <summary>
/// OptimizationId for this result packet if any
/// </summary>
[JsonProperty(PropertyName = "sOptimizationID")]
public string OptimizationId;
/// <summary>
/// Project Id associated with this status packet
/// </summary>

View File

@@ -44,6 +44,12 @@ namespace QuantConnect.Packets
[JsonProperty(PropertyName = "sBacktestID")]
public string BacktestId = DefaultId;
/// <summary>
/// Optimization Id for this task
/// </summary>
[JsonProperty(PropertyName = "sOptimizationID")]
public string OptimizationId;
/// <summary>
/// Backtest start-date as defined in the Initialize() method.
/// </summary>

View File

@@ -52,6 +52,12 @@ namespace QuantConnect.Packets
[JsonProperty(PropertyName = "sBacktestID")]
public string BacktestId = "";
/// <summary>
/// OptimizationId for this result packet if any
/// </summary>
[JsonProperty(PropertyName = "sOptimizationID")]
public string OptimizationId;
/// <summary>
/// Compile Id for the algorithm which generated this result packet.
/// </summary>
@@ -147,6 +153,7 @@ namespace QuantConnect.Packets
Results = packet.Results;
ProcessingTime = packet.ProcessingTime;
TradeableDates = packet.TradeableDates;
OptimizationId = packet.OptimizationId;
}
catch (Exception err)
{
@@ -175,6 +182,7 @@ namespace QuantConnect.Packets
CompileId = job.CompileId;
Channel = job.Channel;
BacktestId = job.BacktestId;
OptimizationId = job.OptimizationId;
Results = results;
Name = job.Name;
UserId = job.UserId;

View File

@@ -146,8 +146,8 @@ namespace QuantConnect.Packets
/// <summary>
/// The cost associated with running this job
/// </summary>
[JsonProperty(PropertyName = "iCreditCost")]
public uint CreditCost;
[JsonProperty(PropertyName = "dCreditCost")]
public decimal CreditCost;
/// <summary>
/// Initializes a new default instance of the <see cref="Controls"/> class

View File

@@ -162,6 +162,9 @@ namespace QuantConnect.Packets
OptimizationEstimate,
/// Optimization work status update
OptimizationStatus
OptimizationStatus,
/// Optimization work result
OptimizationResult
}
}

View File

@@ -84,6 +84,9 @@ def mapper(key):
if keyType is Symbol:
return str(key.ID)
if keyType is str:
reserved = ['high', 'low', 'open', 'close']
if key in reserved:
return key
kvp = SymbolCache.TryGetSymbol(key, None)
if kvp[0]:
return str(kvp[1].ID)

View File

@@ -935,6 +935,9 @@
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Python\Python.Runtime.dll.config" Link="Python.Runtime.dll.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Content Include="decimal.py">

View File

@@ -240,7 +240,7 @@ namespace QuantConnect
{
if (SecurityType != SecurityType.Option && SecurityType != SecurityType.FutureOption)
{
throw new InvalidOperationException("OptionType is only defined for SecurityType.Option and SecurityType.FutureOption");
throw new InvalidOperationException("StrikePrice is only defined for SecurityType.Option and SecurityType.FutureOption");
}
// performance: lets calculate strike price once

View File

@@ -41,8 +41,9 @@ namespace QuantConnect
/// <param name="series">The series to be sampled</param>
/// <param name="start">The date to start sampling, if before start of data then start of data will be used</param>
/// <param name="stop">The date to stop sampling, if after stop of data, then stop of data will be used</param>
/// <param name="truncateValues">True will truncate values to integers</param>
/// <returns>The sampled series</returns>
public Series Sample(Series series, DateTime start, DateTime stop)
public Series Sample(Series series, DateTime start, DateTime stop, bool truncateValues = false)
{
var sampled = new Series(series.Name, series.SeriesType, series.Index, series.Unit);
@@ -59,7 +60,13 @@ namespace QuantConnect
{
if (point.x >= nextSample && point.x <= unixStopDate)
{
sampled.Values.Add(point);
var samplePoint = point;
if (truncateValues)
{
// let's not modify the original
samplePoint = new ChartPoint(samplePoint) { y = Math.Truncate(samplePoint.y) };
}
sampled.Values.Add(samplePoint);
}
}
return sampled;
@@ -106,7 +113,12 @@ namespace QuantConnect
while (nextSample <= current.x && nextSample <= unixStopDate)
{
var value = Interpolate(previous, current, (long) nextSample);
sampled.Values.Add(new ChartPoint {x = (long) nextSample, y = value});
var point = new ChartPoint {x = (long) nextSample, y = value};
if (truncateValues)
{
point.y = Math.Truncate(point.y);
}
sampled.Values.Add(point);
nextSample += _seconds;
}

View File

@@ -307,6 +307,10 @@ namespace QuantConnect
throw new ArgumentNullException(nameof(value));
}
ID = sid;
if (ID.HasUnderlying)
{
Underlying = new Symbol(ID.Underlying, ID.Underlying.Symbol);
}
Value = value.LazyToUpper();
}

View File

@@ -1030,19 +1030,26 @@ namespace QuantConnect.Lean.Engine
{
for (var i = delistings.Count - 1; i >= 0; i--)
{
// check if we are holding position
var security = algorithm.Securities[delistings[i].Symbol];
var delisting = delistings[i];
var security = algorithm.Securities[delisting.Symbol];
if (security.Holdings.Quantity == 0)
{
continue;
}
// check if the time has come for delisting
var delistingTime = delistings[i].Time;
var nextMarketOpen = security.Exchange.Hours.GetNextMarketOpen(delistingTime, false);
var nextMarketClose = security.Exchange.Hours.GetNextMarketClose(nextMarketOpen, false);
var delistingTime = delisting.Time;
if (!security.Exchange.Hours.IsOpen(delistingTime, false))
{
// This exists as a defensive measure to ensure that the delisting time
// does not get moved if the market is open. If the market is closed,
// we get the next market open, which will be on the same day if the delisting
// date is a trading day. If the delisting date is after market close, then
// the delisting will be adjusted to the next market open.
delistingTime = security.Exchange.Hours.GetNextMarketOpen(delistingTime, false);
delistingTime = security.Exchange.Hours.GetNextMarketClose(delistingTime, false);
}
if (security.LocalTime < nextMarketClose)
if (security.LocalTime < delistingTime)
{
continue;
}

View File

@@ -31,6 +31,7 @@ namespace QuantConnect.Lean.Engine.DataFeeds
private readonly int _uid = Config.GetInt("job-user-id", 0);
private readonly string _token = Config.Get("api-access-token", "1");
private readonly string _dataPath = Config.Get("data-folder", "../../../Data/");
private static readonly int DownloadPeriod = Config.GetInt("api-data-update-period", 5);
private readonly Api.Api _api;
/// <summary>
@@ -51,40 +52,70 @@ namespace QuantConnect.Lean.Engine.DataFeeds
/// <returns>A <see cref="Stream"/> of the data requested</returns>
public Stream Fetch(string key)
{
if (File.Exists(key))
{
return new FileStream(key, FileMode.Open, FileAccess.Read, FileShare.Read);
}
// If the file cannot be found on disc, attempt to retrieve it from the API
Symbol symbol;
DateTime date;
Resolution resolution;
// Fetch the details of this data request
if (LeanData.TryParsePath(key, out symbol, out date, out resolution))
{
Log.Trace("ApiDataProvider.Fetch(): Attempting to get data from QuantConnect.com's data library for symbol({0}), resolution({1}) and date({2}).",
if (!File.Exists(key) || IsOutOfDate(resolution, key))
{
return DownloadData(key, symbol, date, resolution);
}
// Use the file already on the disk
return new FileStream(key, FileMode.Open, FileAccess.Read, FileShare.Read);
}
Log.Error("ApiDataProvider.Fetch(): failed to parse key {0}", key);
return null;
}
/// <summary>
/// Determine if the file is out of date based on configuration and needs to be updated
/// </summary>
/// <param name="resolution">Data resolution</param>
/// <param name="filepath">Path to the file</param>
/// <returns>True if the file is out of date</returns>
/// <remarks>Files are only "out of date" for Hourly/Daily data because this data is stored all in one file</remarks>
public static bool IsOutOfDate(Resolution resolution, string filepath)
{
return resolution >= Resolution.Hour &&
(DateTime.Now - TimeSpan.FromDays(DownloadPeriod)) > File.GetLastWriteTime(filepath);
}
/// <summary>
/// Attempt to download data using the Api for and return a FileStream of that data.
/// </summary>
/// <param name="key"></param>
/// <param name="symbol"></param>
/// <param name="date"></param>
/// <param name="resolution"></param>
/// <returns>A FileStream of the data</returns>
private FileStream DownloadData(string filepath, Symbol symbol, DateTime date, Resolution resolution)
{
Log.Trace("ApiDataProvider.Fetch(): Attempting to get data from QuantConnect.com's data library for symbol({0}), resolution({1}) and date({2}).",
symbol.Value,
resolution,
date.Date.ToShortDateString());
var downloadSuccessful = _api.DownloadData(symbol, resolution, date);
if (downloadSuccessful)
{
Log.Trace("ApiDataProvider.Fetch(): Successfully retrieved data for symbol({0}), resolution({1}) and date({2}).",
symbol.Value,
resolution,
date.Date.ToShortDateString());
var downloadSuccessful = _api.DownloadData(symbol, resolution, date);
if (downloadSuccessful)
{
Log.Trace("ApiDataProvider.Fetch(): Successfully retrieved data for symbol({0}), resolution({1}) and date({2}).",
symbol.Value,
resolution,
date.Date.ToShortDateString());
return new FileStream(key, FileMode.Open, FileAccess.Read, FileShare.Read);
}
return new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
// Failed to download
Log.Error("ApiDataProvider.Fetch(): Unable to remotely retrieve data for path {0}. " +
"Please make sure you have the necessary data in your online QuantConnect data library.",
key);
"Please make sure you have the necessary data in your online QuantConnect data library.",
filepath);
return null;
}
}

View File

@@ -653,7 +653,7 @@ namespace QuantConnect.Lean.Engine.Results
/// <param name="message">Additional optional status message.</param>
public virtual void SendStatusUpdate(AlgorithmStatus status, string message = "")
{
var statusPacket = new AlgorithmStatusPacket(_algorithmId, _projectId, status, message);
var statusPacket = new AlgorithmStatusPacket(_algorithmId, _projectId, status, message) { OptimizationId = _job.OptimizationId };
MessagingHandler.Send(statusPacket);
}

View File

@@ -42,6 +42,8 @@ namespace QuantConnect.Lean.Engine.Results
private static readonly TextWriter StandardOut = Console.Out;
private static readonly TextWriter StandardError = Console.Error;
private string _hostName;
/// <summary>
/// The main loop update interval
/// </summary>
@@ -232,6 +234,7 @@ namespace QuantConnect.Lean.Engine.Results
protected virtual Dictionary<string, string> GetServerStatistics(DateTime utcNow)
{
var serverStatistics = OS.GetServerStatistics();
serverStatistics["Hostname"] = _hostName;
var upTime = utcNow - StartTime;
serverStatistics["Up Time"] = $"{upTime.Days}d {upTime:hh\\:mm\\:ss}";
serverStatistics["Total RAM (MB)"] = RamAllocation;
@@ -305,6 +308,7 @@ namespace QuantConnect.Lean.Engine.Results
/// <param name="transactionHandler">The transaction handler used to get the algorithms <see cref="Order"/> information</param>
public virtual void Initialize(AlgorithmNodePacket job, IMessagingHandler messagingHandler, IApi api, ITransactionHandler transactionHandler)
{
_hostName = job.HostName ?? Environment.MachineName;
MessagingHandler = messagingHandler;
TransactionHandler = transactionHandler;
CompileId = job.CompileId;

View File

@@ -0,0 +1,101 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
using System;
namespace QuantConnect.Indicators
{
/// <summary>
/// The Awesome Oscillator Indicator tracks the price midpoint-movement of a security. Specifically,
/// <para>
/// AO = MAfast[(H+L)/2] - MAslow[(H+L)/2]
/// </para>
/// where MAfast and MAslow denote simple moving averages wherein fast has a shorter period.
/// https://www.barchart.com/education/technical-indicators/awesome_oscillator
/// </summary>
public class AwesomeOscillator : BarIndicator, IIndicatorWarmUpPeriodProvider
{
/// <summary>
/// Gets the indicators slow period moving average.
/// </summary>
public IndicatorBase<IndicatorDataPoint> SlowAo { get; }
/// <summary>
/// Gets the indicators fast period moving average.
/// </summary>
public IndicatorBase<IndicatorDataPoint> FastAo { get; }
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady => SlowAo.IsReady && FastAo.IsReady;
/// <summary>
/// Required period, in data points, for the indicator to be ready and fully initialized.
/// </summary>
public int WarmUpPeriod { get; }
/// <summary>
/// Creates a new Awesome Oscillator from the specified periods.
/// </summary>
/// <param name="fastPeriod">The period of the fast moving average associated with the AO</param>
/// <param name="slowPeriod">The period of the slow moving average associated with the AO</param>
/// <param name="type">The type of moving average used when computing the fast and slow term. Defaults to simple moving average.</param>
public AwesomeOscillator(int fastPeriod, int slowPeriod, MovingAverageType type=MovingAverageType.Simple)
: this($"AO({fastPeriod},{slowPeriod},{type})", fastPeriod, slowPeriod, type)
{
}
/// <summary>
/// Creates a new Awesome Oscillator from the specified periods.
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="fastPeriod">The period of the fast moving average associated with the AO</param>
/// <param name="slowPeriod">The period of the slow moving average associated with the AO</param>
/// <param name="type">The type of moving average used when computing the fast and slow term. Defaults to simple moving average.</param>
public AwesomeOscillator(string name, int fastPeriod, int slowPeriod, MovingAverageType type=MovingAverageType.Simple)
: base(name)
{
SlowAo = type.AsIndicator(slowPeriod);
FastAo = type.AsIndicator(fastPeriod);
WarmUpPeriod = Math.Max(slowPeriod, fastPeriod);
}
/// <summary>
/// Computes the next value of this indicator from the given state.
/// </summary>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IBaseDataBar input)
{
var presentValue = (input.High + input.Low) / 2;
SlowAo.Update(input.Time, presentValue);
FastAo.Update(input.Time, presentValue);
return IsReady ? FastAo - SlowAo : 0m;
}
/// <summary>
/// Resets this indicator
/// </summary>
public override void Reset()
{
FastAo.Reset();
SlowAo.Reset();
base.Reset();
}
}
}

View File

@@ -0,0 +1,95 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators
{
/// <summary>
/// The Chaikin Money Flow Index (CMF) is a volume-weighted average of accumulation and distribution over
/// a specified period.
///
/// CMF = n-day Sum of [(((C - L) - (H - C)) / (H - L)) x Vol] / n-day Sum of Vol
///
/// Where:
/// n = number of periods, typically 21
/// H = high
/// L = low
/// C = close
/// Vol = volume
///
/// https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/cmf
/// </summary>
public class ChaikinMoneyFlow : TradeBarIndicator, IIndicatorWarmUpPeriodProvider
{
/// <summary>
/// Holds the point-wise flow-sum and volume terms.
/// </summary>
private readonly Sum _flowRatioSum;
private readonly Sum _volumeSum;
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady => _flowRatioSum.IsReady;
/// <summary>
/// Required period, in data points, for the indicator to be ready and fully initialized.
/// </summary>
public int WarmUpPeriod { get; }
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_volumeSum.Reset();
_flowRatioSum.Reset();
base.Reset();
}
/// <summary>
/// Initializes a new instance of the ChaikinMoneyFlow class
/// </summary>
/// <param name="name">A name for the indicator</param>
/// <param name="period">The period over which to perform computation</param>
public ChaikinMoneyFlow(string name, int period)
: base($"CMF({name})")
{
WarmUpPeriod = period;
_flowRatioSum = new Sum(period);
_volumeSum = new Sum(period);
}
/// <summary>
/// Computes the next value for this indicator from the given state.
/// </summary>
/// <param name="input">The input value to this indicator on this time step</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(TradeBar input)
{
var denominator = (input.High - input.Low);
var flowRatio = denominator > 0
? input.Volume * (input.Close - input.Low - (input.High - input.Close)) / denominator
: 0m;
_flowRatioSum.Update(input.EndTime, flowRatio);
_volumeSum.Update(input.EndTime, input.Volume);
return !IsReady || _volumeSum == 0m ? 0m : _flowRatioSum / _volumeSum;
}
}
}

View File

@@ -0,0 +1,120 @@
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using QuantConnect.Data.Market;
namespace QuantConnect.Indicators
{
/// <summary>
/// In the DeMarker strategy, for some period of size N, set:
/// <para>
/// DeMax = High - Previous High, and
/// DeMin = Previous Low - Low
/// </para>
/// where, in the prior, if either term is less than zero (DeMax or DeMin), set it to zero.
/// We can now define the indicator itself, DEM, as:
///<para>
/// DEM = MA(DeMax)/(MA(DeMax)+MA(DeMin))
///</para>
/// where MA denotes a Moving Average of period N.
///
/// https://www.investopedia.com/terms/d/demarkerindicator.asp
/// </summary>
public class DeMarkerIndicator : BarIndicator, IIndicatorWarmUpPeriodProvider
{
private readonly IndicatorBase<IndicatorDataPoint> _maxMA;
private readonly IndicatorBase<IndicatorDataPoint> _minMA;
private decimal _lastHigh;
private decimal _lastLow;
/// <summary>
/// Initializes a new instance of the DeMarkerIndicator class with the specified period
/// </summary>
/// <param name="period">The period of the DeMarker Indicator</param>
/// <param name="type">The type of moving average to use in calculations</param>
public DeMarkerIndicator(int period, MovingAverageType type = MovingAverageType.Simple)
: this($"DEM({period},{type})", period, type)
{
}
/// <summary>
/// Initializes a new instance of the DeMarkerIndicator class with the specified name and period
/// </summary>
/// <param name="name">The name of this indicator</param>
/// <param name="period">The period of the DeMarker Indicator</param>
/// <param name="type">The type of moving average to use in calculations</param>
public DeMarkerIndicator(string name, int period, MovingAverageType type = MovingAverageType.Simple)
: base(name)
{
var _lastHigh = 0m;
var _lastLow = 0m;
WarmUpPeriod = period;
_maxMA = type.AsIndicator(period);
_minMA = type.AsIndicator(period);
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady => _maxMA.IsReady && _minMA.IsReady;
/// <summary>
/// Required period, in data points, for the indicator to be ready and fully initialized.
/// </summary>
public int WarmUpPeriod { get; }
/// <summary>
/// Resets this indicator to its initial state
/// </summary>
public override void Reset()
{
_maxMA.Reset();
_minMA.Reset();
base.Reset();
}
/// <summary>
/// Computes the next value of this indicator from the given state
/// </summary>
/// <param name="input">The input given to the indicator</param>
/// <returns>A new value for this indicator</returns>
protected override decimal ComputeNextValue(IBaseDataBar input)
{
var deMax = 0m;
var deMin = 0m;
if (Samples > 1)
{
// By default, DeMin and DeMax must be 0m initially
deMax = Math.Max(input.High - _lastHigh, 0);
deMin = Math.Max(_lastLow - input.Low, 0);
}
_maxMA.Update(input.Time, deMax);
_minMA.Update(input.Time, deMin);
_lastHigh = input.High;
_lastLow = input.Low;
if (!IsReady)
{
return 0m;
}
var currentValue = _maxMA + _minMA;
return currentValue > 0m ? _maxMA / currentValue : 0m;
}
}
}

View File

@@ -120,7 +120,18 @@ namespace QuantConnect.Indicators
return Update((T)(object)new IndicatorDataPoint(time, value));
}
throw new NotSupportedException($"{GetType().Name} does not support Update(DateTime, decimal) method overload. Use Update({typeof(T).Name}) instead.");
var suggestions = new List<string>
{
"Update(TradeBar)",
"Update(QuoteBar)"
};
if (typeof(T) == typeof(IBaseData))
{
suggestions.Add("Update(Tick)");
}
throw new NotSupportedException($"{GetType().Name} does not support the `Update(DateTime, decimal)` method. Use one of the following methods instead: {string.Join(", ", suggestions)}");
}
/// <summary>
@@ -257,4 +268,4 @@ namespace QuantConnect.Indicators
Updated?.Invoke(this, consolidated);
}
}
}
}

View File

@@ -108,6 +108,7 @@
<Compile Include="ArnaudLegouxMovingAverage.cs" />
<Compile Include="AverageDirectionalIndex.cs" />
<Compile Include="AverageDirectionalMovementIndexRating.cs" />
<Compile Include="AwesomeOscillator.cs" />
<Compile Include="BalanceOfPower.cs" />
<Compile Include="CandlestickPatterns\UpDownGapThreeMethods.cs" />
<Compile Include="CandlestickPatterns\UpsideGapTwoCrows.cs" />
@@ -173,8 +174,10 @@
<Compile Include="CandlestickPatterns\ThreeWhiteSoldiers.cs" />
<Compile Include="CandlestickPatterns\Doji.cs" />
<Compile Include="CandlestickPatterns\TwoCrows.cs" />
<Compile Include="ChaikinMoneyFlow.cs" />
<Compile Include="ChandeMomentumOscillator.cs" />
<Compile Include="CoppockCurve.cs" />
<Compile Include="DeMarkerIndicator.cs" />
<Compile Include="DetrendedPriceOscillator.cs" />
<Compile Include="DonchianChannel.cs" />
<Compile Include="DoubleExponentialMovingAverage.cs" />
@@ -183,7 +186,7 @@
<Compile Include="SchaffTrendCycle.cs" />
<Compile Include="WilderMovingAverage.cs" />
<Compile Include="FractalAdaptiveMovingAverage.cs" />
<Compile Include="EaseOfMovementValue.cs"/>
<Compile Include="EaseOfMovementValue.cs" />
<Compile Include="FilteredIdentity.cs" />
<Compile Include="HullMovingAverage.cs" />
<Compile Include="MassIndex.cs" />

View File

@@ -236,9 +236,6 @@
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
<None Include="Python.Runtime.dll.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.VersionCheckAnalyzer.2.9.3\analyzers\dotnet\Microsoft.CodeAnalysis.VersionCheckAnalyzer.dll" />

View File

@@ -0,0 +1,39 @@
/*
* 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.
*/
namespace QuantConnect.Logging
{
/// <summary>
/// Subclass of ConsoleLogHandler that only logs error messages
/// </summary>
public class ConsoleErrorLogHandler : ConsoleLogHandler
{
/// <summary>
/// Hide debug messages from log
/// </summary>
/// <param name="text">The debug text to log</param>
public override void Debug(string text)
{
}
/// <summary>
/// Hide trace messages from log
/// </summary>
/// <param name="text">The trace text to log</param>
public override void Trace(string text)
{
}
}
}

View File

@@ -54,7 +54,7 @@ namespace QuantConnect.Logging
/// Write error message to log
/// </summary>
/// <param name="text">The error text to log</param>
public void Error(string text)
public virtual void Error(string text)
{
#if DEBUG
Console.ForegroundColor = ConsoleColor.Red;
@@ -69,7 +69,7 @@ namespace QuantConnect.Logging
/// Write debug message to log
/// </summary>
/// <param name="text">The debug text to log</param>
public void Debug(string text)
public virtual void Debug(string text)
{
_trace.WriteLine(DateTime.Now.ToString(_dateFormat, CultureInfo.InvariantCulture) + " DEBUG:: " + text);
}
@@ -78,7 +78,7 @@ namespace QuantConnect.Logging
/// Write debug message to log
/// </summary>
/// <param name="text">The trace text to log</param>
public void Trace(string text)
public virtual void Trace(string text)
{
_trace.WriteLine(DateTime.Now.ToString(_dateFormat, CultureInfo.InvariantCulture) + " Trace:: " + text);
}

View File

@@ -109,6 +109,7 @@
</Compile>
<Compile Include="CompositeLogHandler.cs" />
<Compile Include="CompositeNLogHandler.cs" />
<Compile Include="ConsoleErrorLogHandler.cs" />
<Compile Include="NLogHandler.cs" />
<Compile Include="QueueLogHandler.cs" />
<Compile Include="FunctionalLogHandler.cs" />

View File

@@ -18,6 +18,7 @@ using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Linq;
using QuantConnect.Optimizer.Parameters;
using Log = QuantConnect.Logging.Log;
@@ -142,7 +143,8 @@ namespace QuantConnect.Optimizer.Launcher
if (Status != OptimizationStatus.Ended && Status != OptimizationStatus.Aborted)
{
var currentEstimate = GetCurrentEstimate();
var message = $"ConsoleLeanOptimizer.SendUpdate(): {currentEstimate}";
var stats = GetRuntimeStatistics();
var message = $"ConsoleLeanOptimizer.SendUpdate(): {currentEstimate} {string.Join(", ", stats.Select(pair => $"{pair.Key}:{pair.Value}"))}";
var currentBestBacktest = Strategy.Solution;
if (currentBestBacktest != null)
{

View File

@@ -19,6 +19,8 @@ using QuantConnect.Util;
using QuantConnect.Logging;
using QuantConnect.Configuration;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using QuantConnect.Optimizer.Objectives;
using QuantConnect.Optimizer.Parameters;
using QuantConnect.Optimizer.Strategies;
@@ -276,19 +278,27 @@ namespace QuantConnect.Optimizer
/// <summary>
/// Returns the current optimization status and strategy estimates
/// </summary>
public OptimizationEstimate GetCurrentEstimate()
public int GetCurrentEstimate()
{
return Strategy.GetTotalBacktestEstimate();
}
/// <summary>
/// Get the current runtime statistics
/// </summary>
public Dictionary<string, string> GetRuntimeStatistics()
{
var completedCount = _completedBacktest;
var totalCount = completedCount + _failedBacktest;
var runtime = DateTime.UtcNow - _startedAt;
return new OptimizationEstimate
return new Dictionary<string, string>
{
TotalBacktest = Strategy.GetTotalBacktestEstimate(),
CompletedBacktest = completedCount,
FailedBacktest = _failedBacktest,
RunningBacktest = RunningParameterSetForBacktest.Count,
InQueueBacktest = PendingParameterSet.Count,
AverageBacktest = completedCount > 0 ? new TimeSpan(runtime.Ticks / completedCount) : TimeSpan.Zero,
TotalRuntime = runtime
{ "Completed", $"{completedCount}"},
{ "Failed", $"{_failedBacktest}"},
{ "Running", $"{RunningParameterSetForBacktest.Count}"},
{ "In Queue", $"{PendingParameterSet.Count}"},
{ "Average Length", $"{(totalCount > 0 ? new TimeSpan(runtime.Ticks / totalCount) : TimeSpan.Zero).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture)}"},
{ "Total Runtime", $"{runtime.ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture)}" }
};
}
@@ -301,7 +311,7 @@ namespace QuantConnect.Optimizer
{
return $"OID {NodePacket.OptimizationId}";
}
return $"UI {NodePacket.UserId} PID {NodePacket.ProjectId} OID {NodePacket.OptimizationId}";
return $"UI {NodePacket.UserId} PID {NodePacket.ProjectId} OID {NodePacket.OptimizationId} S {Status}";
}
/// <summary>

View File

@@ -1,74 +0,0 @@
/*
* 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 Newtonsoft.Json;
namespace QuantConnect.Optimizer
{
public class OptimizationEstimate
{
/// <summary>
/// Total number of backtests, approximately
/// </summary>
[JsonProperty("totalBacktest")]
public int TotalBacktest { get; set; }
/// <summary>
/// Number of completed backtests
/// </summary>
[JsonProperty("completedBacktest")]
public int CompletedBacktest { get; set; }
/// <summary>
/// Number of failed backtests
/// </summary>
[JsonProperty("failedBacktest")]
public int FailedBacktest { get; set; }
/// <summary>
/// Number of running backtests
/// </summary>
[JsonProperty("runningBacktest")]
public int RunningBacktest { get; set; }
/// <summary>
/// Number of backtests in queue
/// </summary>
[JsonProperty("inQueueBacktest")]
public int InQueueBacktest { get; set; }
/// <summary>
/// Indicates backtest average duration; (start - now) / CompletedBacktest
/// </summary>
[JsonProperty("averageBacktest")]
public TimeSpan AverageBacktest { get; set; }
/// <summary>
/// The run time of this optimization
/// </summary>
[JsonProperty(PropertyName = "totalRuntime")]
public TimeSpan TotalRuntime { get; set; }
/// <summary>
/// Pretty representation of an optimization estimate
/// </summary>
public override string ToString()
{
return $"TotalBacktest: {TotalBacktest}. CompletedBacktest: {CompletedBacktest}. FailedBacktest: {FailedBacktest}." +
$" RunningBacktest: {RunningBacktest}. InQueueBacktest: {InQueueBacktest}. TotalRuntime {TotalRuntime}. AverageBacktest: {AverageBacktest}";
}
}
}

View File

@@ -63,7 +63,6 @@
<Compile Include="Strategies\OptimizationStrategySettings.cs" />
<Compile Include="Strategies\StepBaseOptimizationStrategy.cs" />
<Compile Include="Objectives\Objective.cs" />
<Compile Include="OptimizationEstimate.cs" />
<Compile Include="Objectives\Target.cs" />
<Compile Include="Objectives\Constraint.cs" />
<Compile Include="LeanOptimizer.cs" />

View File

@@ -128,6 +128,9 @@ namespace QuantConnect.Report
// More initialization, this time with Algorithm and other misc. classes
_resultHandler.Initialize(job, new Messaging.Messaging(), new Api.Api(), transactions);
_resultHandler.SetAlgorithm(Algorithm, Algorithm.Portfolio.TotalPortfolioValue);
Algorithm.Transactions.SetOrderProcessor(transactions);
transactions.Initialize(Algorithm, new BacktestingBrokerage(Algorithm), _resultHandler);
feed.Initialize(Algorithm, job, _resultHandler, null, null, null, _dataManager, null, null);

View File

@@ -27,7 +27,7 @@
"metadata": {},
"outputs": [],
"source": [
"#load \"QuantConnect.csx\"\n",
"#load \"../QuantConnect.csx\"\n",
"var qb = new QuantBook();\n",
"\n",
"// Selecting asset data\n",

View File

@@ -324,7 +324,22 @@ namespace QuantConnect.Research
// Load a canonical option Symbol if the user provides us with an underlying Symbol
if (symbol.SecurityType != SecurityType.Option && symbol.SecurityType != SecurityType.FutureOption)
{
symbol = AddOption(symbol, resolution, symbol.ID.Market).Symbol;
var option = AddOption(symbol, resolution, symbol.ID.Market);
// Allow 20 strikes from the money for futures. No expiry filter is applied
// so that any future contract provided will have data returned.
if (symbol.SecurityType == SecurityType.Future && symbol.IsCanonical())
{
throw new ArgumentException("The Future Symbol provided is a canonical Symbol (i.e. a Symbol representing all Futures), which is not supported at this time. " +
"If you are using the Symbol accessible from `AddFuture(...)`, use the Symbol from `AddFutureContract(...)` instead. " +
"You can use `qb.FutureOptionChainProvider(canonicalFuture, datetime)` to get a list of futures contracts for a given date, and add them to your algorithm with `AddFutureContract(symbol, Resolution)`.");
}
if (symbol.SecurityType == SecurityType.Future && !symbol.IsCanonical())
{
option.SetFilter(universe => universe.Strikes(-10, +10));
}
symbol = option.Symbol;
}
IEnumerable<Symbol> symbols;
@@ -337,8 +352,19 @@ namespace QuantConnect.Research
.GetHighestResolution();
if (!Securities.ContainsKey(symbol.Underlying))
{
// only add underlying if not present
AddEquity(symbol.Underlying.Value, resolutionToUseForUnderlying);
if (symbol.Underlying.SecurityType == SecurityType.Equity)
{
// only add underlying if not present
AddEquity(symbol.Underlying.Value, resolutionToUseForUnderlying);
}
if (symbol.Underlying.SecurityType == SecurityType.Future && symbol.Underlying.IsCanonical())
{
AddFuture(symbol.Underlying.ID.Symbol, resolutionToUseForUnderlying);
}
else if (symbol.Underlying.SecurityType == SecurityType.Future)
{
AddFutureContract(symbol.Underlying, resolutionToUseForUnderlying);
}
}
var allSymbols = new List<Symbol>();
for (var date = start; date < end; date = date.AddDays(1))

View File

@@ -71,6 +71,47 @@ namespace QuantConnect.Tests.Algorithm.Framework
Assert.IsTrue(construction.Insights.All(insight => insight.CloseTimeUtc != default(DateTime)));
}
[TestCase(true, 0)]
[TestCase(false, 2)]
public void DelistedSecuritiesInsightsTest(bool isDelisted, int expectedCount)
{
var algorithm = new QCAlgorithm();
algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
algorithm.Transactions.SetOrderProcessor(new FakeOrderProcessor());
algorithm.SetStartDate(2007, 5, 16);
algorithm.SetUniverseSelection(new ManualUniverseSelectionModel());
algorithm.SetFinishedWarmingUp();
var alpha = new FakeAlpha();
algorithm.SetAlpha(alpha);
var construction = new FakePortfolioConstruction();
algorithm.SetPortfolioConstruction(construction);
var actualInsights = new List<Insight>();
algorithm.InsightsGenerated += (s, e) => actualInsights.AddRange(e.Insights);
var security = algorithm.AddEquity("SPY", Resolution.Daily);
var tick = new Tick
{
Symbol = security.Symbol,
Value = 1,
Quantity = 2
};
security.SetMarketPrice(tick);
security.IsDelisted = isDelisted;
// Trigger Alpha to emit insight
algorithm.OnFrameworkData(new Slice(new DateTime(2000, 01, 01), new List<BaseData>() { tick }));
// Manually emit insight
algorithm.EmitInsights(Insight.Price(Symbols.SPY, TimeSpan.FromDays(1), InsightDirection.Up, .5, .75));
// Should be zero because security is delisted
Assert.AreEqual(expectedCount, actualInsights.Count);
}
class FakeAlpha : AlphaModel
{
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)

View File

@@ -86,12 +86,14 @@ namespace QuantConnect.Tests
? "../../../Algorithm.Python/" + algorithm + ".py"
: "QuantConnect.Algorithm." + language + ".dll");
// Store initial log variables
var initialLogHandler = Log.LogHandler;
var initialDebugEnabled = Log.DebuggingEnabled;
var debugEnabled = Log.DebuggingEnabled;
// Log handlers specific to this test function
var newLogHandlers = new ILogHandler[] { new ConsoleErrorLogHandler(), new FileLogHandler(logFile, false) };
var logHandlers = new ILogHandler[] {new ConsoleLogHandler(), new FileLogHandler(logFile, false)};
using (Log.LogHandler = new CompositeLogHandler(logHandlers))
using (Log.LogHandler = new CompositeLogHandler(newLogHandlers))
using (var algorithmHandlers = LeanEngineAlgorithmHandlers.FromConfiguration(Composer.Instance))
using (var systemHandlers = LeanEngineSystemHandlers.FromConfiguration(Composer.Instance))
using (var workerThread = new TestWorkerThread())
@@ -103,7 +105,6 @@ namespace QuantConnect.Tests
Log.Trace("");
// run the algorithm in its own thread
var engine = new Lean.Engine.Engine(systemHandlers, algorithmHandlers, false);
Task.Factory.StartNew(() =>
{
@@ -137,9 +138,11 @@ namespace QuantConnect.Tests
var defaultAlphaHandler = (DefaultAlphaHandler) algorithmHandlers.Alphas;
alphaStatistics = defaultAlphaHandler.RuntimeStatistics;
Log.DebuggingEnabled = debugEnabled;
}
// Reset settings to initial values
Log.LogHandler = initialLogHandler;
Log.DebuggingEnabled = initialDebugEnabled;
}
catch (Exception ex)
{

View File

@@ -353,7 +353,8 @@ namespace QuantConnect.Tests.API
Assert.IsTrue(backtestRead.Success);
Assert.IsTrue(backtestRead.Progress == 1);
Assert.IsTrue(backtestRead.Name == backtestName);
Assert.IsTrue(backtestRead.Result.Statistics["Total Trades"] == "1");
Assert.IsTrue(backtestRead.Statistics["Total Trades"] == "1");
Assert.IsTrue(backtestRead.Charts["Benchmark"].Series.Count > 0);
// Verify we have the backtest in our project
var listBacktests = _api.ListBacktests(project.Projects.First().ProjectId);

View File

@@ -21,16 +21,27 @@ using QuantConnect;
using QuantConnect.Configuration;
using QuantConnect.Logging;
using QuantConnect.Python;
using QuantConnect.Util;
[SetUpFixture]
public class AssemblyInitialize
{
[OneTimeSetUp]
public void SetLogHandler()
public void InitializeTestEnvironment()
{
AdjustCurrentDirectory();
// save output to file as well
Log.LogHandler = new ConsoleLogHandler();
if (TestContext.Parameters.Exists("log-handler"))
{
var logHandler = TestContext.Parameters["log-handler"];
Log.Trace($"QuantConnect.Tests.AssemblyInitialize(): Log handler test parameter loaded {logHandler}");
Log.LogHandler = Composer.Instance.GetExportedValueByTypeName<ILogHandler>(logHandler);
}
else
{
Log.LogHandler = new ConsoleLogHandler();
}
}
public static void AdjustCurrentDirectory()

View File

@@ -62,8 +62,6 @@ namespace QuantConnect.Tests.Brokerages.Alpaca
[Test, TestCaseSource(nameof(TestParameters))]
public void GetsHistory(Symbol symbol, Resolution resolution, TimeSpan period, bool shouldBeEmpty)
{
Log.LogHandler = new ConsoleLogHandler();
var keyId = Config.Get("alpaca-key-id");
var secretKey = Config.Get("alpaca-secret-key");
var tradingMode = Config.Get("alpaca-trading-mode");
@@ -101,14 +99,14 @@ namespace QuantConnect.Tests.Brokerages.Alpaca
{
foreach (var tick in slice.Ticks[symbol])
{
Console.WriteLine($"{tick.Time}: {tick.Symbol} - P={tick.Price}, Q={tick.Quantity}");
Log.Trace($"{tick.Time}: {tick.Symbol} - P={tick.Price}, Q={tick.Quantity}");
}
}
else
{
var bar = slice.Bars[symbol];
Console.WriteLine($"{bar.Time}: {bar.Symbol} - O={bar.Open}, H={bar.High}, L={bar.Low}, C={bar.Close}, V={bar.Volume}");
Log.Trace($"{bar.Time}: {bar.Symbol} - O={bar.Open}, H={bar.High}, L={bar.Low}, C={bar.Close}, V={bar.Volume}");
}
}

View File

@@ -25,6 +25,7 @@ using NUnit.Framework;
using QuantConnect.Brokerages.Alpaca;
using QuantConnect.Configuration;
using QuantConnect.Interfaces;
using QuantConnect.Logging;
using QuantConnect.Orders;
using QuantConnect.Securities;
@@ -162,12 +163,12 @@ namespace QuantConnect.Tests.Brokerages.Alpaca
{
var order = new MarketOrder(symbol, 10, DateTime.UtcNow);
OrderProvider.Add(order);
Console.WriteLine("Buy Order");
Log.Trace("Buy Order");
alpaca.PlaceOrder(order);
var orderr = new MarketOrder(symbol, -10, DateTime.UtcNow);
OrderProvider.Add(orderr);
Console.WriteLine("Sell Order");
Log.Trace("Sell Order");
alpaca.PlaceOrder(orderr);
}
@@ -291,9 +292,9 @@ namespace QuantConnect.Tests.Brokerages.Alpaca
var tenMinutes = TimeSpan.FromMinutes(10);
Console.WriteLine("------");
Console.WriteLine("Waiting for internet disconnection ");
Console.WriteLine("------");
Log.Trace("------");
Log.Trace("Waiting for internet disconnection ");
Log.Trace("------");
// spin while we manually disconnect the internet
while (brokerage.IsConnected)
@@ -304,9 +305,9 @@ namespace QuantConnect.Tests.Brokerages.Alpaca
var stopwatch = Stopwatch.StartNew();
Console.WriteLine("------");
Console.WriteLine("Trying to reconnect ");
Console.WriteLine("------");
Log.Trace("------");
Log.Trace("Trying to reconnect ");
Log.Trace("------");
// spin until we're reconnected
while (!brokerage.IsConnected && stopwatch.Elapsed < tenMinutes)

View File

@@ -461,7 +461,7 @@ namespace QuantConnect.Tests.Brokerages
lock (sync)
{
remaining -= orderEvent.FillQuantity;
Console.WriteLine("Remaining: " + remaining + " FillQuantity: " + orderEvent.FillQuantity);
Log.Trace("Remaining: " + remaining + " FillQuantity: " + orderEvent.FillQuantity);
if (orderEvent.Status == OrderStatus.Filled)
{
manualResetEvent.Set();
@@ -480,7 +480,7 @@ namespace QuantConnect.Tests.Brokerages
manualResetEvent.WaitOne(2500);
manualResetEvent.WaitOne(2500);
Console.WriteLine("Remaining: " + remaining);
Log.Trace("Remaining: " + remaining);
Assert.AreEqual(0, remaining);
}
@@ -636,7 +636,7 @@ namespace QuantConnect.Tests.Brokerages
}
catch (Exception err)
{
Console.WriteLine(err.Message);
Log.Error(err.Message);
}
}, cancellationToken.Token);
}

View File

@@ -22,6 +22,7 @@ using QuantConnect.Brokerages.Fxcm;
using QuantConnect.Configuration;
using QuantConnect.Interfaces;
using QuantConnect.Lean.Engine.DataFeeds;
using QuantConnect.Logging;
using QuantConnect.Orders;
using QuantConnect.Securities;
@@ -114,9 +115,9 @@ namespace QuantConnect.Tests.Brokerages.Fxcm
var tenMinutes = TimeSpan.FromMinutes(10);
Console.WriteLine("------");
Console.WriteLine("Waiting for internet disconnection ");
Console.WriteLine("------");
Log.Trace("------");
Log.Trace("Waiting for internet disconnection ");
Log.Trace("------");
// spin while we manually disconnect the internet
while (brokerage.IsConnected)
@@ -127,9 +128,9 @@ namespace QuantConnect.Tests.Brokerages.Fxcm
var stopwatch = Stopwatch.StartNew();
Console.WriteLine("------");
Console.WriteLine("Trying to reconnect ");
Console.WriteLine("------");
Log.Trace("------");
Log.Trace("Trying to reconnect ");
Log.Trace("------");
// spin until we're reconnected
while (!brokerage.IsConnected && stopwatch.Elapsed < tenMinutes)

View File

@@ -27,6 +27,7 @@ using QuantConnect.Brokerages.InteractiveBrokers;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Lean.Engine.DataFeeds;
using QuantConnect.Logging;
using QuantConnect.Securities;
using QuantConnect.Util;
using Order = QuantConnect.Orders.Order;
@@ -68,7 +69,7 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
var stopwatch = Stopwatch.StartNew();
var value = (ContractDetails)method.Invoke(brokerage, parameters);
stopwatch.Stop();
Console.WriteLine($"{DateTime.UtcNow:O} Response time: {stopwatch.Elapsed}");
Log.Trace($"{DateTime.UtcNow:O} Response time: {stopwatch.Elapsed}");
});
while (!result.IsCompleted) Thread.Sleep(1000);
}

View File

@@ -137,7 +137,7 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
}
catch (Exception err)
{
Console.WriteLine(err.Message);
QuantConnect.Logging.Log.Error(err.Message);
}
});
}
@@ -146,7 +146,7 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
{
if (tick != null)
{
Console.WriteLine("{0}: {1} - {2} @ {3}", tick.Time, tick.Symbol, tick.Price, ((Tick)tick).Quantity);
QuantConnect.Logging.Log.Trace("{0}: {1} - {2} @ {3}", tick.Time, tick.Symbol, tick.Price, ((Tick)tick).Quantity);
}
}
}

View File

@@ -447,7 +447,7 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
foreach (var holding in previousHoldings)
{
Console.WriteLine(holding.Value);
Log.Trace(holding.Value.ToString());
}
var hasSymbol = previousHoldings.ContainsKey(Symbols.USDJPY);
@@ -497,7 +497,7 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
Assert.IsTrue(cashBalance.Any(x => x.Currency == Currencies.USD));
foreach (var cash in cashBalance)
{
Console.WriteLine(cash);
Log.Trace(cash.ToString());
if (cash.Currency == Currencies.USD)
{
Assert.AreNotEqual(0m, cashBalance.Single(x => x.Currency == Currencies.USD));
@@ -590,7 +590,7 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
var executions = ib.GetExecutions(null, null, null, DateTime.UtcNow.AddDays(-1), null);
stopwatch.Stop();
Console.WriteLine("Total executions fetched: {0}, elapsed time: {1} ms", executions.Count, stopwatch.ElapsedMilliseconds);
Log.Trace("Total executions fetched: {0}, elapsed time: {1} ms", executions.Count, stopwatch.ElapsedMilliseconds);
Assert.IsTrue(executions.Any(x => order.BrokerId.Any(id => executions.Any(e => e.Execution.OrderId == Parse.Int(id)))));
}
@@ -630,9 +630,9 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
var tenMinutes = TimeSpan.FromMinutes(10);
Console.WriteLine("------");
Console.WriteLine("Waiting for internet disconnection ");
Console.WriteLine("------");
Log.Trace("------");
Log.Trace("Waiting for internet disconnection ");
Log.Trace("------");
// spin while we manually disconnect the internet
while (ib.IsConnected)
@@ -643,9 +643,9 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
var stopwatch = Stopwatch.StartNew();
Console.WriteLine("------");
Console.WriteLine("Trying to reconnect ");
Console.WriteLine("------");
Log.Trace("------");
Log.Trace("Trying to reconnect ");
Log.Trace("------");
// spin until we're reconnected
while (!ib.IsConnected && stopwatch.Elapsed < tenMinutes)

View File

@@ -31,8 +31,6 @@ namespace QuantConnect.Tests.Brokerages.InteractiveBrokers
[Test]
public void CreatesExpectedFuturesContracts()
{
Log.LogHandler = new ConsoleLogHandler();
var symbolMapper = new InteractiveBrokersSymbolMapper();
using (var ib = new InteractiveBrokersBrokerage(new QCAlgorithm(), new OrderProvider(), new SecurityProvider(), new AggregationManager()))

View File

@@ -94,7 +94,7 @@ namespace QuantConnect.Tests.Brokerages.Oanda
brokerage.Subscribe(config, (s, e) => { });
}
stopwatch.Stop();
Console.WriteLine("Subscribe: Elapsed time: " + stopwatch.Elapsed);
Log.Trace("Subscribe: Elapsed time: " + stopwatch.Elapsed);
Thread.Sleep(10000);
@@ -103,7 +103,7 @@ namespace QuantConnect.Tests.Brokerages.Oanda
{
brokerage.Unsubscribe(config);
}
Console.WriteLine("Unsubscribe: Elapsed time: " + stopwatch.Elapsed);
Log.Trace("Unsubscribe: Elapsed time: " + stopwatch.Elapsed);
Thread.Sleep(5000);
}

View File

@@ -25,6 +25,7 @@ using QuantConnect.Configuration;
using QuantConnect.Data;
using QuantConnect.Interfaces;
using QuantConnect.Lean.Engine.DataFeeds;
using QuantConnect.Logging;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Util;
@@ -213,9 +214,9 @@ namespace QuantConnect.Tests.Brokerages.Oanda
var tenMinutes = TimeSpan.FromMinutes(10);
Console.WriteLine("------");
Console.WriteLine("Waiting for internet disconnection ");
Console.WriteLine("------");
Log.Trace("------");
Log.Trace("Waiting for internet disconnection ");
Log.Trace("------");
// spin while we manually disconnect the internet
while (brokerage.IsConnected)
@@ -226,9 +227,9 @@ namespace QuantConnect.Tests.Brokerages.Oanda
var stopwatch = Stopwatch.StartNew();
Console.WriteLine("------");
Console.WriteLine("Trying to reconnect ");
Console.WriteLine("------");
Log.Trace("------");
Log.Trace("Trying to reconnect ");
Log.Trace("------");
// spin until we're reconnected
while (!brokerage.IsConnected && stopwatch.Elapsed < tenMinutes)

View File

@@ -23,6 +23,7 @@ using QuantConnect.Brokerages;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Lean.Engine.TransactionHandlers;
using QuantConnect.Logging;
using QuantConnect.Orders;
using QuantConnect.Securities;
@@ -76,7 +77,7 @@ namespace QuantConnect.Tests.Common.Brokerages
if (!isValid)
{
Console.WriteLine(messageEvent.Message);
Log.Trace(messageEvent.Message);
Assert.That(messageEvent.Message.Contains(errorMessage));
}
}

View File

@@ -22,6 +22,7 @@ using NUnit.Framework;
using QuantConnect.Data;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Data.Market;
using QuantConnect.Logging;
using QuantConnect.Securities;
using QuantConnect.Util;
@@ -219,7 +220,7 @@ namespace QuantConnect.Tests.Common.Data.Auxiliary
var splitsAndDividends = factorFile.GetSplitsAndDividends(Symbols.AAPL, exchangeHours).ToList();
foreach (var sad in splitsAndDividends)
{
Console.WriteLine($"{sad.Time.Date:yyyy-MM-dd}: {sad}");
Log.Trace($"{sad.Time.Date:yyyy-MM-dd}: {sad}");
}
var splits = splitsAndDividends.OfType<Split>().ToList();
var dividends = splitsAndDividends.OfType<Dividend>().ToList();
@@ -248,7 +249,7 @@ namespace QuantConnect.Tests.Common.Data.Auxiliary
foreach (var item in factorFileAfterDividend.Reverse().Zip(actual.Reverse(), (a,e) => new{actual=a, expected=e}))
{
Console.WriteLine($"expected: {item.expected} actual: {item.actual} diff: {100* (1 - item.actual.PriceFactor/item.expected.PriceFactor):0.0000}%");
Log.Trace($"expected: {item.expected} actual: {item.actual} diff: {100* (1 - item.actual.PriceFactor/item.expected.PriceFactor):0.0000}%");
Assert.AreEqual(item.expected.Date, item.actual.Date);
Assert.AreEqual(item.expected.ReferencePrice, item.actual.ReferencePrice);
Assert.AreEqual(item.expected.SplitFactor, item.actual.SplitFactor);
@@ -276,7 +277,7 @@ namespace QuantConnect.Tests.Common.Data.Auxiliary
Assert.True(actual.First().SplitFactor == 25m, "Factor File split factor is not computed correctly");
foreach (var item in actual.Reverse().Zip(factorFileAfterSplit.Reverse(), (a, e) => new { actual = a, expected = e }))
{
Console.WriteLine($"expected: {item.expected} actual: {item.actual} diff: {100 * (1 - item.actual.PriceFactor / item.expected.PriceFactor):0.0000}%");
Log.Trace($"expected: {item.expected} actual: {item.actual} diff: {100 * (1 - item.actual.PriceFactor / item.expected.PriceFactor):0.0000}%");
Assert.AreEqual(item.expected.Date, item.actual.Date);
Assert.AreEqual(item.expected.ReferencePrice, item.actual.ReferencePrice);
Assert.AreEqual(item.expected.SplitFactor, item.actual.SplitFactor);
@@ -305,7 +306,7 @@ namespace QuantConnect.Tests.Common.Data.Auxiliary
Assert.True(actual.First().SplitFactor == 25m, "Factor File split factor is not computed correctly");
foreach (var item in actual.Reverse().Zip(factorFileAfterSplit.Reverse(), (a, e) => new { actual = a, expected = e }))
{
Console.WriteLine($"expected: {item.expected} actual: {item.actual} diff: {100 * (1 - item.actual.PriceFactor / item.expected.PriceFactor):0.0000}%");
Log.Trace($"expected: {item.expected} actual: {item.actual} diff: {100 * (1 - item.actual.PriceFactor / item.expected.PriceFactor):0.0000}%");
Assert.AreEqual(item.expected.Date, item.actual.Date);
Assert.AreEqual(item.expected.ReferencePrice, item.actual.ReferencePrice);
Assert.AreEqual(item.expected.SplitFactor, item.actual.SplitFactor);
@@ -333,7 +334,7 @@ namespace QuantConnect.Tests.Common.Data.Auxiliary
foreach (var item in actual.Reverse().Zip(expected.Reverse(), (a, e) => new {actual = a, expected = e}))
{
Console.WriteLine($"expected: {item.expected} actual: {item.actual} diff: {100 * (1 - item.actual.PriceFactor / item.expected.PriceFactor):0.0000}%");
Log.Trace($"expected: {item.expected} actual: {item.actual} diff: {100 * (1 - item.actual.PriceFactor / item.expected.PriceFactor):0.0000}%");
Assert.AreEqual(item.expected.Date, item.actual.Date);
Assert.AreEqual(item.expected.ReferencePrice, item.actual.ReferencePrice);
Assert.AreEqual(item.expected.SplitFactor, item.actual.SplitFactor);

View File

@@ -24,6 +24,7 @@ using QuantConnect.Data;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Market;
using QuantConnect.Logging;
using QuantConnect.Tests.Engine.DataFeeds;
namespace QuantConnect.Tests.Common.Data
@@ -152,25 +153,25 @@ namespace QuantConnect.Tests.Common.Data
var readTask = new TaskFactory().StartNew(() =>
{
Console.WriteLine("Read task started");
Log.Trace("Read task started");
while (DateTime.UtcNow < end)
{
subscriptionManager.Subscriptions.Select(x => x.Resolution).DefaultIfEmpty(Resolution.Minute).Min();
Thread.Sleep(1);
}
Console.WriteLine("Read task ended");
Log.Trace("Read task ended");
});
while (readTask.Status != TaskStatus.Running) Thread.Sleep(1);
var addTask = new TaskFactory().StartNew(() =>
{
Console.WriteLine("Add task started");
Log.Trace("Add task started");
foreach (var symbol in symbols)
{
subscriptionManager.Add(symbol, Resolution.Minute, DateTimeZone.Utc, DateTimeZone.Utc, true, false);
}
Console.WriteLine("Add task ended");
Log.Trace("Add task ended");
});
Task.WaitAll(addTask, readTask);

View File

@@ -16,11 +16,13 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using NodaTime;
using NUnit.Framework;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Logging;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
@@ -134,7 +136,7 @@ namespace QuantConnect.Tests.Common.Scheduling
Assert.AreNotEqual(DayOfWeek.Saturday, date.DayOfWeek);
Assert.AreNotEqual(DayOfWeek.Sunday, date.DayOfWeek);
Assert.IsTrue(date.Day <= 3);
Console.WriteLine(date.Day);
Log.Trace(date.Day.ToString(CultureInfo.InvariantCulture));
}
Assert.AreEqual(12, count);
@@ -154,7 +156,7 @@ namespace QuantConnect.Tests.Common.Scheduling
Assert.AreNotEqual(DayOfWeek.Saturday, date.DayOfWeek);
Assert.AreNotEqual(DayOfWeek.Sunday, date.DayOfWeek);
Assert.IsTrue(date.Day <= 3);
Console.WriteLine(date.Day);
Log.Trace(date.Day.ToString(CultureInfo.InvariantCulture));
}
Assert.AreEqual(11, count);
@@ -229,7 +231,7 @@ namespace QuantConnect.Tests.Common.Scheduling
Assert.AreNotEqual(DayOfWeek.Saturday, date.DayOfWeek);
Assert.AreNotEqual(DayOfWeek.Sunday, date.DayOfWeek);
Assert.IsTrue(date.Day >= 28);
Console.WriteLine(date + " " + date.DayOfWeek);
Log.Trace(date + " " + date.DayOfWeek);
}
Assert.AreEqual(12, count);

View File

@@ -22,6 +22,7 @@ using NUnit.Framework;
using QuantConnect.Algorithm;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Logging;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Securities.Future;
@@ -533,7 +534,7 @@ namespace QuantConnect.Tests.Common.Securities
var expected = (algorithm.Portfolio.TotalPortfolioValue * Math.Abs(target) - model.GetInitialMarginRequirement(futureSecurity, futureSecurity.Holdings.AbsoluteQuantity))
/ model.InitialOvernightMarginRequirement - 1 * Math.Abs(target); // -1 fees
expected -= expected % futureSecurity.SymbolProperties.LotSize;
Console.WriteLine($"Expected {expected}");
Log.Trace($"Expected {expected}");
Assert.AreEqual(expected * Math.Sign(target), quantity);
@@ -574,7 +575,7 @@ namespace QuantConnect.Tests.Common.Securities
var expected = (algorithm.Portfolio.TotalPortfolioValue * Math.Abs(target) + model.GetInitialMarginRequirement(futureSecurity, futureSecurity.Holdings.AbsoluteQuantity))
/ model.InitialOvernightMarginRequirement - 1 * Math.Abs(target); // -1 fees
expected -= expected % futureSecurity.SymbolProperties.LotSize;
Console.WriteLine($"Expected {expected}");
Log.Trace($"Expected {expected}");
Assert.AreEqual(expected * Math.Sign(target), quantity);

View File

@@ -18,6 +18,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using NUnit.Framework;
using QuantConnect.Logging;
using QuantConnect.Securities.Option.StrategyMatcher;
using static QuantConnect.Securities.Option.StrategyMatcher.OptionPositionCollection;
using static QuantConnect.Securities.Option.StrategyMatcher.OptionStrategyDefinitions;
@@ -35,7 +36,7 @@ namespace QuantConnect.Tests.Common.Securities.Options.StrategyMatcher
var result = test.Definition.Match(test.Positions).ToList();
foreach (var match in result)
{
Console.WriteLine(string.Join(";", match.Legs.Select(leg => String(leg.Position))));
Log.Trace(string.Join(";", match.Legs.Select(leg => String(leg.Position))));
}
test.AssertMatch(result);

View File

@@ -19,6 +19,7 @@ using NUnit.Framework;
using QuantConnect.Securities.Option.StrategyMatcher;
using static QuantConnect.Tests.Common.Securities.Options.StrategyMatcher.Option;
using static QuantConnect.Securities.Option.StrategyMatcher.OptionStrategyDefinitions;
using QuantConnect.Logging;
namespace QuantConnect.Tests.Common.Securities.Options.StrategyMatcher
{
@@ -76,7 +77,7 @@ namespace QuantConnect.Tests.Common.Securities.Options.StrategyMatcher
var match = matcher.MatchOnce(positions);
foreach (var strategy in match.Strategies)
{
Console.WriteLine($"{strategy.Name}");
Log.Trace($"{strategy.Name}");
foreach (var leg in strategy.OptionLegs)
{
// steal OptionPosition's ToString() implementation

View File

@@ -18,6 +18,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using QuantConnect.Logging;
using QuantConnect.Securities;
using DayOfWeek = System.DayOfWeek;
@@ -308,7 +309,7 @@ namespace QuantConnect.Tests.Common.Securities
}
stopwatch.Stop();
Console.WriteLine("forex1: " + stopwatch.Elapsed);
Log.Trace("forex1: " + stopwatch.Elapsed);
}
[Test]

View File

@@ -19,11 +19,13 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using Accord;
using Newtonsoft.Json;
using NUnit.Framework;
using QuantConnect.Algorithm.CSharp;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Lean.Engine.DataFeeds;
using QuantConnect.Logging;
namespace QuantConnect.Tests.Common.Securities
{
@@ -53,7 +55,7 @@ namespace QuantConnect.Tests.Common.Securities
var sid1 = SPY;
var sid2 = SPY;
Assert.AreEqual(sid1, sid2);
Console.WriteLine(sid1);
Log.Trace(sid1.ToString());
}
[Test]
@@ -72,7 +74,7 @@ namespace QuantConnect.Tests.Common.Securities
Assert.IsTrue(spyPut.HasUnderlying);
Assert.AreEqual(SPY, spyPut.Underlying);
Console.WriteLine(SPY_Put_19550);
Log.Trace(SPY_Put_19550.ToString());
}
[Test]
@@ -86,7 +88,7 @@ namespace QuantConnect.Tests.Common.Securities
Assert.AreEqual(SecurityType.Equity, sid1.SecurityType);
Assert.AreEqual("SPY", sid1.Symbol);
Console.WriteLine(sid1);
Log.Trace(sid1.ToString());
}
[Test]
@@ -100,7 +102,7 @@ namespace QuantConnect.Tests.Common.Securities
Assert.AreEqual(SecurityType.Forex, eurusd.SecurityType);
Assert.AreEqual("EURUSD", eurusd.Symbol);
Console.WriteLine(eurusd);
Log.Trace(eurusd.ToString());
}
[Test]
public void FuturesSecurityIdReturnsProperties()
@@ -111,7 +113,7 @@ namespace QuantConnect.Tests.Common.Securities
Assert.AreEqual(SecurityType.Future, ED_Dec_2020.SecurityType);
Assert.AreEqual("ED", ED_Dec_2020.Symbol);
Console.WriteLine(ED_Dec_2020);
Log.Trace(ED_Dec_2020.ToString());
}
[Test]
@@ -119,14 +121,14 @@ namespace QuantConnect.Tests.Common.Securities
{
var sid1 = SecurityIdentifier.GenerateBase(null, "123456789012", Market.USA);
Assert.AreEqual("123456789012", sid1.Symbol);
Console.WriteLine(sid1);
Log.Trace(sid1.ToString());
}
[Test]
public void ParsedToStringEqualsValue()
{
var value = SPY_Put_19550.ToString();
Console.WriteLine(value);
Log.Trace(value);
var sid2 = SecurityIdentifier.Parse(value);
Assert.AreEqual(SPY_Put_19550, sid2);
}
@@ -330,7 +332,7 @@ namespace QuantConnect.Tests.Common.Securities
SecurityIdentifier.TryParse(value, out sid);
}
stopwatch.Stop();
Console.WriteLine("Elapsed: " + stopwatch.Elapsed);
Log.Trace("Elapsed: " + stopwatch.Elapsed);
Assert.Less(stopwatch.Elapsed, TimeSpan.FromSeconds(2));
}

View File

@@ -20,6 +20,7 @@ using System.Net;
using System.Text;
using Newtonsoft.Json;
using NUnit.Framework;
using QuantConnect.Logging;
using QuantConnect.Securities;
namespace QuantConnect.Tests.Common.Securities
@@ -149,7 +150,7 @@ namespace QuantConnect.Tests.Common.Securities
}
}
Console.WriteLine(sb.ToString());
Log.Trace(sb.ToString());
}
private class GdaxCurrency
@@ -273,19 +274,19 @@ namespace QuantConnect.Tests.Common.Securities
else
{
// should never happen
Console.WriteLine($"Skipping pair with unknown format: {pair}");
Log.Trace($"Skipping pair with unknown format: {pair}");
continue;
}
string baseDescription, quoteDescription;
if (!currencyLabels.TryGetValue(baseCurrency, out baseDescription))
{
Console.WriteLine($"Base currency description not found: {baseCurrency}");
Log.Trace($"Base currency description not found: {baseCurrency}");
baseDescription = baseCurrency;
}
if (!currencyLabels.TryGetValue(quoteCurrency, out quoteDescription))
{
Console.WriteLine($"Quote currency description not found: {quoteCurrency}");
Log.Trace($"Quote currency description not found: {quoteCurrency}");
quoteDescription = quoteCurrency;
}
@@ -329,7 +330,7 @@ namespace QuantConnect.Tests.Common.Securities
}
}
Console.WriteLine(sb.ToString());
Log.Trace(sb.ToString());
}
private class BitfinexSymbolDetails

View File

@@ -15,6 +15,7 @@
using System;
using NUnit.Framework;
using QuantConnect.Logging;
using QuantConnect.Statistics;
namespace QuantConnect.Tests.Common.Statistics
@@ -40,7 +41,7 @@ namespace QuantConnect.Tests.Common.Statistics
var estimate = kellyCriterionManager.KellyCriterionEstimate;
var probabilityValue = kellyCriterionManager.KellyCriterionProbabilityValue;
Console.WriteLine($"Estimate {estimate} - ProbabilityValue {probabilityValue}");
Log.Trace($"Estimate {estimate} - ProbabilityValue {probabilityValue}");
Assert.AreEqual(extremeCase == 1
? 0.00031578947368421 : -0.00031578947368421, kellyCriterionManager.KellyCriterionEstimate);
Assert.AreEqual(1, kellyCriterionManager.KellyCriterionProbabilityValue);
@@ -65,7 +66,7 @@ namespace QuantConnect.Tests.Common.Statistics
var estimate = kellyCriterionManager.KellyCriterionEstimate;
var probabilityValue = kellyCriterionManager.KellyCriterionProbabilityValue;
Console.WriteLine($"Estimate {estimate} - ProbabilityValue {probabilityValue}");
Log.Trace($"Estimate {estimate} - ProbabilityValue {probabilityValue}");
Assert.AreEqual(extremeCase == 1
? 0.315789473684211m : -0.315789473684211m, kellyCriterionManager.KellyCriterionEstimate);
Assert.AreEqual(1, kellyCriterionManager.KellyCriterionProbabilityValue);
@@ -87,9 +88,9 @@ namespace QuantConnect.Tests.Common.Statistics
var estimate = kellyCriterionManager.KellyCriterionEstimate;
var probabilityValue = kellyCriterionManager.KellyCriterionProbabilityValue;
Console.WriteLine($"Estimate {estimate} - ProbabilityValue {probabilityValue}");
Log.Trace($"Estimate {estimate} - ProbabilityValue {probabilityValue}");
Console.WriteLine($"Estimate {estimate} - ProbabilityValue {probabilityValue}");
Log.Trace($"Estimate {estimate} - ProbabilityValue {probabilityValue}");
// compare with a delta
Assert.Less(Math.Abs(0 - kellyCriterionManager.KellyCriterionEstimate), 0.000000000000001m);
@@ -106,7 +107,7 @@ namespace QuantConnect.Tests.Common.Statistics
kellyCriterionManager.AddNewValue(10, start);
kellyCriterionManager.UpdateScores();
Console.WriteLine($"Estimate {kellyCriterionManager.KellyCriterionEstimate}" +
Log.Trace($"Estimate {kellyCriterionManager.KellyCriterionEstimate}" +
$" - ProbabilityValue {kellyCriterionManager.KellyCriterionProbabilityValue}");
Assert.AreEqual(0.1, kellyCriterionManager.KellyCriterionEstimate);
Assert.AreEqual(0.5, kellyCriterionManager.KellyCriterionProbabilityValue);
@@ -116,7 +117,7 @@ namespace QuantConnect.Tests.Common.Statistics
kellyCriterionManager.AddNewValue(-10, start.AddDays(365));
kellyCriterionManager.UpdateScores();
Console.WriteLine($"Estimate {kellyCriterionManager.KellyCriterionEstimate}" +
Log.Trace($"Estimate {kellyCriterionManager.KellyCriterionEstimate}" +
$" - ProbabilityValue {kellyCriterionManager.KellyCriterionProbabilityValue}");
Assert.AreEqual(-0.1, kellyCriterionManager.KellyCriterionEstimate);
Assert.AreEqual(0.5, kellyCriterionManager.KellyCriterionProbabilityValue);

View File

@@ -587,6 +587,23 @@ namespace QuantConnect.Tests.Common
Assert.IsTrue(nonCanonicalFutureOption.Value.StartsWith(expectedFutureOptionTicker));
}
[Test]
public void SymbolWithSidContainingUnderlyingCreatedWithoutNullUnderlying()
{
var future = Symbol.CreateFuture("ES", Market.CME, new DateTime(2020, 6, 19));
var optionSid = SecurityIdentifier.GenerateOption(
future.ID.Date,
future.ID,
future.ID.Market,
3500m,
OptionRight.Call,
OptionStyle.American);
var option = new Symbol(optionSid, "ES");
Assert.IsNotNull(option.Underlying);
Assert.AreEqual(future, option.Underlying);
}
class OldSymbol
{
public string Value { get; set; }

View File

@@ -16,6 +16,7 @@
using System;
using NodaTime;
using NUnit.Framework;
using QuantConnect.Logging;
namespace QuantConnect.Tests.Common
{
@@ -31,7 +32,7 @@ namespace QuantConnect.Tests.Common
var value = field.GetValue(null);
Assert.IsNotNull(value);
Assert.IsInstanceOf(typeof (DateTimeZone), value);
Console.WriteLine(((DateTimeZone)value).Id);
Log.Trace(((DateTimeZone)value).Id);
}
}
}

View File

@@ -22,6 +22,7 @@ using NUnit.Framework;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Logging;
using QuantConnect.Util;
namespace QuantConnect.Tests.Common.Util
@@ -41,7 +42,7 @@ namespace QuantConnect.Tests.Common.Util
}
stopwatch.Stop();
var elapsed1 = stopwatch.Elapsed;
Console.WriteLine(elapsed1.TotalMilliseconds);
Log.Trace(elapsed1.TotalMilliseconds.ToStringInvariant());
stopwatch.Reset();
stopwatch.Start();
@@ -51,7 +52,7 @@ namespace QuantConnect.Tests.Common.Util
}
stopwatch.Stop();
var elapsed2 = stopwatch.Elapsed;
Console.WriteLine(elapsed2.TotalMilliseconds);
Log.Trace(elapsed2.TotalMilliseconds.ToStringInvariant());
Assert.Less(elapsed2, elapsed1);
}

View File

@@ -21,6 +21,7 @@ using NUnit.Framework;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Lean.Engine.DataFeeds;
using QuantConnect.Logging;
using QuantConnect.Util;
namespace QuantConnect.Tests.Common.Util
@@ -379,8 +380,8 @@ namespace QuantConnect.Tests.Common.Util
getLineReaderMilliSeconds = stopWatch.ElapsedMilliseconds;
zipCache.DisposeSafely();
}
Console.WriteLine($"StreamReader: {streamReaderMilliSeconds}ms. Count {streamReaderCount}");
Console.WriteLine($"GetLine Reader: {getLineReaderMilliSeconds}ms. Count {getLineReaderCount}");
Log.Trace($"StreamReader: {streamReaderMilliSeconds}ms. Count {streamReaderCount}");
Log.Trace($"GetLine Reader: {getLineReaderMilliSeconds}ms. Count {getLineReaderCount}");
// its 50% faster but lets leave some room to avoid noise
Assert.IsTrue((streamReaderMilliSeconds * 1.5d) < getLineReaderMilliSeconds);

View File

@@ -22,6 +22,7 @@ using QuantConnect.Brokerages.Backtesting;
using QuantConnect.Data.Market;
using QuantConnect.Lean.Engine.Results;
using QuantConnect.Lean.Engine.TransactionHandlers;
using QuantConnect.Logging;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
@@ -127,7 +128,7 @@ namespace QuantConnect.Tests.Engine.BrokerageTransactionHandlerTests
Assert.AreEqual(OrderStatus.Filled, orderEvent.Status);
break;
}
Console.WriteLine($"{orderEvent}");
Log.Trace($"{orderEvent}");
};
var ticket = transactionHandler.Process(orderRequest);
@@ -207,7 +208,7 @@ namespace QuantConnect.Tests.Engine.BrokerageTransactionHandlerTests
Assert.AreEqual(OrderStatus.Filled, orderEvent.Status);
break;
}
Console.WriteLine($"{orderEvent}");
Log.Trace($"{orderEvent}");
};
var ticket = transactionHandler.Process(orderRequest);

View File

@@ -19,6 +19,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using NUnit.Framework;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Logging;
using QuantConnect.Util;
namespace QuantConnect.Tests.Engine.DataFeeds.Auxiliary
@@ -69,7 +70,7 @@ namespace QuantConnect.Tests.Engine.DataFeeds.Auxiliary
var sw = Stopwatch.StartNew();
var mapFileresolver = mapFileProvider.Get(Market.USA);
sw.Stop();
Console.WriteLine($"elapsed: {sw.Elapsed.TotalSeconds} seconds");
Log.Trace($"elapsed: {sw.Elapsed.TotalSeconds} seconds");
}
[Test]

View File

@@ -28,16 +28,18 @@ namespace QuantConnect.Tests.Engine.DataFeeds
private ILogHandler _logHandler;
private BacktestingFutureChainProvider _provider;
[SetUp]
[OneTimeSetUp]
public void SetUp()
{
// Store initial Log Handler
_logHandler = Log.LogHandler;
_provider = new BacktestingFutureChainProvider();
}
[TearDown]
[OneTimeTearDown]
public void TearDown()
{
// Restore intial Log Handler
Log.LogHandler = _logHandler;
}

View File

@@ -66,7 +66,7 @@ namespace QuantConnect.Tests.Engine.DataFeeds.Enumerators.Factories
}
stopwatch.Stop();
Console.WriteLine("Total rows: {0}, elapsed time: {1}", rows.Count, stopwatch.Elapsed);
Log.Trace("Total rows: {0}, elapsed time: {1}", rows.Count, stopwatch.Elapsed);
Assert.AreEqual(parameters.RowCount, rows.Count);

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