I am trying to calculate moving averages (simple and exponential) and I have come across the simple_statistics gem, which is perfect for my needs. I am trying to modify the code from this link: How to calculate simple moving average) for my purposes.
GOAL: I have a JSON like this which lists historical prices for a single stock over a long time period:
[
{
"Low": 8.63,
"Volume": 14211900,
"Date": "2012-10-26",
"High": 8.79,
"Close": 8.65,
"Adj Close": 8.65,
"Open": 8.7
},
To this, I would like to add moving averages for each day (simple and exponential - which the simple_statistics gem seems to do easily) for 20, and 50 day averages (and others as required) so it would appear something like this for each day:
[
{
"Low": 8.63,
"Volume": 14211900,
"Date": "2012-10-26",
"High": 8.79,
"Close": 8.65,
"Adj Close": 8.65,
"Open": 8.7,
"SMA20":
"SMA50":
},
I would prefer to use the yahoo_finance, and simple_statistics gems and then append the output to the original JSON as I have a feeling that once I gain a better understanding, it will be easier for me to modify.
Right now, I'm still reading up on how I will do this (any help is appreciated) Below is my attempt to calculate a 20 day simple moving average for Microsoft (doesn't work). This way (using HistoricalQuotes_days) seems to assume that the start date is today, which wont work for my overall goal.
require 'rubygems'
require 'yahoofinance'
require 'simple_statistics'
averages = {}
dates.each do |dates|
quotes = YahooFinance::get_HistoricalQuotes_days ( 'MSFT' , 20 ) start, finish
closes = quotes.collect { |quote| quote.close }
averages = closes.mean
end
Thank you
UPDATE: I don't actually need to use YahooFinance gem as I already have the data in a JSON. What I dont know how to do is pull from the JSON array, make the calculations using the simple_statistics gem, and then add the new data into the original JSON.
Using the gem, I see two ways to get your data. Here they are (note they both can take a block):
YahooFinance::get_HistoricalQuotes_days('MSFT', 20)
Which returns an array of YahooFinance::HistoricalQuote objects with the following methods:
[ :recno, :recno=, :symbol, :symbol=, :date, :date=,
:open, :open=, :high, :high=, :low, :low=, :close,
:close=, :adjClose, :adjClose=, :volume, :volume=,
:to_a, :date_to_Date ]
Or:
YahooFinance::get_historical_quotes_days('MSFT', 20)
which returns an array of values from the documentation :
Getting the historical quote data as a raw array.
The elements of the array are:
[0] - Date
[1] - Open
[2] - High
[3] - Low
[4] - Close
[5] - Volume
[6] - Adjusted Close
And to take an average (simple moving average), you can easily do:
ary.reduce(:+) / ary.length
Where ary
would hold the values to average (need to be floats or it will integer divide). To do the exponential moving average, just use the following formula:
(close - previous_ema) * (2 / (amount_of_days_ago + 1) ) + previous_ema
Where close is the stock's close, previous_ema is yesterday's ema, and amount_of_days_ago is the range of the average into the past, for instance 20 (days).
oh. Yeah parsing json is easy: https://github.com/flori/json
I can't write a whole beginning ruby guide, but the basics for what you need are Hash
and Array
. Look up how to use ruby hashes and arrays, and thats probably a good 30% of ruby programming right there.
For example to get the json objects in an array and then get just the closes, you could use Array#map like so:
stocks = JSON.parse( your_json_here )
array = stocks.map{ |hash| hash["Close"] }
# => [8.65, 9.32, etc... ]
hope that gets you started n good luck