Skip to content

Commit

Permalink
Fix close price after conditional order execution (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
evsamsonov authored Jan 21, 2023
1 parent 6df4b76 commit d1e312f
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 28 deletions.
36 changes: 9 additions & 27 deletions tinkoff.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,12 +385,8 @@ func (t *Tinkoff) processOrderTrades(ctx context.Context, orderTrades *investapi
t.currentPosition.AddOrderTrade(orderTrades.GetTrades()...)

var executedQuantity int64
var closePrice float64
for _, trade := range t.currentPosition.OrderTrades() {
quan := trade.GetQuantity() / int64(t.currentPosition.Instrument().Lot)
executedQuantity += quan
price := NewMoneyValue(trade.Price)
closePrice += price.ToFloat() * float64(quan)
executedQuantity += trade.GetQuantity() / int64(t.currentPosition.Instrument().Lot)
}
if executedQuantity < t.currentPosition.Position().Quantity {
t.logger.Info("Position partially closed", zap.Any("executedQuantity", executedQuantity))
Expand All @@ -401,11 +397,16 @@ func (t *Tinkoff) processOrderTrades(ctx context.Context, orderTrades *investapi
return err
}

commission := t.orderCommission(ctx, orderTrades.OrderId)
orderState, err := t.getExecutedOrderState(ctx, orderTrades.OrderId)
if err != nil {
return fmt.Errorf("get executed order state: %w", err)
}

closePrice := NewMoneyValue(orderState.AveragePositionPrice)
commission := NewMoneyValue(orderState.InitialCommission)
t.currentPosition.AddCommission(commission.ToFloat())

closePrice /= float64(executedQuantity)
position, err := t.currentPosition.Close(closePrice)
position, err = t.currentPosition.Close(closePrice.ToFloat())
if err != nil {
if errors.Is(err, trengin.ErrAlreadyClosed) {
t.logger.Info("Position already closed", zap.Any("position", t.currentPosition))
Expand Down Expand Up @@ -641,25 +642,6 @@ func (t *Tinkoff) cancelStopOrders(ctx context.Context) error {
return nil
}

func (t *Tinkoff) orderCommission(ctx context.Context, orderID string) *MoneyValue {
orderStateRequest := &investapi.GetOrderStateRequest{
AccountId: t.accountID,
OrderId: orderID,
}
orderState, err := t.orderClient.GetOrderState(ctx, orderStateRequest)
if err != nil {
t.logger.Error(
"Failed to get order commission",
zap.Error(err),
zap.Any("orderStateRequest", orderStateRequest),
)
return NewZeroMoneyValue()
}
t.logger.Info("Order state was received", zap.Any("orderState", orderState))

return NewMoneyValue(orderState.InitialCommission)
}

func (t *Tinkoff) getLastPrice(ctx context.Context, figi string) (*investapi.Quotation, error) {
prices, err := t.marketDataClient.GetLastPrices(ctx, &investapi.GetLastPricesRequest{
Figi: []string{figi},
Expand Down
4 changes: 3 additions & 1 deletion tinkoff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,9 @@ func TestTinkoff_processOrderTrades(t *testing.T) {
AccountId: "123",
OrderId: "1953465028754600565",
}).Return(&investapi.OrderState{
InitialCommission: &investapi.MoneyValue{Units: 125, Nano: 0.6 * 10e8},
InitialCommission: &investapi.MoneyValue{Units: 125, Nano: 0.6 * 10e8},
ExecutionReportStatus: investapi.OrderExecutionReportStatus_EXECUTION_REPORT_STATUS_FILL,
AveragePositionPrice: &investapi.MoneyValue{Units: 174, Nano: 0.7 * 10e8},
}, nil)

tinkoff := &Tinkoff{
Expand Down

0 comments on commit d1e312f

Please sign in to comment.