Есть ли простой способ подсчета sumproduct в Rails? - PullRequest
0 голосов
/ 22 марта 2020

У меня есть PositionGroup, что has_many :positions.

При каждом прикосновении к объекту position_group я бы хотел обновить pg.average_price следующим образом:

# Average Price = ((position1.transaction_price * (position1.volume/total_volume) + 
# position2.transaction_price * (position2.volume/total_volme)) 

In мой метод обратного вызова, я попробовал это:

  def update_average_price
    total_volume = positions.sum(:volume)
    avg_price = positions.sum("transaction_price * (volume/#{total_volume})")
    update_column(:average_price, avg_price)
  end

Но когда я проверяю значение avg_price после нескольких positions существует, я получаю 0.0.

Это мой spe c для этой специфической c функциональности:

it "should calculate the Weighted Average Purchase Price of all positions" do
  # Position 3: Price = 20, volume = 200
  # (Position 1 Price * (Position 1 Units/Total # of Units)) +
  # (Position 2 Price * (Position 2 Units/Total # of Units)) +
  # (Position 3 Price * (Position 3 Units/Total # of Units))
  # ($10 * (100/400)) + ($15 * (100/400) + $20 * (100/400)) =
  # ($2.50 + $3.75 + $5) = $11.25
  price3 = 20
  pos3 = create(:position, stock: stock, portfolio: portfolio, transaction_price: 20, current_price: price3, action: :buy, volume: 200, position_group: pg)
  expect(pg.average_price).to eql 11.25
end

Это результат, когда я запускаю его:

1) PositionGroup methods should calculate the Weighted Average Purchase Price of all positions
     Failure/Error: expect(pg.average_price).to eql 11.25

       expected: 11.25
            got: 0.0

       (compared using eql?)

Я почти уверен, что проблема заключается в этой строке, из мой метод обратного вызова update_average_price на PositionGroup:

avg_price = positions.sum("transaction_price * (volume/#{total_volume})")

Есть ли лучший способ приблизиться к этому или есть что-то еще, дающее мне это 0.0, когда меня не должно быть?

1 Ответ

2 голосов
/ 22 марта 2020
avg_price = positions.sum("transaction_price * (volume/#{total_volume.to_f})")

to_f отсутствует, преобразование в число с плавающей точкой для получения десятичной дроби для работы.

Пример

irb(main):022:0> Position.all
  Position Load (0.3ms)  SELECT "positions".* FROM "positions" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Position id: 1, transaction_price: 0.5e2, volume: 150, position_group_id: 1>, #<Position id: 2, transaction_price: 0.1e1, volume: 50, position_group_id: 1>]>
irb(main):023:0> Position.all.sum("transaction_price * (volume/#{total_volume.to_f})")
   (0.2ms)  SELECT SUM(transaction_price * (volume/200.0)) FROM "positions"
=> 37.75
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...