interactive_brokers_2_tasty_works 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -4
- data/README.md +11 -5
- data/interactive_brokers_2_tasty_works.gemspec +2 -2
- data/lib/interactive_brokers_2_tasty_works.rb +40 -5
- data/lib/interactive_brokers_2_tasty_works/version.rb +1 -1
- metadata +4 -6
- data/bin/ib2tw +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 863983279975a5eb786885e48bb92933181e179f6c1d99d7a5858a0c72ead21e
|
4
|
+
data.tar.gz: e656aa6e2c917ef034c839553f03d137a7ac37bd9d633bbf8ea86f28873ae5b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4457b86322469c760021ab2046b7b2aa0ece5e51c279af331aae43e21ad6aecc6e463ab2049295896b30fdbdcf7a16b48ff3aea34b2f969de02d3ef98533bee7
|
7
|
+
data.tar.gz: 19dc89f4ffd60a37ca565eda0b23f860a785b5d62e28f4b53bd90478402c8ab5e5befd92255334b91dca70214fac03fce96dcb3019d79d04deffea9949fa1ec4
|
data/Gemfile.lock
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
interactive_brokers_2_tasty_works (0.
|
4
|
+
interactive_brokers_2_tasty_works (0.3.0)
|
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.2)
|
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.4)
|
18
18
|
diff-lcs (1.3)
|
19
19
|
escape_utils (1.2.1)
|
20
|
-
i18n (1.
|
20
|
+
i18n (1.3.0)
|
21
21
|
concurrent-ruby (~> 1.0)
|
22
22
|
minitest (5.11.3)
|
23
23
|
ox (2.10.0)
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ This library converts the output of an Interactive Brokers Execution Flex Query
|
|
5
5
|
### Flex Query Parameters in Interactive Brokers
|
6
6
|
|
7
7
|
- Leave all defaults
|
8
|
-
- Set time period to LAST 365 DAYS
|
8
|
+
- Set time period to LAST 365 DAYS (or whatever you want, really)
|
9
9
|
- In Sections, select Trades
|
10
10
|
+ Select Executions
|
11
11
|
+ Select All
|
@@ -26,13 +26,19 @@ Or install it yourself as:
|
|
26
26
|
|
27
27
|
$ gem install interactive_brokers_2_tasty_works
|
28
28
|
|
29
|
-
##
|
29
|
+
## Usage
|
30
30
|
|
31
|
-
`
|
31
|
+
`InteractiveBrokers2TastyWorks.new(input_path: '~/trades.xml').save_as("/tmp/trades.csv")`
|
32
32
|
|
33
|
-
|
33
|
+
### Adding additional fields to the output (non standard output format)
|
34
34
|
|
35
|
-
|
35
|
+
```
|
36
|
+
InteractiveBrokers2TastyWorks.new(input_path: '~/trades.xml', add_output: ['ibExecID', 'ibOrderID'])
|
37
|
+
|
38
|
+
# or to specify a different header for the additional fields
|
39
|
+
|
40
|
+
InteractiveBrokers2TastyWorks.new(input_path: '~/trades.xml', add_output: { ibExecID: 'IB Execution ID', ibOrderID: 'IB Order ID' })
|
41
|
+
```
|
36
42
|
|
37
43
|
## Development
|
38
44
|
|
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
21
21
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
22
|
end
|
23
|
-
|
24
|
-
spec.executables =
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
25
|
spec.require_paths = ["lib"]
|
26
26
|
|
27
27
|
spec.add_development_dependency "bundler", "~> 1.16"
|
@@ -19,10 +19,11 @@ class InteractiveBrokers2TastyWorks
|
|
19
19
|
'Average Price', 'Commissions', 'Fees', 'Multiplier', 'Underlying Symbol', 'Expiration Date',
|
20
20
|
'Strike Price', 'Call or Put']
|
21
21
|
|
22
|
-
def initialize(data_hash: nil, input_path: nil, file_format: :xml)
|
22
|
+
def initialize(data_hash: nil, input_path: nil, file_format: :xml, add_output: nil)
|
23
23
|
@data_hash = data_hash
|
24
24
|
@input_path = input_path
|
25
25
|
@file_format = file_format
|
26
|
+
@add_output = add_output
|
26
27
|
|
27
28
|
raise ArgumenrError.new("Must specify `data_hash` or `input_path`.") if data_hash.empty? && input_path.empty?
|
28
29
|
|
@@ -31,8 +32,6 @@ class InteractiveBrokers2TastyWorks
|
|
31
32
|
file_format = file_format.to_s.to_sym unless file_format.is_a?(Symbol)
|
32
33
|
raise ArgumentError.new("Unknown file format: #{file_format}") unless %i(xml json).include?(file_format)
|
33
34
|
end
|
34
|
-
|
35
|
-
Time.zone ||= Time.now.getlocal.zone
|
36
35
|
end
|
37
36
|
|
38
37
|
def save_as(output_path)
|
@@ -48,7 +47,8 @@ class InteractiveBrokers2TastyWorks
|
|
48
47
|
private
|
49
48
|
|
50
49
|
def convert!
|
51
|
-
output = [OUTPUT_HEADER]
|
50
|
+
output = [add_output_headers ? (OUTPUT_HEADER + add_output_headers) : OUTPUT_HEADER]
|
51
|
+
# require 'byebug';byebug
|
52
52
|
|
53
53
|
trades = if data_hash[:FlexQueryResponse].is_a?(Array)
|
54
54
|
data_hash[:FlexQueryResponse][1][:FlexStatements][1][:FlexStatement][1][:Trades][:Trade]
|
@@ -77,8 +77,9 @@ class InteractiveBrokers2TastyWorks
|
|
77
77
|
trade[:strike],
|
78
78
|
Utils.put_or_call(trade)
|
79
79
|
]
|
80
|
-
end
|
81
80
|
|
81
|
+
output.last.concat(add_output_values(trade)) if add_output_values(trade)
|
82
|
+
end
|
82
83
|
output
|
83
84
|
end
|
84
85
|
|
@@ -96,6 +97,34 @@ class InteractiveBrokers2TastyWorks
|
|
96
97
|
end
|
97
98
|
end
|
98
99
|
|
100
|
+
def add_output_values(trade)
|
101
|
+
return nil unless @add_output.present?
|
102
|
+
|
103
|
+
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
|
+
end
|
111
|
+
|
112
|
+
def add_output_fields
|
113
|
+
if @add_output.is_a?(Hash)
|
114
|
+
@add_output.keys
|
115
|
+
elsif @add_output.is_a?(Array)
|
116
|
+
@add_output
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_output_headers
|
121
|
+
if @add_output.is_a?(Hash)
|
122
|
+
@add_output.values
|
123
|
+
elsif @add_output.is_a?(Array)
|
124
|
+
@add_output
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
99
128
|
module Utils
|
100
129
|
class << self
|
101
130
|
def build_date_time_str(trade)
|
@@ -165,6 +194,12 @@ class InteractiveBrokers2TastyWorks
|
|
165
194
|
return nil unless trade[:assetCategory] == 'OPT'
|
166
195
|
trade[:putCall] == 'P' ? 'PUT' : 'CALL'
|
167
196
|
end
|
197
|
+
|
198
|
+
def indifferent_fetch(h, key)
|
199
|
+
h.fetch(key)
|
200
|
+
rescue KeyError
|
201
|
+
h[key.is_a?(String) ? key.to_sym : key.to_s]
|
202
|
+
end
|
168
203
|
end
|
169
204
|
end
|
170
205
|
end
|
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.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carl Mercier
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -97,8 +97,7 @@ dependencies:
|
|
97
97
|
description: Interactive Brokers to Tasty Works trade statement converter
|
98
98
|
email:
|
99
99
|
- foss@carlmercier.com
|
100
|
-
executables:
|
101
|
-
- ib2tw
|
100
|
+
executables: []
|
102
101
|
extensions: []
|
103
102
|
extra_rdoc_files: []
|
104
103
|
files:
|
@@ -112,7 +111,6 @@ files:
|
|
112
111
|
- README.md
|
113
112
|
- Rakefile
|
114
113
|
- bin/console
|
115
|
-
- bin/ib2tw
|
116
114
|
- bin/setup
|
117
115
|
- interactive_brokers_2_tasty_works.gemspec
|
118
116
|
- lib/interactive_brokers_2_tasty_works.rb
|
data/bin/ib2tw
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require_relative '../lib/interactive_brokers_2_tasty_works'
|
4
|
-
|
5
|
-
if ARGV[0].nil? || ARGV[1].nil? || ARGV[0].include?('--help') || ARGV[0].include?('-?')
|
6
|
-
puts "\nUsage: ./ib2tw /path/to/input.xml /path/to/output.csv\n\n"
|
7
|
-
exit 1
|
8
|
-
end
|
9
|
-
|
10
|
-
input_file = File.expand_path(ARGV[0])
|
11
|
-
output_file = File.expand_path(ARGV[1])
|
12
|
-
|
13
|
-
unless File.exists?(input_file)
|
14
|
-
puts "\nFile not found: #{input_file}\n\n"
|
15
|
-
exit 1
|
16
|
-
end
|
17
|
-
|
18
|
-
puts "\n"
|
19
|
-
puts "Input: #{input_file}"
|
20
|
-
puts "Output: #{output_file}\n"
|
21
|
-
puts "Converting..."
|
22
|
-
|
23
|
-
InteractiveBrokers2TastyWorks.new(input_path: input_file).save_as(output_file)
|
24
|
-
|
25
|
-
puts "Done!"
|