mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-18 20:59:39 +02:00
Handle bad API data for trade quantity signage (#2416)
This commit is contained in:
parent
f3ab4a27ee
commit
e60b5df442
2 changed files with 59 additions and 3 deletions
|
@ -43,14 +43,14 @@ class PlaidAccount::Investments::TransactionsProcessor
|
|||
end
|
||||
|
||||
entry.assign_attributes(
|
||||
amount: transaction["quantity"] * transaction["price"],
|
||||
amount: derived_qty(transaction) * transaction["price"],
|
||||
currency: transaction["iso_currency_code"],
|
||||
date: transaction["date"]
|
||||
)
|
||||
|
||||
entry.trade.assign_attributes(
|
||||
security: resolved_security_result.security,
|
||||
qty: transaction["quantity"],
|
||||
qty: derived_qty(transaction),
|
||||
price: transaction["price"],
|
||||
currency: transaction["iso_currency_code"]
|
||||
)
|
||||
|
@ -87,4 +87,21 @@ class PlaidAccount::Investments::TransactionsProcessor
|
|||
def transactions
|
||||
plaid_account.raw_investments_payload["transactions"] || []
|
||||
end
|
||||
|
||||
# Plaid unfortunately returns incorrect signage on some `quantity` values. They claim all "sell" transactions
|
||||
# are negative signage, but we have found multiple instances of production data where this is not the case.
|
||||
#
|
||||
# This method attempts to use several Plaid data points to derive the true quantity with the correct signage.
|
||||
def derived_qty(transaction)
|
||||
reported_qty = transaction["quantity"]
|
||||
abs_qty = reported_qty.abs
|
||||
|
||||
if transaction["type"] == "sell" || transaction["amount"] < 0
|
||||
-abs_qty
|
||||
elsif transaction["type"] == "buy" || transaction["amount"] > 0
|
||||
abs_qty
|
||||
else
|
||||
reported_qty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,7 +6,6 @@ class PlaidAccount::Investments::TransactionsProcessorTest < ActiveSupport::Test
|
|||
@security_resolver = PlaidAccount::Investments::SecurityResolver.new(@plaid_account)
|
||||
end
|
||||
|
||||
|
||||
test "creates regular trade entries" do
|
||||
test_investments_payload = {
|
||||
transactions: [
|
||||
|
@ -16,6 +15,7 @@ class PlaidAccount::Investments::TransactionsProcessorTest < ActiveSupport::Test
|
|||
"type" => "buy",
|
||||
"quantity" => 1, # Positive, so "buy 1 share"
|
||||
"price" => 100,
|
||||
"amount" => 100,
|
||||
"iso_currency_code" => "USD",
|
||||
"date" => Date.current,
|
||||
"name" => "Buy 1 share of AAPL"
|
||||
|
@ -108,4 +108,43 @@ class PlaidAccount::Investments::TransactionsProcessorTest < ActiveSupport::Test
|
|||
assert_equal Date.current, entry.date
|
||||
assert_equal "Miscellaneous fee", entry.name
|
||||
end
|
||||
|
||||
test "handles bad plaid quantity signage data" do
|
||||
test_investments_payload = {
|
||||
transactions: [
|
||||
{
|
||||
"transaction_id" => "123",
|
||||
"type" => "sell", # Correct type
|
||||
"subtype" => "sell", # Correct subtype
|
||||
"quantity" => 1, # ***Incorrect signage***, this should be negative
|
||||
"price" => 100, # Correct price
|
||||
"amount" => -100, # Correct amount
|
||||
"iso_currency_code" => "USD",
|
||||
"date" => Date.current,
|
||||
"name" => "Sell 1 share of AAPL"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@plaid_account.update!(raw_investments_payload: test_investments_payload)
|
||||
|
||||
@security_resolver.expects(:resolve).returns(OpenStruct.new(
|
||||
security: securities(:aapl)
|
||||
))
|
||||
|
||||
processor = PlaidAccount::Investments::TransactionsProcessor.new(@plaid_account, security_resolver: @security_resolver)
|
||||
|
||||
assert_difference [ "Entry.count", "Trade.count" ], 1 do
|
||||
processor.process
|
||||
end
|
||||
|
||||
entry = Entry.order(created_at: :desc).first
|
||||
|
||||
assert_equal -100, entry.amount
|
||||
assert_equal "USD", entry.currency
|
||||
assert_equal Date.current, entry.date
|
||||
assert_equal "Sell 1 share of AAPL", entry.name
|
||||
|
||||
assert_equal -1, entry.trade.qty
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue