Example #1
0
    def summarize_account(self):
        account_summary = self.ib.accountSummary(self.config["account"]["number"])
        click.echo()
        click.secho(f"Account summary:", fg="green")
        click.echo()
        account_summary = account_summary_to_dict(account_summary)

        click.secho(
            f"  Excess liquidity  = {justify(account_summary['ExcessLiquidity'].value)}",
            fg="cyan",
        )
        click.secho(
            f"  Net liquidation   = {justify(account_summary['NetLiquidation'].value)}",
            fg="cyan",
        )
        click.secho(
            f"  Cushion           = {account_summary['Cushion'].value} ({round(float(account_summary['Cushion'].value) * 100, 1)}%)",
            fg="cyan",
        )
        click.secho(
            f"  Full maint margin = {justify(account_summary['FullMaintMarginReq'].value)}",
            fg="cyan",
        )
        click.secho(
            f"  Buying power      = {justify(account_summary['BuyingPower'].value)}",
            fg="cyan",
        )
        click.secho(
            f"  Total cash value  = {justify(account_summary['TotalCashValue'].value)}",
            fg="cyan",
        )

        portfolio_positions = self.get_portfolio_positions()

        click.echo()
        click.secho("Portfolio positions:", fg="green")
        click.echo()
        for symbol in portfolio_positions.keys():
            click.secho(f"  {symbol}:", fg="cyan")
            for p in portfolio_positions[symbol]:
                if isinstance(p.contract, Stock):
                    pnl = round(position_pnl(p) * 100, 2)
                    click.secho(
                        f"    Stock Qty={int(p.position)} Price={round(p.marketPrice,2)} Value={round(p.marketValue,2)} AvgCost={round(p.averageCost,2)} P&L={pnl}%",
                        fg="cyan",
                    )
                elif isinstance(p.contract, Option):
                    pnl = round(position_pnl(p) * 100, 2)

                    def p_or_c(p):
                        return "Call" if p.contract.right.startswith("C") else "Put "

                    click.secho(
                        f"    {p_or_c(p)}  Qty={int(p.position)} Price={round(p.marketPrice,2)} Value={round(p.marketValue,2)} AvgCost={round(p.averageCost,2)} P&L={pnl}% Strike={p.contract.strike} Exp={p.contract.lastTradeDateOrContractMonth}",
                        fg="cyan",
                    )
                else:
                    click.secho(f"    {p.contract}", fg="cyan")

        return (account_summary, portfolio_positions)
Example #2
0
    def put_can_be_rolled(self, put):
        # Check if this put is ITM, and if it's o.k. to roll
        if not self.config["roll_when"]["puts"]["itm"] and self.put_is_itm(
                put.contract):
            return False

        dte = option_dte(put.contract.lastTradeDateOrContractMonth)
        pnl = position_pnl(put)

        roll_when_dte = self.config["roll_when"]["dte"]
        roll_when_pnl = self.config["roll_when"]["pnl"]
        roll_when_min_pnl = self.config["roll_when"]["min_pnl"]

        if dte <= roll_when_dte:
            if pnl >= roll_when_min_pnl:
                click.secho(
                    f"  {put.contract.localSymbol} can be rolled because DTE of {dte} is <= {self.config['roll_when']['dte']} and P&L of {round(pnl * 100, 1)}% is >= {round(roll_when_min_pnl * 100, 1)}%",
                    fg="blue",
                )
                return True
            else:
                click.secho(
                    f"  {put.contract.localSymbol} can't be rolled because P&L of {round(pnl * 100, 1)}% is < {round(roll_when_min_pnl * 100, 1)}%",
                    fg="red",
                )

        if pnl >= roll_when_pnl:
            click.secho(
                f"  {put.contract.localSymbol} can be rolled because P&L of {round(pnl * 100, 1)}% is >= {round(roll_when_pnl * 100, 1)}",
                fg="blue",
            )
            return True

        return False
    def call_can_be_rolled(self, call):
        # Check if this call is ITM, and it's o.k. to roll
        if ("calls" in self.config["roll_when"]
                and not self.config["roll_when"]["calls"]["itm"]
            ) and self.call_is_itm(call.contract):
            return False

        dte = option_dte(call.contract.lastTradeDateOrContractMonth)
        pnl = position_pnl(call)

        if dte <= self.config["roll_when"]["dte"]:
            click.secho(
                f"{call.contract.localSymbol} can be rolled because DTE of {dte} is <= {self.config['roll_when']['dte']}",
                fg="blue",
            )
            return True

        if pnl >= self.config["roll_when"]["pnl"]:
            click.secho(
                f"{call.contract.localSymbol} can be rolled because P&L of {round(pnl * 100, 1)}% is >= {round(self.config['roll_when']['pnl'] * 100, 1)}",
                fg="blue",
            )
            return True

        return False
Example #4
0
    def call_can_be_rolled(self, call):
        # Ignore long positions, we only roll shorts
        if call.position > 0:
            return False

        # Check if this call is ITM, and it's o.k. to roll
        if not self.config["roll_when"]["calls"]["itm"] and self.call_is_itm(
            call.contract
        ):
            return False

        dte = option_dte(call.contract.lastTradeDateOrContractMonth)
        pnl = position_pnl(call)

        roll_when_dte = self.config["roll_when"]["dte"]
        roll_when_pnl = self.config["roll_when"]["pnl"]
        roll_when_min_pnl = self.config["roll_when"]["min_pnl"]

        if (
            "max_dte" in self.config["roll_when"]
            and dte > self.config["roll_when"]["max_dte"]
        ):
            return False

        if dte <= roll_when_dte:
            if pnl >= roll_when_min_pnl:
                click.secho(
                    f"  {call.contract.localSymbol} can be rolled because DTE of {dte} is <= {self.config['roll_when']['dte']} and P&L of {round(pnl * 100, 1)}% is >= {round(roll_when_min_pnl * 100, 1)}%",
                    fg="blue",
                )
                return True
            else:
                click.secho(
                    f"  {call.contract.localSymbol} can't be rolled because P&L of {round(pnl * 100, 1)}% is < {round(roll_when_min_pnl * 100, 1)}%",
                    fg="red",
                )

        if pnl >= roll_when_pnl:
            click.secho(
                f"  {call.contract.localSymbol} can be rolled because P&L of {round(pnl * 100, 1)}% is >= {round(roll_when_pnl * 100, 1)}",
                fg="blue",
            )
            return True

        return False
Example #5
0
    def call_can_be_rolled(self, call):
        dte = option_dte(call.contract.lastTradeDateOrContractMonth)
        pnl = position_pnl(call)

        if dte <= self.config["roll_when"]["dte"]:
            click.secho(
                f"{call.contract.localSymbol} can be rolled because DTE of {dte} is <= {self.config['roll_when']['dte']}",
                fg="blue",
            )
            return True

        if pnl >= self.config["roll_when"]["pnl"]:
            click.secho(
                f"{call.contract.localSymbol} can be rolled because P&L of {round(pnl * 100, 1)}% is >= {round(self.config['roll_when']['pnl'] * 100,1)}",
                fg="blue",
            )
            return True

        return False
Example #6
0
    def put_can_be_rolled(self, put):
        # Check if this put is ITM. Do not roll ITM puts.
        if self.put_is_itm(put.contract):
            return False

        dte = option_dte(put.contract.lastTradeDateOrContractMonth)
        pnl = position_pnl(put)

        if dte <= self.config["roll_when"]["dte"]:
            click.secho(
                f"  {put.contract.localSymbol} can be rolled because DTE of {dte} is <= {self.config['roll_when']['dte']}",
                fg="blue",
            )
            return True

        if pnl >= self.config["roll_when"]["pnl"]:
            click.secho(
                f"  {put.contract.localSymbol} can be rolled because P&L of {round(pnl * 100, 1)}% is >= {round(self.config['roll_when']['pnl'] * 100,1)}",
                fg="blue",
            )
            return True

        return False
Example #7
0
def test_position_pnl():
    qqq_put = PortfolioItem(
        contract=Option(
            conId=397556522,
            symbol="QQQ",
            lastTradeDateOrContractMonth="20201218",
            strike=300.0,
            right="P",
            multiplier="100",
            primaryExchange="AMEX",
            currency="USD",
            localSymbol="QQQ   201218P00300000",
            tradingClass="QQQ",
        ),
        position=-1.0,
        marketPrice=4.1194396,
        marketValue=-411.94,
        averageCost=222.4293,
        unrealizedPNL=-189.51,
        realizedPNL=0.0,
        account="DU2962946",
    )
    assert round(position_pnl(qqq_put), 2) == -0.85

    spy = PortfolioItem(
        contract=Stock(
            conId=756733,
            symbol="SPY",
            right="0",
            primaryExchange="ARCA",
            currency="USD",
            localSymbol="SPY",
            tradingClass="SPY",
        ),
        position=100.0,
        marketPrice=365.4960022,
        marketValue=36549.6,
        averageCost=368.42,
        unrealizedPNL=-292.4,
        realizedPNL=0.0,
        account="DU2962946",
    )
    assert round(position_pnl(spy), 4) == -0.0079

    spy_call = PortfolioItem(
        contract=Option(
            conId=454208258,
            symbol="SPY",
            lastTradeDateOrContractMonth="20201214",
            strike=373.0,
            right="C",
            multiplier="100",
            primaryExchange="AMEX",
            currency="USD",
            localSymbol="SPY   201214C00373000",
            tradingClass="SPY",
        ),
        position=-1.0,
        marketPrice=0.08,
        marketValue=-8.0,
        averageCost=96.422,
        unrealizedPNL=88.42,
        realizedPNL=0.0,
        account="DU2962946",
    )
    assert round(position_pnl(spy_call), 2) == 0.92

    spy_put = PortfolioItem(
        contract=Option(
            conId=458705534,
            symbol="SPY",
            lastTradeDateOrContractMonth="20210122",
            strike=352.5,
            right="P",
            multiplier="100",
            primaryExchange="AMEX",
            currency="USD",
            localSymbol="SPY   210122P00352500",
            tradingClass="SPY",
        ),
        position=-1.0,
        marketPrice=5.96710015,
        marketValue=-596.71,
        averageCost=528.9025,
        unrealizedPNL=-67.81,
        realizedPNL=0.0,
        account="DU2962946",
    )
    assert round(position_pnl(spy_put), 2) == -0.13