Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor fix live existing cash or holdings state #504

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions lean/components/util/live_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,13 @@ def get_last_portfolio_cash_holdings(api_client: APIClient, brokerage_instance:
if cash_balance_option != LiveInitialStateInput.NotSupported or holdings_option != LiveInitialStateInput.NotSupported:
last_portfolio = _get_last_portfolio(api_client, project_id, project)
if last_portfolio is not None:
for key, value in last_portfolio["cash"].items():
last_cash[key] = InsensitiveCaseDict(value)
for key, value in last_portfolio["holdings"].items():
last_holdings[key] = InsensitiveCaseDict(value)
last_holdings[key]["symbol"] = InsensitiveCaseDict(last_holdings[key]["symbol"])
if "cash" in last_portfolio:
for key, value in last_portfolio["cash"].items():
last_cash[key] = InsensitiveCaseDict(value)
if "holdings" in last_portfolio:
for key, value in last_portfolio["holdings"].items():
last_holdings[key] = InsensitiveCaseDict(value)
last_holdings[key]["symbol"] = InsensitiveCaseDict(last_holdings[key]["symbol"])
else:
last_cash = None
last_holdings = None
Expand Down
37 changes: 36 additions & 1 deletion tests/commands/test_live.py
Original file line number Diff line number Diff line change
Expand Up @@ -1139,11 +1139,16 @@ def test_live_non_interactive_deploy_with_real_brokerage_without_credentials() -
assert "--oanda-environment" in error_msg
assert "--iex-price-plan" not in error_msg

def create_lean_option(brokerage_name: str, data_provider_live_name: str, data_provider_historical_name: str, api_client: any) -> Result:

def create_lean_option(brokerage_name: str, data_provider_live_name: str, data_provider_historical_name: str,
api_client: any, environment_modifier=None) -> Result:
reset_state_installed_modules()
create_fake_lean_cli_directory()
create_fake_environment("live-paper", True)

if environment_modifier:
environment_modifier()

initialize_container(api_client_to_use=api_client)

option = ["--brokerage", brokerage_name]
Expand Down Expand Up @@ -1249,3 +1254,33 @@ def test_live_non_interactive_deploy_paper_brokerage_different_live_data_provide
is_exist = True

assert is_exist


@pytest.mark.parametrize("brokerage_name,data_provider_live_name,existing_cash,existing_holdings",
[("Paper Trading", "Polygon", "True", "True"),
("Paper Trading", "Polygon", "True", "False"),
("Paper Trading", "Polygon", "False", "True"),
("Paper Trading", "Polygon", "False", "False")])
def test_live_state_file(brokerage_name: str, data_provider_live_name: str,
existing_cash: bool, existing_holdings: bool) -> None:
api_client = mock.MagicMock()

def environment_modifier():
result_directory = Path.cwd() / "Python Project" / "live" / "2024-09-26_17-25-28"
result_file = result_directory / f"L-3875119070.json"
result_file.parent.mkdir(parents=True, exist_ok=True)
with open(result_file, "w+") as out_file:
state = {}
if existing_cash:
state["cash"] = {"USD": {"symbol": "USD", "amount": 100000.0}}
if existing_holdings:
state["holdings"] = {"BTCUSD 2XR":{"symbol":{"value":"BTCUSD","id":"BTCUSD 2XR","permtick":"BTCUSD"},
"type":7,"currencySymbol":"$","averagePrice":64778.92,"quantity":0.3,
"marketPrice":63425.05,"conversionRate":1.0,"marketValue":19027.515,
"unrealizedPnl":-25.98,"unrealizedPnLPercent":-0.13}}
json.dump(state, out_file)
with open(result_directory / "config", "w+") as out_file:
json.dump({"algorithm-language": "Python", "parameters": {}, "id": "3875119070"}, out_file)

create_lean_option(brokerage_name, data_provider_live_name, None, api_client,
environment_modifier=environment_modifier)
3 changes: 3 additions & 0 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def create_fake_lean_cli_directory() -> None:

_write_fake_directory(files)


def create_fake_lean_cli_project(name: str, language: str) -> None:
"""Creates a directory structure similar to the one created by `lean init` with a given project info"""
(Path.cwd() / "data").mkdir()
Expand All @@ -121,6 +122,7 @@ def create_fake_lean_cli_project(name: str, language: str) -> None:

_write_fake_directory(files)


def create_fake_lean_cli_directory_with_subdirectories(depth: int) -> None:
"""Creates a directory structure similar to the one created by `lean init` with a Python and a C# project,
and a Python and a C# library"""
Expand Down Expand Up @@ -229,6 +231,7 @@ def create_lean_environments() -> List[QCLeanEnvironment]:
public=True)
]


def reset_state_installed_modules() -> None:
for data_provider in (cli_brokerages + cli_data_downloaders + cli_data_queue_handlers
+ cli_addon_modules + cli_history_provider):
Expand Down
Loading