options-lib 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +56 -1
- data/Rakefile +56 -0
- data/bin/show_quotes +1 -1
- data/lib/options-lib/option_quote.rb +3 -6
- data/lib/options-lib/yahoo_crawler.rb +26 -10
- data/options-lib.gemspec +1 -1
- data/spec/option_quote_spec.rb +11 -4
- data/spec/yahoo_crawler_spec.rb +11 -2
- metadata +2 -1
data/README.markdown
CHANGED
@@ -3,7 +3,62 @@
|
|
3
3
|
A set of classes for dealing with options. It includes a crawler for Yahoo!Finance. The crawler has an internal
|
4
4
|
thread that can be started to periodically update the option quotes.
|
5
5
|
|
6
|
+
## Install
|
7
|
+
|
8
|
+
gem install options-lib
|
9
|
+
|
6
10
|
## Usage
|
7
11
|
|
8
|
-
|
12
|
+
require 'options-lib'
|
13
|
+
|
14
|
+
# Create a crawler for all the options for ('AAPL') expiring on '2013-01-18'
|
15
|
+
y = YahooCrawler.new('AAPL', '2013-01-18')
|
16
|
+
|
17
|
+
# Fetch the entire options chain for this stock and expiration
|
18
|
+
y.fetch
|
19
|
+
|
20
|
+
# Show an option quote for a given strike price
|
21
|
+
y.call_options[300] # => AAPL_C300_18JAN2013: bid => 88.5, ask => 90.5
|
22
|
+
y.put_options[300] # => AAPL_P300_18JAN2013: bid => 40.7, ask => 41.95
|
23
|
+
|
24
|
+
# Options quote has stock price, bid and ask for option
|
25
|
+
q = y.call_options[300]
|
26
|
+
q.stock_price # => 342.88
|
27
|
+
q.bid # => 88.5
|
28
|
+
q.ask # => 90.5
|
29
|
+
|
30
|
+
# Crawler also has current stock price, as each option quote
|
31
|
+
y.stock_price # => 342.88
|
32
|
+
|
33
|
+
# You can get a list of all stock prices from the crawler
|
34
|
+
y.call_strikes # => [135.0, 140.0, ..., 530.0, 540.0]
|
35
|
+
y.put_strikes # => [135.0, 140.0, ..., 530.0, 540.0]
|
36
|
+
|
37
|
+
# So to print the entire options chain, you can do something like that
|
38
|
+
y.call_strikes.each { |strike| puts y.call_options[strike] }
|
39
|
+
y.put_strikes.each { |strike| puts y.put_options[strike] }
|
40
|
+
|
41
|
+
# you can place the crawler in auto_reload mode, passing a period to refresh itself
|
42
|
+
y.auto_reload 5
|
43
|
+
y.call_options[300].bid # => 88.5
|
44
|
+
sleep 6
|
45
|
+
y.call_options[300].bid # => 90.3
|
46
|
+
|
47
|
+
# you can also receive callbacks from the internal thread when the crawler gets updated
|
48
|
+
y.auto_reload(5) do
|
49
|
+
puts "Current bid: #{y.call_options[300].bid}"
|
50
|
+
end
|
51
|
+
|
52
|
+
# if you need to block ruby from exiting while your thread is executing in the background
|
53
|
+
# you can use the method below
|
54
|
+
y.join_reload_thread
|
55
|
+
|
56
|
+
# internal symbol versus real symbol
|
57
|
+
y.internal_symbol # => AAPL_C300_18JAN2013
|
58
|
+
y.symbol # => AAPL130119C00300000
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
|
9
64
|
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
def gemspec
|
4
|
+
@gemspec ||= begin
|
5
|
+
file = File.expand_path("../options-lib.gemspec", __FILE__)
|
6
|
+
eval(File.read(file), binding, file)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def alias_task(old_task, new_task)
|
11
|
+
task new_task do
|
12
|
+
Rake::Task[old_task].invoke
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
desc "Validate the gemspec"
|
18
|
+
task :gemspec do
|
19
|
+
gemspec.validate
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Build gem locally"
|
23
|
+
task :build => :gemspec do
|
24
|
+
system "gem build #{gemspec.name}.gemspec"
|
25
|
+
FileUtils.mkdir_p "pkg"
|
26
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "pkg"
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Install gem locally"
|
30
|
+
task :install => :build do
|
31
|
+
system "gem install pkg/#{gemspec.name}-#{gemspec.version}"
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Uninstall gem locally"
|
35
|
+
task :uninstall => :gemspec do
|
36
|
+
system "gem uninstall -x #{gemspec.name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Reinstall gem locally"
|
40
|
+
task :reinstall do
|
41
|
+
Rake::Task[:uninstall].invoke
|
42
|
+
Rake::Task[:install].invoke
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Push gem to RubyGems.org"
|
46
|
+
task :push do
|
47
|
+
system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_task(:reinstall, :r)
|
51
|
+
alias_task(:uninstall, :u)
|
52
|
+
alias_task(:install, :i)
|
53
|
+
alias_task(:build, :b)
|
54
|
+
alias_task(:push, :p)
|
55
|
+
|
56
|
+
|
data/bin/show_quotes
CHANGED
@@ -25,7 +25,7 @@ y.auto_reload(reload_period) do
|
|
25
25
|
|
26
26
|
options = is_call ? y.call_options : y.put_options
|
27
27
|
quote = options[strike]
|
28
|
-
stock_price = y.
|
28
|
+
stock_price = y.stock_price
|
29
29
|
|
30
30
|
puts "Stock @ #{stock_price} Options: #{quote.bid} | #{quote.ask} Spread: #{quote.spread}"
|
31
31
|
|
@@ -2,12 +2,13 @@ require_relative 'option'
|
|
2
2
|
|
3
3
|
class OptionQuote
|
4
4
|
|
5
|
-
attr_reader :option, :bid, :ask
|
5
|
+
attr_reader :option, :bid, :ask, :stock_price
|
6
6
|
|
7
7
|
def initialize(option, args)
|
8
8
|
@option = option
|
9
9
|
@bid = args[:bid] || nil
|
10
10
|
@ask = args[:ask] || nil
|
11
|
+
@stock_price = args[:stock_price] || nil
|
11
12
|
end
|
12
13
|
|
13
14
|
def spread
|
@@ -19,11 +20,7 @@ class OptionQuote
|
|
19
20
|
end
|
20
21
|
|
21
22
|
def to_s
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
def inspect
|
26
|
-
"#{option.inspect}: bid => #{bid.inspect}, ask => #{ask.inspect}"
|
23
|
+
"#{option}: bid => #{bid}, ask => #{ask}"
|
27
24
|
end
|
28
25
|
|
29
26
|
end
|
@@ -11,9 +11,9 @@ class YahooCrawler
|
|
11
11
|
|
12
12
|
def initialize(stock, exp)
|
13
13
|
@mech = Mechanize.new
|
14
|
-
@stock, @exp = stock, exp
|
14
|
+
@stock, @exp = stock.upcase, exp
|
15
15
|
@url = "http://finance.yahoo.com/q/op?s=#{stock}&m=#{exp[0,7]}"
|
16
|
-
@
|
16
|
+
@stock_price = nil
|
17
17
|
@call_options = Hash.new
|
18
18
|
@put_options = Hash.new
|
19
19
|
@call_strikes = Array.new
|
@@ -23,6 +23,10 @@ class YahooCrawler
|
|
23
23
|
@thread = nil
|
24
24
|
end
|
25
25
|
|
26
|
+
def to_s
|
27
|
+
"YahooCrawler('#{@stock}','#{@exp})"
|
28
|
+
end
|
29
|
+
|
26
30
|
def auto_reload(period = 60)
|
27
31
|
if not @thread.nil?
|
28
32
|
stop
|
@@ -58,6 +62,9 @@ class YahooCrawler
|
|
58
62
|
c_options, p_options = Hash.new, Hash.new
|
59
63
|
c_strikes, p_strikes = Array.new, Array.new
|
60
64
|
stock_price = nil
|
65
|
+
|
66
|
+
# A small hack to make my hashes accept integers instead of floats for the strike prices
|
67
|
+
add_convert_method_for_keys(c_options, p_options)
|
61
68
|
|
62
69
|
@t_lock.synchronize { # don't step into each other in case someone calls fetch
|
63
70
|
|
@@ -74,7 +81,7 @@ class YahooCrawler
|
|
74
81
|
lines = lines.chunk(lines.length / 8)
|
75
82
|
|
76
83
|
lines.each do |array|
|
77
|
-
quote = parse_quote(array, Option::CALL)
|
84
|
+
quote = parse_quote(array, Option::CALL, stock_price)
|
78
85
|
c_options[quote.option.strike] = quote
|
79
86
|
end
|
80
87
|
|
@@ -82,7 +89,7 @@ class YahooCrawler
|
|
82
89
|
lines = lines.chunk(lines.length / 8)
|
83
90
|
|
84
91
|
lines.each do |array|
|
85
|
-
quote = parse_quote(array, Option::PUT)
|
92
|
+
quote = parse_quote(array, Option::PUT, stock_price)
|
86
93
|
p_options[quote.option.strike] = quote
|
87
94
|
end
|
88
95
|
|
@@ -95,9 +102,9 @@ class YahooCrawler
|
|
95
102
|
@lock.synchronize {
|
96
103
|
@call_options, @put_options = c_options, p_options
|
97
104
|
@call_strikes, @put_strikes = c_strikes, p_strikes
|
98
|
-
@
|
105
|
+
@stock_price = stock_price
|
99
106
|
}
|
100
|
-
|
107
|
+
nil
|
101
108
|
end
|
102
109
|
|
103
110
|
def get_option_quote(type, strike)
|
@@ -132,8 +139,8 @@ class YahooCrawler
|
|
132
139
|
@lock.synchronize { @put_options }
|
133
140
|
end
|
134
141
|
|
135
|
-
def
|
136
|
-
@lock.synchronize { @
|
142
|
+
def stock_price
|
143
|
+
@lock.synchronize { @stock_price }
|
137
144
|
end
|
138
145
|
|
139
146
|
def show_calls
|
@@ -146,14 +153,14 @@ class YahooCrawler
|
|
146
153
|
|
147
154
|
private
|
148
155
|
|
149
|
-
def parse_quote(line, type)
|
156
|
+
def parse_quote(line, type, stock_price)
|
150
157
|
strike = line[0].to_f
|
151
158
|
symbol = line[1]
|
152
159
|
bid = f line[4]
|
153
160
|
ask = f line[5]
|
154
161
|
|
155
162
|
o = Option.new(type, @stock, strike, @exp, symbol)
|
156
|
-
OptionQuote.new(o, :bid => bid, :ask => ask)
|
163
|
+
OptionQuote.new(o, :bid => bid, :ask => ask, :stock_price => stock_price)
|
157
164
|
end
|
158
165
|
|
159
166
|
# Get all values inside tags
|
@@ -165,5 +172,14 @@ class YahooCrawler
|
|
165
172
|
def f(data)
|
166
173
|
data == 'N/A' ? nil : data.to_f
|
167
174
|
end
|
175
|
+
|
176
|
+
def add_convert_method_for_keys(*args)
|
177
|
+
args.each do |obj|
|
178
|
+
def obj.[](key)
|
179
|
+
super key.to_f
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
168
184
|
|
169
185
|
end
|
data/options-lib.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'options-lib'
|
3
|
-
s.version = '0.9.
|
3
|
+
s.version = '0.9.4'
|
4
4
|
s.platform = Gem::Platform::RUBY
|
5
5
|
s.summary = 'Options Library'
|
6
6
|
s.description = 'A set of classes for dealing with options. It includes a crawler for Yahoo!Finance.'
|
data/spec/option_quote_spec.rb
CHANGED
@@ -3,10 +3,15 @@ Dir["./lib/*.rb"].each {|file| require file }
|
|
3
3
|
|
4
4
|
describe OptionQuote do
|
5
5
|
|
6
|
+
o,q = nil,nil
|
7
|
+
|
8
|
+
before(:all) do
|
9
|
+
o = Option.new(Option::CALL, 'AAPL', 250, '2010-02-14')
|
10
|
+
q = OptionQuote.new(o, :bid => 1.2, :ask => 1.4, :stock_price => 10)
|
11
|
+
end
|
12
|
+
|
6
13
|
it 'has option, bid and ask prices' do
|
7
14
|
|
8
|
-
o = Option.new(Option::CALL, 'AAPL', 250, '2010-02-14')
|
9
|
-
q = OptionQuote.new(o, :bid => 1.2, :ask => 1.4)
|
10
15
|
q.option.should == o
|
11
16
|
q.bid.should == 1.2
|
12
17
|
q.ask.should == 1.4
|
@@ -14,10 +19,12 @@ describe OptionQuote do
|
|
14
19
|
end
|
15
20
|
|
16
21
|
it 'should have an spread' do
|
17
|
-
o = Option.new(Option::CALL, 'AAPL', 250, '2010-02-14')
|
18
|
-
q = OptionQuote.new(o, :bid => 1.2, :ask => 1.4)
|
19
22
|
q.spread.prettify.should == "0.2"
|
20
23
|
|
21
24
|
end
|
22
25
|
|
26
|
+
it 'should have the current stock price' do
|
27
|
+
q.stock_price.should == 10
|
28
|
+
end
|
29
|
+
|
23
30
|
end
|
data/spec/yahoo_crawler_spec.rb
CHANGED
@@ -19,7 +19,7 @@ describe YahooCrawler do
|
|
19
19
|
|
20
20
|
it 'should be able to get current price of stock' do
|
21
21
|
|
22
|
-
y.
|
22
|
+
y.stock_price.should > 0
|
23
23
|
|
24
24
|
end
|
25
25
|
|
@@ -33,17 +33,19 @@ describe YahooCrawler do
|
|
33
33
|
it 'should be able to give an option quote by strike price' do
|
34
34
|
|
35
35
|
# get a good strike price by rounding the current stock price
|
36
|
-
good_price = ((y.
|
36
|
+
good_price = ((y.stock_price / 100).to_i * 100).to_f
|
37
37
|
|
38
38
|
call_quote = y.call_options[good_price]
|
39
39
|
call_quote.option.internal_symbol.should == "AAPL_C#{good_price.to_i}_18JAN2013"
|
40
40
|
call_quote.bid.should > 0 if not call_quote.bid.nil?
|
41
41
|
call_quote.ask.should > 0 if not call_quote.ask.nil?
|
42
|
+
call_quote.stock_price.should > 0 if not call_quote.stock_price.nil?
|
42
43
|
|
43
44
|
put_quote = y.put_options[good_price]
|
44
45
|
put_quote.option.internal_symbol.should == "AAPL_P#{good_price.to_i}_18JAN2013"
|
45
46
|
put_quote.bid.should > 0 if not put_quote.bid.nil?
|
46
47
|
put_quote.ask.should > 0 if not put_quote.ask.nil?
|
48
|
+
put_quote.stock_price.should > 0 if not put_quote.stock_price.nil?
|
47
49
|
|
48
50
|
end
|
49
51
|
|
@@ -54,6 +56,13 @@ describe YahooCrawler do
|
|
54
56
|
y.put_options.length.should > 0
|
55
57
|
|
56
58
|
end
|
59
|
+
|
60
|
+
it 'should accept integers as well as floats for strike prices when accessing the options hash' do
|
61
|
+
|
62
|
+
y.call_options[300].should == y.call_options[300.0]
|
63
|
+
|
64
|
+
end
|
65
|
+
|
57
66
|
|
58
67
|
|
59
68
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: options-lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.9.
|
5
|
+
version: 0.9.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Sergio Oliveira Jr.
|
@@ -45,6 +45,7 @@ extra_rdoc_files: []
|
|
45
45
|
|
46
46
|
files:
|
47
47
|
- README.markdown
|
48
|
+
- Rakefile
|
48
49
|
- bin/show_quotes
|
49
50
|
- lib/options-lib.rb
|
50
51
|
- lib/options-lib/helpers.rb
|