interactive_brokers_2_tasty_works 0.3.0 → 0.3.1
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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile.lock +5 -5
- data/README.md +1 -1
- data/lib/interactive_brokers_2_tasty_works.rb +39 -14
- data/lib/interactive_brokers_2_tasty_works/version.rb +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 85439ff64f749ff412c32280e884acfb490998b86e471b1d779ea1c551c110f4
|
|
4
|
+
data.tar.gz: 166a8a99aca8c600d4d36628ff0b113b092bfa6e5486d0e868e11977ba7cdfd7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 616b232752b8fb717e10bd4d86339337bbb3c9db1d5e6dd4bb4294844f185faf35f474232666ba3f41e42b7833be87e927e83e3c678680b4c7f1f7e629403eef
|
|
7
|
+
data.tar.gz: 212d46e6b31d883274cde708a9082bf74925b5966ddb04a257c7683319bb061b1d70feaae930b1c66eeed0db772ee0bc8f4df7b40dd74a54a5e9d994ef2e1995
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.6.2
|
data/Gemfile.lock
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
interactive_brokers_2_tasty_works (0.3.
|
|
4
|
+
interactive_brokers_2_tasty_works (0.3.1)
|
|
5
5
|
activesupport
|
|
6
6
|
xmlhasher
|
|
7
7
|
|
|
8
8
|
GEM
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
|
-
activesupport (5.2.
|
|
11
|
+
activesupport (5.2.3)
|
|
12
12
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
13
13
|
i18n (>= 0.7, < 2)
|
|
14
14
|
minitest (~> 5.1)
|
|
15
15
|
tzinfo (~> 1.1)
|
|
16
16
|
byebug (10.0.2)
|
|
17
|
-
concurrent-ruby (1.1.
|
|
17
|
+
concurrent-ruby (1.1.5)
|
|
18
18
|
diff-lcs (1.3)
|
|
19
19
|
escape_utils (1.2.1)
|
|
20
|
-
i18n (1.
|
|
20
|
+
i18n (1.6.0)
|
|
21
21
|
concurrent-ruby (~> 1.0)
|
|
22
22
|
minitest (5.11.3)
|
|
23
23
|
ox (2.10.0)
|
|
@@ -53,4 +53,4 @@ DEPENDENCIES
|
|
|
53
53
|
rspec (~> 3.0)
|
|
54
54
|
|
|
55
55
|
BUNDLED WITH
|
|
56
|
-
1.17.
|
|
56
|
+
1.17.2
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This library converts the output of an Interactive Brokers Execution Flex Query to a TastyWorks-compatible CSV file.
|
|
4
4
|
|
|
5
|
-
### Flex Query Parameters in Interactive Brokers
|
|
5
|
+
### Activity Flex Query Parameters in Interactive Brokers
|
|
6
6
|
|
|
7
7
|
- Leave all defaults
|
|
8
8
|
- Set time period to LAST 365 DAYS (or whatever you want, really)
|
|
@@ -25,7 +25,7 @@ class InteractiveBrokers2TastyWorks
|
|
|
25
25
|
@file_format = file_format
|
|
26
26
|
@add_output = add_output
|
|
27
27
|
|
|
28
|
-
raise
|
|
28
|
+
raise ArgumentError.new("Must specify `data_hash` or `input_path`.") if data_hash.empty? && input_path.empty?
|
|
29
29
|
|
|
30
30
|
if !input_path.empty?
|
|
31
31
|
file_format = input_path.split(".").last.to_sym if file_format.empty?
|
|
@@ -48,7 +48,6 @@ class InteractiveBrokers2TastyWorks
|
|
|
48
48
|
|
|
49
49
|
def convert!
|
|
50
50
|
output = [add_output_headers ? (OUTPUT_HEADER + add_output_headers) : OUTPUT_HEADER]
|
|
51
|
-
# require 'byebug';byebug
|
|
52
51
|
|
|
53
52
|
trades = if data_hash[:FlexQueryResponse].is_a?(Array)
|
|
54
53
|
data_hash[:FlexQueryResponse][1][:FlexStatements][1][:FlexStatement][1][:Trades][:Trade]
|
|
@@ -68,7 +67,7 @@ class InteractiveBrokers2TastyWorks
|
|
|
68
67
|
Utils.build_description(trade),
|
|
69
68
|
Utils.build_value(trade),
|
|
70
69
|
trade[:quantity],
|
|
71
|
-
trade
|
|
70
|
+
Utils.build_trade_price(trade),
|
|
72
71
|
Utils.build_commission(trade),
|
|
73
72
|
'',
|
|
74
73
|
trade[:multiplier],
|
|
@@ -99,14 +98,7 @@ class InteractiveBrokers2TastyWorks
|
|
|
99
98
|
|
|
100
99
|
def add_output_values(trade)
|
|
101
100
|
return nil unless @add_output.present?
|
|
102
|
-
|
|
103
101
|
add_output_fields.map { |f| Utils.indifferent_fetch(trade, f) }
|
|
104
|
-
# output = []
|
|
105
|
-
# add_output_fields.each do |f|
|
|
106
|
-
# output << trade[f]
|
|
107
|
-
# end
|
|
108
|
-
|
|
109
|
-
# output
|
|
110
102
|
end
|
|
111
103
|
|
|
112
104
|
def add_output_fields
|
|
@@ -170,9 +162,9 @@ class InteractiveBrokers2TastyWorks
|
|
|
170
162
|
str += case (ac = trade[:assetCategory])
|
|
171
163
|
when 'OPT'
|
|
172
164
|
exp = build_date(trade[:expiry])
|
|
173
|
-
"#{trade[:symbol]} #{exp} #{put_or_call(trade)} #{trade[:strike]} @ #{trade
|
|
165
|
+
"#{trade[:symbol]} #{exp} #{put_or_call(trade)} #{trade[:strike]} @ #{build_trade_price(trade)}"
|
|
174
166
|
when 'STK'
|
|
175
|
-
"#{trade[:symbol]} @ #{trade
|
|
167
|
+
"#{trade[:symbol]} @ #{build_trade_price(trade)}"
|
|
176
168
|
else
|
|
177
169
|
raise ArgumentError.new("Unknown asset category: #{ac}")
|
|
178
170
|
end
|
|
@@ -180,9 +172,25 @@ class InteractiveBrokers2TastyWorks
|
|
|
180
172
|
str
|
|
181
173
|
end
|
|
182
174
|
|
|
175
|
+
def build_trade_price(trade)
|
|
176
|
+
if string_is_zero?(trade[:tradePrice]) && !string_is_zero?(build_value(trade))
|
|
177
|
+
value = build_value(trade).to_f
|
|
178
|
+
strip_zero_decimal (value / trade[:quantity].to_i / trade[:multiplier].to_i).abs
|
|
179
|
+
else
|
|
180
|
+
trade[:tradePrice]
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
183
184
|
def build_value(trade)
|
|
184
|
-
|
|
185
|
-
|
|
185
|
+
if !proceeds_is_zero?(trade)
|
|
186
|
+
v = trade[:proceeds]
|
|
187
|
+
elsif is_option_assignment_exercise_or_expiration(trade)
|
|
188
|
+
v = strip_zero_decimal(trade[:mtmPnl].to_f * -1)
|
|
189
|
+
else
|
|
190
|
+
raise ArgumentError.new("Cannot parse trade: #{trade}")
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
(v.to_f == -0.0 ? 0 : v).to_s
|
|
186
194
|
end
|
|
187
195
|
|
|
188
196
|
def build_commission(trade)
|
|
@@ -195,6 +203,23 @@ class InteractiveBrokers2TastyWorks
|
|
|
195
203
|
trade[:putCall] == 'P' ? 'PUT' : 'CALL'
|
|
196
204
|
end
|
|
197
205
|
|
|
206
|
+
def string_is_zero?(str)
|
|
207
|
+
str = str.to_s.strip
|
|
208
|
+
str == '0' || str == '-0'
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def proceeds_is_zero?(trade)
|
|
212
|
+
string_is_zero?(trade[:proceeds])
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def strip_zero_decimal(val)
|
|
216
|
+
val.to_s.sub(/\.0$/, '')
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def is_option_assignment_exercise_or_expiration(trade)
|
|
220
|
+
proceeds_is_zero?(trade) && trade[:transactionType] == "BookTrade" && trade[:notes] =~ /^A$|^Ex$|^Ep$/i
|
|
221
|
+
end
|
|
222
|
+
|
|
198
223
|
def indifferent_fetch(h, key)
|
|
199
224
|
h.fetch(key)
|
|
200
225
|
rescue KeyError
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: interactive_brokers_2_tasty_works
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Carl Mercier
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2019-04-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -134,8 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
134
134
|
- !ruby/object:Gem::Version
|
|
135
135
|
version: '0'
|
|
136
136
|
requirements: []
|
|
137
|
-
|
|
138
|
-
rubygems_version: 2.7.6
|
|
137
|
+
rubygems_version: 3.0.3
|
|
139
138
|
signing_key:
|
|
140
139
|
specification_version: 4
|
|
141
140
|
summary: Interactive Brokers to Tasty Works trade statement converter
|