rapflag 0.0.2 → 0.0.3

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.
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]