app/models/iro/stock.rb in iron_warbler-2.0.7.23 vs app/models/iro/stock.rb in iron_warbler-2.0.7.24
- old
+ new
@@ -1,5 +1,7 @@
+include Math
+require 'business_time'
class Iro::Stock
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Paranoia
@@ -18,19 +20,98 @@
index({ ticker: -1 }, { unique: true })
field :last, type: :float
field :options_price_increment, type: :float
+ field :stdev, type: :float
+
has_many :positions, class_name: 'Iro::Position', inverse_of: :stock
has_many :strategies, class_name: 'Iro::Strategy', inverse_of: :stock
has_many :purses, class_name: 'Iro::Purse', inverse_of: :stock
+ has_many :options, class_name: 'Iro::Option', inverse_of: :stock
+ def self.f ticker
+ self.find_by ticker: ticker
+ end
+
def to_s
ticker
end
def self.list
[[nil,nil]] + all.map { |sss| [ sss.ticker, sss.id ] }
end
def self.tickers_list
[[nil,nil]] + all.map { |sss| [ sss.ticker, sss.ticker ] }
end
+
+=begin
+ stock = Iro::Stock.find_by( ticker: 'NVDA' )
+
+ duration = 1.month
+ stock.volatility_from_mo
+
+ duration = 1.year
+ stock.volatility_from_yr
+
+=end
+ def volatility duration:
+ stock = self
+ begin_on = Time.now - duration - 1.day
+ points = Iro::Datapoint.where( kind: 'STOCK', symbol: stock.ticker,
+ :date.gte => begin_on,
+ ).order_by( date: :asc )
+
+ puts! [points.first.date, points.last.date], "from,to"
+
+ points_p = []
+ points.each_with_index do |p, idx|
+ next if idx == 0
+ prev = points[idx-1]
+
+ out = p.value / prev.value - 1
+ points_p.push out
+ end
+ n = points_p.length
+
+ avg = points_p.reduce(&:+) / n
+ _sum_of_sq = []
+ points_p.map do |p|
+ _sum_of_sq.push( ( p - avg )*( p - avg ) )
+ end
+ sum_of_sq = _sum_of_sq.reduce( &:+ ) / n
+
+ # n_periods = begin_on.to_date.business_days_until( Date.today )
+ out = Math.sqrt( sum_of_sq )*sqrt( n )
+ adjustment = 2.0
+ out = out * adjustment
+ puts! out, 'volatility (adjusted)'
+ return out
+ end
+
+ def volatility_from_mo
+ volatility( duration: 1.month )
+ end
+ def volatility_from_yr
+ volatility( duration: 1.year )
+ end
+ def stdev recompute: nil
+ if !self[:stdev] || recompute
+ out = volatility_from_yr
+ self[:stdev] = out
+ save( validate: false )
+ return out
+ else
+ self[:stdev]
+ end
+ end
+
+ ## stdev
+ ## From: https://stackoverflow.com/questions/19484891/how-do-i-find-the-standard-deviation-in-ruby
+ # contents = [1,2,3,4,5,6,7,8,9]
+ # n = contents.size # => 9
+ # contents.map!(&:to_f) # => [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
+ # mean = contents.reduce(&:+)/n # => 5.0
+ # sum_sqr = contents.map {|x| x * x}.reduce(&:+) # => 285.0
+ # std_dev = Math.sqrt((sum_sqr - n * mean * mean)/(n-1)) # => 2.7386127875258306
+
+
end