rapflag 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/Gemfile +2 -0
- data/History.md +5 -0
- data/bin/rapflag +17 -5
- data/fixtures/vcr_cassettes/rapflag.yml +44 -0
- data/lib/rapflag/bitfinex.rb +93 -0
- data/lib/rapflag/config.rb +0 -6
- data/lib/rapflag/history.rb +125 -0
- data/lib/rapflag/poloniex.rb +325 -0
- data/lib/rapflag/version.rb +1 -1
- data/rapflag.gemspec +1 -0
- data/spec/bitfinex_spec.rb +128 -0
- data/spec/poloniex_spec.rb +115 -0
- data/spec/spec_helper.rb +6 -0
- metadata +24 -5
- data/lib/rapflag/fetch.rb +0 -176
- data/spec/rapflag_spec.rb +0 -115
@@ -0,0 +1,325 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'faraday'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'rapflag/history'
|
6
|
+
require 'poloniex'
|
7
|
+
require 'json'
|
8
|
+
require 'pp'
|
9
|
+
|
10
|
+
module RAPFLAG
|
11
|
+
|
12
|
+
class Poloniex < History
|
13
|
+
attr_reader :complete_balances, :active_loans, :lending_history, :deposits, :withdrawals, :deposit_addresses,
|
14
|
+
:trade_history, :available_account_balances, :open_orders, :tradable_balances
|
15
|
+
|
16
|
+
@@btc_to_usd = {}
|
17
|
+
@@bfx_to_usd = {}
|
18
|
+
|
19
|
+
def get_usd_exchange(date_time = Time.now, from='BTC')
|
20
|
+
return 1.0 if from == 'USD'
|
21
|
+
daily = ::Poloniex.get_all_daily_exchange_rates('BTC_GNT')
|
22
|
+
|
23
|
+
key = date_time.strftime(DATE_FORMAT)
|
24
|
+
return @@btc_to_usd[key] if from.eql?('BTC') && @@btc_to_usd.size > 0
|
25
|
+
return @@bfx_to_usd[key] if from.eql?('BFX') && @@bfx_to_usd.size > 0
|
26
|
+
ms = (date_time.is_a?(Date) ? date_time.to_time : date_time).to_i*1000
|
27
|
+
ms_next_date = ms + (3*24*3600)*1000
|
28
|
+
# this does not work
|
29
|
+
# url = "https://api.bitfinex.com/v2/candles/trade:1D:t#{from}USD/hist?start:#{ms}?end:#{ms_next_date}"
|
30
|
+
url = "https://api.bitfinex.com/v2/candles/trade:1D:t#{from}USD/hist?start:#{ms}?end:#{ms_next_date}"
|
31
|
+
# therefore we just return the most uptodate
|
32
|
+
url = "https://api.bitfinex.com/v2/candles/trade:1D:t#{from}USD/hist?start:#{ms}"
|
33
|
+
puts "Fetching #{date_time}: #{url} #{@@btc_to_usd.size} BTC #{@@bfx_to_usd.size} BFX" if $VERBOSE
|
34
|
+
response = Faraday.get(url)
|
35
|
+
items = eval(response.body)
|
36
|
+
rates = {}
|
37
|
+
items.each do |item|
|
38
|
+
if item.first.eql?(:error)
|
39
|
+
puts "Fetching returned #{item}. Aborting"
|
40
|
+
exit(1)
|
41
|
+
end
|
42
|
+
timestamp = Time.at(item.first/1000).strftime(DATE_FORMAT)
|
43
|
+
rates[timestamp] = item[2]
|
44
|
+
end;
|
45
|
+
from.eql?('BTC') ? @@btc_to_usd = rates.clone : @@bfx_to_usd = rates.clone
|
46
|
+
rates[key] ? rates[key] : nil
|
47
|
+
rescue => err
|
48
|
+
puts "Err #{err}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def dump_history
|
52
|
+
load_history_info
|
53
|
+
FileUtils.makedirs('output') unless File.directory?('output')
|
54
|
+
CSV.open('output/trade_history.csv','w+',
|
55
|
+
:col_sep => ';',
|
56
|
+
:write_headers=> true,
|
57
|
+
:headers => [ 'currency_pair'] + @trade_history.values.first.first.to_h.keys
|
58
|
+
) do |csv|
|
59
|
+
@trade_history.each do |currency_pair, trades|
|
60
|
+
trades.each do |trace|
|
61
|
+
csv << [ currency_pair] + trace.to_h.values
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
CSV.open('output/lending_history.csv','w+',
|
66
|
+
:col_sep => ';',
|
67
|
+
:write_headers=> true,
|
68
|
+
:headers => @lending_history.first.to_h.keys
|
69
|
+
) do |csv|
|
70
|
+
@lending_history.each do |info|
|
71
|
+
csv << info.to_h.values
|
72
|
+
end
|
73
|
+
end
|
74
|
+
CSV.open('output/tradable_balances.csv','w+',
|
75
|
+
:col_sep => ';',
|
76
|
+
:write_headers=> true,
|
77
|
+
:headers => [ 'from_currency', 'to_from_currency', ]
|
78
|
+
) do |csv|
|
79
|
+
@tradable_balances.each do |currency_pair, balance|
|
80
|
+
balance.each do |info|
|
81
|
+
csv << [ currency_pair] + info
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
CSV.open('output/complete_balances.csv', 'w+',
|
86
|
+
:col_sep => ';',
|
87
|
+
:write_headers=> true,
|
88
|
+
:headers => [ 'currency', 'available', 'onOrders', 'btcValue' ]
|
89
|
+
) do |csv|
|
90
|
+
@complete_balances.each do |balance|
|
91
|
+
csv << [balance[0]] + balance[1].values
|
92
|
+
end
|
93
|
+
end
|
94
|
+
CSV.open('output/active_loans.csv', 'w+',
|
95
|
+
:col_sep => ';',
|
96
|
+
:write_headers=> true,
|
97
|
+
:headers => [ 'key', 'id', 'currency', 'rate', 'amount', 'duration', 'autoRenew', 'date', 'fees', ]
|
98
|
+
) do |csv|
|
99
|
+
@active_loans.each do |key, loans|
|
100
|
+
loans.each do | loan |
|
101
|
+
csv << [key] + loan.values
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
CSV.open('output/available_account_balances.csv', 'w+',
|
107
|
+
:col_sep => ';',
|
108
|
+
:write_headers=> true,
|
109
|
+
:headers => [ 'key', 'currency', 'balance']
|
110
|
+
) do |csv|
|
111
|
+
@available_account_balances.each do |key, balances|
|
112
|
+
balances.each do |currency, balance|
|
113
|
+
csv << [key, currency, balance]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
CSV.open('output/deposit_addresses.csv', 'w+',
|
118
|
+
:col_sep => ';',
|
119
|
+
:write_headers=> true,
|
120
|
+
:headers => [ 'currency', 'id']
|
121
|
+
) do |csv|
|
122
|
+
@deposit_addresses.each do |currency, id|
|
123
|
+
csv << [currency, id]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
CSV.open('output/withdrawals.csv','w+',
|
127
|
+
:col_sep => ';',
|
128
|
+
:write_headers=> true,
|
129
|
+
:headers => @deposits.first.to_h.keys
|
130
|
+
) do |csv|
|
131
|
+
@deposits.each do |info|
|
132
|
+
csv << info.to_h.values
|
133
|
+
end
|
134
|
+
end
|
135
|
+
CSV.open('output/deposits.csv','w+',
|
136
|
+
:col_sep => ';',
|
137
|
+
:write_headers=> true,
|
138
|
+
:headers => @withdrawals.first.to_h.keys
|
139
|
+
) do |csv|
|
140
|
+
@withdrawals.each do |info|
|
141
|
+
csv << info.to_h.values
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def find_per_currency_and_day(items, currency, date)
|
147
|
+
puts "Searching for #{currency} in day #{date}" if $VERBOSE
|
148
|
+
start_time = date.to_time.to_i
|
149
|
+
end_time = (date + 1).to_time.to_i
|
150
|
+
found = items.find_all{|item| item.currency.eql?(currency) && item.timestamp >= start_time && item.timestamp < end_time}
|
151
|
+
puts "find_per_currency_and_day: found #{found.size} #{found.first} #{found.last}" if $VERBOSE
|
152
|
+
found
|
153
|
+
end
|
154
|
+
|
155
|
+
def find_lending_info_day(currency, date)
|
156
|
+
puts "Searching lending (close) for #{currency} in day #{date}" if $VERBOSE
|
157
|
+
found = @lending_history.find_all { |item| item.currency.eql?(currency) && date.eql?(Date.parse(item.close)) }
|
158
|
+
puts "find_lending_info_day: found #{found.size} #{found.first} #{found.last}" if $VERBOSE
|
159
|
+
found
|
160
|
+
end
|
161
|
+
|
162
|
+
# type is either buy or sell
|
163
|
+
def find_day_trade(currency, date, type)
|
164
|
+
found = []
|
165
|
+
@trade_history.each do |currency_pair, trades|
|
166
|
+
next unless /^#{currency}/.match(currency_pair)
|
167
|
+
trades.each do |trade|
|
168
|
+
if trade.type.eql?(type) && date.eql?(Date.parse(trade.date))
|
169
|
+
trade.cucurrency_pair = currency_pair
|
170
|
+
found << trade
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
puts "find_day_trade: #{date} #{currency} found #{found.size}" if $VERBOSE
|
175
|
+
found
|
176
|
+
end
|
177
|
+
def create_csv_file
|
178
|
+
binding.pry
|
179
|
+
puts "create_csv_file: already done"
|
180
|
+
end
|
181
|
+
|
182
|
+
def fetch_csv_history
|
183
|
+
load_history_info
|
184
|
+
@trade_history.values.collect{|values| values.collect{|x| x.date} }.max
|
185
|
+
|
186
|
+
max_time = [ @deposits.collect{|x| x.timestamp}.max,
|
187
|
+
Time.parse(@trade_history.values.collect{|values| values.collect{|x| x.date} }.max.max).to_i,
|
188
|
+
Time.parse(@lending_history.collect{|x| x.close}.max).to_i,
|
189
|
+
@withdrawals.collect{|x| x.timestamp}.max,].max
|
190
|
+
min_time = [ @deposits.collect{|x| x.timestamp}.min,
|
191
|
+
Time.parse(@trade_history.values.collect{|values| values.collect{|x| x.date} }.min.min).to_i,
|
192
|
+
Time.parse(@lending_history.collect{|x| x.close}.min).to_i,
|
193
|
+
@withdrawals.collect{|x| x.timestamp}.min,].min
|
194
|
+
|
195
|
+
min_date = Time.at(min_time).to_date
|
196
|
+
max_date = Time.at(max_time).to_date
|
197
|
+
|
198
|
+
puts "We start using the available_account_balances"
|
199
|
+
pp @available_account_balances
|
200
|
+
puts
|
201
|
+
puts "Should we better start using the complete_balances"
|
202
|
+
pp @complete_balances
|
203
|
+
puts "How should I handle the following currency_pair"
|
204
|
+
pp @trade_history.keys
|
205
|
+
@available_account_balances.each do |key, balances|
|
206
|
+
balances.each do |currency, balance|
|
207
|
+
puts "Calculation history for #{key} #{currency} with current balance of #{balance}"
|
208
|
+
out_name = "output/poloniex/#{key}_#{currency}.csv"
|
209
|
+
FileUtils.makedirs(File.dirname(out_name)) unless File.exists?(File.dirname(out_name))
|
210
|
+
@history = []
|
211
|
+
current_day = max_date
|
212
|
+
current_balance = balance.to_f
|
213
|
+
while (current_day >= min_date)
|
214
|
+
entry = OpenStruct.new
|
215
|
+
entry.current_day = current_day
|
216
|
+
entry.current_balance = current_balance
|
217
|
+
|
218
|
+
deposits = find_per_currency_and_day(@deposits, currency,current_day)
|
219
|
+
sum_deposits = 0.0; deposits.each{ |x| sum_deposits += x.amount.to_f }
|
220
|
+
entry.deposits = sum_deposits
|
221
|
+
|
222
|
+
withdrawals = find_per_currency_and_day(@withdrawals, currency, current_day)
|
223
|
+
sum_withdrawals = 0.0; withdrawals.each{ |x| sum_withdrawals += x.amount.to_f }
|
224
|
+
entry.withdrawals = sum_withdrawals
|
225
|
+
|
226
|
+
lendings = find_lending_info_day(currency, current_day)
|
227
|
+
earned = 0.0; sum_fee = 0.0; lendings.each{ |x| earned += x.earned.to_f; sum_fee += x.fee.to_f }
|
228
|
+
entry.earned = earned
|
229
|
+
entry.fees = sum_fee
|
230
|
+
|
231
|
+
# End_of_Day_Balance = End_of_Day_Balance(-1) + Deposits - Withdrawals + Lending_Income - Trading_Fees + Purchases - Sales
|
232
|
+
sales = find_day_trade(currency, current_day, 'sell')
|
233
|
+
sum_sales = 0.0; sales.each{ |sale| sum_sales += sale.amount.to_f }
|
234
|
+
entry.sales = sum_sales
|
235
|
+
|
236
|
+
purchases = find_day_trade(currency, current_day, 'buy')
|
237
|
+
sum_purchase = 0.0; purchases.each{ |purchase| sum_purchase += purchase.amount.to_f }
|
238
|
+
entry.purchases = sum_purchase
|
239
|
+
entry.day_difference = sum_deposits - sum_withdrawals + sum_purchase - sum_sales + sum_fee
|
240
|
+
@history << entry
|
241
|
+
current_day -= 1
|
242
|
+
# balance for previous day
|
243
|
+
current_balance = entry.current_balance - entry.day_difference
|
244
|
+
end
|
245
|
+
next unless @history.size > 0
|
246
|
+
CSV.open(out_name,'w+',
|
247
|
+
:col_sep => ';',
|
248
|
+
:write_headers=> true,
|
249
|
+
:headers => @history.first.to_h.keys
|
250
|
+
) do |csv|
|
251
|
+
@history.each do |info|
|
252
|
+
csv << info.to_h.values
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
private
|
259
|
+
def check_config
|
260
|
+
@spec_data = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec', 'data'))
|
261
|
+
['poloniex_api_key',
|
262
|
+
'poloniex_secret',
|
263
|
+
].each do |item|
|
264
|
+
raise "Must define #{item} in config.yml" unless Config[item]
|
265
|
+
end
|
266
|
+
::Poloniex.setup do | config |
|
267
|
+
config.key = Config['poloniex_api_key']
|
268
|
+
config.secret = Config['poloniex_secret']
|
269
|
+
end
|
270
|
+
nil
|
271
|
+
end
|
272
|
+
private
|
273
|
+
def load_or_save_json(name, param = nil)
|
274
|
+
json_file = File.join(@spec_data, name.to_s + '.json')
|
275
|
+
if File.exist?(json_file) && defined?(RSpec)
|
276
|
+
body = IO.read(json_file)
|
277
|
+
else
|
278
|
+
cmd = param ? "::Poloniex.#{name.to_s}('#{param}').body" : "::Poloniex.#{name.to_s}.body"
|
279
|
+
body = eval(cmd)
|
280
|
+
File.open(json_file, 'w+') { |f| f.write(body)}
|
281
|
+
end
|
282
|
+
eval("@#{name} = JSON.parse(body)")
|
283
|
+
end
|
284
|
+
def load_history_info
|
285
|
+
check_config
|
286
|
+
begin
|
287
|
+
@balances = load_or_save_json(:balances)
|
288
|
+
rescue => error
|
289
|
+
puts "Error was #{error.inspect}"
|
290
|
+
puts "Calling @balances from poloniex failed. Configuration was"
|
291
|
+
pp ::Poloniex.configuration
|
292
|
+
exit 1
|
293
|
+
end
|
294
|
+
@active_loans = load_or_save_json(:active_loans)
|
295
|
+
@available_account_balances = load_or_save_json(:available_account_balances)
|
296
|
+
all = load_or_save_json(:complete_balances)
|
297
|
+
@complete_balances = all.find_all{ | currency, values| values["available"].to_f != 0.0 }
|
298
|
+
@deposit_addresses = load_or_save_json(:deposit_addresses)
|
299
|
+
|
300
|
+
@deposits_withdrawals = load_or_save_json(:deposits_withdrawls)
|
301
|
+
# deposits and withdrawals have a different structure
|
302
|
+
@deposits = []
|
303
|
+
@deposits_withdrawals['deposits'].each {|x| @deposits << OpenStruct.new(x) };
|
304
|
+
@withdrawals =[]
|
305
|
+
@deposits_withdrawals['withdrawals'].each {|x| @withdrawals << OpenStruct.new(x) };
|
306
|
+
info = load_or_save_json(:lending_history)
|
307
|
+
@lending_history = []
|
308
|
+
info.each {|x| @lending_history << OpenStruct.new(x) };
|
309
|
+
|
310
|
+
@open_orders = load_or_save_json(:open_orders, 'all')
|
311
|
+
info = load_or_save_json(:trade_history, 'all')
|
312
|
+
@trade_history = {}
|
313
|
+
info.each do |currency_pair, trades|
|
314
|
+
@trade_history[currency_pair] = []
|
315
|
+
trades.each {|x| @trade_history[currency_pair] << OpenStruct.new(x) };
|
316
|
+
@trade_history[currency_pair].sort!{|x,y| x[:date] <=> y[:date]}.collect{ |x| x[:date]}
|
317
|
+
end
|
318
|
+
# @trade_history.values.first.first.tradeID
|
319
|
+
@tradable_balances = load_or_save_json(:tradable_balances)
|
320
|
+
@active_loans # key
|
321
|
+
@provided_loans = []; @active_loans['provided'].each {|x| @provided_loans << OpenStruct.new(x) };
|
322
|
+
@used_loans = []; @active_loans['used'].each {|x| @used_loans << OpenStruct.new(x) };
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
data/lib/rapflag/version.rb
CHANGED
data/rapflag.gemspec
CHANGED
@@ -0,0 +1,128 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'rapflag/bitfinex'
|
4
|
+
require 'vcr'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
VCR.configure do |config|
|
8
|
+
config.cassette_library_dir = "fixtures/vcr_cassettes"
|
9
|
+
config.hook_into :faraday # or :fakeweb
|
10
|
+
end
|
11
|
+
|
12
|
+
VCR.eject_cassette # we use insert/eject around each example
|
13
|
+
describe RAPFLAG::Bitfinex do
|
14
|
+
OUTPUT_ROOT = File.expand_path(File.join(__FILE__, '..', '..', 'output', 'bitfinex'))
|
15
|
+
Bitfinex_CSV_Test_File = OUTPUT_ROOT + '/BTC_exchange.csv'
|
16
|
+
BITFINEX_SUMMARY_EXCHANGE_BTC_File = OUTPUT_ROOT + '/BTC_exchange_summary.csv'
|
17
|
+
BITFINEX_SUMMARY_DEPOSIT_BFX_File = OUTPUT_ROOT + '/BFX_deposit_summary.csv'
|
18
|
+
|
19
|
+
# include ServerMockHelper
|
20
|
+
before(:all) do
|
21
|
+
end
|
22
|
+
after(:all) do
|
23
|
+
end
|
24
|
+
context 'bitfinex' do
|
25
|
+
before(:all) do
|
26
|
+
VCR.use_cassette("rapflag", :record => :new_episodes) do
|
27
|
+
FileUtils.rm_f(Bitfinex_CSV_Test_File) if File.exist?(Bitfinex_CSV_Test_File)
|
28
|
+
FileUtils.rm_f(BITFINEX_SUMMARY_DEPOSIT_BFX_File) if File.exist?(BITFINEX_SUMMARY_DEPOSIT_BFX_File)
|
29
|
+
FileUtils.rm_f(BITFINEX_SUMMARY_EXCHANGE_BTC_File) if File.exist?(Bitfinex_CSV_Test_File)
|
30
|
+
expect(File.exist?(Bitfinex_CSV_Test_File)).to eql(false)
|
31
|
+
@rap = RAPFLAG::Bitfinex.new('exchange', 'BTC')
|
32
|
+
@rap.fetch_csv_history
|
33
|
+
@rap.create_csv_file
|
34
|
+
end
|
35
|
+
end
|
36
|
+
context 'history' do
|
37
|
+
it 'should have correct currency' do
|
38
|
+
expect(@rap.currency).to eql('BTC')
|
39
|
+
end
|
40
|
+
it 'should have correct size' do
|
41
|
+
expect(@rap.history.size).to eql(206)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
context 'bitfinex CSV' do
|
46
|
+
context 'csv' do
|
47
|
+
it 'should have generated a correct CSV file' do
|
48
|
+
expect(File.exist?(Bitfinex_CSV_Test_File)).to eql(true)
|
49
|
+
lines = IO.readlines(Bitfinex_CSV_Test_File)
|
50
|
+
expect(lines.first.chomp).to eql('currency;amount;balance;description;date_time')
|
51
|
+
expect(lines[1].chomp).to eql(
|
52
|
+
'BTC;-0.00000005;0.0;Transfer of 0.0 BTC from wallet Exchange to Deposit on wallet Exchange;2016.12.03 21:20:47')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
context 'exchange option --clean' do
|
57
|
+
before(:all) do
|
58
|
+
@date_bfx_1 = Date.new(2017,1,10)
|
59
|
+
@date_btx_1 = Date.new(2017,1,21)
|
60
|
+
@date_btx_2 = Date.new(2017,1,10)
|
61
|
+
VCR.use_cassette("rapflag", :record => :new_episodes) do
|
62
|
+
FileUtils.rm_f(BITFINEX_SUMMARY_EXCHANGE_BTC_File) if File.exist?(Bitfinex_CSV_Test_File)
|
63
|
+
expect(File.exist?(BITFINEX_SUMMARY_EXCHANGE_BTC_File)).to eql(false)
|
64
|
+
@exchange = RAPFLAG::Bitfinex.new('exchange', 'BTC')
|
65
|
+
@exchange.fetch_csv_history
|
66
|
+
@exchange.create_summary
|
67
|
+
@bfx = @exchange.get_usd_exchange(@date_bfx_1, 'BFX')
|
68
|
+
@btx_1 = @exchange.get_usd_exchange(@date_btx_1, 'BTC')
|
69
|
+
@btx_2 = @exchange.get_usd_exchange(@date_btx_2, 'BTC')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
it 'should have generated a correct summary CSV file' do
|
73
|
+
expect(File.exist?(BITFINEX_SUMMARY_EXCHANGE_BTC_File)).to eql(true)
|
74
|
+
lines = IO.readlines(BITFINEX_SUMMARY_EXCHANGE_BTC_File)
|
75
|
+
expect(lines.first.chomp).to eql('currency;date;income;balance;rate;balance_in_usd')
|
76
|
+
expect(lines[1].chomp).to eql('BTC;2016.01.15;0.0;8.99788147;;')
|
77
|
+
expect(lines[-1].chomp).to eql('BTC;2016.12.03;0.0;0.0;765.46;0.0')
|
78
|
+
end
|
79
|
+
it 'should have a balance for for each day' do
|
80
|
+
expect(File.exist?(BITFINEX_SUMMARY_EXCHANGE_BTC_File)).to eql(true)
|
81
|
+
lines = IO.readlines(BITFINEX_SUMMARY_EXCHANGE_BTC_File)
|
82
|
+
first_date = Date.strptime(lines[1].chomp.split(';')[1], '%Y.%m.%d')
|
83
|
+
last_date = Date.strptime(lines[-1].chomp.split(';')[1], '%Y.%m.%d')
|
84
|
+
(last_date > first_date).should be true
|
85
|
+
nr_dates = 323
|
86
|
+
(last_date - first_date).to_i.should eql nr_dates
|
87
|
+
(1..nr_dates).each do |j|
|
88
|
+
wish_date = (first_date + j).strftime('%Y.%m.%d')
|
89
|
+
binding.pry unless lines.find_all{|line| line.index(wish_date)}.size == 1
|
90
|
+
lines.find_all{|line| line.index(wish_date)}.size.should eql 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
it 'should have NOT have generated a correct summary deposit BFX CSV file' do
|
94
|
+
expect(File.exist?(BITFINEX_SUMMARY_DEPOSIT_BFX_File)).to eql(false)
|
95
|
+
end
|
96
|
+
it 'should have the correct BTC -> USD rate' do
|
97
|
+
expect(@btx_1).to eql 924.02
|
98
|
+
expect(@btx_2).to eql 905.76
|
99
|
+
end
|
100
|
+
it 'should have the correct BFX -> USD rate' do
|
101
|
+
expect(@bfx).to eql 0.5697
|
102
|
+
end
|
103
|
+
end
|
104
|
+
context 'deposit option --clean' do
|
105
|
+
before(:all) do
|
106
|
+
FileUtils.rm_f(BITFINEX_SUMMARY_EXCHANGE_BTC_File) if File.exist?(BITFINEX_SUMMARY_EXCHANGE_BTC_File)
|
107
|
+
FileUtils.rm_f(BITFINEX_SUMMARY_DEPOSIT_BFX_File) if File.exist?(Bitfinex_CSV_Test_File)
|
108
|
+
@date_bfx_1 = Date.new(2017,1,10)
|
109
|
+
@date_btx_1 = Date.new(2017,1,21)
|
110
|
+
@date_btx_2 = Date.new(2017,1,10)
|
111
|
+
VCR.use_cassette("rapflag", :record => :new_episodes) do
|
112
|
+
expect(File.exist?(BITFINEX_SUMMARY_DEPOSIT_BFX_File)).to eql(false)
|
113
|
+
@deposit = RAPFLAG::Bitfinex.new('deposit', 'BFX')
|
114
|
+
@deposit.fetch_csv_history
|
115
|
+
@deposit.create_summary
|
116
|
+
end
|
117
|
+
end
|
118
|
+
it 'should have NOT generated a exchange BTC summary CSV file' do
|
119
|
+
expect(File.exist?(BITFINEX_SUMMARY_EXCHANGE_BTC_File)).to eql(false)
|
120
|
+
end
|
121
|
+
it 'should have NOT generated a correct summary CSV file' do
|
122
|
+
expect(File.exist?(BITFINEX_SUMMARY_DEPOSIT_BFX_File)).to eql(true)
|
123
|
+
lines = IO.readlines(BITFINEX_SUMMARY_DEPOSIT_BFX_File)
|
124
|
+
expect(lines.first.chomp).to eql('currency;date;income;balance;rate;balance_in_usd')
|
125
|
+
expect(lines[1].chomp).to eql('BFX;2016.01.15;0.0;8.99788147;;')
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'rapflag/poloniex'
|
4
|
+
require 'vcr'
|
5
|
+
|
6
|
+
VCR.configure do |config|
|
7
|
+
config.cassette_library_dir = "fixtures/vcr_cassettes"
|
8
|
+
config.hook_into :faraday
|
9
|
+
end
|
10
|
+
|
11
|
+
VCR.eject_cassette # we use insert/eject around each example
|
12
|
+
|
13
|
+
describe RAPFLAG::Poloniex do
|
14
|
+
TEST_OUTPUT_ROOT = File.expand_path(File.join(__FILE__, '..', '..', 'output/poloniex'))
|
15
|
+
Poloniex_CSV_Test_File = TEST_OUTPUT_ROOT + '/BTC_exchange.csv'
|
16
|
+
Poloniex_SUMMARY_EXCHANGE_BTC_File = TEST_OUTPUT_ROOT + '/BTC_exchange_summary.csv'
|
17
|
+
Poloniex_SUMMARY_DEPOSIT_BFX_File = TEST_OUTPUT_ROOT + '/BFX_deposit_summary.csv'
|
18
|
+
|
19
|
+
context 'poloniex' do
|
20
|
+
before(:all) do
|
21
|
+
# skip("We cannot yet use VCR here. Therefore omitting all spec tests")
|
22
|
+
# VCR.use_cassette("poloniex", :record => :new_episodes) do
|
23
|
+
FileUtils.rm_f(Poloniex_CSV_Test_File) if File.exist?(Poloniex_CSV_Test_File)
|
24
|
+
FileUtils.rm_f(Poloniex_SUMMARY_DEPOSIT_BFX_File) if File.exist?(Poloniex_SUMMARY_DEPOSIT_BFX_File)
|
25
|
+
FileUtils.rm_f(Poloniex_SUMMARY_EXCHANGE_BTC_File) if File.exist?(Poloniex_CSV_Test_File)
|
26
|
+
expect(File.exist?(Poloniex_CSV_Test_File)).to eql(false)
|
27
|
+
@rap = RAPFLAG::Poloniex.new('exchange', 'BTC')
|
28
|
+
@rap.fetch_csv_history
|
29
|
+
# @rap.create_csv_file
|
30
|
+
# end
|
31
|
+
end
|
32
|
+
context 'history' do
|
33
|
+
it 'should have correct currency' do
|
34
|
+
expect(@rap.currency).to eql('BTC')
|
35
|
+
end
|
36
|
+
it 'should have correct size' do
|
37
|
+
expect(@rap.history.size).to eql(368)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
context 'poloniex CSV' do
|
42
|
+
before(:all) do
|
43
|
+
skip("We cannot yet use VCR here. Therefore omitting all spec tests")
|
44
|
+
end
|
45
|
+
context 'csv' do
|
46
|
+
it 'should have generated a correct CSV file' do
|
47
|
+
expect(File.exist?(Poloniex_CSV_Test_File)).to eql(true)
|
48
|
+
lines = IO.readlines(Poloniex_CSV_Test_File)
|
49
|
+
expect(lines.first.chomp).to eql('currency,amount,balance,description,date_time')
|
50
|
+
expect(lines[1].chomp).to eql(
|
51
|
+
'BTC,-0.00000005,0.0,Transfer of 0.0 BTC from wallet Exchange to Deposit on wallet Exchange,2016.12.03 21:20:47')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
context 'exchange option --clean' do
|
56
|
+
before(:all) do
|
57
|
+
skip("We cannot yet use VCR here. Therefore omitting all spec tests")
|
58
|
+
@date_bfx_1 = Date.new(2017,1,10)
|
59
|
+
@date_btx_1 = Date.new(2017,1,21)
|
60
|
+
@date_btx_2 = Date.new(2017,1,10)
|
61
|
+
VCR.use_cassette("poloniex", :record => :new_episodes) do
|
62
|
+
FileUtils.rm_f(Poloniex_SUMMARY_EXCHANGE_BTC_File) if File.exist?(Poloniex_CSV_Test_File)
|
63
|
+
expect(File.exist?(Poloniex_SUMMARY_EXCHANGE_BTC_File)).to eql(false)
|
64
|
+
@exchange = RAPFLAG::Poloniex.new('exchange', 'BTC')
|
65
|
+
@exchange.fetch_csv_history
|
66
|
+
@exchange.create_summary
|
67
|
+
@bfx = @exchange.get_usd_exchange(@date_bfx_1, 'BFX')
|
68
|
+
@btx_1 = @exchange.get_usd_exchange(@date_btx_1, 'BTC')
|
69
|
+
@btx_2 = @exchange.get_usd_exchange(@date_btx_2, 'BTC')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
it 'should have generated a correct summary CSV file' do
|
73
|
+
expect(File.exist?(Poloniex_SUMMARY_EXCHANGE_BTC_File)).to eql(true)
|
74
|
+
lines = IO.readlines(Poloniex_SUMMARY_EXCHANGE_BTC_File)
|
75
|
+
expect(lines.first.chomp).to eql('currency,date,income,balance,rate,balance_in_usd')
|
76
|
+
expect(lines[1].chomp).to eql('BTC,2016.01.15,0.0,8.99788147,,')
|
77
|
+
expect(lines[-1].chomp).to eql('BTC,2016.12.03,0.0,0.0,765.46,0.0')
|
78
|
+
end
|
79
|
+
it 'should have NOT have generated a correct summary deposit BFX CSV file' do
|
80
|
+
expect(File.exist?(Poloniex_SUMMARY_DEPOSIT_BFX_File)).to eql(false)
|
81
|
+
end
|
82
|
+
it 'should have the correct BTC -> USD rate' do
|
83
|
+
expect(@btx_1).to eql 924.02
|
84
|
+
expect(@btx_2).to eql 905.76
|
85
|
+
end
|
86
|
+
it 'should have the correct BFX -> USD rate' do
|
87
|
+
expect(@bfx).to eql 0.5697
|
88
|
+
end
|
89
|
+
end
|
90
|
+
context 'deposit option --clean' do
|
91
|
+
before(:all) do
|
92
|
+
skip("We cannot yet use VCR here. Therefore omitting all spec tests")
|
93
|
+
FileUtils.rm_f(Poloniex_SUMMARY_EXCHANGE_BTC_File) if File.exist?(Poloniex_SUMMARY_EXCHANGE_BTC_File)
|
94
|
+
FileUtils.rm_f(Poloniex_SUMMARY_DEPOSIT_BFX_File) if File.exist?(Poloniex_CSV_Test_File)
|
95
|
+
@date_bfx_1 = Date.new(2017,1,10)
|
96
|
+
@date_btx_1 = Date.new(2017,1,21)
|
97
|
+
@date_btx_2 = Date.new(2017,1,10)
|
98
|
+
VCR.use_cassette("rapflag", :record => :new_episodes) do
|
99
|
+
expect(File.exist?(Poloniex_SUMMARY_DEPOSIT_BFX_File)).to eql(false)
|
100
|
+
@deposit = RAPFLAG::Poloniex.new('deposit', 'BFX')
|
101
|
+
@deposit.fetch_csv_history
|
102
|
+
@deposit.create_summary
|
103
|
+
end
|
104
|
+
end
|
105
|
+
it 'should have NOT generated a exchange BTC summary CSV file' do
|
106
|
+
expect(File.exist?(Poloniex_SUMMARY_EXCHANGE_BTC_File)).to eql(false)
|
107
|
+
end
|
108
|
+
it 'should have NOT generated a correct summary CSV file' do
|
109
|
+
expect(File.exist?(Poloniex_SUMMARY_DEPOSIT_BFX_File)).to eql(true)
|
110
|
+
lines = IO.readlines(Poloniex_SUMMARY_DEPOSIT_BFX_File)
|
111
|
+
expect(lines.first.chomp).to eql('currency,date,income,balance,rate,balance_in_usd')
|
112
|
+
expect(lines[1].chomp).to eql('BFX,2016.01.15,0.0,8.99788147,,')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,7 +4,9 @@ rescue LOAD_ERROR
|
|
4
4
|
end
|
5
5
|
|
6
6
|
require 'rapflag/version'
|
7
|
+
require 'rapflag/config'
|
7
8
|
require 'bitfinex-api-rb'
|
9
|
+
require 'poloniex'
|
8
10
|
|
9
11
|
module RAPFLAG
|
10
12
|
# create dummy config for spec tests
|
@@ -13,6 +15,10 @@ module RAPFLAG
|
|
13
15
|
conf.secret = 'SECRECT_KEY'
|
14
16
|
conf.websocket_api_endpoint = 'wss://api.bitfinex.com/ws'
|
15
17
|
end
|
18
|
+
Poloniex.setup do | config |
|
19
|
+
config.key = 'P_123467889'
|
20
|
+
config.secret = 'P_SECRECT_KEY'
|
21
|
+
end
|
16
22
|
end
|
17
23
|
|
18
24
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rapflag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zeno R.R. Davatz, Niklaus Giger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: poloniex
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bitfinex-rb
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,16 +147,20 @@ files:
|
|
133
147
|
- ".rspec"
|
134
148
|
- ".travis.yml"
|
135
149
|
- Gemfile
|
150
|
+
- History.md
|
136
151
|
- LICENSE
|
137
152
|
- README.md
|
138
153
|
- Rakefile
|
139
154
|
- bin/rapflag
|
140
155
|
- fixtures/vcr_cassettes/rapflag.yml
|
156
|
+
- lib/rapflag/bitfinex.rb
|
141
157
|
- lib/rapflag/config.rb
|
142
|
-
- lib/rapflag/
|
158
|
+
- lib/rapflag/history.rb
|
159
|
+
- lib/rapflag/poloniex.rb
|
143
160
|
- lib/rapflag/version.rb
|
144
161
|
- rapflag.gemspec
|
145
|
-
- spec/
|
162
|
+
- spec/bitfinex_spec.rb
|
163
|
+
- spec/poloniex_spec.rb
|
146
164
|
- spec/spec_helper.rb
|
147
165
|
homepage: https://github.com/zdavatz/rapflag
|
148
166
|
licenses:
|
@@ -169,5 +187,6 @@ signing_key:
|
|
169
187
|
specification_version: 4
|
170
188
|
summary: Bitfinex Exporter for your Taxman from ywesee
|
171
189
|
test_files:
|
172
|
-
- spec/
|
190
|
+
- spec/bitfinex_spec.rb
|
191
|
+
- spec/poloniex_spec.rb
|
173
192
|
- spec/spec_helper.rb
|