From afca59c35da0a759cbb44a20f9ed8c09eff28e19 Mon Sep 17 00:00:00 2001 From: "Alfred J. Fazio" Date: Tue, 25 Aug 2015 09:41:10 -0400 Subject: [PATCH] Fix bugs and warnings: * Old way of finding a commodity's active month was updated with better criteria matching * Ability to manually enter a commodity's forward month was added * Fixed a number of deprecation and other warnings * Fixed bugs preventing commodities and ^VIX from being displayed * Fixed bug preventing option position values from being displayed --- bin/rticker | 0 lib/rticker/equity.rb | 3 +-- lib/rticker/future.rb | 21 ++++++++++++++++----- lib/rticker/net.rb | 4 ++-- lib/rticker/option.rb | 2 +- lib/rticker/parser.rb | 13 ++++++++++++- lib/rticker/printer.rb | 2 +- 7 files changed, 33 insertions(+), 12 deletions(-) mode change 100644 => 100755 bin/rticker diff --git a/bin/rticker b/bin/rticker old mode 100644 new mode 100755 diff --git a/lib/rticker/equity.rb b/lib/rticker/equity.rb index e15bc49..73aea12 100644 --- a/lib/rticker/equity.rb +++ b/lib/rticker/equity.rb @@ -1,7 +1,6 @@ require 'rticker/entry' require 'rticker/net' require 'cgi' -require 'rational' require 'date' module RTicker @@ -66,7 +65,7 @@ def Equity.update_yahoo (entries) price = fields[0] change = fields[1] last_date = fields[2] - return if last_date.nil? or Date.strptime(last_date, '"%m/%d/%Y"') != Date.today + return if last_date.nil? or Date.strptime(last_date, '"%m/%d/%Y"') <= Date.today - 3 if price.to_f != entry.curr_value and not entry.curr_value.nil? # The price has changed entry.last_changed = Time.now() diff --git a/lib/rticker/future.rb b/lib/rticker/future.rb index 91fbbca..ad50e68 100644 --- a/lib/rticker/future.rb +++ b/lib/rticker/future.rb @@ -14,9 +14,10 @@ class Future < Entry # ahead of time what the nearest expiration for a contract will be, we'll # have to figure this out for each contract with web calls. Once we know # the expiration, we'll calculate the real symbol for the contract and - # store it in @real_symbol. + # store it in @real_symbol. A future may also have an explicit amount of + # months forward to look. attr_accessor :start_value, :exp_month, :exp_year, :market - attr_accessor :real_symbol + attr_accessor :real_symbol, :forward_months # Commodities have strange codes for months COMMODITY_MONTHS = %w[F G H J K M N Q U V X Z] @@ -46,6 +47,15 @@ def Future.update (entries) Thread.new { entry.determine_spot_contract } end + entries.each do |e| + unless e.forward_months.nil? + symbol, exchange = e.symbol.split(".") + month_symbol = Future::COMMODITY_MONTHS[(Time.now().month + e.forward_months - 1) % 12] + year_symbol = (Time.now().year + ((Time.now().month + e.forward_months - 1) / 12.0).floor) % 100 + e.real_symbol = "#{symbol}#{month_symbol}#{year_symbol}.#{exchange}" + end + end + if entries.any? {|e| e.real_symbol.nil?} #puts "Please wait... determining spot contracts" threads = [] @@ -71,7 +81,7 @@ def Future.update (entries) price = fields[0] change = fields[1] last_date = fields[2] - return if last_date.nil? or Date.strptime(last_date, '"%m/%d/%Y"') != Date.today + return if last_date.nil? #or Date.strptime(last_date, '"%m/%d/%Y"') != Date.today if price.to_f != _entry.curr_value and not _entry.curr_value.nil? # The price has changed _entry.last_changed = Time.now() @@ -103,12 +113,13 @@ def determine_spot_contract month_symbol = Future::COMMODITY_MONTHS[curr_month] year_symbol = curr_year % 100 # Only want last two digits of year. real_symbol_attempt = "#{symbol}#{month_symbol}#{year_symbol}.#{exchange}" - uri = "http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=l1c1va2xj1b4j4dyekjm3m4rr5p5p6s7" % CGI::escape(real_symbol_attempt) + uri = "http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=l1c1d1va2xj1b4j4dyekjm3m4rr5p5p6s7" % CGI::escape(real_symbol_attempt) response = RTicker::Net.get_response(uri) rescue return # This contract is only valid if the response doesn't start with # 0.00. A commodity is never worth nothing! - unless response =~ /^0.00/ + last_date = response.split("\n")[0].split(",")[2] + if not response =~ /^0.00/ and last_date and last_date != 'N/A' and Date.strptime(last_date, '"%m/%d/%Y"') >= Date.today - 3 @real_symbol = real_symbol_attempt @exp_month = curr_month+1 # Convert from 0-based back to 1-based @exp_year = curr_year diff --git a/lib/rticker/net.rb b/lib/rticker/net.rb index 9addf41..5c22adb 100644 --- a/lib/rticker/net.rb +++ b/lib/rticker/net.rb @@ -22,14 +22,14 @@ def self.proxy= (proxy) def self.get_response (url) begin return ::Net::HTTP::Proxy(@@proxy_host, @@proxy_port).get(URI.parse url) - rescue Timeout::Error => e + rescue Timeout::Error return "" end end def self.detect_system_proxy () require 'rbconfig' - os = Config::CONFIG['host_os'] + os = RbConfig::CONFIG['host_os'] # Only support mac os x right now return detect_system_proxy_macosx() if os.start_with? "darwin" return nil diff --git a/lib/rticker/option.rb b/lib/rticker/option.rb index 2ef1e7d..c0e83ae 100644 --- a/lib/rticker/option.rb +++ b/lib/rticker/option.rb @@ -47,7 +47,7 @@ def Option.run_update (entry) begin bid = /id="yfs_b00_[^"]*">([^<]*)([^<]*) e + rescue Exception # These results aren't available from about 9am to 9:30am. # Yahoo's results are often 20-30 minutes behind. Thread.current.exit diff --git a/lib/rticker/parser.rb b/lib/rticker/parser.rb index c678198..0fb93ab 100644 --- a/lib/rticker/parser.rb +++ b/lib/rticker/parser.rb @@ -71,6 +71,15 @@ def RTicker.parse_entry (entry) sign = match[1] symbol = match[2] + + if sign == '#' # This is a future + submatch = /(.*)\+([0-9]+)$/.match symbol + if submatch + symbol = submatch[1] + forward_months = submatch[2].to_i + end + end + # Because description is optional, let's make it clear with a nil that no # description was provided. description = match[3] == "" ? nil : match[3] @@ -82,7 +91,9 @@ def RTicker.parse_entry (entry) when "#" # An entry starting with a hash is a Future. A useful mnemonic is to # think of the "pound" sign and think of lbs of a commodity. - return Future.new(*args) + f = Future.new(*args) + f.forward_months = forward_months + return f when "!" # An entry starting with an exclamation mark is an option contract. return Option.new(*args) diff --git a/lib/rticker/printer.rb b/lib/rticker/printer.rb index 33a3697..9dad1e0 100644 --- a/lib/rticker/printer.rb +++ b/lib/rticker/printer.rb @@ -11,7 +11,7 @@ def RTicker.update_screen (entries, no_color=false, once=false) # So setting no_color effectively turns all of the following variables # into empty strings, turning off terminal manipulation. hide_cursor = tput "civis" unless no_color - show_cursor = tput "cnorm" unless no_color + #show_cursor = tput "cnorm" unless no_color bold = tput "bold" unless no_color unbold = tput "sgr0" unless no_color default = tput "sgr0" unless no_color