def test_pos():
    bid = Position(pos=Decimal('1'), price=100, side=Side.ASK) + Position(pos=Decimal('0.1'), price=101, side=Side.BID)
    assert bid.position() == Decimal('-0.9')
    assert bid.side() == Side.ASK

    bid = Position(pos=Decimal('1'), price=100, side=Side.BID) + Position(pos=Decimal('0.1'), price=101, side=Side.ASK)
    assert bid.position() == Decimal('0.9')
    assert bid.side() == Side.BID

    print(bid)
示例#2
0
class PNL:
    def __init__(self, fee):
        self.method = BipolarContainer('NONE', 'NONE')
        self.pos = Position(0, 0)
        self.nbbo = BipolarContainer(0, 0)
        self.closed_pnl = Decimal('0')
        self.clean_closed_pnl = Decimal('0')
        self.exit_price = Decimal('0')
        self.fee = Decimal(fee)
        self.ema = EMAHolder(5 * 60)
        self.zero_position_time = time.time()

    def execution(self, tx: Exec):
        exec_pos = Position(pos=tx.delta, price=tx.price, side=tx.side)
        if tx.delta > 0:
            self.pos += exec_pos + exec_pos.fee_pos(tx.fee)

        if self.pos.position() == 0:
            self.closed_pnl += self.pos.balance
            self.pos = Position(0, 0)
            self.zero_position_time = time.time()
            # self.clean_closed_pnl += self.closed_pnl
            # self.closed_pnl = 0

    def position(self):
        return self.pos.position()

    def abs_position(self):
        return self.pos.abs_position()

    def quote_changed(self, quote):
        self.nbbo.set_side(quote.side, quote.price)
        if self.nbbo.bid() == 0 or self.nbbo.ask() == 0:
            return
        mid_price = (self.nbbo.bid() + self.nbbo.ask()) / 2
        self.ema.add(mid_price)

    def balance(self):
        return self.pos.balance

    def open_pnl(self):
        return self.balance() + self.position() * self.exit_price

    def update_open_pnl(self, exit_price):
        self.exit_price = exit_price

    def nbbo_pnl(self):
        exit_side = Side.opposite_side(self.position())
        nbbo_price = self.nbbo.side(exit_side)
        return (self.pos + Position(pos=self.pos.abs_position(),
                                    price=nbbo_price,
                                    side=exit_side)).balance

    def take_pnl(self):
        if self.pos.position() == 0:
            return Decimal('0')
        exit_side = Side.opposite_side(self.position())
        take_price = self.nbbo.side(Side.side(self.position()))
        take_order = Position(pos=self.pos.abs_position(),
                              price=take_price,
                              side=exit_side)
        take_pos = self.pos + take_order + take_order.fee_pos(self.fee)

        return take_pos.balance

    def position_zero_price(self):
        if self.abs_position() == 0:
            return Decimal('0')
        else:
            return abs(self.balance() / self.abs_position())

    def position_side(self):
        return Side.side(self.position())

    def set_order_method(self, side, method):
        self.method.set_side(side, method)

    def exit_method(self):
        return str(self.method)