Key Concepts

Duck Typing

Introduction

Duck typing is popular type system in Python. The language documentation defines duck typing as follows:

A programming style which does not look at an object's type to determine if it has the right interface; instead, the method or attribute is simply called or used (“If it looks like a duck and quacks like a duck, it must be a duck.”) By emphasizing interfaces rather than specific types, well-designed code improves its flexibility by allowing polymorphic substitution.

Duck-typing avoids tests using type() or isinstance(). (Note, however, that duck-typing can be complemented with abstract base classes.) Instead, it typically employs hasattr() tests or EAFP programming.


You can't use duck-typing to add members to regular C# types.

You can use duck-typing to add attributes to all non-primitive types in Python

// Duck-typing doesn't work on regular C# types.
class Duck { }
var duck = new Duck();
duck.quacks = "Quack!"   // This yields a compilation error.

dynamic duck = new Duck();
duck.quacks = "Quack!"   // This yields a runtime error.
# Duck-typing allows adding attributes to non-primitive types in Python.
class Duck:
    pass

duck = Duck()
duck.quacks = "Quack!"
print(duck.quacks)

LEAN allows duck-typing in the Security type.

Custom Security Properties

You can add propertiesattributes to the Security object. For example, you can add an exponential moving average.

// Cast the Equity to a dynamic object to add an EMA indicator to it.
dynamic equity = AddEquity("SPY");
equity.ema = EMA(equity.Symbol, 10, Resolution.Daily);
# Add an EMA indicator to the SPY Equity object.
equity = self.add_equity("SPY")
equity.ema = self.ema(equity.symbol, 10, Resolution.DAILY)

This feature is helpful because you can get the Security object from the Securitiessecurities object.

// Get the SPY Equity object from Securities to get the EMA indicator.
var ema = (decimal)(Securities["SPY"] as dynamic).ema.Current.Value;
# Get the SPY Equity object from Securities to get the EMA indicator.
ema = self.securities["SPY"].ema.current.value

To avoid casting to and from the dynamic type, you can use the Get<T> method to access the dynamic member and return the object with its type.

// Get the SPY Equity object from Securities to get the EMA indicator and its current value
var ema = Securities["SPY"].Get<ExponentialMovingAverage>("ema");   // The type of ema is ExponentialMovingAverage
var emaValue = ema.Current.Value;    // The type of emaValue is decimal

If the type or the member name is incorrect, the Get<T> method causes a runtime error.

Other Types

You can only add properties to the Security type.

You can add properties to all types. However, these properties live in the Python space, so you can't access them without a reference. The following example demonstrates that you can add an exponential moving average to the symbol attribute of a Security object.

# Add an EMA to the SPY security.
equity = self.add_equity("SPY")
self._symbol = equity.symbol
self._symbol.ema = self.ema(self._symbol, 10)
ema = self._symbol.ema.current.value

ema = self.securities["SPY"].symbol.ema.current.value

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: