Skip to content

Commit 6a8edc1

Browse files
authored
Add SetSettlementModel() method (#7684)
* Rebase - Add Support * nit changes
1 parent 4913a59 commit 6a8edc1

File tree

4 files changed

+190
-5
lines changed

4 files changed

+190
-5
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3+
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using QuantConnect.Data;
17+
using QuantConnect.Securities;
18+
using QuantConnect.Brokerages;
19+
using System;
20+
using QuantConnect.Interfaces;
21+
using System.Collections.Generic;
22+
23+
namespace QuantConnect.Algorithm.CSharp
24+
{
25+
/// <summary>
26+
/// Regression algorithm to test we can specify a custom settlement model using Security.SetSettlementModel() method
27+
/// </summary>
28+
public class SetCustomSettlementModelRegressionAlgorithm: QCAlgorithm, IRegressionAlgorithmDefinition
29+
{
30+
private Security _spy;
31+
public override void Initialize()
32+
{
33+
SetStartDate(2013, 10, 7);
34+
SetEndDate(2013, 10, 11);
35+
SetCash(10000);
36+
_spy = AddEquity("SPY", Resolution.Daily);
37+
_spy.SetSettlementModel(new CustomSettlementModel());
38+
}
39+
40+
public override void OnData(Slice slice)
41+
{
42+
if (Portfolio.CashBook[Currencies.USD].Amount == 10000)
43+
{
44+
var parameters = new ApplyFundsSettlementModelParameters(Portfolio, _spy, Time, new CashAmount(101, Currencies.USD), null);
45+
_spy.SettlementModel.ApplyFunds(parameters);
46+
}
47+
}
48+
49+
public override void OnEndOfAlgorithm()
50+
{
51+
if (Portfolio.CashBook[Currencies.USD].Amount != 10101)
52+
{
53+
throw new Exception($"It was expected to have 10101 USD in Portfolio, but was {Portfolio.CashBook[Currencies.USD].Amount}");
54+
}
55+
56+
var parameters = new ScanSettlementModelParameters(Portfolio, _spy, new DateTime(2013, 10, 6));
57+
_spy.SettlementModel.Scan(parameters);
58+
59+
if (Portfolio.CashBook[Currencies.USD].Amount != 10000)
60+
{
61+
throw new Exception($"It was expected to have 10000 USD in Portfolio, but was {Portfolio.CashBook[Currencies.USD].Amount}");
62+
}
63+
}
64+
65+
/// <summary>
66+
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
67+
/// </summary>
68+
public bool CanRunLocally { get; } = true;
69+
70+
/// <summary>
71+
/// This is used by the regression test system to indicate which languages this algorithm is written in.
72+
/// </summary>
73+
public Language[] Languages { get; } = { Language.CSharp, Language.Python };
74+
75+
/// <summary>
76+
/// Data Points count of all timeslices of algorithm
77+
/// </summary>
78+
public long DataPoints => 48;
79+
80+
/// <summary>
81+
/// Data Points count of the algorithm history
82+
/// </summary>
83+
public int AlgorithmHistoryDataPoints => 0;
84+
85+
/// <summary>
86+
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
87+
/// </summary>
88+
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
89+
{
90+
{"Total Trades", "0"},
91+
{"Average Win", "0%"},
92+
{"Average Loss", "0%"},
93+
{"Compounding Annual Return", "108.257%"},
94+
{"Drawdown", "0%"},
95+
{"Expectancy", "0"},
96+
{"Net Profit", "1.010%"},
97+
{"Sharpe Ratio", "10.983"},
98+
{"Sortino Ratio", "0"},
99+
{"Probabilistic Sharpe Ratio", "95.977%"},
100+
{"Loss Rate", "0%"},
101+
{"Win Rate", "0%"},
102+
{"Profit-Loss Ratio", "0"},
103+
{"Alpha", "1.42"},
104+
{"Beta", "-0.273"},
105+
{"Annual Standard Deviation", "0.08"},
106+
{"Annual Variance", "0.006"},
107+
{"Information Ratio", "-3.801"},
108+
{"Tracking Error", "0.288"},
109+
{"Treynor Ratio", "-3.226"},
110+
{"Total Fees", "$0.00"},
111+
{"Estimated Strategy Capacity", "$0"},
112+
{"Lowest Capacity Asset", ""},
113+
{"Portfolio Turnover", "0%"},
114+
{"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"}
115+
};
116+
}
117+
118+
public class CustomSettlementModel : ISettlementModel
119+
{
120+
private string _currency;
121+
private decimal _amount;
122+
public void ApplyFunds(ApplyFundsSettlementModelParameters applyFundsParameters)
123+
{
124+
_currency = applyFundsParameters.CashAmount.Currency;
125+
_amount = applyFundsParameters.CashAmount.Amount;
126+
applyFundsParameters.Portfolio.CashBook[_currency].AddAmount(_amount);
127+
}
128+
129+
public void Scan(ScanSettlementModelParameters settlementParameters)
130+
{
131+
if (settlementParameters.UtcTime == new DateTime(2013, 10, 6))
132+
{
133+
settlementParameters.Portfolio.CashBook[_currency].AddAmount(-_amount);
134+
}
135+
}
136+
}
137+
}

Algorithm.Python/CustomSettlementModelRegressionAlgorithm.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ def Initialize(self):
2323
self.SetEndDate(2013,10,11)
2424
self.SetCash(10000)
2525
self.spy = self.AddEquity("SPY", Resolution.Daily)
26+
self.SetSettlementModel(self.spy)
27+
28+
def SetSettlementModel(self, security):
2629
self.SetBrokerageModel(CustomBrokerageModelWithCustomSettlementModel())
27-
self.updateRequestSubmitted = False
2830

2931
def OnData(self, slice):
3032
if self.Portfolio.CashBook[Currencies.USD].Amount == 10000:
@@ -34,15 +36,20 @@ def OnData(self, slice):
3436
def OnEndOfAlgorithm(self):
3537
if self.Portfolio.CashBook[Currencies.USD].Amount != 10101:
3638
raise Exception(f"It was expected to have 10101 USD in Portfolio, but was {self.Portfolio.CashBook[Currencies.USD].Amount}")
39+
parameters = ScanSettlementModelParameters(self.Portfolio, self.spy, datetime(2013, 10, 6))
40+
self.spy.SettlementModel.Scan(parameters)
41+
if self.Portfolio.CashBook[Currencies.USD].Amount != 10000:
42+
raise Exception(f"It was expected to have 10000 USD in Portfolio, but was {self.Portfolio.CashBook[Currencies.USD].Amount}")
3743

3844
class CustomSettlementModel:
3945
def ApplyFunds(self, parameters):
40-
currency = parameters.CashAmount.Currency;
41-
amount = parameters.CashAmount.Amount
42-
parameters.Portfolio.CashBook[currency].AddAmount(amount)
46+
self.currency = parameters.CashAmount.Currency;
47+
self.amount = parameters.CashAmount.Amount
48+
parameters.Portfolio.CashBook[self.currency].AddAmount(self.amount)
4349

4450
def Scan(self, parameters):
45-
pass
51+
if parameters.UtcTime == datetime(2013, 10, 6):
52+
parameters.Portfolio.CashBook[self.currency].AddAmount(-self.amount)
4653

4754
class CustomBrokerageModelWithCustomSettlementModel(CustomBrokerageModel):
4855
def GetSettlementModel(self, security):
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
2+
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
from AlgorithmImports import *
15+
from CustomSettlementModelRegressionAlgorithm import CustomSettlementModel, CustomSettlementModelRegressionAlgorithm
16+
17+
### <summary>
18+
### Regression algorithm to test we can specify a custom settlement model using Security.SetSettlementModel() method
19+
### (without a custom brokerage model)
20+
### </summary>
21+
class SetCustomSettlementModelRegressionAlgorithm(CustomSettlementModelRegressionAlgorithm):
22+
def SetSettlementModel(self, security):
23+
security.SetSettlementModel(CustomSettlementModel())

Common/Securities/Security.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,24 @@ public void SetFillModel(PyObject fillModel)
720720
FillModel = new FillModelPythonWrapper(fillModel);
721721
}
722722

723+
/// <summary>
724+
/// Sets the settlement model
725+
/// </summary>
726+
/// <param name="settlementModel"> Model that represents a settlement model</param>
727+
public void SetSettlementModel(ISettlementModel settlementModel)
728+
{
729+
SettlementModel = settlementModel;
730+
}
731+
732+
/// <summary>
733+
/// Sets the settlement model
734+
/// </summary>
735+
/// <param name="settlementModel">Model that represents a settlement model</param>
736+
public void SetSettlementModel(PyObject settlementModel)
737+
{
738+
SettlementModel = new SettlementModelPythonWrapper(settlementModel);
739+
}
740+
723741
/// <summary>
724742
/// Sets the slippage model
725743
/// </summary>

0 commit comments

Comments
 (0)