108108 DCA_MODE_VARIABLE ,
109109 DCA_BASE_INVESTMENT_VARIABLE ,
110110)
111+ DCA_MODE_CONTROL_FIELD = "dca_mode"
112+ DCA_BASE_INVESTMENT_CONTROL_FIELD = "dca_base_investment_usd"
111113DEFAULT_VARIABLE_SCOPE = {
112114 "longbridge" : "environment" ,
113115 "ibkr" : "repository" ,
@@ -236,21 +238,40 @@ def _normalize_positive_decimal(value: str, *, field_name: str) -> str:
236238 return text
237239
238240
239- def _dca_extra_variables (args : argparse .Namespace , strategy_profile : str ) -> dict [str , Any ]:
241+ def _extract_dca_control_fields (extra_variables : dict [str , Any ]) -> dict [str , Any ]:
242+ controls : dict [str , Any ] = {}
243+ for field_name in (DCA_MODE_CONTROL_FIELD , DCA_BASE_INVESTMENT_CONTROL_FIELD ):
244+ if field_name in extra_variables :
245+ controls [field_name ] = extra_variables .pop (field_name )
246+ return controls
247+
248+
249+ def _dca_extra_variables (
250+ args : argparse .Namespace ,
251+ strategy_profile : str ,
252+ controls : dict [str , Any ] | None = None ,
253+ ) -> dict [str , Any ]:
254+ controls = dict (controls or {})
240255 is_dca_profile = strategy_profile in DCA_PROFILES
241- has_dca_mode = bool (str (args .dca_mode or "" ).strip ())
242- has_dca_base = bool (str (args .dca_base_investment_usd or "" ).strip ())
256+ dca_mode = args .dca_mode if str (args .dca_mode or "" ).strip () else controls .get (DCA_MODE_CONTROL_FIELD , "" )
257+ dca_base_investment_usd = (
258+ args .dca_base_investment_usd
259+ if str (args .dca_base_investment_usd or "" ).strip ()
260+ else controls .get (DCA_BASE_INVESTMENT_CONTROL_FIELD , "" )
261+ )
262+ has_dca_mode = bool (str (dca_mode or "" ).strip ())
263+ has_dca_base = bool (str (dca_base_investment_usd or "" ).strip ())
243264 if not is_dca_profile :
244265 if has_dca_mode or has_dca_base :
245266 raise ValueError ("DCA settings are only supported for DCA strategy profiles" )
246267 return {variable : "" for variable in DCA_RUNTIME_VARIABLES }
247268
248269 extra_variables : dict [str , Any ] = {}
249270 if has_dca_mode :
250- extra_variables [DCA_MODE_VARIABLE ] = _normalize_dca_mode (args . dca_mode )
271+ extra_variables [DCA_MODE_VARIABLE ] = _normalize_dca_mode (dca_mode )
251272 if has_dca_base :
252273 extra_variables [DCA_BASE_INVESTMENT_VARIABLE ] = _normalize_positive_decimal (
253- args . dca_base_investment_usd ,
274+ dca_base_investment_usd ,
254275 field_name = "dca_base_investment_usd" ,
255276 )
256277 return extra_variables
@@ -264,7 +285,9 @@ def _reject_direct_dca_extra_variables(extra_variables: dict[str, Any]) -> None:
264285 ]
265286 if provided :
266287 names = ", " .join (provided )
267- raise ValueError (f"use --dca-mode and --dca-base-investment-usd instead of extra_variables_json for { names } " )
288+ raise ValueError (
289+ f"use dca_mode and dca_base_investment_usd control fields instead of extra_variables_json for { names } "
290+ )
268291
269292
270293def _auto_plugin_mounts (strategy_profile : str , artifact_bucket_uri : str ) -> list [dict [str , Any ]]:
@@ -463,6 +486,7 @@ def build_switch_target(args: argparse.Namespace) -> dict[str, Any]:
463486 mounts = _plugin_mounts (args , runtime_target ["strategy_profile" ])
464487 mounts_variable = f"{ SUPPORTED_PLATFORMS [platform ]['plugin_mounts_prefix' ]} STRATEGY_PLUGIN_MOUNTS_JSON"
465488 extra_variables = _parse_extra_variables (args .extra_variable , args .extra_variables_json )
489+ dca_controls = _extract_dca_control_fields (extra_variables )
466490 _reject_direct_dca_extra_variables (extra_variables )
467491
468492 if args .set_platform_dry_run_variable :
@@ -479,7 +503,7 @@ def build_switch_target(args: argparse.Namespace) -> dict[str, Any]:
479503 extra_variables ["INCOME_THRESHOLD_USD" ] = args .income_threshold_usd
480504 if args .qqqi_income_ratio :
481505 extra_variables ["QQQI_INCOME_RATIO" ] = args .qqqi_income_ratio
482- extra_variables .update (_dca_extra_variables (args , runtime_target ["strategy_profile" ]))
506+ extra_variables .update (_dca_extra_variables (args , runtime_target ["strategy_profile" ], dca_controls ))
483507
484508 service_targets = _load_json_from_file (
485509 args .existing_service_targets_json_file ,
0 commit comments