Skip to content

Instantly share code, notes, and snippets.

@wesee
Last active December 20, 2017 20:08
Show Gist options
  • Save wesee/6363509 to your computer and use it in GitHub Desktop.
Save wesee/6363509 to your computer and use it in GitHub Desktop.
Stock Quote & Chart Dashing Widget

Description

Stock Quote & Chart Dashing Dashboard consists of two widgets. While one displays a stock's current quote and other details; another displays its last 30-days closing stock prices.

Preview

Dependencies

json

Add the gem to your dashing gemfile:

gem 'json'

and run bundle install.

Usage

First, copy stock.coffee, stock.html, and stock.sass into the /widgets/stock directory and chart.coffee, chart.html, and chart.sass into the /widgets/chart directory. Put the yahoo_stock_quote.rb and yahoo_stock_quote.rb files in the /jobs folder.

To use the widget, put the following codes into one of the /dashboards directory's .erb file:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="yahoo_stock_quote" data-view="Stock" data-prefix="$"></div>
</li>  

<li data-row="1" data-col="1" data-sizex="3" data-sizey="1">
  <div data-id="yahoo_stock_chart" data-view="Chart" data-prefix="$"></div>
</li>	

Settings

There are two jobs running for this dashboard, which are yahoo_stock_quote.rb and yahoo_stock_chart.rb. yahoo_stock_quote.rb selects data from yahoo.finance.quotes table, and yahoo_stock_chart.rb retrieves data from yahoo.finance.historicaldata table. You can change to another stock with the following line within the jobs.

symbol = "YHOO"
class Dashing.Chart extends Dashing.Widget
@accessor 'current', ->
return @get('displayedValue') if @get('displayedValue')
points = @get('points')
if points
points[points.length - 1].y
@accessor 'moreinfo', ->
return @get('symbol') + ' (Closing stock prices from ' + @get('startdate') + ' to ' + @get('enddate') + ')' if @get('symbol')
ready: ->
container = $(@node).parent()
# Gross hacks. Let's fix this.
width = (Dashing.widget_base_dimensions[0] * container.data("sizex")) + Dashing.widget_margins[0] * 2 * (container.data("sizex") - 1)
height = (Dashing.widget_base_dimensions[1] * container.data("sizey"))
@graph = new Rickshaw.Graph(
element: @node
width: width
height: height
series: [
{
color: "#fff",
data: [{x:0, y:0}]
}
]
)
@graph.series[0].data = @get('points') if @get('points')
x_axis = new Rickshaw.Graph.Axis.Time(graph: @graph)
y_axis = new Rickshaw.Graph.Axis.Y(graph: @graph, tickFormat: Rickshaw.Fixtures.Number.formatKMBT)
@graph.render()
onData: (data) ->
if @graph
@graph.series[0].data = data.points
@graph.render()
<h1 class="title" data-bind="title"></h1>
<h2 class="value" data-bind="current | prettyNumber | prepend prefix"></h2>
<p class="more-info" data-bind="moreinfo"></p>
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #dc5945; //#47bbb3;
$title-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.3);
$tick-color: rgba(0, 0, 0, 0.4);
// ----------------------------------------------------------------------------
// Widget-chart styles
// ----------------------------------------------------------------------------
.widget-chart {
background-color: $background-color;
position: relative;
svg {
position: absolute;
opacity: 0.5;
fill-opacity: 0.8;
left: 0px;
top: 0px;
}
.title, .value {
position: relative;
z-index: 99;
}
.title {
color: $title-color;
}
.more-info {
color: $moreinfo-color;
font-weight: 600;
font-size: 20px;
margin-top: 0;
}
.x_tick {
position: absolute;
bottom: 0;
.title {
font-size: 20px;
color: $tick-color;
opacity: 0.5;
padding-bottom: 3px;
}
}
.y_ticks {
font-size: 20px;
fill: $tick-color;
fill-opacity: 1;
}
.domain {
display: none;
}
}
class Dashing.Stock extends Dashing.Widget
@accessor 'price', Dashing.AnimatedValue
@accessor 'changepercent', ->
@get('change')[1..-1] + ' (' + @get('percentchange')[1..-1] + ')'
@accessor 'title', ->
@get('name') + ' (' +@get('symbol') + ')'
@accessor 'lasttrade', ->
'Last traded at ' + @get('lasttradetime')
@accessor 'arrow', ->
if parseFloat(@get('change')) > 0 then 'icon-arrow-up' else 'icon-arrow-down'
<h1 class="title" data-bind="title"></h1>
<h2 class="value" data-bind="price | shortenedNumber | prepend prefix"></h2>
<p class="change-percent">
<i data-bind-class="arrow"></i><span data-bind="changepercent"></span>
</p>
<p class="more-info" data-bind="moreinfo | raw"></p>
<p class="last-trade-time" data-bind="lasttrade"></p>
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #47bbb3;
$value-color: #fff;
$title-color: rgba(255, 255, 255, 0.7);;
$moreinfo-color: rgba(255, 255, 255, 0.7);;
$last-trade-color: rgba(255, 255, 255, 0.7);;
// ----------------------------------------------------------------------------
// Widget-stock styles
// ----------------------------------------------------------------------------
.widget-stock {
background-color: $background-color;
.title {
color: $title-color;
}
.value {
color: $value-color;
font-size: 60px;
}
.change-percent {
font-weight: 500;
font-size: 50px;
color: $value-color;
}
.more-info {
color: $moreinfo-color;
}
.updated-at {
color: rgba(0, 0, 0, 0.3);
}
.last-trade-time {
color: $last-trade-color;
}
}
require 'net/http'
require 'json'
require 'date'
enddate = Date.today
startdate = Date.today - 30
symbol = "YHOO"
# query = URI::encode "select * from yahoo.finance.quotes where symbol='#{symbol}'&format=json&env=http://datatables.org/alltables.env&callback="
# query = URI::encode "select * from yahoo.finance.historicaldata where symbol='#{symbol}' and startDate='2009-09-11' and endDate='2010-03-10'&format=json&env=http://datatables.org/alltables.env&callback="
query = URI::encode "select * from yahoo.finance.historicaldata where symbol='#{symbol}' and startDate='#{startdate}' and endDate='#{enddate}'&format=json&env=http://datatables.org/alltables.env&callback="
SCHEDULER.every "12h", :first_in => 0 do |job|
http = Net::HTTP.new "query.yahooapis.com"
request = http.request Net::HTTP::Get.new("/v1/public/yql?q=#{query}")
response = JSON.parse request.body
results = response["query"]["results"]["quote"]
if results
points = []
i = 0
results.each do |q|
i += 1
points << { x: i, y: q["Close"].to_f}
end
send_event("yahoo_stock_chart", { points: points.reverse, symbol: symbol, startdate: startdate, enddate: enddate })
end
end
require "net/http"
require "json"
symbol = "YHOO"
query = URI::encode "select * from yahoo.finance.quotes where symbol='#{symbol}'&format=json&env=http://datatables.org/alltables.env&callback="
SCHEDULER.every "15s", :first_in => 0 do |job|
http = Net::HTTP.new "query.yahooapis.com"
request = http.request Net::HTTP::Get.new("/v1/public/yql?q=#{query}")
response = JSON.parse request.body
results = response["query"]["results"]["quote"]
if results
quote = {
name: results['Name'],
symbol: results['Symbol'],
price: results['LastTradePriceOnly'],
change: results['Change'],
percentchange: results['PercentChange'],
lasttradetime: results['LastTradeTime']
}
send_event "yahoo_stock_quote", quote
end
end
@markmnich
Copy link

Another thing I noticed is that the points array in line 29 of yahoo_stock_chart.rb doesn't work correctly with the .reverse method. What that is trying to achieve is take the objects (or points) that are pushed to form that array and reverse the order so the graph/widget shows the current share price instead of the one that is 30 days old. Since the .reverse method doesn't work as intended, the workaround that I think actually ends up being a little cleaner is modifying the YQL query in line 12 of yahoo_stock_chart.rb to:

"select * from yahoo.finance.historicaldata where symbol='#{symbol}' and startDate='#{startdate}' and endDate='#{enddate}' | reverse()&format=json&env=http://datatables.org/alltables.env&callback="

Note the | reverse() function. This returns the dates in reverse order (day 30 is first rather than the current day) and pipes as we need it to into the points array, displaying the graph is we need it to. If you do add this, you'll want to remove the .reverse method from line 29 in yahoo_stock_chart.rb.

Copy link

ghost commented Mar 21, 2016

@markmnich Thank you for your help. I had to make a slight adjust for it to work for me. :)

points << { x: i, y: q["Close"].to_f.round(2)}

@adabow
Copy link

adabow commented May 10, 2017

Does anyone have this working currently, it seems like the API may have changed? I would like to use this but cannot get data to display and just get an Undefined message. Any help would be appreciated. Thanks

Copy link

ghost commented Dec 20, 2017

it's worse than that...it's dead Jim. Yahoo killed the API that this widget used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment