bitflyer-cli 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: eddec9fdab7e0144f2446ddedb5df78ad1f4049a
4
- data.tar.gz: e6304e8648c4cb41105449693cddff812e69e8dc
2
+ SHA256:
3
+ metadata.gz: ddca3f608079462d31cb86831e22fe67edfb00fa055bc3bef1ff092c4647ba60
4
+ data.tar.gz: 383c32699f7aa5d8f554b1edcc5a6aa5bd82dd07518edf93cf1069794c9e5d80
5
5
  SHA512:
6
- metadata.gz: 965bebf6e21317192d60fb643b6855c677a6545fbef0c2c7ebf0a41178d29afdf7b96ae5665df0815ac0490546ac2f359bdf8e5810a3cb8d8152add37c5569cc
7
- data.tar.gz: 77fbfd170935a02610ecf319d2ab147115a80ff5a63a56b2ffe0c4f8cf6550dfa87b39b7e9a679a717eee66f88d32fab8dc579531de29e3e859e71a162473248
6
+ metadata.gz: 8d00cc6795858857d1e5165777c0389afb3ed8b355e128349f1b068e6afb31a7da2538697b6132b32a514e804db766560a3cd8159bd9101c96dc621e972b20e2
7
+ data.tar.gz: faf067d80282c993290ff84ae73a3f0880b89fe6193df8489d32ecadb9cc83eab0458d8ea48416216625316f4400210fd336c61c3772ae9a6db5a00e0c6e61a3
@@ -0,0 +1,14 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ time: "12:00"
8
+ timezone: Asia/Tokyo
9
+ open-pull-requests-limit: 20
10
+ reviewers:
11
+ - unhappychoice
12
+ allow:
13
+ - dependency-type: direct
14
+ - dependency-type: indirect
@@ -0,0 +1,41 @@
1
+ name: release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ version:
7
+ description: Release version
8
+ required: true
9
+ type: choice
10
+ options:
11
+ - major
12
+ - minor
13
+ - patch
14
+ jobs:
15
+ push:
16
+ name: Push gem to RubyGems.org
17
+ runs-on: ubuntu-latest
18
+ environment:
19
+ name: release
20
+ permissions:
21
+ id-token: write
22
+ contents: write
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - name: Set up Ruby
26
+ uses: ruby/setup-ruby@v1
27
+ with:
28
+ bundler-cache: true
29
+ ruby-version: .ruby-version
30
+ - name: Setup Git
31
+ run: |
32
+ git config --global user.email "unhappychoice@gmail.com"
33
+ git config --global user.name "unhappychoice"
34
+ - name: Install gem-release
35
+ run: gem install gem-release
36
+ - name: Bump version
37
+ run: |
38
+ gem bump --version ${{inputs.version}} --message ':tada: Bump %{name} to %{version}'
39
+ bundle config set frozen false && bundle install
40
+ git add . && git commit --amend --no-edit
41
+ - uses: rubygems/release-gem@v1
@@ -0,0 +1,43 @@
1
+ name: test
2
+
3
+ on: [push]
4
+
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
+
22
+ test:
23
+ runs-on: ubuntu-latest
24
+ strategy:
25
+ matrix:
26
+ ruby: ['3.4.4', '3.3.8', '3.2.8', '3.1.7']
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ - name: Set up Ruby
30
+ uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{ matrix.ruby }}
33
+ rubygems: latest
34
+ - name: Install bundler
35
+ run: gem install bundler
36
+ - name: Install dependencies
37
+ run: bundle install --jobs 4
38
+ - name: Run test
39
+ env:
40
+ RAILS_ENV: test
41
+ COVERAGE: true
42
+ CODECOV_TOKEN: d9091f65-2e14-4029-86e6-f6ec9c59ecec
43
+ run: bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,57 @@
1
+ # Created by https://www.gitignore.io/api/ruby
2
+ # Edit at https://www.gitignore.io/?templates=ruby
3
+
4
+ ### Ruby ###
5
+ *.gem
6
+ *.rbc
7
+ /.config
8
+ /coverage/
9
+ /InstalledFiles
10
+ /pkg/
11
+ /spec/reports/
12
+ /spec/examples.txt
13
+ /test/tmp/
14
+ /test/version_tmp/
15
+ /tmp/
16
+
17
+ # Used by dotenv library to load environment variables.
18
+ # .env
19
+
20
+ ## Specific to RubyMotion:
21
+ .dat*
22
+ .repl_history
23
+ build/
24
+ *.bridgesupport
25
+ build-iPhoneOS/
26
+ build-iPhoneSimulator/
27
+
28
+ ## Specific to RubyMotion (use of CocoaPods):
29
+ #
30
+ # We recommend against adding the Pods directory to your .gitignore. However
31
+ # you should judge for yourself, the pros and cons are mentioned at:
32
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
33
+ #
34
+ # vendor/Pods/
35
+
36
+ ## Documentation cache and generated files:
37
+ /.yardoc/
38
+ /_yardoc/
39
+ /doc/
40
+ /rdoc/
41
+
42
+ ## Environment normalization:
43
+ /.bundle/
44
+ /vendor/bundle
45
+ /lib/bundler/man/
46
+ vendor/bundle
47
+
48
+ # for a library or gem, you might want to ignore these files since the code is
49
+ # intended to run in multiple environments; otherwise, check them in:
50
+ # Gemfile.lock
51
+ # .ruby-version
52
+ # .ruby-gemset
53
+
54
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
55
+ .rvmrc
56
+
57
+ # End of https://www.gitignore.io/api/ruby
data/.rubocop.yml ADDED
@@ -0,0 +1,12 @@
1
+ inherit_from: .rubocop_todo.yml
2
+ AllCops:
3
+ NewCops: enable
4
+ Include:
5
+ - 'lib/**/*.rb'
6
+ TargetRubyVersion: 3.1
7
+ Style/Documentation:
8
+ Enabled: false
9
+ Layout/LineLength:
10
+ Max: 120
11
+ Naming/HeredocDelimiterNaming:
12
+ Enabled: false
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/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.4
data/Gemfile.lock CHANGED
@@ -1,44 +1,102 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bitflyer-cli (0.5.0)
5
- bitflyer (~> 0.2.2)
6
- colorize (~> 0.8.1)
7
- thor (~> 0.20.0)
4
+ bitflyer-cli (1.0.1)
5
+ bigdecimal
6
+ bitflyer (>= 2.0)
7
+ colorize (>= 0.8.1, < 1.2.0)
8
+ thor (>= 0.20, < 1.6)
8
9
 
9
10
  GEM
10
11
  remote: https://rubygems.org/
11
12
  specs:
12
- bitflyer (0.2.2)
13
- faraday (~> 0.14.0)
14
- faraday_middleware (~> 0.12.0)
15
- websocket-client-simple (~> 0.3.0)
16
- colorize (0.8.1)
17
- diff-lcs (1.3)
13
+ ast (2.4.3)
14
+ base64 (0.3.0)
15
+ bigdecimal (4.0.1)
16
+ bitflyer (2.0.1)
17
+ faraday (>= 1.0)
18
+ faraday_middleware (>= 1.2)
19
+ websocket-client-simple (>= 0.9)
20
+ colorize (1.1.0)
21
+ diff-lcs (1.6.2)
18
22
  event_emitter (0.2.6)
19
- faraday (0.14.0)
20
- multipart-post (>= 1.2, < 3)
21
- faraday_middleware (0.12.2)
22
- faraday (>= 0.7.4, < 1.0)
23
- multipart-post (2.0.0)
24
- rake (12.3.0)
25
- rspec (3.7.0)
26
- rspec-core (~> 3.7.0)
27
- rspec-expectations (~> 3.7.0)
28
- rspec-mocks (~> 3.7.0)
29
- rspec-core (3.7.1)
30
- rspec-support (~> 3.7.0)
31
- rspec-expectations (3.7.0)
23
+ faraday (1.10.4)
24
+ faraday-em_http (~> 1.0)
25
+ faraday-em_synchrony (~> 1.0)
26
+ faraday-excon (~> 1.1)
27
+ faraday-httpclient (~> 1.0)
28
+ faraday-multipart (~> 1.0)
29
+ faraday-net_http (~> 1.0)
30
+ faraday-net_http_persistent (~> 1.0)
31
+ faraday-patron (~> 1.0)
32
+ faraday-rack (~> 1.0)
33
+ faraday-retry (~> 1.0)
34
+ ruby2_keywords (>= 0.0.4)
35
+ faraday-em_http (1.0.0)
36
+ faraday-em_synchrony (1.0.1)
37
+ faraday-excon (1.1.0)
38
+ faraday-httpclient (1.0.1)
39
+ faraday-multipart (1.2.0)
40
+ multipart-post (~> 2.0)
41
+ faraday-net_http (1.0.2)
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)
46
+ faraday_middleware (1.2.1)
47
+ faraday (~> 1.0)
48
+ json (2.18.1)
49
+ language_server-protocol (3.17.0.5)
50
+ lint_roller (1.1.0)
51
+ multipart-post (2.4.1)
52
+ mutex_m (0.3.0)
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)
63
+ rspec-core (~> 3.13.0)
64
+ rspec-expectations (~> 3.13.0)
65
+ rspec-mocks (~> 3.13.0)
66
+ rspec-core (3.13.6)
67
+ rspec-support (~> 3.13.0)
68
+ rspec-expectations (3.13.5)
32
69
  diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.7.0)
34
- rspec-mocks (3.7.0)
70
+ rspec-support (~> 3.13.0)
71
+ rspec-mocks (3.13.7)
35
72
  diff-lcs (>= 1.2.0, < 2.0)
36
- rspec-support (~> 3.7.0)
37
- rspec-support (3.7.1)
38
- thor (0.20.3)
39
- websocket (1.2.8)
40
- websocket-client-simple (0.3.0)
73
+ rspec-support (~> 3.13.0)
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)
90
+ ruby2_keywords (0.0.5)
91
+ thor (1.5.0)
92
+ unicode-display_width (3.2.0)
93
+ unicode-emoji (~> 4.1)
94
+ unicode-emoji (4.2.0)
95
+ websocket (1.2.11)
96
+ websocket-client-simple (0.9.0)
97
+ base64
41
98
  event_emitter
99
+ mutex_m
42
100
  websocket
43
101
 
44
102
  PLATFORMS
@@ -46,9 +104,10 @@ PLATFORMS
46
104
 
47
105
  DEPENDENCIES
48
106
  bitflyer-cli!
49
- bundler (~> 1.12)
107
+ bundler (~> 2.0)
50
108
  rake
51
109
  rspec
110
+ rubocop
52
111
 
53
112
  BUNDLED WITH
54
- 1.17.3
113
+ 2.6.9
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # bitflyer-cli
2
2
  [![Gem Version](https://badge.fury.io/rb/bitflyer-cli.svg)](https://badge.fury.io/rb/bitflyer-cli)
3
- [![Circle CI](https://circleci.com/gh/unhappychoice/bitflyer-cli.svg?style=shield)](https://circleci.com/gh/unhappychoice/bitflyer-cli)
4
- [![Code Climate](https://codeclimate.com/github/unhappychoice/bitflyer-cli/badges/gpa.svg)](https://codeclimate.com/github/unhappychoice/bitflyer-cli)
3
+ [![Circle CI](https://circleci.com/gh/bitflyer-tools/bitflyer-cli.svg?style=shield)](https://circleci.com/gh/bitflyer-tools/bitflyer-cli)
4
+ [![Code Climate](https://codeclimate.com/github/bitflyer-tools/bitflyer-cli/badges/gpa.svg)](https://codeclimate.com/github/bitflyer-tools/bitflyer-cli)
5
+ ![Libraries.io dependency status for GitHub repo](https://img.shields.io/librariesio/github/bitflyer-tools/bitflyer-cli.svg)
5
6
  ![](http://ruby-gem-downloads-badge.herokuapp.com/bitflyer-cli?type=total)
7
+ ![GitHub](https://img.shields.io/github/license/bitflyer-tools/bitflyer-cli.svg)
6
8
 
7
9
  bitflyer-cli is a CLI tool for [Bitflyer](https://bitflyer.jp/) FXBTC.
8
10
 
data/bitflyer-cli.gemspec CHANGED
@@ -1,28 +1,31 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bitflyer/cli/version'
4
5
 
5
6
  Gem::Specification.new do |spec|
6
- spec.name = 'bitflyer-cli'
7
- spec.version = '0.5.0'
8
- spec.authors = ['Yuji Ueki']
9
- spec.email = ['unhappychoice@gmail.com']
7
+ spec.name = 'bitflyer-cli'
8
+ spec.version = Bitflyer::Cli::VERSION
9
+ spec.required_ruby_version = '>= 3.1'
10
+ spec.authors = ['Yuji Ueki']
11
+ spec.email = ['unhappychoice@gmail.com']
12
+ spec.summary = 'CLI tool for Bitflyer'
13
+ spec.description = 'CLI tool for Bitflyer'
14
+ spec.homepage = 'https://github.com/bitflyer-tools/bitflyer-cli'
15
+ spec.license = 'MIT'
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = 'exe'
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
10
20
 
11
- spec.summary = 'CLI tool for Bitflyer'
12
- spec.description = 'CLI tool for Bitflyer'
13
- spec.homepage = 'https://github.com/unhappychoice/bitflyer-cli'
14
- spec.license = 'MIT'
15
21
 
16
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- spec.bindir = 'exe'
18
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
- spec.require_paths = ['lib']
22
+ spec.add_dependency 'bitflyer', '>= 2.0'
23
+ spec.add_dependency 'bigdecimal'
24
+ spec.add_dependency 'colorize', '>= 0.8.1', '< 1.2.0'
25
+ spec.add_dependency 'thor', '>= 0.20', '< 1.6'
20
26
 
21
- spec.add_dependency 'thor', '~> 0.20.0'
22
- spec.add_dependency 'bitflyer', '~> 0.2.2'
23
- spec.add_dependency 'colorize', '~> 0.8.1'
24
-
25
- spec.add_development_dependency 'bundler', '~> 1.12'
27
+ spec.add_development_dependency 'bundler', '~> 2.0'
26
28
  spec.add_development_dependency 'rake'
27
29
  spec.add_development_dependency 'rspec'
30
+ spec.add_development_dependency 'rubocop'
28
31
  end
data/exe/bitflyer CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'bitflyer/cli'
4
4
 
5
- Bitflyer::CLI.start
5
+ Bitflyer::Cli::Runner.start
@@ -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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bitflyer/cli/has_http_client'
2
4
 
3
5
  class CancelAllCommand
@@ -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 > 0 ? 'SELL' : 'BUY'
11
+ type = position.size.positive? ? 'SELL' : 'BUY'
10
12
  response = http_private_client.send_child_order(
11
- product_code: 'FX_BTC_JPY',
12
- child_order_type: 'MARKET',
13
- side: type,
14
- size: size
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 'An error has occurred' + response.to_s
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,23 +1,25 @@
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
11
13
  range = options.range.to_f
12
14
 
13
- current_price = http_public_client.ticker('FX_BTC_JPY')['ltp'].to_i
15
+ current_price = http_public_client.ticker(product_code: 'FX_BTC_JPY')['ltp'].to_i
14
16
  profit_price = profit_line(side: side, current_price: current_price, range: range, ratio: ratio).to_i
15
17
  loss_price = loss_line(side: side, current_price: current_price, range: range, ratio: ratio).to_i
16
18
  request = request(side: side, size: size, profit_price: profit_price, loss_price: loss_price)
17
19
  response = http_private_client.send_parent_order(request)
18
20
 
19
21
  if response['parent_order_acceptance_id'].nil?
20
- puts 'An error has occurred' + response.to_s
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,27 +1,29 @@
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
 
10
- ticker = http_public_client.ticker('FX_BTC_JPY')
12
+ ticker = http_public_client.ticker(product_code: 'FX_BTC_JPY')
11
13
  price = type == 'buy' ? ticker['best_bid'] : ticker['best_ask']
12
14
 
13
15
  response = http_private_client.send_child_order(
14
- product_code: 'FX_BTC_JPY',
15
- child_order_type: 'LIMIT',
16
- side: type.upcase,
17
- price: price,
18
- size: amount
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 'An error has occurred' + response.to_s
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
- product_code: 'FX_BTC_JPY',
23
- child_order_type: 'MARKET',
24
- side: type.upcase,
25
- size: amount
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" + response.to_s
31
+ puts "An error has occurred\n#{response}"
30
32
  else
31
- puts response.to_s
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.size == 0
11
+ return puts "You don't have any position now." if position.empty?
10
12
 
11
- side = position.average > 0 ? 'SELL' : 'BUY'
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
- order_method: 'SIMPLE',
16
- parameters: [{
17
- product_code: 'FX_BTC_JPY',
18
- condition_type: 'STOP',
19
- side: side,
20
- trigger_price: price,
21
- size: position.size.to_f
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 'An error has occurred' + response.to_s
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.freeze
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 = ->(message) {
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
- while true
28
+ loop do
27
29
  update_balance
28
30
  sleep 5
29
31
  end
30
32
  end
31
33
 
32
- while true
33
- print <<-"EOS"
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 == 0
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 == 0
57
- return 0 if @position.average.to_i == 0
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 'colorize'
2
4
 
3
5
  class String
@@ -7,6 +9,6 @@ class String
7
9
  end
8
10
 
9
11
  def split_by_comma
10
- reverse.gsub( /(\d{3})(?=\d)/, '\1,').reverse
12
+ reverse.gsub(/(\d{3})(?=\d)/, '\1,').reverse
11
13
  end
12
- end
14
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bitflyer'
2
4
  require 'bitflyer/cli/authorization'
3
5
 
@@ -11,4 +13,4 @@ module HasHTTPClient
11
13
  def http_private_client
12
14
  @http_private_client ||= Bitflyer.http_private_client(api_key, api_secret)
13
15
  end
14
- end
16
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bitflyer'
2
4
 
3
5
  module HasRealtimeClient
4
6
  def realtime_client
5
7
  @realtime_client ||= Bitflyer.realtime_client
6
8
  end
7
- end
9
+ 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 > 0 ? (sum / size.abs).to_i : 0
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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bitflyer
4
+ module Cli
5
+ VERSION = '1.0.1'
6
+ end
7
+ end
data/lib/bitflyer/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
  require 'bitflyer/cli/command/cancel_all_command'
3
5
  require 'bitflyer/cli/command/counter_trade_command'
@@ -6,53 +8,56 @@ require 'bitflyer/cli/command/order_by_best_command'
6
8
  require 'bitflyer/cli/command/order_by_twap_command'
7
9
  require 'bitflyer/cli/command/stop_by_range_command'
8
10
  require 'bitflyer/cli/command/summary_command'
11
+ require 'bitflyer/cli/version'
9
12
 
10
13
  module Bitflyer
11
- class CLI < Thor
12
- desc 'cancel_all', 'cancel all of orders'
13
- def cancel_all
14
- CancelAllCommand.new.run
15
- end
14
+ module Cli
15
+ class Runner < Thor
16
+ desc 'cancel_all', 'cancel all of orders'
17
+ def cancel_all
18
+ CancelAllCommand.new.run
19
+ end
16
20
 
17
- desc 'counter_trade', 'clear all positions'
18
- def counter_trade
19
- CounterTradeCommand.new.run
20
- end
21
+ desc 'counter_trade', 'clear all positions'
22
+ def counter_trade
23
+ CounterTradeCommand.new.run
24
+ end
21
25
 
22
- desc 'order_by_best', 'create limit order by best price in the board'
23
- method_option :amount, aliases: 'a', type: :numeric, banner: 'amount', required: true
24
- method_option :type, aliases: 't', type: :string, banner: 'buy/sell', required: true
25
- def order_by_best
26
- OrderByBestCommand.new.run(options)
27
- end
26
+ desc 'order_by_best', 'create limit order by best price in the board'
27
+ method_option :amount, aliases: 'a', type: :numeric, banner: 'amount', required: true
28
+ method_option :type, aliases: 't', type: :string, banner: 'buy/sell', required: true
29
+ def order_by_best
30
+ OrderByBestCommand.new.run(options)
31
+ end
28
32
 
29
- desc 'order_by_twap', 'order by using TWAP algorithm'
30
- method_option :amount, aliases: 'a', type: :numeric, banner: 'amount', required: true
31
- method_option :type, aliases: 't', type: :string, banner: 'buy/sell', required: true
32
- method_option :number_of_times, aliases: 'n', type: :numeric, banner: 'N', required: true
33
- method_option :interval, aliases: 'i', type: :numeric, banner: 'second', required: true
34
- def order_by_twap
35
- OrderByTWAPCommand.new.run(options)
36
- end
33
+ desc 'order_by_twap', 'order by using TWAP algorithm'
34
+ method_option :amount, aliases: 'a', type: :numeric, banner: 'amount', required: true
35
+ method_option :type, aliases: 't', type: :string, banner: 'buy/sell', required: true
36
+ method_option :number_of_times, aliases: 'n', type: :numeric, banner: 'N', required: true
37
+ method_option :interval, aliases: 'i', type: :numeric, banner: 'second', required: true
38
+ def order_by_twap
39
+ OrderByTWAPCommand.new.run(options)
40
+ end
37
41
 
38
- desc 'stop_by_range', 'create stop order by range based on current position'
39
- method_option :range, aliases: 'r', type: :numeric, banner: 'price range', required: true
40
- def stop_by_range
41
- StopByRangeCommand.new.run(options)
42
- end
42
+ desc 'stop_by_range', 'create stop order by range based on current position'
43
+ method_option :range, aliases: 'r', type: :numeric, banner: 'price range', required: true
44
+ def stop_by_range
45
+ StopByRangeCommand.new.run(options)
46
+ end
43
47
 
44
- desc 'ifdoco_by_range', 'create IFDOCO order by range based on current price'
45
- method_option :amount, aliases: 'a', type: :numeric, banner: 'amount', required: true
46
- method_option :type, aliases: 't', type: :string, banner: 'buy/sell', required: true
47
- method_option :range, aliases: 'r', type: :numeric, banner: 'price range', required: true
48
- method_option :percentage, aliases: 'p', type: :numeric, banner: 'price ratio percentage', required: true
49
- def ifdoco_by_range
50
- IFDOCOByRangeCommand.new.run(options)
51
- end
48
+ desc 'ifdoco_by_range', 'create IFDOCO order by range based on current price'
49
+ method_option :amount, aliases: 'a', type: :numeric, banner: 'amount', required: true
50
+ method_option :type, aliases: 't', type: :string, banner: 'buy/sell', required: true
51
+ method_option :range, aliases: 'r', type: :numeric, banner: 'price range', required: true
52
+ method_option :percentage, aliases: 'p', type: :numeric, banner: 'price ratio percentage', required: true
53
+ def ifdoco_by_range
54
+ IFDOCOByRangeCommand.new.run(options)
55
+ end
52
56
 
53
- desc 'summary', 'show current balance information'
54
- def summary
55
- SummaryCommand.new.run
57
+ desc 'summary', 'show current balance information'
58
+ def summary
59
+ SummaryCommand.new.run
60
+ end
56
61
  end
57
62
  end
58
63
  end
metadata CHANGED
@@ -1,71 +1,96 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitflyer-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuji Ueki
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2019-07-14 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: thor
13
+ name: bitflyer
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: 0.20.0
18
+ version: '2.0'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - "~>"
23
+ - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: 0.20.0
25
+ version: '2.0'
27
26
  - !ruby/object:Gem::Dependency
28
- name: bitflyer
27
+ name: bigdecimal
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
- - - "~>"
30
+ - - ">="
32
31
  - !ruby/object:Gem::Version
33
- version: 0.2.2
32
+ version: '0'
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
- - - "~>"
37
+ - - ">="
39
38
  - !ruby/object:Gem::Version
40
- version: 0.2.2
39
+ version: '0'
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: colorize
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
- - - "~>"
44
+ - - ">="
46
45
  - !ruby/object:Gem::Version
47
46
  version: 0.8.1
47
+ - - "<"
48
+ - !ruby/object:Gem::Version
49
+ version: 1.2.0
48
50
  type: :runtime
49
51
  prerelease: false
50
52
  version_requirements: !ruby/object:Gem::Requirement
51
53
  requirements:
52
- - - "~>"
54
+ - - ">="
53
55
  - !ruby/object:Gem::Version
54
56
  version: 0.8.1
57
+ - - "<"
58
+ - !ruby/object:Gem::Version
59
+ version: 1.2.0
60
+ - !ruby/object:Gem::Dependency
61
+ name: thor
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0.20'
67
+ - - "<"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.6'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0.20'
77
+ - - "<"
78
+ - !ruby/object:Gem::Version
79
+ version: '1.6'
55
80
  - !ruby/object:Gem::Dependency
56
81
  name: bundler
57
82
  requirement: !ruby/object:Gem::Requirement
58
83
  requirements:
59
84
  - - "~>"
60
85
  - !ruby/object:Gem::Version
61
- version: '1.12'
86
+ version: '2.0'
62
87
  type: :development
63
88
  prerelease: false
64
89
  version_requirements: !ruby/object:Gem::Requirement
65
90
  requirements:
66
91
  - - "~>"
67
92
  - !ruby/object:Gem::Version
68
- version: '1.12'
93
+ version: '2.0'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: rake
71
96
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +119,20 @@ dependencies:
94
119
  - - ">="
95
120
  - !ruby/object:Gem::Version
96
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'
97
136
  description: CLI tool for Bitflyer
98
137
  email:
99
138
  - unhappychoice@gmail.com
@@ -102,6 +141,13 @@ executables:
102
141
  extensions: []
103
142
  extra_rdoc_files: []
104
143
  files:
144
+ - ".github/dependabot.yml"
145
+ - ".github/workflows/release.yaml"
146
+ - ".github/workflows/test.yml"
147
+ - ".gitignore"
148
+ - ".rubocop.yml"
149
+ - ".rubocop_todo.yml"
150
+ - ".ruby-version"
105
151
  - CODE_OF_CONDUCT.md
106
152
  - Gemfile
107
153
  - Gemfile.lock
@@ -123,11 +169,11 @@ files:
123
169
  - lib/bitflyer/cli/has_http_client.rb
124
170
  - lib/bitflyer/cli/has_realtime_client.rb
125
171
  - lib/bitflyer/cli/model/position.rb
126
- homepage: https://github.com/unhappychoice/bitflyer-cli
172
+ - lib/bitflyer/cli/version.rb
173
+ homepage: https://github.com/bitflyer-tools/bitflyer-cli
127
174
  licenses:
128
175
  - MIT
129
176
  metadata: {}
130
- post_install_message:
131
177
  rdoc_options: []
132
178
  require_paths:
133
179
  - lib
@@ -135,16 +181,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
181
  requirements:
136
182
  - - ">="
137
183
  - !ruby/object:Gem::Version
138
- version: '0'
184
+ version: '3.1'
139
185
  required_rubygems_version: !ruby/object:Gem::Requirement
140
186
  requirements:
141
187
  - - ">="
142
188
  - !ruby/object:Gem::Version
143
189
  version: '0'
144
190
  requirements: []
145
- rubyforge_project:
146
- rubygems_version: 2.6.14
147
- signing_key:
191
+ rubygems_version: 3.6.7
148
192
  specification_version: 4
149
193
  summary: CLI tool for Bitflyer
150
194
  test_files: []