The GUI-Version of the TWS organizes symbols in different pages (Watchlists).
IB-Ruby uses the same concept to organize and optimize operational issues and to support research and systematic trading efforts. The lists are organized as Enumerator
, which extents its use. This feature lives entirely in the filesystem, no database is required, no further dependency is involved.
Prerequisites
The symbols
-plugin has to be activated
require 'ib-api'
ib = IB::Connection.new
ib.activate_plugin :symbols
By default, Watchlists reside in the symbols
-directory of ib-api
-sourcecode. This can be changed anytime through
IB::Symbols.set_origin '.' # (a valid path, either relative or absolute)
=> #<Pathname:.>
IB::Symbols.set_origin( "." ).realpath
=> #<Pathname:/home/ubuntu/workspace/ib-ruby/bin>
Symbol Collections
Everything is kept elementary simple: Collections are stored as editable files. The format is YAML.
The CRUD Cycle
IB::Symbols.allocate_collection :Demo
=> IB::Symbols::Demo # file /symbols/Demo is created
IB::Symbols::Demo.add_contract :uso , IB::Stock.new( symbol: 'USO' )
=> 235 # returns the count of written bytes to the file
IB::Symbols::Demo.uso # returns the stored contract
=> #<IB::Stock:0x0000000002c814f8 @attributes={:symbol=>"USO", :created_at=>2018-04-29 18:47:01 +0000, :con_id=>0, :right=>"", :exchange=>"SMART", :include_expired=>false, :sec_type=>"STK", :currency=>"USD"}>
IB::Symbols::Demo.add_contract :ford , IB::Stock.new( symbol: 'F' )
=> 465
IB::Symbols::Demo.all
=> [:ford, :uso] # lists all stored contracts
IB::Symbols::Demo.remove_contract :uso
IB::Symbols::Demo.all
=> [:ford]
IB::Symbols::Demo.purge_collection # deletes the file and erases contracts kept in memory
=> nil
IB::Symbols::Demo.all
=> []
Using the Collection to Trade Complex Contracts
Any IB::Contract
can be stored in the Collection.
The composition of suitable Contracts and their trading can be separated using Collections
as handy Contract-Stores.
If – for instant – trading-ideas for several scenarios are outlined, Collections can act as easy and transparent stores. Occasionally the stored trading-concepts can be transmitted.
bear = IB::Symbols.allocate_collection :BearishSzenario
bear.add_contract :bear_spread_3000_2400,
IB::Vertical.new( underlying: IB::Symbols::Index.stoxx, sell: 2500, buy: 3000,
right: :put, expiry: 201903)
neutral = IB::Symbols.allocate_collection :NeurtalSzenario
neutral.add_contract :slight_defensive_straddle,
IB::Straddle.new( underlying: IB::Symbols::Index.stoxx, strike: 3200, expiry: 291893 )
Option Chains
Dynamically allocated Collections implement an Enumerator
of IB::Contracts
.
This has neat consequences.
First read an option chain into the collection
IB::Symbols.allocate_collection :Test
IB::Symbols::Options.ibm_lazy_strike.verify{|y| Symbols::Test.add_contract y.strike.to_i, y }
29 Options are stored in the collection.
They can be inspected and manipulated as comfortably as ordinary arrays:
IB::Symbols::Test.size => 29
IB::Symbols::Test.first.to_human
=> "<Option: IBM 20180921 put 100.0 SMART USD>"
IB::Symbols::Test.map &:strike
=> [100.0, 105.0, 110.0, 115.0, 120.0, 125.0, 130.0, 135.0, 140.0, 145.0, 150.0, 155.0, 160.0, 165.0, 170.0, 175.0, 180.0, 185.0, 190.0, 195.0, 200.0, 210.0, 220.0, 230.0, 80.0, 85.0, 90.0, 95.0, 75.0]
IB::Symbols::Test[100].to_human
=> "<Option: IBM 20180921 put 100.0 SMART USD>"
IB::Symbols::Test.find{| x | x.strike == 130 }.to_human
=> "<Option: IBM 20180921 put 130.0 SMART USD>"
puts IB::Symbols::Test.find_all {| x | x.strike > 130 && x.strike < 190 }.to_human.join "\n"
<Option: IBM 20180921 put 135.0 SMART USD>
<Option: IBM 20180921 put 140.0 SMART USD>
<Option: IBM 20180921 put 145.0 SMART USD>
<Option: IBM 20180921 put 150.0 SMART USD>
<Option: IBM 20180921 put 155.0 SMART USD>
<Option: IBM 20180921 put 160.0 SMART USD>
<Option: IBM 20180921 put 165.0 SMART USD>
<Option: IBM 20180921 put 170.0 SMART USD>
<Option: IBM 20180921 put 175.0 SMART USD>
<Option: IBM 20180921 put 180.0 SMART USD>
<Option: IBM 20180921 put 185.0 SMART USD>
puts IB::Symbols::Test.sort{|x,y| x.strike <=> y.strike }.to_human.join("\n")
<Option: IBM 20180921 put 75.0 SMART USD>
<Option: IBM 20180921 put 80.0 SMART USD>
<Option: IBM 20180921 put 85.0 SMART USD>
<Option: IBM 20180921 put 90.0 SMART USD>
<Option: IBM 20180921 put 95.0 SMART USD>
<Option: IBM 20180921 put 100.0 SMART USD>
<Option: IBM 20180921 put 105.0 SMART USD>
<Option: IBM 20180921 put 110.0 SMART USD>
<Option: IBM 20180921 put 115.0 SMART USD>
<Option: IBM 20180921 put 120.0 SMART USD>
<Option: IBM 20180921 put 125.0 SMART USD>
<Option: IBM 20180921 put 130.0 SMART USD>
<Option: IBM 20180921 put 135.0 SMART USD>
<Option: IBM 20180921 put 140.0 SMART USD>
<Option: IBM 20180921 put 145.0 SMART USD>
<Option: IBM 20180921 put 150.0 SMART USD>
<Option: IBM 20180921 put 155.0 SMART USD>
<Option: IBM 20180921 put 160.0 SMART USD>
<Option: IBM 20180921 put 165.0 SMART USD>
<Option: IBM 20180921 put 170.0 SMART USD>
<Option: IBM 20180921 put 175.0 SMART USD>
<Option: IBM 20180921 put 180.0 SMART USD>
<Option: IBM 20180921 put 185.0 SMART USD>
<Option: IBM 20180921 put 190.0 SMART USD>
<Option: IBM 20180921 put 195.0 SMART USD>
<Option: IBM 20180921 put 200.0 SMART USD>
<Option: IBM 20180921 put 210.0 SMART USD>
<Option: IBM 20180921 put 220.0 SMART USD>
<Option: IBM 20180921 put 230.0 SMART USD>