Skip to content

Commit

Permalink
Update 99 Examples.html
Browse files Browse the repository at this point in the history
  • Loading branch information
LouisSzeto authored Sep 24, 2024
1 parent d0f41a3 commit 66653ed
Showing 1 changed file with 165 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,195 +3,207 @@
<h4>Example 1: Rollover</h4>
<p>Future contracts expire monthly or quarterly in most cases. Hence, if we hold Future position in month or quarter end, we must consider rolling over to the mapped contract. The following algorithm shows how to buy and roll over to the next front month Future contract. We make use of the universe selection filter to select the front month contract and order the next mapped contract during the previous one expires.</p>
<div class="section-example-container">
<pre class="csharp">private Symbol _future;

public override void Initialize()
<pre class="csharp">public class FutureExampleAlgorithm : QCAlgorithm
{
var future = AddFuture(Futures.Indices.SP500EMini, extendedMarketHours: true);
_future = future.Symbol;
// We only want to hold position of the front month contract
future.SetFilter((u) =&gt; u.OnlyApplyFilterAtMarketOpen().FrontMonth());
}
private Symbol _future;

public override void OnSecuritiesChanged(SecurityChanges changes)
{
// Liquidate if expired (or not being the front month contract anymore) and exit universe
foreach (var removed in changes.RemovedSecurities)
public override void Initialize()
{
Liquidate(removed.Symbol);
var future = AddFuture(Futures.Indices.SP500EMini, extendedMarketHours: true);
_future = future.Symbol;
// We only want to hold position of the front month contract.
future.SetFilter((u) =&gt; u.OnlyApplyFilterAtMarketOpen().FrontMonth());
}

foreach (var added in changes.AddedSecurities)
public override void OnSecuritiesChanged(SecurityChanges changes)
{
// Make sure the newly added contract is an actual mapped tradable contract
if (!added.Symbol.IsCanonical())
// Liquidate if expired (or not being the front month contract anymore) and exit universe.
foreach (var removed in changes.RemovedSecurities)
{
// Roll over by ordering the same quantity
// Use limit order since market on open order is not supported on Future and avoid extreme quote filling
LimitOrder(added.Symbol, 1m, Securities[_future].Price);
Liquidate(removed.Symbol);
}

foreach (var added in changes.AddedSecurities)
{
// Make sure the newly added contract is an actual mapped tradable contract.
if (!added.Symbol.IsCanonical())
{
// Roll over by ordering the same quantity.
// Use limit order since market on open order is not supported on Future and avoid extreme quote filling.
LimitOrder(added.Symbol, 1m, Securities[_future].Price);
}
}
}
}</pre>
<pre class="python">def initialize(self) -&gt; None:
future = self.add_future(Futures.Indices.SP_500_E_MINI, extended_market_hours=True)
self._future = future.symbol
# We only want to hold position of the front month contract
future.set_filter(lambda u: u.only_apply_filter_at_market_open().front_month())

def on_securities_changed(self, changes: SecurityChanges) -&gt; None:
# Liquidate if expired (or not being the front month contract anymore) and exit universe
for removed in changes.removed_securities:
self.liquidate(removed.symbol)
<pre class="python">class FutureExampleAlgorithm(QCAlgorithm):
def initialize(self) -&gt; None:
future = self.add_future(Futures.Indices.SP_500_E_MINI, extended_market_hours=True)
self._future = future.symbol
# We only want to hold position of the front month contract.
future.set_filter(lambda u: u.only_apply_filter_at_market_open().front_month())

for added in changes.added_securities:
# Make sure the newly added contract is an actual mapped tradable contract
if not added.symbol.is_canonical():
# Roll over by ordering the same quantity
# Use limit order since market on open order is not supported on Future and avoid extreme quote filling
self.limit_order(added.symbol, 1, self.securities[self._future].price)</pre>
def on_securities_changed(self, changes: SecurityChanges) -&gt; None:
# Liquidate if expired (or not being the front month contract anymore) and exit universe.
for removed in changes.removed_securities:
self.liquidate(removed.symbol)

for added in changes.added_securities:
# Make sure the newly added contract is an actual mapped tradable contract.
if not added.symbol.is_canonical():
# Roll over by ordering the same quantity.
# Use limit order since market on open order is not supported on Future and avoid extreme quote filling.
self.limit_order(added.symbol, 1, self.securities[self._future].price)</pre>
</div>

<h4>Example 2: Continuous Future Indicator</h4>
<p>One of the major applications of <a href='/docs/v2/writing-algorithms/universes/futures#12-Continous-Contracts'>Continuous Future</a> is to obtain smooth price series to feed into indicators. This can ensure the indicator gets the correct price data that is comparable to the current mapped Future contract. In this example, we demonstrate a 252-day <a href="/docs/v2/writing-algorithms/indicators/supported-indicators/exponential-moving-average">Exponential Moving Average indicator</a> update using continuous ES contract data.</p>
<div class="section-example-container">
<pre class="csharp">private dynamic _future;

public override void Initialize()
<pre class="csharp">public class FutureExampleAlgorithm : QCAlgorithm
{
// Use backward ratio normalization for continuous contract to feed smooth, comparable price series to the indicator
_future = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
extendedMarketHours: true);
// We only want to hold position of the front month contract
(_future as Future).SetFilter((u) =&gt; u.OnlyApplyFilterAtMarketOpen().FrontMonth());
// Create a 252-day EMA indicator as a trend estimator
_future.ema = EMA(_future.Symbol, 252, Resolution.Daily);
// Warm up the EMA indicator to make it readily available
WarmUpIndicator((Symbol)_future.Symbol, (ExponentialMovingAverage)_future.ema);
}
private dynamic _future;

public override void OnData(Slice slice)
{
// Ensure the TradeBar data is available for the Future. Only use updated price data to update the indicator and make trading decision
if (slice.Bars.ContainsKey(_future.Symbol))
public override void Initialize()
{
// Buy the mapped contract if the trend is estimated to go up (price above EMA)
if (_future.ema.Current.Value &gt;= slice.Bars[_future.Symbol].Close)
{
SetHoldings(_future.Mapped, 0.1m);
}
// Short the mapped contract if the trend is estimated to go down (price below EMA)
else
// Use backward ratio normalization for continuous contract to feed smooth, comparable price series to the indicator.
_future = AddFuture(Futures.Indices.SP500EMini,
dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
extendedMarketHours: true);
// We only want to hold position of the front month contract.
(_future as Future).SetFilter((u) =&gt; u.OnlyApplyFilterAtMarketOpen().FrontMonth());
// Create a 252-day EMA indicator as a trend estimator.
_future.ema = EMA(_future.Symbol, 252, Resolution.Daily);
// Warm up the EMA indicator to make it readily available.
WarmUpIndicator((Symbol)_future.Symbol, (ExponentialMovingAverage)_future.ema);
}

public override void OnData(Slice slice)
{
// Ensure the TradeBar data is available for the Future. Only use updated price data to update the indicator and make trading decision.
if (slice.Bars.ContainsKey(_future.Symbol))
{
SetHoldings(_future.Mapped, -0.1m);
// Buy the mapped contract if the trend is estimated to go up (price above EMA).
if (_future.ema.Current.Value &gt;= slice.Bars[_future.Symbol].Close)
{
SetHoldings(_future.Mapped, 0.1m);
}
// Short the mapped contract if the trend is estimated to go down (price below EMA).
else
{
SetHoldings(_future.Mapped, -0.1m);
}
}
}
}

public override void OnSecuritiesChanged(SecurityChanges changes)
{
// Liquidate if expired (or not being the front month contract anymore) and exit universe
foreach (var removed in changes.RemovedSecurities)

public override void OnSecuritiesChanged(SecurityChanges changes)
{
Liquidate(removed.Symbol);
// Liquidate if expired (or not being the front month contract anymore) and exit universe.
foreach (var removed in changes.RemovedSecurities)
{
Liquidate(removed.Symbol);
}
}
}</pre>
<pre class="python">def initialize(self) -&gt; None:
# Use backward ratio normalization for continuous contract to feed smooth, comparable price series to the indicator
self._future = self.add_future(Futures.Indices.SP_500_E_MINI,
data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
extended_market_hours=True)
# We only want to hold position of the front month contract
self._future.set_filter(lambda u: u.only_apply_filter_at_market_open().front_month())
# Create a 252-day EMA indicator as a trend estimator
self._future.ema = self.ema(self._future.symbol, 252, Resolution.DAILY)
# Warm up the EMA indicator to make it readily available
self.warm_up_indicator(self._future.symbol, self._future.ema)

def on_data(self, slice: Slice) -&gt; None:
# Ensure the TradeBar data is available for the Future. Only use updated price data to update the indicator and make trading decision
if self._future.symbol in slice.bars:
# Buy the mapped contract if the trend is estimated to go up (price above EMA)
if self._future.ema.current.value &gt;= slice.bars[self._future.symbol].close:
self.set_holdings(self._future.mapped, 0.1)
# Short the mapped contract if the trend is estimated to go down (price below EMA)
else:
self.set_holdings(self._future.mapped, -0.1)

def on_securities_changed(self, changes: SecurityChanges) -&gt; None:
# Liquidate if expired (or not being the front month contract anymore) and exit universe
for removed in changes.removed_securities:
self.liquidate(removed.symbol)</pre>
<pre class="python">class FutureExampleAlgorithm(QCAlgorithm):
def initialize(self) -&gt; None:
# Use backward ratio normalization for continuous contract to feed smooth, comparable price series to the indicator.
self._future = self.add_future(Futures.Indices.SP_500_E_MINI,
data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
extended_market_hours=True)
# We only want to hold position of the front month contract.
self._future.set_filter(lambda u: u.only_apply_filter_at_market_open().front_month())
# Create a 252-day EMA indicator as a trend estimator.
self._future.ema = self.ema(self._future.symbol, 252, Resolution.DAILY)
# Warm up the EMA indicator to make it readily available.
self.warm_up_indicator(self._future.symbol, self._future.ema)

def on_data(self, slice: Slice) -&gt; None:
# Ensure the TradeBar data is available for the Future. Only use updated price data to update the indicator and make trading decision.
if self._future.symbol in slice.bars:
# Buy the mapped contract if the trend is estimated to go up (price above EMA).
if self._future.ema.current.value &gt;= slice.bars[self._future.symbol].close:
self.set_holdings(self._future.mapped, 0.1)
# Short the mapped contract if the trend is estimated to go down (price below EMA).
else:
self.set_holdings(self._future.mapped, -0.1)

def on_securities_changed(self, changes: SecurityChanges) -&gt; None:
# Liquidate if expired (or not being the front month contract anymore) and exit universe.
for removed in changes.removed_securities:
self.liquidate(removed.symbol)</pre>
</div>

<h4>Example 3: Contango</h4>
<p>In Future trading, contango refers to the far-to-expiry Future contract price is higher than the spot price due to various reasons, such as storage fee and insurance of the commodities. The following example shows a contango trading by shorting the far contract that the price is above a threshold compared to the front month contract price and buying the front month contract to earn the premium in between.</p>
<div class="section-example-container">
<pre class="csharp">private Symbol _future;

public override void Initialize()
<pre class="csharp">public class FutureExampleAlgorithm : QCAlgorithm
{
// Allow extended market hours trade, which is common for Future
var future = AddFuture(Futures.Metals.MicroGold, extendedMarketHours: true);
_future = future.Symbol;
// Limit the expiration to within 6 months, as the longer the expiration, the higher the price uncertainty
future.SetFilter((u) =&gt; u.OnlyApplyFilterAtMarketOpen().Expiration(0, 183));
}
private Symbol _future;

public override void OnData(Slice slice)
{
// Get Future chain only for the selected Future contract
if (!Portfolio.Invested && slice.FutureChains.TryGetValue(_future, out var chain))
public override void Initialize()
{
// It takes 2 contracts with different expiries to form a horizontal spread arbitration to earn price difference in contango
if (chain.Count() &lt; 2) return;
var farContract = chain.MaxBy(x =&gt; x.Expiry);
var nearContract = chain.MinBy(x =&gt; x.Expiry);

// Check if the far contract price is 1% higher than the near one
// If so, short the far contract and buy the near one to earn the horizontal spread premium
if (farContract.BidPrice &gt;= nearContract.AskPrice * 1.01m)
// Allow extended market hours trade, which is common for Future since extended market hour is still popular.
var future = AddFuture(Futures.Metals.MicroGold, extendedMarketHours: true);
_future = future.Symbol;
// Limit the expiration to within 6 months, as the longer the expiration, the higher the price uncertainty.
future.SetFilter((u) =&gt; u.OnlyApplyFilterAtMarketOpen().Expiration(0, 183));
}

public override void OnData(Slice slice)
{
// Get Future chain only for the selected Future contract.
if (!Portfolio.Invested && slice.FutureChains.TryGetValue(_future, out var chain))
{
MarketOrder(farContract.Symbol, -1);
MarketOrder(nearContract.Symbol, 1);
// It takes 2 contracts with different expiries to form a horizontal spread arbitration to earn price difference in contango.
if (chain.Count() &lt; 2) return;
var farContract = chain.MaxBy(x =&gt; x.Expiry);
var nearContract = chain.MinBy(x =&gt; x.Expiry);

// Check if the far contract price is 1% higher than the near one.
// If so, short the far contract and buy the near one to earn the horizontal spread premium.
if (farContract.BidPrice &gt;= nearContract.AskPrice * 1.01m)
{
MarketOrder(farContract.Symbol, -1);
MarketOrder(nearContract.Symbol, 1);
}
}
}
}

public override void OnSecuritiesChanged(SecurityChanges changes)
{
// Liquidate if expired (or not being the front month contract anymore) and exit universe
foreach (var removed in changes.RemovedSecurities)

public override void OnSecuritiesChanged(SecurityChanges changes)
{
Liquidate();
// Liquidate if expired (or not being the front month contract anymore) and exit universe.
foreach (var removed in changes.RemovedSecurities)
{
Liquidate();
}
}
}</pre>
<pre class="python">def initialize(self) -&gt; None:
# Allow extended market hours trade, which is common for Future
future = self.add_future(Futures.Metals.MICRO_GOLD, extended_market_hours=True)
self._future = future.symbol
# Limit the expiration to within 6 months, as the longer the expiration, the higher the price uncertainty
future.set_filter(lambda u: u.only_apply_filter_at_market_open().expiration(0, 183))

def on_data(self, slice: Slice) -&gt; None:
# Get Future chain only for the selected Future contract
chain = slice.future_chains.get(self._future)
if not self.portfolio.invested and chain:
# It takes 2 contracts with different expiries to form a horizontal spread arbitration to earn price difference in contango
if len(list(chain)) &lt; 2:
return
sorted_by_expiry = sorted(chain, key=lambda x: x.expiry)
far_contract = sorted_by_expiry[-1]
near_contract = sorted_by_expiry[0]

# Check if the far contract price is 1% higher than the near one
# If so, short the far contract and buy the near one to earn the horizontal spread premium
if far_contract.bid_price &gt;= near_contract.ask_price * 1.01:
self.market_order(far_contract.symbol, -1)
self.market_order(near_contract.symbol, 1)

def on_securities_changed(self, changes: SecurityChanges) -&gt; None:
# Liquidate if expired (or not being the front month contract anymore) and exit universe
for removed in changes.removed_securities:
self.liquidate()</pre>
</div>
<pre class="python">class FutureExampleAlgorithm(QCAlgorithm):
def initialize(self) -&gt; None:
# Allow extended market hours trade, which is common for Future since extended market hour is still popular.
future = self.add_future(Futures.Metals.MICRO_GOLD, extended_market_hours=True)
self._future = future.symbol
# Limit the expiration to within 6 months, as the longer the expiration, the higher the price uncertainty.
future.set_filter(lambda u: u.only_apply_filter_at_market_open().expiration(0, 183))

def on_data(self, slice: Slice) -&gt; None:
# Get Future chain only for the selected Future contract.
chain = slice.future_chains.get(self._future)
if not self.portfolio.invested and chain:
# It takes 2 contracts with different expiries to form a horizontal spread arbitration to earn price difference in contango.
if len(list(chain)) &lt; 2:
return
sorted_by_expiry = sorted(chain, key=lambda x: x.expiry)
far_contract = sorted_by_expiry[-1]
near_contract = sorted_by_expiry[0]

# Check if the far contract price is 1% higher than the near one.
# If so, short the far contract and buy the near one to earn the horizontal spread premium.
if far_contract.bid_price &gt;= near_contract.ask_price * 1.01:
self.market_order(far_contract.symbol, -1)
self.market_order(near_contract.symbol, 1)

def on_securities_changed(self, changes: SecurityChanges) -&gt; None:
# Liquidate if expired (or not being the front month contract anymore) and exit universe.
for removed in changes.removed_securities:
self.liquidate()</pre>
</div>

0 comments on commit 66653ed

Please sign in to comment.