AlphaModel#

API documentation for tradeexecutor.strategy.alpha_model.AlphaModel Python class in Trading Strategy framework.

class AlphaModel[source]#

Bases: object

Capture alpha model state for one strategy cycle.

  • A helper class for portfolio construction models and such

  • Converts portfolio weightings to rebalancing trades

  • Supports stop loss and passing through other trade execution parameters

  • Each strategy cycle creates its own AlphaModel instance in decide_trades() function of the strategy

  • Stores the intermediate results of the calculationsn between raw weights and the final investment amount

  • We are serializable as JSON, so we can pass the calculations as data around in tradeexecutor.state.visualisation.Visualisation.calculations and then later visualise alph model progress over time with other analytic diagrams

__init__(timestamp=None, raw_signals=<factory>, signals=<factory>, investable_equity=None, accepted_investable_equity=None, close_position_weight_epsilon=0.005)#
Parameters:
Return type:

None

Methods

__init__([timestamp, raw_signals, signals, ...])

assign_weights([method])

Convert raw signals to their portfolio weight counterparts.

calculate_target_positions(position_manager)

Calculate individual dollar amount for each position based on its normalised weight.

calculate_weight_diffs()

Calculate how much % asset weight has changed between strategy cycles.

from_dict(kvs, *[, infer_missing])

from_json(s, *[, parse_float, parse_int, ...])

generate_rebalance_trades_and_triggers(...)

Generate the trades that will rebalance the portfolio.

get_debug_print()

Present the alpha model in a format suitable for the console.

get_signal_by_pair(pair)

Get a trading pair signal instance for one pair.

get_signal_by_pair_id(pair_id)

Get a trading pair signal instance for one pair.

get_signals_sorted_by_weight()

Get the signals sorted by the weight.

has_any_position()

For this cycle, are we going to do any trades.

has_any_signal()

For this cycle, should we try to do any trades.

iterate_signals()

Iterate over all recorded signals.

map_pair_for_signal(position_manager, signal)

Figure out if we are going to trade spot, leveraged long, leveraged short.

normalise_weights([max_weight, ...])

Normalise weights to 0...1 scale.

schema(*[, infer_missing, only, exclude, ...])

select_top_signals(count[, threshold])

Chooses top signals.

set_old_weight(pair, old_weight, old_value, ...)

Set the weights for the8 current portfolio trading positions before rebalance.

set_signal(pair, alpha[, stop_loss, ...])

Set trading pair alpha to a value.

to_dict([encode_json])

to_json(*[, skipkeys, ensure_ascii, ...])

update_old_weights(portfolio[, ...])

Update the old weights of the last strategy cycle to the alpha model.

Attributes

timestamp

Timestamp of the strategy cycle for which this alpha model was calculated

raw_signals

Calculated signals for all trading pairs.

signals

The chosen top signals.

investable_equity

How much we can afford to invest on this cycle.

accepted_investable_equity

How much we can decide to invest, after calculating position size risk.

close_position_weight_epsilon

Determine the lower threshold for a position weight.

override_stop_loss

Allow set_signal() to override stop loss set for the position earlier

timestamp: Optional[datetime]#

Timestamp of the strategy cycle for which this alpha model was calculated

raw_signals: Dict[int, TradingPairSignal]#

Calculated signals for all trading pairs.

Pair internal id -> trading signal data.

For all trading pairs in the model.

Set by set_signal()

signals: Dict[int, TradingPairSignal]#

The chosen top signals.

Pair internal id -> trading signal data.

For signals chosen for the rebalance, e.g. top 5 long signals.

Set by select_top_signals()

investable_equity: Optional[float]#

How much we can afford to invest on this cycle.

See also accepted_investable_equity

accepted_investable_equity: Optional[float]#

How much we can decide to invest, after calculating position size risk.

Filled by normalise_weights() and size risk model is used.

See also investable_equity.

close_position_weight_epsilon: float#

Determine the lower threshold for a position weight.

Clean up “dust” by explicitly closing positions if they fall too small.

If position weight is less than 0.5% always close it

override_stop_loss = False#

Allow set_signal() to override stop loss set for the position earlier

iterate_signals()[source]#

Iterate over all recorded signals.

Return type:

Iterable[TradingPairSignal]

get_signal_by_pair_id(pair_id)[source]#

Get a trading pair signal instance for one pair.

Use integer id lookup.

Parameters:

pair_id (int) –

Return type:

Optional[TradingPairSignal]

get_signal_by_pair(pair)[source]#

Get a trading pair signal instance for one pair.

Use verbose TradingPairIdentifier lookup.

Parameters:

pair (TradingPairIdentifier) –

Return type:

Optional[TradingPairSignal]

get_signals_sorted_by_weight()[source]#

Get the signals sorted by the weight.

Return the highest weight first.

Return type:

Iterable[TradingPairSignal]

get_debug_print()[source]#

Present the alpha model in a format suitable for the console.

Return type:

str

has_any_signal()[source]#

For this cycle, should we try to do any trades.

Any of the signals have non-zero value

Returns:

True if alpha model should attempt to do some trades on this timestamp/cycle.

Trades could be still cancelled (zeroed out) by a risk model.

Return type:

bool

has_any_position()[source]#

For this cycle, are we going to do any trades.

Some signals have TradingSignal.position_target set after the risk adjustments.

Returns:

True if alpha model should attempt to do some trades on this timestamp/cycle.

Trades could be still cancelled (zeroed out) by a risk model.

Return type:

bool

set_signal(pair, alpha, stop_loss=None, take_profit=None, trailing_stop_loss=None, leverage=None)[source]#

Set trading pair alpha to a value.

If called repeatatle for the same trading pair, remember the last value.

Parameters:
  • pair (TradingPairIdentifier) –

    Trading pair.

    Always the underlying spot pair.

  • alpha (float | numpy.float32) –

    How much alpha signal this trading pair carries.

    Set to zero to have the pair excluded out after a risk assessment

  • stop_loss (float | None) –

    Stop loss threshold for this pair.

    As the percentage of the position value.

    0.98 means 2% stop loss.

  • take_profit (float | None) –

    Stop loss threshold for this pair.

    As the percentage of the position value.

    1.02 means 2% take profit.

  • trailing_stop_loss (float | None) –

    Trailing stop loss threshold for this pair.

    As the percentage of the position value.

    0.98 means 2% trailing stop loss.

  • leverage (float | None) –

    Position leverage.

    Must be set for short and leveraged long.

    If not set assume spot.

set_old_weight(pair, old_weight, old_value, old_synthetic_pair)[source]#

Set the weights for the8 current portfolio trading positions before rebalance.

Parameters:
select_top_signals(count, threshold=0.0)[source]#

Chooses top signals.

Choose trading pairs to the next rebalance by their signal strength.

Sets signals attribute of the model

Example:

alpha_model.select_top_signals(
    count=5,  # Pick top 5 trading pairs
    threshold=0.01,  # Need at least 1% signal certainty to be eligible
)
Parameters:
  • count (int) – How many signals to pick.

  • threshold

    If the raw signal value is lower than this threshold then don’t pick the signal.

    Note

    It’s better to filter signals in your decide_trades() functinos before calling this, as this allows you have to different thresholds for long and short signals.

    Inclusive.

    0.01 = 1% signal strenght.

normalise_weights(max_weight=1.0, investable_equity=None, size_risk_model=None)[source]#

Normalise weights to 0…1 scale.

  • Apply different risk-adjustments for the normalised positions sizes, if given

  • After normalising, we can allocate the positionts normalised_weight * portfolio equity.

  • See also tradeexecutor.strategy.size_risk_model to set per-pair specific US dollar nominated settings for a position size

Parameters:
  • max_weight

    Do not allow equity allocation to exceed this % for a single asset.

    Set to 1.0 to no portfolio concentrated risk considered.

    This may happen if you have a portfolio of max assets of 10, but due to market conditions there is signal only for 1-2 pairs. max_weight caps the asset allocation, preventing too concentrated positions.

  • size_risk_model (tradeexecutor.strategy.size_risk_model.SizeRiskModel | None) –

    Limit position sizes by the current market conditions.

    E.g. Do not allow large positions that exceed available lit liquidity.

  • investable_equity (float | None) – Only needed if size_risk_model is given.

assign_weights(method=<function weight_by_1_slash_n>)[source]#

Convert raw signals to their portfolio weight counterparts.

Update TradingPairSignal.raw_weight attribute to our target trading pairs.

Parameters:

method – What method we use to convert a trading signal to a portfolio weights

update_old_weights(portfolio, portfolio_pairs=None, ignore_credit=True)[source]#

Update the old weights of the last strategy cycle to the alpha model.

  • Update % of portfolio weight of an asset

  • Update USD portfolio value of an asset

Parameters:
calculate_weight_diffs()[source]#

Calculate how much % asset weight has changed between strategy cycles.

Returns:

Pair id, weight delta dict

Return type:

Dict[int, float]

calculate_target_positions(position_manager, investable_equity=None)[source]#

Calculate individual dollar amount for each position based on its normalised weight.

  • Sets the dollar value of the position

  • Adjusts the existing dollar value of positions

  • Map the signal to a trading pair (spot, synthetic short pair, etc.)

Parma position_manager:

Used to genenerate TradeExecution instances

Parameters:
  • investable_equity (float | None) –

    How much cash we have if we convert the whole portfolio to cash.

    Only needed to give now if size risk model not used with normalise_weights().

  • position_manager (PositionManager) –

map_pair_for_signal(position_manager, signal)[source]#

Figure out if we are going to trade spot, leveraged long, leveraged short.

Parameters:
Return type:

TradingPairIdentifier

generate_rebalance_trades_and_triggers(position_manager, min_trade_threshold=10.0, invidiual_rebalance_min_threshold=0.0, use_spot_for_long=True)[source]#

Generate the trades that will rebalance the portfolio.

This will generate

  • Sells for the existing assets

  • Buys for new assets or assets where we want to increase our position

  • Set up take profit/stop loss triggers for positions

Parameters:
  • position_manager (PositionManager) – Portfolio of our existing holdings

  • min_trade_threshold (float) –

    Threshold for too small trades.

    If the notional value of a rebalance trade is smaller than this USD amount don’t make a trade, but keep whatever position we currently we have.

    This is to prevent doing too small trades due to fuzziness in the valuations and calculations.

  • invidiual_rebalance_min_threshold (float) – If an invidual treade value is smaller than this, skip it.

  • use_spot_for_long

    If we go long a pair, use spot.

    If set False, use leveraged long.

Returns:

List of trades we need to execute to reach the target portfolio. The sells are sorted always before buys.

Return type:

List[TradeExecution]

__init__(timestamp=None, raw_signals=<factory>, signals=<factory>, investable_equity=None, accepted_investable_equity=None, close_position_weight_epsilon=0.005)#
Parameters:
Return type:

None