mytradewizard 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/mytradewizard.rb +2 -0
- data/lib/mytradewizard/action.rb +32 -0
- data/lib/mytradewizard/cli.rb +2 -2
- data/lib/mytradewizard/date_time.rb +28 -0
- data/lib/mytradewizard/interactive_brokers.rb +112 -15
- data/lib/mytradewizard/trading_system.rb +6 -0
- data/lib/mytradewizard/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjUzNjhhZjAwM2M3OTI2NDEzYjMxNzM0ODU4NDI1NjIxNzBlYzNlNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjE4MjgzMDc1MmZhMTZkZmIwMzVhMWRmNWU5ODQwZjNmOGQ2MzVhYQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YWY1MmNkNDc4MzQ2MWIxOTdjYjQ4ZDg5ZjFlNGEwMzIwYzViNWI3YzY2ODI4
|
10
|
+
MjAyYjA0ZGNiZjUzNDVmNmQzYjM4NmIyNDBmMDY4ZmFlYjNjZDZiNDdiODJk
|
11
|
+
ZWNhMDgzNDY0MzMwOWZhYzUwM2IzMTI4YWZlYzk4YjRmMzc0ZTY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NTJlMDIzZDM4MjBjMDg5MDlmNDUyNWIyMzJlMDZlZTM2MzM3Zjk0MjhkNGRk
|
14
|
+
ODZmNGMwNThhNmZiMzM1MjQwZWZhNjA1YzBiZDhlMWZmMWQ1NTI3MjQyNjQ1
|
15
|
+
MGI2ZjUyNTY5ZmRkNGIzNjY2NDFiOTA0Mjk3NTk5MjM1YjgyYTY=
|
data/lib/mytradewizard.rb
CHANGED
@@ -3,10 +3,12 @@ require 'mytradewizard/interactive_brokers'
|
|
3
3
|
require 'mytradewizard/cme'
|
4
4
|
require 'mytradewizard/yahoo'
|
5
5
|
require 'mytradewizard/ohlc'
|
6
|
+
require 'mytradewizard/date_time'
|
6
7
|
require 'mytradewizard/stock'
|
7
8
|
require 'mytradewizard/watch_list'
|
8
9
|
require 'mytradewizard/technical_indicator'
|
9
10
|
require 'mytradewizard/trading_system'
|
11
|
+
require 'mytradewizard/action'
|
10
12
|
|
11
13
|
module MyTradeWizard
|
12
14
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MyTradeWizard
|
2
|
+
class Action
|
3
|
+
|
4
|
+
def initialize(signal)
|
5
|
+
@signal = signal
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
if @signal > 0
|
10
|
+
return "BUY"
|
11
|
+
elsif @signal < 0
|
12
|
+
return "SELL"
|
13
|
+
else
|
14
|
+
return "None"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def reverse!
|
19
|
+
@signal = -@signal
|
20
|
+
return self
|
21
|
+
end
|
22
|
+
|
23
|
+
def reverse
|
24
|
+
return MyTradeWizard::Action.new(-@signal)
|
25
|
+
end
|
26
|
+
|
27
|
+
def nil?
|
28
|
+
@signal == 0
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/mytradewizard/cli.rb
CHANGED
@@ -34,14 +34,14 @@ module MyTradeWizard
|
|
34
34
|
def CL
|
35
35
|
ib = MyTradeWizard::InteractiveBrokers.new
|
36
36
|
ib.connect
|
37
|
-
puts "Front month: " + ib.front_month(:CL)
|
37
|
+
puts "Front month: " + ib.front_month(:CL).expiry
|
38
38
|
end
|
39
39
|
|
40
40
|
desc "QM", "Determines the front month Mini-Crude future contract"
|
41
41
|
def QM
|
42
42
|
ib = MyTradeWizard::InteractiveBrokers.new
|
43
43
|
ib.connect
|
44
|
-
puts "Front month: " + ib.front_month(:QM)
|
44
|
+
puts "Front month: " + ib.front_month(:QM).expiry
|
45
45
|
end
|
46
46
|
|
47
47
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module MyTradeWizard
|
2
|
+
class DateTime
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def WaitUntil(hour, minute)
|
6
|
+
print "Waiting until #{hour}:#{minute} ..."
|
7
|
+
until time_is(hour, minute)
|
8
|
+
sleep 60
|
9
|
+
print '.'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def time_is(hour, minute)
|
16
|
+
if (1..5).include?(Time.now.utc.wday)
|
17
|
+
if Time.now.utc.hour == hour
|
18
|
+
if Time.now.utc.min >= minute
|
19
|
+
return true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,17 +1,26 @@
|
|
1
1
|
require 'ib'
|
2
|
-
|
2
|
+
begin
|
3
|
+
require "#{Dir.pwd}/config/interactive_brokers"
|
4
|
+
rescue LoadError
|
5
|
+
puts "Please configure Interactive Brokers!"
|
6
|
+
end
|
3
7
|
|
4
8
|
module MyTradeWizard
|
5
9
|
class InteractiveBrokers
|
6
10
|
|
11
|
+
attr_reader :accounts
|
12
|
+
|
7
13
|
def connect(timeout = nil)
|
14
|
+
puts "Connecting to IB..."
|
8
15
|
start_time = Time.now
|
9
16
|
exception = nil
|
10
17
|
while (timeout.nil? || Time.now - start_time <= timeout)
|
11
18
|
begin
|
12
|
-
@
|
19
|
+
@ib_ruby = IB::Connection.new :host => self.class.host, :port => self.class.port
|
13
20
|
subscribe_to_alerts
|
14
|
-
|
21
|
+
sleep 0.1
|
22
|
+
fetch_accounts
|
23
|
+
return @ib_ruby
|
15
24
|
rescue Exception => exception
|
16
25
|
puts exception
|
17
26
|
sleep 10
|
@@ -20,13 +29,87 @@ module MyTradeWizard
|
|
20
29
|
raise exception
|
21
30
|
end
|
22
31
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
32
|
+
def daily_bars(contract, days, confirm = true)
|
33
|
+
puts "Fetching daily bars..."
|
34
|
+
bars = nil
|
35
|
+
@ib_ruby.subscribe(IB::Messages::Incoming::HistoricalData) { |msg| bars = msg.results }
|
36
|
+
@ib_ruby.send_message IB::Messages::Outgoing::RequestHistoricalData.new(
|
37
|
+
:request_id => 123,
|
38
|
+
:contract => contract,
|
39
|
+
:end_date_time => Time.now.utc.to_ib,
|
40
|
+
:duration => "#{days} D",
|
41
|
+
:bar_size => '1 day',
|
42
|
+
:what_to_show => :trades,
|
43
|
+
:use_rth => 1,
|
44
|
+
:format_date => 1)
|
45
|
+
while bars.nil?
|
27
46
|
sleep 1
|
28
47
|
end
|
29
|
-
|
48
|
+
if confirm && bars.size < days
|
49
|
+
raise "Invalid Data! (#{bars.size}/#{days} valid bars.)"
|
50
|
+
else
|
51
|
+
bars.reverse!
|
52
|
+
puts bars
|
53
|
+
return bars
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def hourly_bars(contract, hourly_range, confirm = true)
|
58
|
+
range_size = hourly_range.last - hourly_range.first
|
59
|
+
puts "Fetching hourly bars..."
|
60
|
+
bars = nil
|
61
|
+
@ib_ruby.subscribe(IB::Messages::Incoming::HistoricalData) { |msg| bars = msg.results }
|
62
|
+
@ib_ruby.send_message IB::Messages::Outgoing::RequestHistoricalData.new(
|
63
|
+
:request_id => 123,
|
64
|
+
:contract => contract,
|
65
|
+
:end_date_time => Time.now.utc.to_ib,
|
66
|
+
:duration => "#{60*60*range_size} S",
|
67
|
+
:bar_size => '1 hour',
|
68
|
+
:what_to_show => :trades,
|
69
|
+
:use_rth => 0,
|
70
|
+
:format_date => 1)
|
71
|
+
while bars.nil?
|
72
|
+
sleep 1
|
73
|
+
end
|
74
|
+
if confirm
|
75
|
+
bars.keep_if { |bar| Time.parse(bar.time).wday == Time.now.utc.wday && hourly_range.include?(Time.parse(bar.time).hour) }
|
76
|
+
if bars.size == range_size
|
77
|
+
puts bars
|
78
|
+
return bars
|
79
|
+
else
|
80
|
+
raise "Invalid Data! (#{bars.size}/#{range_size} valid bars.)"
|
81
|
+
end
|
82
|
+
else
|
83
|
+
puts bars
|
84
|
+
return bars
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def positions(account)
|
89
|
+
p = Array.new
|
90
|
+
@ib_ruby.subscribe(:AccountValue, :PortfolioValue, :AccountUpdateTime, :AccountDownloadEnd) do |msg|
|
91
|
+
if msg.message_type == :PortfolioValue
|
92
|
+
if msg.contract.sec_type == :stock
|
93
|
+
stock = MyTradeWizard::Stock.new(msg.contract.symbol)
|
94
|
+
p << stock
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
@ib_ruby.send_message :RequestAccountData, :account_code => account
|
99
|
+
p
|
100
|
+
end
|
101
|
+
|
102
|
+
def place_market_order(account, action, quantity, contract, good_after, good_till)
|
103
|
+
order = IB::Order.new :total_quantity => quantity,
|
104
|
+
:action => action.to_s,
|
105
|
+
:order_type => 'MKT',
|
106
|
+
:good_after_time => "#{Time.now.utc.strftime('%Y%m%d')} #{good_after}",
|
107
|
+
:good_till_date => "#{Time.now.utc.strftime('%Y%m%d')} #{good_till}",
|
108
|
+
:tif => 'GTD',
|
109
|
+
:account => account
|
110
|
+
@ib_ruby.wait_for :NextValidId
|
111
|
+
@ib_ruby.place_order order, contract
|
112
|
+
puts "#{action} #{quantity} #{contract.symbol} @ #{good_after}"
|
30
113
|
end
|
31
114
|
|
32
115
|
def front_month(symbol)
|
@@ -37,14 +120,28 @@ module MyTradeWizard
|
|
37
120
|
raise ErrorDeterminingFrontMonth
|
38
121
|
end
|
39
122
|
end
|
40
|
-
expiry
|
123
|
+
contract(symbol, expiry)
|
41
124
|
end
|
42
125
|
|
43
126
|
private
|
44
127
|
|
45
128
|
def subscribe_to_alerts
|
46
|
-
@
|
47
|
-
|
129
|
+
@ib_ruby.subscribe(:Alert, :ReceiveFA, :OpenOrder, :OrderStatus, :ExecutionData, :CommissionReport, :ManagedAccounts) do |msg|
|
130
|
+
unless [:Alert, :ManagedAccounts].include? msg.message_type
|
131
|
+
unless msg.to_human.include?("No security definition has been found for the request")
|
132
|
+
puts msg.to_human
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def fetch_accounts
|
139
|
+
puts "Fetching accounts... "
|
140
|
+
@accounts = nil
|
141
|
+
@ib_ruby.subscribe(:ManagedAccounts) { |msg| @accounts = msg.accounts_list.split(',') }
|
142
|
+
@ib_ruby.send_message :RequestManagedAccounts
|
143
|
+
while @accounts.nil?
|
144
|
+
sleep 1
|
48
145
|
end
|
49
146
|
end
|
50
147
|
|
@@ -66,10 +163,10 @@ module MyTradeWizard
|
|
66
163
|
|
67
164
|
def valid(contract)
|
68
165
|
valid = false
|
69
|
-
@
|
70
|
-
@
|
71
|
-
@
|
72
|
-
@
|
166
|
+
@ib_ruby.subscribe(:ContractData, :ContractDataEnd) { |msg| valid = true }
|
167
|
+
@ib_ruby.send_message :RequestContractData, :id => 1, :contract => contract
|
168
|
+
@ib_ruby.wait_for :ContractDataEnd, 5
|
169
|
+
@ib_ruby.clear_received :ContractDataEnd
|
73
170
|
valid
|
74
171
|
end
|
75
172
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mytradewizard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mytradewizard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -186,8 +186,10 @@ files:
|
|
186
186
|
- features/interactive_brokers.feature
|
187
187
|
- features/support/setup.rb
|
188
188
|
- lib/mytradewizard.rb
|
189
|
+
- lib/mytradewizard/action.rb
|
189
190
|
- lib/mytradewizard/cli.rb
|
190
191
|
- lib/mytradewizard/cme.rb
|
192
|
+
- lib/mytradewizard/date_time.rb
|
191
193
|
- lib/mytradewizard/generators/config/interactive_brokers.rb
|
192
194
|
- lib/mytradewizard/generators/interactive_brokers.rb
|
193
195
|
- lib/mytradewizard/interactive_brokers.rb
|