rapflag 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rapflag/fetch.rb DELETED
@@ -1,176 +0,0 @@
1
- require 'csv'
2
- require 'open-uri'
3
- require 'faraday'
4
- require 'fileutils'
5
-
6
- module RAPFLAG
7
-
8
- class History
9
- attr_reader :history, :wallet, :currency, :btc_to_usd, :bfx_to_usd
10
- DATE_FORMAT = '%Y.%m.%d'
11
- DATE_TIME_FORMAT = '%Y.%m.%d %H:%M:%S'
12
- @@btc_to_usd = {}
13
- @@bfx_to_usd = {}
14
-
15
- def initialize(wallet = 'trading', currency = 'USD')
16
- @wallet = wallet
17
- @currency = currency
18
- end
19
-
20
- def get_usd_exchange(date_time = Time.now, from='BTC')
21
- return 1.0 if from == 'USD'
22
- key = date_time.strftime(DATE_FORMAT)
23
- return @@btc_to_usd[key] if from.eql?('BTC') && @@btc_to_usd.size > 0
24
- return @@bfx_to_usd[key] if from.eql?('BFX') && @@bfx_to_usd.size > 0
25
-
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
- # http://docs.bitfinex.com/v2/reference#rest-public-candles
43
- # field definitions for [ MTS, OPEN, CLOSE, HIGH, LOW, VOLUME ],
44
- # MTS int millisecond time stamp
45
- # OPEN float First execution during the time frame
46
- # CLOSE float Last execution during the time frame
47
- # HIGH integer Highest execution during the time frame
48
- # LOW float Lowest execution during the timeframe
49
- # VOLUME float Quantity of symbol traded within the timeframe
50
- # [[1489363200000,1224.4,1211.2,1238,1206.7,6157.96283895],
51
- timestamp = Time.at(item.first/1000).strftime(DATE_FORMAT)
52
- rates[timestamp] = item[2]
53
- end;
54
- from.eql?('BTC') ? @@btc_to_usd = rates.clone : @@bfx_to_usd = rates.clone
55
- rates[key] ? rates[key] : nil
56
- rescue => err
57
- puts "Err #{err}"
58
- binding.pry if defined?(MiniTest)
59
- end
60
-
61
- def fetch_csv_history
62
- client = Bitfinex::Client.new
63
- @history = []
64
- timestamp = Time.now.to_i + 1
65
- while true
66
- begin
67
- partial = client.history(@currency, { :limit => 500, :until => timestamp, :wallet => @wallet})
68
- break unless partial && partial.size > 0
69
- if partial.is_a?(Hash)
70
- puts "Got #{partial['error']} while fetching #{@wallet} #{@currency} until #{Time.at(timestamp)}"
71
- exit 3
72
- end
73
- first_time = Time.at(partial.first['timestamp'].to_i).strftime(DATE_TIME_FORMAT)
74
- last_time = Time.at(partial.last['timestamp'].to_i).strftime(DATE_TIME_FORMAT)
75
- puts "Feched #{partial.size} @history entries #{first_time} -> #{last_time}" if $VERBOSE
76
- timestamp = (partial.last['timestamp'].to_i - 1)
77
- @history = @history | partial
78
- break if partial.size <= 1
79
- rescue => error
80
- puts "error #{error}"
81
- end
82
- end
83
- puts "Feched #{@history.size} history entries" if $VERBOSE
84
- end
85
-
86
- # Configure the client with the proper KEY/SECRET, you can create a new one from:
87
- # https://www.bitfinex.com/api
88
- def create_csv_file
89
- out_file = "output/#{@wallet}_#{@currency}.csv"
90
- FileUtils.makedirs(File.dirname(out_file))
91
- CSV.open(out_file,'w',
92
- :write_headers=> true,
93
- :headers => ['currency',
94
- 'amount',
95
- 'balance',
96
- 'description',
97
- 'date_time',
98
- ] #< column header
99
- ) do |csv|
100
- @history.each do | hist_item|
101
- csv << [ hist_item['currency'],
102
- hist_item['amount'],
103
- hist_item['balance'],
104
- hist_item['description'],
105
- Time.at(hist_item['timestamp'].to_i).strftime(DATE_TIME_FORMAT),
106
- ]
107
- end
108
- end
109
-
110
- sums = {}
111
- @history.each do | hist_item|
112
- key = /^[^\d]+/.match(hist_item['description'])[0].chomp
113
- value = hist_item['amount'].to_f
114
- if sums[key]
115
- sums[key] += value
116
- else
117
- sums[key] = value
118
- end
119
- end
120
-
121
- puts
122
- puts "Summary for #{@wallet} #{@currency} (#{@history.size} entries}"
123
- sums.each do |key, value|
124
- puts " #{sprintf('%40s', key)} is #{value}"
125
- end
126
- end
127
-
128
- Struct.new("Daily", :date, :amount, :balance, :description, :income)
129
- def create_summary
130
- @daily = {}
131
- @history.sort{|x,y| x['timestamp'] <=> y['timestamp']}.each do | hist_item|
132
- date = Time.at(hist_item['timestamp'].to_i).strftime(DATE_FORMAT)
133
- info = Struct::Daily.new(date, hist_item['amount'].to_f, hist_item['balance'].to_f, hist_item['description'])
134
- amount = hist_item['amount'].to_f
135
- balance = hist_item['balance'].to_f
136
- if @daily[date]
137
- old_balance = @daily[date]
138
- existing = @daily[date]
139
- else
140
- info.income = 0.0
141
- existing = info
142
- end
143
- if /Wire Withdrawal fee|Trading fees for|Margin Funding Payment on wallet/i.match( hist_item['description'])
144
- existing.income += amount
145
- end
146
- existing.balance = balance if balance != 0.0
147
- @daily[date] = existing
148
- end
149
- out_file = "output/#{@wallet}_#{@currency}_summary.csv"
150
- FileUtils.makedirs(File.dirname(out_file))
151
- CSV.open(out_file,'w',
152
- :write_headers=> true,
153
- :headers => ['currency',
154
- 'date',
155
- 'income',
156
- 'balance',
157
- 'rate',
158
- 'balance_in_usd',
159
- ] #< column header
160
- ) do |csv|
161
- @daily.each do |date, info|
162
- strings = date.split('.')
163
- fetch_date = Date.new(strings[0].to_i, strings[1].to_i, strings[2].to_i)
164
- rate = get_usd_exchange(fetch_date, @currency)
165
- csv << [@currency,
166
- date,
167
- info.income,
168
- info.balance,
169
- rate ? rate : nil,
170
- rate ? info.balance * get_usd_exchange(fetch_date, @currency) : nil,
171
- ]
172
- end
173
- end
174
- end
175
- end
176
- end
data/spec/rapflag_spec.rb DELETED
@@ -1,115 +0,0 @@
1
- # encoding: utf-8
2
- require 'spec_helper'
3
- require 'rapflag/fetch'
4
- require 'vcr'
5
-
6
- VCR.configure do |config|
7
- config.cassette_library_dir = "fixtures/vcr_cassettes"
8
- config.hook_into :faraday # or :fakeweb
9
- end
10
-
11
- CSV_Test_File = File.expand_path(File.join(__FILE__, '..', '..', 'output/exchange_BTC.csv'))
12
- SUMMARY_EXCHANGE_BTC_File = File.expand_path(File.join(__FILE__, '..', '..', 'output/exchange_BTC_summary.csv'))
13
- SUMMARY_DEPOSIT_BFX_File = File.expand_path(File.join(__FILE__, '..', '..', 'output/deposit_BFX_summary.csv'))
14
-
15
- VCR.eject_cassette # we use insert/eject around each example
16
- describe RAPFLAG do
17
- # include ServerMockHelper
18
- before(:all) do
19
- end
20
- after(:all) do
21
- end
22
- context 'bitfinex' do
23
- before(:all) do
24
- VCR.use_cassette("rapflag", :record => :new_episodes) do
25
- FileUtils.rm_f(CSV_Test_File) if File.exist?(CSV_Test_File)
26
- FileUtils.rm_f(SUMMARY_DEPOSIT_BFX_File) if File.exist?(SUMMARY_DEPOSIT_BFX_File)
27
- FileUtils.rm_f(SUMMARY_EXCHANGE_BTC_File) if File.exist?(CSV_Test_File)
28
- expect(File.exist?(CSV_Test_File)).to eql(false)
29
- @rap = RAPFLAG::History.new('exchange', 'BTC')
30
- @rap.fetch_csv_history
31
- @rap.create_csv_file
32
- end
33
- end
34
- context 'history' do
35
- it 'should have correct currency' do
36
- expect(@rap.currency).to eql('BTC')
37
- end
38
- it 'should have correct size' do
39
- expect(@rap.history.size).to eql(206)
40
- end
41
- end
42
- end
43
- context 'bitfinex CSV' do
44
- context 'csv' do
45
- it 'should have generated a correct CSV file' do
46
- expect(File.exist?(CSV_Test_File)).to eql(true)
47
- lines = IO.readlines(CSV_Test_File)
48
- expect(lines.first.chomp).to eql('currency,amount,balance,description,date_time')
49
- expect(lines[1].chomp).to eql(
50
- 'BTC,-0.00000005,0.0,Transfer of 0.0 BTC from wallet Exchange to Deposit on wallet Exchange,2016.12.03 21:20:47')
51
- end
52
- end
53
- end
54
- context 'exchange option --clean' do
55
- before(:all) do
56
- @date_bfx_1 = Date.new(2017,1,10)
57
- @date_btx_1 = Date.new(2017,1,21)
58
- @date_btx_2 = Date.new(2017,1,10)
59
- VCR.use_cassette("rapflag", :record => :new_episodes) do
60
- FileUtils.rm_f(SUMMARY_EXCHANGE_BTC_File) if File.exist?(CSV_Test_File)
61
- expect(File.exist?(SUMMARY_EXCHANGE_BTC_File)).to eql(false)
62
- @exchange = RAPFLAG::History.new('exchange', 'BTC')
63
- @exchange.fetch_csv_history
64
- @exchange.create_summary
65
- @bfx = @exchange.get_usd_exchange(@date_bfx_1, 'BFX')
66
- @btx_1 = @exchange.get_usd_exchange(@date_btx_1, 'BTC')
67
- @btx_2 = @exchange.get_usd_exchange(@date_btx_2, 'BTC')
68
- end
69
- end
70
- it 'should have generated a correct summary CSV file' do
71
- expect(File.exist?(SUMMARY_EXCHANGE_BTC_File)).to eql(true)
72
- lines = IO.readlines(SUMMARY_EXCHANGE_BTC_File)
73
- expect(lines.first.chomp).to eql('currency,date,income,balance,rate,balance_in_usd')
74
- expect(lines[1].chomp).to eql('BTC,2016.01.15,0.0,8.99788147,,')
75
- expect(lines[-1].chomp).to eql('BTC,2016.12.03,0.0,0.0,765.46,0.0')
76
- end
77
- it 'should have NOT have generated a correct summary deposit BFX CSV file' do
78
- expect(File.exist?(SUMMARY_DEPOSIT_BFX_File)).to eql(false)
79
- end
80
- it 'should have the correct BTC -> USD rate' do
81
- expect(@btx_1).to eql 924.02
82
- expect(@btx_2).to eql 905.76
83
- end
84
- it 'should have the correct BFX -> USD rate' do
85
- expect(@bfx).to eql 0.5697
86
- end
87
- end
88
- context 'deposit option --clean' do
89
- before(:all) do
90
- FileUtils.rm_f(SUMMARY_EXCHANGE_BTC_File) if File.exist?(SUMMARY_EXCHANGE_BTC_File)
91
- FileUtils.rm_f(SUMMARY_DEPOSIT_BFX_File) if File.exist?(CSV_Test_File)
92
- @date_bfx_1 = Date.new(2017,1,10)
93
- @date_btx_1 = Date.new(2017,1,21)
94
- @date_btx_2 = Date.new(2017,1,10)
95
- VCR.use_cassette("rapflag", :record => :new_episodes) do
96
- expect(File.exist?(SUMMARY_DEPOSIT_BFX_File)).to eql(false)
97
- @deposit = RAPFLAG::History.new('deposit', 'BFX')
98
- @deposit.fetch_csv_history
99
- @deposit.create_summary
100
- end
101
- end
102
- it 'should have NOT generated a exchange BTC summary CSV file' do
103
- expect(File.exist?(SUMMARY_EXCHANGE_BTC_File)).to eql(false)
104
- end
105
- it 'should have NOT generated a correct summary CSV file' do
106
- expect(File.exist?(SUMMARY_DEPOSIT_BFX_File)).to eql(true)
107
- lines = IO.readlines(SUMMARY_DEPOSIT_BFX_File)
108
- expect(lines.first.chomp).to eql('currency,date,income,balance,rate,balance_in_usd')
109
- expect(lines[1].chomp).to eql('BFX,2016.01.15,0.0,8.99788147,,')
110
- end
111
- end
112
- end
113
- # https://api.bitfinex.com/v2/candles/trade:1D:tBTCUSD/hist
114
- # [[1489363200000,1224.4,1211.2,1238,1206.7,6157.96283895],
115
- # [1489276800000,1172.5,1224.4,1232.7,1166.8,18976.8181757]