Skip to content

Commit

Permalink
Show positions formatting (#1072)
Browse files Browse the repository at this point in the history
- Clean up `show-positions` CLI command output, so that it works better if the output is long
  • Loading branch information
miohtama authored Oct 25, 2024
1 parent 828f1b6 commit ddc2f15
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 24 deletions.
2 changes: 1 addition & 1 deletion deps/trading-strategy
1 change: 1 addition & 0 deletions tests/cli/show-positions-long.json

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions tests/cli/test_cli_show_positions_long.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Command show-positions with long output"""
import os.path
from contextlib import redirect_stdout
from io import StringIO
from pathlib import Path


from tradeexecutor.cli.main import app

def test_cli_show_positions_long(mocker):
"""show-positions command work with long output of various output.
"""
path = Path(os.path.dirname(__file__)) / "show-positions-long.json"

environment = {
"STATE_FILE": path.as_posix(),
}

mocker.patch.dict("os.environ", environment, clear=True)

f = StringIO()
with redirect_stdout(f):
app(["show-positions"], standalone_mode=False)

assert "Open positions" in f.getvalue()
assert "No frozen positions" in f.getvalue()


41 changes: 31 additions & 10 deletions tradeexecutor/analysis/position.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,35 @@ def display_positions(positions: Iterable[TradingPosition]) -> pd.DataFrame:
items.append({
"Flags": ", ".join(flags),
"Ticker": p.pair.get_ticker(),
f"Size {p.pair.base.token_symbol}": p.get_quantity(),
"Profit": p.get_realised_profit_percent() * 100 if p.is_closed() else "",
"Opened at": _ftime(p.opened_at),
"Closed at": _ftime(p.closed_at),
"Notes": p.notes,
# f"Size": p.get_quantity(),
# "Profit": p.get_realised_profit_percent() * 100 if p.is_closed() else "",
"Opened": _ftime(p.opened_at),
"Closed": _ftime(p.closed_at),
"Notes": (p.notes or "")[0:20],
})

for t in p.trades.values():
idx.append(p.position_id)

flags = []

flags.append("T")

if t.is_buy():
flags.append("B")

if t.is_sell():
flags.append("S")

if t.is_stop_loss():
flags.append("SL")

if t.is_repair_trade():
flags.append("R2")

if t.is_repaired():
flags.append("R1")

text = []
if t.notes:
text.append(t.notes)
Expand All @@ -69,12 +88,14 @@ def display_positions(positions: Iterable[TradingPosition]) -> pd.DataFrame:
text.append(revert_reason)

items.append({
"Flags": ", ".join(flags),
"Ticker": "‎ ‎ ‎ ‎ ‎ ┗",
"Trade id": str(t.trade_id), # Mixed NA/number column fix
"Price": t.executed_price,
f"Trade size": t.get_position_quantity(),
"Trade opened": _ftime(t.opened_at),
"Trade executed": _ftime(t.executed_at),
"Trade notes": "\n".join(text),
"Price": f"{t.executed_price:.6f}" if t.executed_price else "-",
f"Trade size": f"{t.get_position_quantity():,.2f}",
"Opened": _ftime(t.opened_at),
"Executed": _ftime(t.executed_at),
"Notes": "\n".join(text)[0:20],
})

df = pd.DataFrame(items, index=idx)
Expand Down
34 changes: 23 additions & 11 deletions tradeexecutor/cli/commands/show_positions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@


class PositionType(enum.Enum):
"""What output we want from show-positions command."""

#: Show only open positions
open = "open"

#: Show only open positions
open_and_frozen = "open_and_frozen"

#: Show all positions
all = "all"

Expand All @@ -30,7 +34,7 @@ def show_positions(
id: str = shared_options.id,
state_file: Optional[Path] = shared_options.state_file,
strategy_file: Optional[Path] = shared_options.optional_strategy_file,
position_type: PositionType = Option(PositionType.open.value, envvar="POSITION_TYPE", help="Which position types to display")
position_type: PositionType = Option(PositionType.open_and_frozen.value, envvar="POSITION_TYPE", help="Which position types to display")
):
"""Display trading positions from a state file.
Expand All @@ -54,21 +58,29 @@ def show_positions(

print(f"Displaying positions and trades for state {state.name}")
print(f"State last updated: {state.last_updated_at}")

if position_type == PositionType.open:
print("Open positions")
df = display_positions(state.portfolio.open_positions.values())
# https://pypi.org/project/tabulate/
# https://stackoverflow.com/a/31885295/315168
print(f"Position flags: F = frozen, R = contains repairs, UE = unexpected trades, SL = stop loss triggered, - = trade")
print(f"Trade flags: T = trade, B = buy, S = sell, SL = stop loss, R1 = repaired, R2 = repairing")

print("Open positions")
df = display_positions(state.portfolio.open_positions.values())
# https://pypi.org/project/tabulate/
# https://stackoverflow.com/a/31885295/315168
if len(df) > 0:
print(tabulate(df, headers='keys', tablefmt='rounded_outline'))
print()
else:
print("No open positions")
print()

if position_type == PositionType.all:
if position_type in (PositionType.all, PositionType.open_and_frozen):
print("Frozen positions")
df = display_positions(state.portfolio.frozen_positions.values())
print(tabulate(df, headers='keys', tablefmt='rounded_outline'))

if len(df) > 0:
print(tabulate(df, headers='keys', tablefmt='rounded_outline'))
else:
print("No frozen positions")
print()

if position_type == PositionType.all:
print("Closed positions")
df = display_positions(state.portfolio.closed_positions.values())
print(tabulate(df, headers='keys', tablefmt='rounded_outline'))
4 changes: 2 additions & 2 deletions tradeexecutor/strategy/pandas_trader/decision_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,13 +350,13 @@ def wait_for_universe_data_availability_jsonl(
)

# Avoid excessive logging output if > 10 pairs
last_timestamps_log = last_timestamps_log[0:400]
last_timestamps_log_str = str(last_timestamps_log)[0:400]

logger.info("Timestamp wanted %s, Completed pairs: %d, Incompleted pairs: %d, last candles %s, diff is %s, sleeping %s",
wanted_timestamp,
len(completed_pairs),
len(incompleted_pairs),
last_timestamps_log,
last_timestamps_log_str,
diff,
poll_delay)

Expand Down

0 comments on commit ddc2f15

Please sign in to comment.