bitflyer-cli 1.0.0 → 1.0.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/.github/workflows/test.yml +17 -1
- data/.rubocop.yml +12 -0
- data/.rubocop_todo.yml +16 -0
- data/Gemfile.lock +56 -15
- data/bitflyer-cli.gemspec +2 -1
- data/lib/bitflyer/cli/authorization.rb +3 -1
- data/lib/bitflyer/cli/command/cancel_all_command.rb +2 -0
- data/lib/bitflyer/cli/command/counter_trade_command.rb +10 -8
- data/lib/bitflyer/cli/command/ifdoco_by_range_command.rb +10 -8
- data/lib/bitflyer/cli/command/order_by_best_command.rb +10 -8
- data/lib/bitflyer/cli/command/order_by_twap_command.rb +10 -8
- data/lib/bitflyer/cli/command/stop_by_range_command.rb +16 -14
- data/lib/bitflyer/cli/command/summary_command.rb +18 -14
- data/lib/bitflyer/cli/ext/string.rb +4 -2
- data/lib/bitflyer/cli/has_http_client.rb +3 -1
- data/lib/bitflyer/cli/has_realtime_client.rb +3 -1
- data/lib/bitflyer/cli/model/position.rb +6 -4
- data/lib/bitflyer/cli/version.rb +1 -1
- data/lib/bitflyer/cli.rb +2 -0
- metadata +19 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ddca3f608079462d31cb86831e22fe67edfb00fa055bc3bef1ff092c4647ba60
|
|
4
|
+
data.tar.gz: 383c32699f7aa5d8f554b1edcc5a6aa5bd82dd07518edf93cf1069794c9e5d80
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8d00cc6795858857d1e5165777c0389afb3ed8b355e128349f1b068e6afb31a7da2538697b6132b32a514e804db766560a3cd8159bd9101c96dc621e972b20e2
|
|
7
|
+
data.tar.gz: faf067d80282c993290ff84ae73a3f0880b89fe6193df8489d32ecadb9cc83eab0458d8ea48416216625316f4400210fd336c61c3772ae9a6db5a00e0c6e61a3
|
data/.github/workflows/test.yml
CHANGED
|
@@ -3,13 +3,29 @@ name: test
|
|
|
3
3
|
on: [push]
|
|
4
4
|
|
|
5
5
|
jobs:
|
|
6
|
+
lint:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@v4
|
|
10
|
+
- name: Set up Ruby
|
|
11
|
+
uses: ruby/setup-ruby@v1
|
|
12
|
+
with:
|
|
13
|
+
ruby-version: '3.4.4'
|
|
14
|
+
rubygems: latest
|
|
15
|
+
- name: Install bundler
|
|
16
|
+
run: gem install bundler
|
|
17
|
+
- name: Install dependencies
|
|
18
|
+
run: bundle install --jobs 4
|
|
19
|
+
- name: Run lint
|
|
20
|
+
run: bundle exec rubocop
|
|
21
|
+
|
|
6
22
|
test:
|
|
7
23
|
runs-on: ubuntu-latest
|
|
8
24
|
strategy:
|
|
9
25
|
matrix:
|
|
10
26
|
ruby: ['3.4.4', '3.3.8', '3.2.8', '3.1.7']
|
|
11
27
|
steps:
|
|
12
|
-
- uses: actions/checkout@
|
|
28
|
+
- uses: actions/checkout@v4
|
|
13
29
|
- name: Set up Ruby
|
|
14
30
|
uses: ruby/setup-ruby@v1
|
|
15
31
|
with:
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config`
|
|
3
|
+
# on 2025-06-28 13:43:17 UTC using RuboCop version 1.77.0.
|
|
4
|
+
# The point is for the user to remove these configuration records
|
|
5
|
+
# one by one as the offenses are removed from the code base.
|
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
|
8
|
+
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
11
|
+
# Configuration parameters: EnforcedStyle.
|
|
12
|
+
# SupportedStyles: always, always_true, never
|
|
13
|
+
Style/FrozenStringLiteralComment:
|
|
14
|
+
Exclude:
|
|
15
|
+
- '**/*.arb'
|
|
16
|
+
- 'exe/bitflyer'
|
data/Gemfile.lock
CHANGED
|
@@ -1,57 +1,97 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
bitflyer-cli (1.0.
|
|
4
|
+
bitflyer-cli (1.0.1)
|
|
5
5
|
bigdecimal
|
|
6
6
|
bitflyer (>= 2.0)
|
|
7
7
|
colorize (>= 0.8.1, < 1.2.0)
|
|
8
|
-
thor (>= 0.20, < 1.
|
|
8
|
+
thor (>= 0.20, < 1.6)
|
|
9
9
|
|
|
10
10
|
GEM
|
|
11
11
|
remote: https://rubygems.org/
|
|
12
12
|
specs:
|
|
13
|
+
ast (2.4.3)
|
|
13
14
|
base64 (0.3.0)
|
|
14
|
-
bigdecimal (
|
|
15
|
+
bigdecimal (4.0.1)
|
|
15
16
|
bitflyer (2.0.1)
|
|
16
17
|
faraday (>= 1.0)
|
|
17
18
|
faraday_middleware (>= 1.2)
|
|
18
19
|
websocket-client-simple (>= 0.9)
|
|
19
20
|
colorize (1.1.0)
|
|
20
|
-
diff-lcs (1.
|
|
21
|
+
diff-lcs (1.6.2)
|
|
21
22
|
event_emitter (0.2.6)
|
|
22
|
-
faraday (1.4
|
|
23
|
+
faraday (1.10.4)
|
|
23
24
|
faraday-em_http (~> 1.0)
|
|
24
25
|
faraday-em_synchrony (~> 1.0)
|
|
25
26
|
faraday-excon (~> 1.1)
|
|
27
|
+
faraday-httpclient (~> 1.0)
|
|
28
|
+
faraday-multipart (~> 1.0)
|
|
26
29
|
faraday-net_http (~> 1.0)
|
|
27
|
-
faraday-net_http_persistent (~> 1.
|
|
28
|
-
|
|
30
|
+
faraday-net_http_persistent (~> 1.0)
|
|
31
|
+
faraday-patron (~> 1.0)
|
|
32
|
+
faraday-rack (~> 1.0)
|
|
33
|
+
faraday-retry (~> 1.0)
|
|
29
34
|
ruby2_keywords (>= 0.0.4)
|
|
30
35
|
faraday-em_http (1.0.0)
|
|
31
|
-
faraday-em_synchrony (1.0.
|
|
36
|
+
faraday-em_synchrony (1.0.1)
|
|
32
37
|
faraday-excon (1.1.0)
|
|
38
|
+
faraday-httpclient (1.0.1)
|
|
39
|
+
faraday-multipart (1.2.0)
|
|
40
|
+
multipart-post (~> 2.0)
|
|
33
41
|
faraday-net_http (1.0.2)
|
|
34
42
|
faraday-net_http_persistent (1.2.0)
|
|
43
|
+
faraday-patron (1.0.0)
|
|
44
|
+
faraday-rack (1.0.0)
|
|
45
|
+
faraday-retry (1.0.3)
|
|
35
46
|
faraday_middleware (1.2.1)
|
|
36
47
|
faraday (~> 1.0)
|
|
48
|
+
json (2.18.1)
|
|
49
|
+
language_server-protocol (3.17.0.5)
|
|
50
|
+
lint_roller (1.1.0)
|
|
37
51
|
multipart-post (2.4.1)
|
|
38
52
|
mutex_m (0.3.0)
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
parallel (1.27.0)
|
|
54
|
+
parser (3.3.10.1)
|
|
55
|
+
ast (~> 2.4.1)
|
|
56
|
+
racc
|
|
57
|
+
prism (1.9.0)
|
|
58
|
+
racc (1.8.1)
|
|
59
|
+
rainbow (3.1.1)
|
|
60
|
+
rake (13.3.1)
|
|
61
|
+
regexp_parser (2.11.3)
|
|
62
|
+
rspec (3.13.2)
|
|
41
63
|
rspec-core (~> 3.13.0)
|
|
42
64
|
rspec-expectations (~> 3.13.0)
|
|
43
65
|
rspec-mocks (~> 3.13.0)
|
|
44
|
-
rspec-core (3.13.
|
|
66
|
+
rspec-core (3.13.6)
|
|
45
67
|
rspec-support (~> 3.13.0)
|
|
46
|
-
rspec-expectations (3.13.
|
|
68
|
+
rspec-expectations (3.13.5)
|
|
47
69
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
48
70
|
rspec-support (~> 3.13.0)
|
|
49
|
-
rspec-mocks (3.13.
|
|
71
|
+
rspec-mocks (3.13.7)
|
|
50
72
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
51
73
|
rspec-support (~> 3.13.0)
|
|
52
|
-
rspec-support (3.13.
|
|
74
|
+
rspec-support (3.13.7)
|
|
75
|
+
rubocop (1.84.1)
|
|
76
|
+
json (~> 2.3)
|
|
77
|
+
language_server-protocol (~> 3.17.0.2)
|
|
78
|
+
lint_roller (~> 1.1.0)
|
|
79
|
+
parallel (~> 1.10)
|
|
80
|
+
parser (>= 3.3.0.2)
|
|
81
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
82
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
83
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
84
|
+
ruby-progressbar (~> 1.7)
|
|
85
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
86
|
+
rubocop-ast (1.49.0)
|
|
87
|
+
parser (>= 3.3.7.2)
|
|
88
|
+
prism (~> 1.7)
|
|
89
|
+
ruby-progressbar (1.13.0)
|
|
53
90
|
ruby2_keywords (0.0.5)
|
|
54
|
-
thor (1.
|
|
91
|
+
thor (1.5.0)
|
|
92
|
+
unicode-display_width (3.2.0)
|
|
93
|
+
unicode-emoji (~> 4.1)
|
|
94
|
+
unicode-emoji (4.2.0)
|
|
55
95
|
websocket (1.2.11)
|
|
56
96
|
websocket-client-simple (0.9.0)
|
|
57
97
|
base64
|
|
@@ -67,6 +107,7 @@ DEPENDENCIES
|
|
|
67
107
|
bundler (~> 2.0)
|
|
68
108
|
rake
|
|
69
109
|
rspec
|
|
110
|
+
rubocop
|
|
70
111
|
|
|
71
112
|
BUNDLED WITH
|
|
72
113
|
2.6.9
|
data/bitflyer-cli.gemspec
CHANGED
|
@@ -22,9 +22,10 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.add_dependency 'bitflyer', '>= 2.0'
|
|
23
23
|
spec.add_dependency 'bigdecimal'
|
|
24
24
|
spec.add_dependency 'colorize', '>= 0.8.1', '< 1.2.0'
|
|
25
|
-
spec.add_dependency 'thor', '>= 0.20', '< 1.
|
|
25
|
+
spec.add_dependency 'thor', '>= 0.20', '< 1.6'
|
|
26
26
|
|
|
27
27
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
28
28
|
spec.add_development_dependency 'rake'
|
|
29
29
|
spec.add_development_dependency 'rspec'
|
|
30
|
+
spec.add_development_dependency 'rubocop'
|
|
30
31
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Authorization
|
|
2
4
|
def api_key
|
|
3
5
|
ENV['BITFLYER_API_KEY'] || puts('environment variable BITFLYER_API_KEY is not set')
|
|
@@ -6,4 +8,4 @@ module Authorization
|
|
|
6
8
|
def api_secret
|
|
7
9
|
ENV['BITFLYER_API_SECRET'] || puts('environment variable BITFLYER_API_SECRET is not set')
|
|
8
10
|
end
|
|
9
|
-
end
|
|
11
|
+
end
|
|
@@ -1,22 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bitflyer/cli/has_http_client'
|
|
2
4
|
|
|
3
5
|
class CounterTradeCommand
|
|
4
6
|
include HasHTTPClient
|
|
5
7
|
|
|
6
|
-
def run
|
|
8
|
+
def run # rubocop:disable Metrics/MethodLength
|
|
7
9
|
position = Position.new(http_private_client.positions)
|
|
8
10
|
size = position.size.abs.to_f
|
|
9
|
-
type = position.size
|
|
11
|
+
type = position.size.positive? ? 'SELL' : 'BUY'
|
|
10
12
|
response = http_private_client.send_child_order(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
product_code: 'FX_BTC_JPY',
|
|
14
|
+
child_order_type: 'MARKET',
|
|
15
|
+
side: type,
|
|
16
|
+
size: size
|
|
15
17
|
)
|
|
16
18
|
if response['child_order_acceptance_id'].nil?
|
|
17
|
-
puts
|
|
19
|
+
puts "An error has occurred#{response}"
|
|
18
20
|
else
|
|
19
21
|
puts "Clear position #{type} / #{size}"
|
|
20
22
|
end
|
|
21
23
|
end
|
|
22
|
-
end
|
|
24
|
+
end
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bitflyer/cli/has_http_client'
|
|
2
4
|
require 'bitflyer/cli/model/position'
|
|
3
5
|
|
|
4
6
|
class IFDOCOByRangeCommand
|
|
5
7
|
include HasHTTPClient
|
|
6
8
|
|
|
7
|
-
def run(options)
|
|
9
|
+
def run(options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
8
10
|
side = options.type.upcase
|
|
9
11
|
size = options.amount.abs
|
|
10
12
|
ratio = options.percentage.to_f
|
|
@@ -17,7 +19,7 @@ class IFDOCOByRangeCommand
|
|
|
17
19
|
response = http_private_client.send_parent_order(request)
|
|
18
20
|
|
|
19
21
|
if response['parent_order_acceptance_id'].nil?
|
|
20
|
-
puts
|
|
22
|
+
puts "An error has occurred#{response}"
|
|
21
23
|
else
|
|
22
24
|
puts "Send market order #{side} / #{size.to_f}"
|
|
23
25
|
puts "Set limit order #{side} / #{profit_price} / #{size.to_f}"
|
|
@@ -27,7 +29,7 @@ class IFDOCOByRangeCommand
|
|
|
27
29
|
|
|
28
30
|
private
|
|
29
31
|
|
|
30
|
-
def request(side:, size:, profit_price:, loss_price:)
|
|
32
|
+
def request(side:, size:, profit_price:, loss_price:) # rubocop:disable Metrics/MethodLength
|
|
31
33
|
{
|
|
32
34
|
order_method: 'IFDOCO',
|
|
33
35
|
time_in_force: 'GTC',
|
|
@@ -58,9 +60,9 @@ class IFDOCOByRangeCommand
|
|
|
58
60
|
|
|
59
61
|
def profit_line(side:, current_price:, range:, ratio:)
|
|
60
62
|
if side == 'BUY'
|
|
61
|
-
current_price + range * ratio / 100.0
|
|
63
|
+
current_price + (range * ratio / 100.0)
|
|
62
64
|
elsif side == 'SELL'
|
|
63
|
-
current_price - range * ratio / 100.0
|
|
65
|
+
current_price - (range * ratio / 100.0)
|
|
64
66
|
else
|
|
65
67
|
0
|
|
66
68
|
end
|
|
@@ -68,11 +70,11 @@ class IFDOCOByRangeCommand
|
|
|
68
70
|
|
|
69
71
|
def loss_line(side:, current_price:, range:, ratio:)
|
|
70
72
|
if side == 'BUY'
|
|
71
|
-
current_price - range * (100.0 - ratio) / 100.0
|
|
73
|
+
current_price - (range * (100.0 - ratio) / 100.0)
|
|
72
74
|
elsif side == 'SELL'
|
|
73
|
-
current_price + range * (100.0 - ratio) / 100.0
|
|
75
|
+
current_price + (range * (100.0 - ratio) / 100.0)
|
|
74
76
|
else
|
|
75
77
|
0
|
|
76
78
|
end
|
|
77
79
|
end
|
|
78
|
-
end
|
|
80
|
+
end
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bitflyer/cli/has_http_client'
|
|
2
4
|
|
|
3
5
|
class OrderByBestCommand
|
|
4
6
|
include HasHTTPClient
|
|
5
7
|
|
|
6
|
-
def run(options)
|
|
8
|
+
def run(options) # rubocop:disable Metrics/MethodLength
|
|
7
9
|
amount = options.amount
|
|
8
10
|
type = options.type
|
|
9
11
|
|
|
@@ -11,17 +13,17 @@ class OrderByBestCommand
|
|
|
11
13
|
price = type == 'buy' ? ticker['best_bid'] : ticker['best_ask']
|
|
12
14
|
|
|
13
15
|
response = http_private_client.send_child_order(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
product_code: 'FX_BTC_JPY',
|
|
17
|
+
child_order_type: 'LIMIT',
|
|
18
|
+
side: type.upcase,
|
|
19
|
+
price: price,
|
|
20
|
+
size: amount
|
|
19
21
|
)
|
|
20
22
|
|
|
21
23
|
if response['child_order_acceptance_id'].nil?
|
|
22
|
-
puts
|
|
24
|
+
puts "An error has occurred#{response}"
|
|
23
25
|
else
|
|
24
26
|
puts "An order is created #{type} / #{price} / #{amount}"
|
|
25
27
|
end
|
|
26
28
|
end
|
|
27
|
-
end
|
|
29
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bitflyer/cli/has_http_client'
|
|
2
4
|
|
|
3
5
|
class OrderByTWAPCommand
|
|
@@ -17,18 +19,18 @@ class OrderByTWAPCommand
|
|
|
17
19
|
|
|
18
20
|
private
|
|
19
21
|
|
|
20
|
-
def order(type, amount)
|
|
22
|
+
def order(type, amount) # rubocop:disable Metrics/MethodLength
|
|
21
23
|
response = http_private_client.send_child_order(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
product_code: 'FX_BTC_JPY',
|
|
25
|
+
child_order_type: 'MARKET',
|
|
26
|
+
side: type.upcase,
|
|
27
|
+
size: amount
|
|
26
28
|
)
|
|
27
29
|
|
|
28
30
|
if response['child_order_acceptance_id'].nil?
|
|
29
|
-
puts "An error has occurred\n"
|
|
31
|
+
puts "An error has occurred\n#{response}"
|
|
30
32
|
else
|
|
31
|
-
puts response
|
|
33
|
+
puts response
|
|
32
34
|
end
|
|
33
35
|
end
|
|
34
|
-
end
|
|
36
|
+
end
|
|
@@ -1,31 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bitflyer/cli/has_http_client'
|
|
2
4
|
require 'bitflyer/cli/model/position'
|
|
3
5
|
|
|
4
6
|
class StopByRangeCommand
|
|
5
7
|
include HasHTTPClient
|
|
6
8
|
|
|
7
|
-
def run(options)
|
|
9
|
+
def run(options) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
8
10
|
position = Position.new(http_private_client.positions)
|
|
9
|
-
return puts "You don't have any position now." if position.
|
|
11
|
+
return puts "You don't have any position now." if position.empty?
|
|
10
12
|
|
|
11
|
-
side = position.average
|
|
12
|
-
price = position.average.abs + options.range * (side == 'BUY' ? 1.0 : -1.0)
|
|
13
|
+
side = position.average.positive? ? 'SELL' : 'BUY'
|
|
14
|
+
price = position.average.abs + (options.range * (side == 'BUY' ? 1.0 : -1.0))
|
|
13
15
|
|
|
14
16
|
response = http_private_client.send_parent_order(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
order_method: 'SIMPLE',
|
|
18
|
+
parameters: [{
|
|
19
|
+
product_code: 'FX_BTC_JPY',
|
|
20
|
+
condition_type: 'STOP',
|
|
21
|
+
side: side,
|
|
22
|
+
trigger_price: price,
|
|
23
|
+
size: position.size.to_f
|
|
24
|
+
}]
|
|
23
25
|
)
|
|
24
26
|
|
|
25
27
|
if response['parent_order_acceptance_id'].nil?
|
|
26
|
-
puts
|
|
28
|
+
puts "An error has occurred#{response}"
|
|
27
29
|
else
|
|
28
30
|
puts "Set limit order #{side} / #{price} / #{position.size.to_f}"
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
|
-
end
|
|
33
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bitflyer/cli/has_http_client'
|
|
2
4
|
require 'bitflyer/cli/has_realtime_client'
|
|
3
5
|
require 'bitflyer/cli/ext/string'
|
|
@@ -7,34 +9,34 @@ class SummaryCommand
|
|
|
7
9
|
include HasHTTPClient
|
|
8
10
|
include HasRealtimeClient
|
|
9
11
|
|
|
10
|
-
BUFFER_SIZE = 30
|
|
12
|
+
BUFFER_SIZE = 30
|
|
11
13
|
|
|
12
14
|
def initialize
|
|
13
15
|
@current_price = 0.0
|
|
14
16
|
|
|
15
|
-
realtime_client.executions_fx_btc_jpy =
|
|
17
|
+
realtime_client.executions_fx_btc_jpy = lambda { |message|
|
|
16
18
|
message.each { |m| @current_price = m['price'].to_f }
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
update_balance
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
def run
|
|
24
|
+
def run # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
23
25
|
$stdout.sync = true
|
|
24
26
|
|
|
25
27
|
Thread.new do
|
|
26
|
-
|
|
28
|
+
loop do
|
|
27
29
|
update_balance
|
|
28
30
|
sleep 5
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
print
|
|
34
|
-
\e[4F\e[0JCurrent: #{@current_price.to_i.to_s.split_by_comma}
|
|
35
|
-
Position: #{@position.average.to_s.split_by_comma} * #{@position.size.to_f}
|
|
36
|
-
Spread: #{spread.to_s.split_by_comma.color_with_number(spread)}
|
|
37
|
-
Balance: #{(@balance + profit).to_s.split_by_comma.ljust(15, ' ')} (#{profit.to_s.split_by_comma.color_with_number(profit)})
|
|
34
|
+
loop do
|
|
35
|
+
print <<~EOS
|
|
36
|
+
\e[4F\e[0JCurrent: #{@current_price.to_i.to_s.split_by_comma}
|
|
37
|
+
Position: #{@position.average.to_s.split_by_comma} * #{@position.size.to_f}
|
|
38
|
+
Spread: #{spread.to_s.split_by_comma.color_with_number(spread)}
|
|
39
|
+
Balance: #{(@balance + profit).to_s.split_by_comma.ljust(15, ' ')} (#{profit.to_s.split_by_comma.color_with_number(profit)})
|
|
38
40
|
EOS
|
|
39
41
|
sleep 0.1
|
|
40
42
|
end
|
|
@@ -48,13 +50,15 @@ Balance: #{(@balance + profit).to_s.split_by_comma.ljust(15, ' ')} (#{profit.to
|
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
def profit
|
|
51
|
-
return 0 if @current_price
|
|
53
|
+
return 0 if @current_price.zero?
|
|
54
|
+
|
|
52
55
|
@position.profit(@current_price).to_i
|
|
53
56
|
end
|
|
54
57
|
|
|
55
58
|
def spread
|
|
56
|
-
return 0 if @current_price
|
|
57
|
-
return 0 if @position.average.to_i
|
|
59
|
+
return 0 if @current_price.zero?
|
|
60
|
+
return 0 if @position.average.to_i.zero?
|
|
61
|
+
|
|
58
62
|
@current_price.to_i - @position.average.to_i
|
|
59
63
|
end
|
|
60
|
-
end
|
|
64
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bigdecimal'
|
|
2
4
|
require 'bigdecimal/util'
|
|
3
5
|
|
|
@@ -8,20 +10,20 @@ class Position
|
|
|
8
10
|
|
|
9
11
|
def profit(current_price)
|
|
10
12
|
@positions.inject('0'.to_d) do |sum, position|
|
|
11
|
-
sum + (current_price - position['price'].to_s.to_d) * position['size'].to_s.to_d * coefficient(position)
|
|
13
|
+
sum + ((current_price - position['price'].to_s.to_d) * position['size'].to_s.to_d * coefficient(position))
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
def average
|
|
16
|
-
@positions.size
|
|
18
|
+
@positions.size.positive? ? (sum / size.abs).to_i : 0
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def sum
|
|
20
|
-
@positions.inject('0'.to_d) { |sum, position| sum + position['price'].to_s.to_d * position['size'].to_s.to_d }
|
|
22
|
+
@positions.inject('0'.to_d) { |sum, position| sum + (position['price'].to_s.to_d * position['size'].to_s.to_d) }
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def size
|
|
24
|
-
@positions.inject('0'.to_d) { |sum, position| sum + position['size'].to_s.to_d * coefficient(position) }
|
|
26
|
+
@positions.inject('0'.to_d) { |sum, position| sum + (position['size'].to_s.to_d * coefficient(position)) }
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
private
|
data/lib/bitflyer/cli/version.rb
CHANGED
data/lib/bitflyer/cli.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bitflyer-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yuji Ueki
|
|
@@ -66,7 +66,7 @@ dependencies:
|
|
|
66
66
|
version: '0.20'
|
|
67
67
|
- - "<"
|
|
68
68
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: '1.
|
|
69
|
+
version: '1.6'
|
|
70
70
|
type: :runtime
|
|
71
71
|
prerelease: false
|
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -76,7 +76,7 @@ dependencies:
|
|
|
76
76
|
version: '0.20'
|
|
77
77
|
- - "<"
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
|
-
version: '1.
|
|
79
|
+
version: '1.6'
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
81
|
name: bundler
|
|
82
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -119,6 +119,20 @@ dependencies:
|
|
|
119
119
|
- - ">="
|
|
120
120
|
- !ruby/object:Gem::Version
|
|
121
121
|
version: '0'
|
|
122
|
+
- !ruby/object:Gem::Dependency
|
|
123
|
+
name: rubocop
|
|
124
|
+
requirement: !ruby/object:Gem::Requirement
|
|
125
|
+
requirements:
|
|
126
|
+
- - ">="
|
|
127
|
+
- !ruby/object:Gem::Version
|
|
128
|
+
version: '0'
|
|
129
|
+
type: :development
|
|
130
|
+
prerelease: false
|
|
131
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
132
|
+
requirements:
|
|
133
|
+
- - ">="
|
|
134
|
+
- !ruby/object:Gem::Version
|
|
135
|
+
version: '0'
|
|
122
136
|
description: CLI tool for Bitflyer
|
|
123
137
|
email:
|
|
124
138
|
- unhappychoice@gmail.com
|
|
@@ -131,6 +145,8 @@ files:
|
|
|
131
145
|
- ".github/workflows/release.yaml"
|
|
132
146
|
- ".github/workflows/test.yml"
|
|
133
147
|
- ".gitignore"
|
|
148
|
+
- ".rubocop.yml"
|
|
149
|
+
- ".rubocop_todo.yml"
|
|
134
150
|
- ".ruby-version"
|
|
135
151
|
- CODE_OF_CONDUCT.md
|
|
136
152
|
- Gemfile
|