Compare commits
26 Commits
feature-py
...
10054
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4006ba01e4 | ||
|
|
6d824b40a6 | ||
|
|
8e410fcaf1 | ||
|
|
d136428556 | ||
|
|
40d81965be | ||
|
|
c650eb6c1c | ||
|
|
aa2f9f927a | ||
|
|
c698a65a84 | ||
|
|
181283a4cd | ||
|
|
b247724a34 | ||
|
|
dde3576161 | ||
|
|
e8734a0797 | ||
|
|
7f5d69bbec | ||
|
|
f6be7a41a5 | ||
|
|
7f30c0cd00 | ||
|
|
6694fe01f8 | ||
|
|
32ab4fdea1 | ||
|
|
fc81f606e4 | ||
|
|
ec74abd4d0 | ||
|
|
bd3ead3480 | ||
|
|
45849962a3 | ||
|
|
8279cf7eac | ||
|
|
4c4a699cb0 | ||
|
|
31a2c31c0a | ||
|
|
877a123276 | ||
|
|
4134b05bfd |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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
15
.vscode/readme.md
vendored
@@ -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
28
.vscode/tasks.json
vendored
@@ -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",
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}")
|
||||
@@ -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" />
|
||||
|
||||
@@ -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"/>
|
||||
```
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
75
Api/Api.cs
75
Api/Api.cs
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -162,6 +162,9 @@ namespace QuantConnect.Packets
|
||||
OptimizationEstimate,
|
||||
|
||||
/// Optimization work status update
|
||||
OptimizationStatus
|
||||
OptimizationStatus,
|
||||
|
||||
/// Optimization work result
|
||||
OptimizationResult
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
101
Indicators/AwesomeOscillator.cs
Normal file
101
Indicators/AwesomeOscillator.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
95
Indicators/ChaikinMoneyFlow.cs
Normal file
95
Indicators/ChaikinMoneyFlow.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
120
Indicators/DeMarkerIndicator.cs
Normal file
120
Indicators/DeMarkerIndicator.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
39
Logging/ConsoleErrorLogHandler.cs
Normal file
39
Logging/ConsoleErrorLogHandler.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user