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 cannot 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

class Duck { }
var duck = new Duck();
duck.quacks = "Quack!"   // Yields a compilation error

dynamic duck = new Duck();
duck.quacks = "Quack!"   // Yields a runtime error
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.

dynamic equity = AddEquity("SPY");
equity.ema = EMA(equity.Symbol, 10, Resolution.Daily);
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.

var ema = (Securities["SPY"] as dynamic).ema.Current.Value;
ema = self.securities["SPY"].ema.current.value

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.

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   # 'Symbol' object has no attribute 'time'

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: