Back

Risk Model Not Liquidating Positions

Debugging some strange issues with an implementation of a custom Risk Model in the Framework - attached a simple example algorithm below.

Expected behavior:

  • Every Monday, emit an insight to Long EURUSD with duration 1 week
  • Portfolio Model computes quantity (100% of portfolio value) and returns array of targets
  • Risk Model checks for drawdowns in portfolio value (set to a very small number in example), and liquidates positions
  • Portfolio should be fully liquidated for the rest of the week until the next insight emission
Actual behavior:
  • Logs confirm that the drawdown is being hit, and is returning PortfolioTarget(symbol, 0). However, the algorithm remains invested.
  • Only a single order was placed at algorithm start despite Risk Model being triggered. Expecting place order, liquidate, do nothing for rest of week, then repeat every week.
Sample Logs:2015-01-06 04:44:00 Risk Model triggered with realized -0.00% drawdown. Liquidated.
2015-01-06 04:45:00 Risk Model triggered with realized -0.00% drawdown. Liquidated.
2015-01-06 04:46:00 Risk Model triggered with realized -0.00% drawdown. Liquidated.
2015-01-06 04:47:00 Risk Model triggered with realized -0.00% drawdown. Liquidated.

This is related to this discussion, where Derek's answer implied that the Risk Model should be continuously returning PortfolioTarget(symbol, 0) once liquidated to achieve the expected behavior. Anyone see where the potential issue may be?

Update Backtest








0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hi Adam,

The issue here is the line

return [ PortfolioTarget(target.Symbol, 0) for target in targets]

`targets` are passed to the method when insights are emitted. Instead of loop through them, we should loop through the portfolio's holdings.

portfolio_targets = []
for kvp in algorithm.Securities:
security = kvp.Value
if security.Invested:
portfolio_targets.append(PortfolioTarget(security.Symbol, 0))
return portfolio_targets

See the attached backtest for reference.

Best,
Derek Melchin

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks Derek! That makes sense - I think this should be added in the documentation.

That also seems to imply that, instead of:

# Reset trackers on new targets
if set(targets) != set(self.currentTargets):
self.currentTargets = set(targets)
self.portfolioHigh = 0
self.isLiquidated = False

to reset the tracking variables with new insight emissions, it's better to do:

# New insights emitted
if targets:
self.portfolioHigh = 0
self.isLiquidated = False

As originally, the period immediately after an insight emission incorrectly triggers the if statement. Do you see any potential bugs/unexpected behavior with this?

On a side note, I ran this with the example algorithm above:

def ManageRisk(self, algorithm, targets):

algorithm.Debug(f'Targs: {len(targets)}')
return []

and for some reason ManageRisk is being called twice with every timestep:

2015-01-01 17:01:00 Targs: 0
2015-01-06 00:15:00 Targs: 1
2015-01-06 00:15:00 Targs: 0
2015-01-13 00:15:00 Targs: 1
2015-01-13 00:15:00 Targs: 0
2015-01-20 00:15:00 Targs: 1
2015-01-20 00:15:00 Targs: 0

 

0

Hi Adam,

Great point above. However, if we use

if targets:
self.portfolioHigh = 0
self.isLiquidated = False

The portfolio's high water mark we use to calculate the drawdown will be reset when new insights are emitted. Thus, it's possible for the portfolio to experience a 100% drawdown if we just emit an insight at each time step.

Instead, we change this to

# Initialize
self.isLiquidated = True

# ManageRisk
portfolioValue = algorithm.Portfolio.TotalPortfolioValue
if targets and self.isLiquidated:
self.portfolioHigh = portfolioValue
self.isLiquidated = False

With this, the high water mark is only reset after the risk model has liquidated the portfolio and a new insight has been emitted. See the attached backtest for reference.

In regards to the ManageRisk being called twice at each time step, it only appears this way because the above uses Debug instead of Log. The rate-limiting of debug messages causes the misleading timestamps. In reality, ManageRisk is called once at each time step.

Best,
Derek Melchin

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed