moex_iss 1.0.0 → 1.1.0

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
2
  SHA256:
3
- metadata.gz: ff742bbab0ebea3db2a2a57e0e8b76285f910ae84e27723217334ee5c86f2797
4
- data.tar.gz: eb0ee71a6ecb99c00abc9e2eff15eaba516a9345161852250e958d92af396922
3
+ metadata.gz: e2a3f9ad4ce42c5fe38d5b16bf09ec3d937654cf12225360c2c24f4a16b0322a
4
+ data.tar.gz: fa3d5358f2ce99cf174c31a1eb27da86f2ba827d632bcd1214e19cd356080431
5
5
  SHA512:
6
- metadata.gz: 9044394d7813c40661d5c7bf0ba690ce80972ad20d80425927d5e290aa1419ba68dcb1148592077f827aa97e16d72981948e5e0b5b5240eb27e8c89821a3a9ef
7
- data.tar.gz: ef3537013d7b14c0b3ba6afb88a7ba25013833782ac97d56b4224cd2d459225485e1aaf74dfa944704aed6840d16d263da7b99477d683ce37b764c9d1e8b8c2a
6
+ metadata.gz: 5a9374940f414e6309bbb3fa1249c1406fb34932deeeb33d50a99c762faffede6a063dd891fa4fac96ec479da194c4dff5c8af5b7c81335cfe29243d40a268e9
7
+ data.tar.gz: feee8548808c648d93726e2a79ac4240f15bd9afd4f469f7123cc743a714e8d12a56ea7d2147d4e42c9b9328fc492d07bb0ac0e048ca390ca3ac7cdb39984f47
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
1
  # Change log
2
+ Все важные изменения в этом проекте будут задокументированы в этом файле.
2
3
 
3
- ## master
4
+ Формат основан на ведении журнала изменений, и этот проект придерживается семантического управления версиями.
5
+ ## [1.1.0] - 2023-12-30
6
+ ### Добавлено
7
+ - Возможность работы с историческими данными акции
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Gem Version](https://badge.fury.io/rb/moex_iss.svg)](https://rubygems.org/gems/moex_iss)
1
+ [![Gem Version](https://badge.fury.io/rb/moex_iss.svg)](https://badge.fury.io/rb/moex_iss)
2
2
  [![Build](https://github.com/K0Hb/moex_iss/workflows/Build/badge.svg)](https://github.com/palkan/moex_iss/actions)
3
3
  [![JRuby Build](https://github.com/K0Hb/moex_iss/workflows/JRuby%20Build/badge.svg)](https://github.com/K0Hb/moex_iss/actions)
4
4
 
@@ -39,23 +39,41 @@ client = MoexIss.client
39
39
 
40
40
  ### Акции
41
41
 
42
- Для получения одной акций:
42
+ Для получения последних актульных данных:
43
+ - Все акции
44
+ ```ruby
45
+ client.stocks # => MoexIss::Market::Stocks
46
+ ```
47
+ Получаем класс, по которому можно итерироваться а так же вызывать искомую ценную бумагу по ее `isin`
48
+ ```ruby
49
+ stocks.sber # => MoexIss::Market::Stock
50
+ ```
51
+ - Одна Акция
43
52
  ```ruby
44
53
  client.stock(:sber) # => MoexIss::Market::Stock
45
54
  ```
46
- Для получения всех акций:
55
+ + Для получения данные об исторических данных:
47
56
  ```ruby
48
- client.stocks # => MoexIss::Market::Stocks
57
+ client.stock(:sber, from: '2023-12-01', till: '2023-12-05') # => MoexIss::Market::History::Stocks
49
58
  ```
50
- Получаем класс, по которому можно итерироваться а так же вызывать искомую ценную бумагу по ее `isin`
59
+ Есть возможность работы с коллекцией через дату:
51
60
  ```ruby
52
- stocks.sber
61
+ stocks = client.stock(:sber, from: '2023-12-01', till: '2023-12-05') # => MoexIss::Market::History::Stocks
62
+ stocks['2023-12-03'] # => MoexIss::Market::History::Stock
53
63
  ```
54
- Экземпляр класса `MoexIss::Market::Stocks` отвечает на методы:
64
+ Максимальное количесво дней: _100_
65
+
66
+ Аргументы `from` и `till` можно использовать по одиночке
67
+
68
+
69
+ Все экземпляры классов отвечает на метод `response`, который содержит полный ответ от MOEX ISS, из которого можно получать доп.параметры,
70
+ так же у кажого класса свой набор спецефических методов для удобства работы с данными.
55
71
  ```ruby
56
- %i[bid market_price_today market_price secid short_name lat_name board_id board_name isin prev_price prev_date response market_data]
72
+ # Пример
73
+ client.stock(:sber).market_price # => 271.37
74
+ client.stock(:sber).prev_date # => 2023-12-2
75
+ ...
57
76
  ```
58
- где `response` содержит полный ответ от MOEX ISS, из которого можно получать доп.параметры
59
77
 
60
78
 
61
79
  ## Лицензия
@@ -21,7 +21,9 @@ module MoexIss
21
21
  MoexIss::Market::Stocks.new(handle_response(raw_response))
22
22
  end
23
23
 
24
- def stock(isin)
24
+ def stock(isin, from: nil, till: nil)
25
+ return historical_data_of_the_stock(isin, from, till) if from || till
26
+
25
27
  endpoint = "#{STOCKS_ENDPOINT}/#{isin}.json"
26
28
  params = STANDARD_PARAMS
27
29
 
@@ -29,5 +31,25 @@ module MoexIss
29
31
 
30
32
  MoexIss::Market::Stock.new(handle_response(raw_response))
31
33
  end
34
+
35
+ private
36
+
37
+ def historical_data_of_the_stock(isin, from, till)
38
+ validate_date(from, till) if from || till
39
+
40
+ endpoint = "history/#{STOCKS_ENDPOINT}/#{isin}.json"
41
+ params = STANDARD_PARAMS.merge({from: from, till: till})
42
+
43
+ raw_response = get(endpoint, params)
44
+
45
+ MoexIss::Market::History::Stocks.new(handle_response(raw_response))
46
+ end
47
+
48
+ def validate_date(*dates)
49
+ error = Error::InvalidDateError
50
+ message = "Невалидная дата"
51
+
52
+ dates.compact.each { |date| date.match?(/^\d{4}-\d{2}-\d{2}$/) ? nil : fail(error, message) }
53
+ end
32
54
  end
33
55
  end
@@ -36,7 +36,3 @@ module MoexIss
36
36
  end
37
37
 
38
38
  # CURENCY https://iss.moex.com/iss/statistics/engines/currency/markets/selt/rates.json?iss.meta=off&iss.json=extended&iss.only=wap_rates
39
-
40
- # STOCKS ALL https://iss.moex.com/iss/engines/stock/markets/shares/boards/tqbr/securities.json?iss.meta=off&iss.json=extended&iss.only=securities,marketdata&marketdata.columns=BID,OPEN,CLOSEPRICE,LOW,HIGH,LAST,VALUE,MARKETPRICETODAY,MARKETPRICE,TIME&securities.columns=SECID,SHORTNAME,LATNAME,BOARDID,BOARDNAME,ISIN,PREVPRICE
41
-
42
- # STOCK ONE https://iss.moex.com/iss/engines/stock/markets/shares/boards/tqbr/securities/sber.json?iss.meta=off&iss.json=extended&iss.only=securities,marketdata&marketdata.columns=BID,OPEN,CLOSEPRICE,LOW,HIGH,LAST,VALUE,MARKETPRICETODAY,MARKETPRICE,TIME&securities.columns=SECID,SHORTNAME,LATNAME,BOARDID,BOARDNAME,ISIN,PREVPRICE
@@ -4,6 +4,7 @@ module MoexIss
4
4
  class Error < StandardError
5
5
  ResponseSchemaError = Class.new(self)
6
6
  ResponseParseError = Class.new(self)
7
+ InvalidDateError = Class.new(self)
7
8
 
8
9
  ClientError = Class.new(self)
9
10
  ServerError = Class.new(self)
@@ -4,6 +4,7 @@ module MoexIss
4
4
  module Hendler
5
5
  def handle_response(response)
6
6
  return standard_hendler(response) if standard_schema?(response)
7
+ return history_hendler(response) if history_schema?(response)
7
8
 
8
9
  fail MoexIss::Error::ResponseSchemaError, "Неизвестная схема ответа"
9
10
  end
@@ -17,10 +18,18 @@ module MoexIss
17
18
  response[1]["marketdata"].is_a?(Array)
18
19
  end
19
20
 
21
+ def history_schema?(response)
22
+ response.is_a?(Array) && response[1]&.has_key?("history")
23
+ end
24
+
20
25
  def standard_hendler(response)
21
26
  response[1]["securities"].map.with_index do |x, i|
22
27
  {"securities" => x, "marketdata" => response[1]["marketdata"][i]}
23
28
  end
24
29
  end
30
+
31
+ def history_hendler(response)
32
+ response[1]
33
+ end
25
34
  end
26
35
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexIss
4
+ module Market
5
+ module History
6
+ class Stock
7
+ METHODS = {
8
+ "TRADEDATE" => :trade_date, "SHORTNAME" => :short_name, "SECID" => :secid, "VALUE" => :value,
9
+ "OPEN" => :open, "LOW" => :low, "HIGH" => :high, "LEGALCLOSEPRICE" => :legal_close_price,
10
+ "VOLUME" => :volume
11
+ }.freeze
12
+
13
+ attr_reader(:response, *METHODS.values)
14
+
15
+ def initialize(response)
16
+ @response = response
17
+
18
+ setup_instance_varibales(@response["history"])
19
+ end
20
+
21
+ private
22
+
23
+ def setup_instance_varibales(data)
24
+ return if data.nil?
25
+
26
+ data.each do |key, value|
27
+ next unless METHODS.has_key?(key)
28
+
29
+ instance_variable_set("@#{METHODS[key]}", value)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexIss
4
+ module Market
5
+ module History
6
+ class Stocks < MoexIss::Market::Stocks
7
+ def create_instances_stock
8
+ @response["history"].each do |data|
9
+ @stocks_map[data["TRADEDATE"]] = History::Stock.new({"history" => data})
10
+ end
11
+ end
12
+
13
+ def [](key)
14
+ @stocks_map[key]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -19,13 +19,23 @@ module MoexIss
19
19
  def initialize(response)
20
20
  @response = response.is_a?(Array) ? response.first : response
21
21
 
22
- @response["securities"].merge(@response["marketdata"]).each do |key, value|
22
+ setup_instance_varibales(@response["securities"])
23
+ setup_instance_varibales(@response["marketdata"])
24
+ setup_instance_varibales(@response["history"])
25
+
26
+ @market_data = @response["marketdata"]&.slice(*MARKET_DATA)
27
+ end
28
+
29
+ private
30
+
31
+ def setup_instance_varibales(data)
32
+ return if data.nil?
33
+
34
+ data.each do |key, value|
23
35
  next unless METHODS.has_key?(key)
24
36
 
25
37
  instance_variable_set("@#{METHODS[key]}", value)
26
38
  end
27
-
28
- @market_data = @response["marketdata"].slice(*MARKET_DATA)
29
39
  end
30
40
  end
31
41
  end
@@ -5,28 +5,34 @@ module MoexIss
5
5
  class Stocks
6
6
  include Enumerable
7
7
 
8
- attr_reader :stocks_response
8
+ attr_reader :response
9
9
 
10
- def initialize(stocks_response)
11
- @stocks_response = stocks_response
10
+ def initialize(response)
11
+ @response = response
12
12
  @stocks_map = {}
13
13
 
14
14
  create_instances_stock
15
15
  end
16
16
 
17
17
  def create_instances_stock
18
- @stocks_response.each do |stock_response|
19
- sicid = stock_response["securities"]["SECID"].downcase.to_sym
18
+ @response.each do |data|
19
+ method = data["securities"]["SECID"].downcase.to_sym
20
20
 
21
- @stocks_map[sicid] = Stock.new(stock_response)
22
-
23
- self.class.send(:define_method, sicid) { @stocks_map[sicid] }
21
+ setup_method(method, data)
24
22
  end
25
23
  end
26
24
 
27
25
  def each
28
26
  @stocks_map.values.each { |stock| yield stock }
29
27
  end
28
+
29
+ private
30
+
31
+ def setup_method(method, data)
32
+ @stocks_map[method] = Stock.new(data)
33
+
34
+ self.class.send(:define_method, method) { @stocks_map[method] }
35
+ end
30
36
  end
31
37
  end
32
38
  end
@@ -21,9 +21,9 @@ module MoexIss
21
21
  end
22
22
 
23
23
  def respond_with_error(code, body)
24
- raise(MoexIss::Error, body) unless MoexIss::Error::ERRORS.key?(code)
24
+ fail(MoexIss::Error, body) unless MoexIss::Error::ERRORS.key?(code)
25
25
 
26
- raise MoexIss::Error::ERRORS[code], body
26
+ fail MoexIss::Error::ERRORS[code], body
27
27
  end
28
28
  end
29
29
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MoexIss # :nodoc:
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moex_iss
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vyacheslav Konovalov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-28 00:00:00.000000000 Z
11
+ date: 2023-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.15'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.15'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.9'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.9'
55
55
  - !ruby/object:Gem::Dependency
@@ -96,6 +96,8 @@ files:
96
96
  - lib/moex_iss/connection.rb
97
97
  - lib/moex_iss/error.rb
98
98
  - lib/moex_iss/hendler.rb
99
+ - lib/moex_iss/market/history/stock.rb
100
+ - lib/moex_iss/market/history/stocks.rb
99
101
  - lib/moex_iss/market/stock.rb
100
102
  - lib/moex_iss/market/stocks.rb
101
103
  - lib/moex_iss/request.rb