diff --git a/systems/provided/dynamic_small_system_optimise/data_for_optimisation.py b/systems/provided/dynamic_small_system_optimise/data_for_optimisation.py index 156e0ac560..be561cdf40 100644 --- a/systems/provided/dynamic_small_system_optimise/data_for_optimisation.py +++ b/systems/provided/dynamic_small_system_optimise/data_for_optimisation.py @@ -15,6 +15,7 @@ def __init__(self, obj_instance: "objectiveFunctionForGreedy"): self.weights_optimal = obj_instance.weights_optimal self.per_contract_value = obj_instance.per_contract_value self.costs = obj_instance.costs + self.long_only = obj_instance.long_only if obj_instance.constraints is arg_not_supplied: reduce_only_keys = no_trade_keys = arg_not_supplied diff --git a/systems/provided/dynamic_small_system_optimise/optimisation.py b/systems/provided/dynamic_small_system_optimise/optimisation.py index 6ea008e32a..ba32e217fb 100644 --- a/systems/provided/dynamic_small_system_optimise/optimisation.py +++ b/systems/provided/dynamic_small_system_optimise/optimisation.py @@ -39,6 +39,7 @@ def __init__( previous_positions: portfolioWeights = arg_not_supplied, constraints: constraintsForDynamicOpt = arg_not_supplied, maximum_positions: portfolioWeights = arg_not_supplied, + long_only: list = arg_not_supplied, log: pst_logger = get_logger("objectiveFunctionForGreedy"), ): @@ -53,6 +54,7 @@ def __init__( self.weights_optimal = weights_optimal self.contracts_optimal = contracts_optimal + self.long_only = long_only if previous_positions is arg_not_supplied: weights_prior = arg_not_supplied diff --git a/systems/provided/dynamic_small_system_optimise/set_up_constraints.py b/systems/provided/dynamic_small_system_optimise/set_up_constraints.py index 25bba896bd..56a7bb218f 100644 --- a/systems/provided/dynamic_small_system_optimise/set_up_constraints.py +++ b/systems/provided/dynamic_small_system_optimise/set_up_constraints.py @@ -72,6 +72,10 @@ def get_data_and_calculate_for_code( no_trade = False else: no_trade = instrument_code in input_data.no_trade_keys + if input_data.long_only is arg_not_supplied: + long_only = False + else: + long_only = instrument_code in input_data.long_only max_position = input_data.maximum_position_weight_for_code(instrument_code) weight_prior = input_data.prior_weight_for_code(instrument_code) @@ -83,6 +87,7 @@ def get_data_and_calculate_for_code( max_position=max_position, weight_prior=weight_prior, optimium_weight=optimium_weight, + long_only=long_only, ) return min_max_and_direction_and_start_for_code @@ -94,6 +99,7 @@ def calculations_for_code( max_position: float = arg_not_supplied, weight_prior: float = arg_not_supplied, optimium_weight: float = np.nan, + long_only: bool = False, ): minimum, maximum = calculate_minima_and_maxima( @@ -101,6 +107,7 @@ def calculations_for_code( no_trade=no_trade, max_position=max_position, weight_prior=weight_prior, + long_only=long_only, ) assert maximum >= minimum @@ -118,6 +125,7 @@ def calculations_for_code( def calculate_minima_and_maxima( reduce_only: bool = False, + long_only: bool = False, no_trade: bool = False, max_position: float = arg_not_supplied, weight_prior: float = arg_not_supplied, @@ -126,6 +134,9 @@ def calculate_minima_and_maxima( minimum = -A_VERY_LARGE_NUMBER maximum = A_VERY_LARGE_NUMBER + if long_only: + minimum = 0.0 + if no_trade: if weight_prior is not arg_not_supplied: return weight_prior, weight_prior @@ -136,7 +147,7 @@ def calculate_minima_and_maxima( minimum = 0.0 maximum = weight_prior elif weight_prior < 0: - minimum = weight_prior + minimum = max(minimum, weight_prior) maximum = 0.0 else: