diff --git a/app/views/shared/_money_field.html.erb b/app/views/shared/_money_field.html.erb
index 059294013..787798c44 100644
--- a/app/views/shared/_money_field.html.erb
+++ b/app/views/shared/_money_field.html.erb
@@ -48,14 +48,14 @@
inline: true,
placeholder: "100",
value: if options[:value]
- sprintf("%.#{currency.default_precision}f", options[:value])
+ sprintf("%.#{options[:precision].presence || currency.default_precision}f", options[:value])
elsif form.object && form.object.respond_to?(amount_method)
val = form.object.public_send(amount_method)
- sprintf("%.#{currency.default_precision}f", val) if val.present?
+ sprintf("%.#{options[:precision].presence || currency.default_precision}f", val) if val.present?
end,
min: options[:min] || -99999999999999,
max: options[:max] || 99999999999999,
- step: currency.step,
+ step: options[:step] || currency.step,
disabled: options[:disabled],
data: {
"money-field-target": "amount",
diff --git a/app/views/trades/_form.html.erb b/app/views/trades/_form.html.erb
index 57e22907a..cb248ece9 100644
--- a/app/views/trades/_form.html.erb
+++ b/app/views/trades/_form.html.erb
@@ -50,7 +50,7 @@
<% if %w[buy sell].include?(type) %>
<%= form.number_field :qty, label: t(".qty"), placeholder: "10", min: 0.000000000000000001, step: "any", required: true %>
- <%= form.money_field :price, label: t(".price"), required: true %>
+ <%= form.money_field :price, label: t(".price"), step: 'any', precision: 10, required: true %>
<% end %>
diff --git a/app/views/trades/show.html.erb b/app/views/trades/show.html.erb
index c80b379d3..227470fba 100644
--- a/app/views/trades/show.html.erb
+++ b/app/views/trades/show.html.erb
@@ -40,6 +40,8 @@
disable_currency: true,
auto_submit: true,
min: 0,
+ step: "any",
+ precision: 10,
disabled: @entry.linked? %>
<% end %>
<% end %>
diff --git a/db/migrate/20250806155348_increase_trade_price_precision.rb b/db/migrate/20250806155348_increase_trade_price_precision.rb
new file mode 100644
index 000000000..0f9cb4020
--- /dev/null
+++ b/db/migrate/20250806155348_increase_trade_price_precision.rb
@@ -0,0 +1,9 @@
+class IncreaseTradePricePrecision < ActiveRecord::Migration[7.2]
+ def up
+ change_column :trades, :price, :decimal, precision: 19, scale: 10
+ end
+
+ def down
+ change_column :trades, :price, :decimal, precision: 19, scale: 4
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index dac00a6e5..90d190dcf 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -789,7 +789,7 @@ ActiveRecord::Schema[7.2].define(version: 2025_08_08_143007) do
create_table "trades", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.uuid "security_id", null: false
t.decimal "qty", precision: 19, scale: 4
- t.decimal "price", precision: 19, scale: 4
+ t.decimal "price", precision: 19, scale: 10
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "currency"
diff --git a/test/models/trade_test.rb b/test/models/trade_test.rb
index c358a5ba1..c86f44210 100644
--- a/test/models/trade_test.rb
+++ b/test/models/trade_test.rb
@@ -20,4 +20,38 @@ class TradeTest < ActiveSupport::TestCase
name = Trade.build_name("buy", 0.25, "BTC")
assert_equal "Buy 0.25 shares of BTC", name
end
+
+ test "price scale is preserved at 10 decimal places" do
+ security = Security.create!(ticker: "TEST", exchange_operating_mic: "XNAS")
+
+ # up to 10 decimal places — should persist exactly
+ precise_price = BigDecimal("12.3456789012")
+ trade = Trade.create!(
+ security: security,
+ price: precise_price,
+ qty: 10000,
+ currency: "USD"
+ )
+
+ trade.reload
+
+ assert_equal precise_price, trade.price
+ end
+
+ test "price is rounded to 10 decimal places" do
+ security = Security.create!(ticker: "TEST", exchange_operating_mic: "XNAS")
+
+ # over 10 decimal places — will be rounded
+ price_with_too_many_decimals = BigDecimal("1.123456789012345")
+ trade = Trade.create!(
+ security: security,
+ price: price_with_too_many_decimals,
+ qty: 1,
+ currency: "USD"
+ )
+
+ trade.reload
+
+ assert_equal BigDecimal("1.1234567890"), trade.price
+ end
end