sqa 0.0.9 → 0.0.10

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: b21ccda9b46c7125afbce0c1ac8f074b945a64e3ee946db5c44566e104bd34e9
4
- data.tar.gz: 5252167d8e7f7520bcbdd43a9cf0bae541466ee09b05b677817cb31d8d74ca71
3
+ metadata.gz: b699ff032eee80858f9cfc3c3cba7e1ad5c0b537cd9b014085d184f4ce052451
4
+ data.tar.gz: 3c7211690c31b6486718306d7e62fdf71c9466a421cfc694955a64e0d0184e66
5
5
  SHA512:
6
- metadata.gz: a9defe0ba2597a23c5edde2d2adb150e4d5b1e8f0b9005ed00b439b60e1c56af766ec959d305e57c416ebc6c8f701ffe6525050e2ff81258a4348430b3cc8ef8
7
- data.tar.gz: 40026c37bb437b44d1f25ebc868f8d166b2bebfcd3476ce7463f6f3534d8f846da5e8179fba2248e5387da0a8ea0f7acd8805c49952f049ea0ebfa1c75df112a
6
+ metadata.gz: f8a319f9b59ce9af8cccf6ee0cd436e7847db90e95703da13ea50cf33d03cd5c5aeb996b87503f2ddc6f7991f18441be7c49a099377a19a89b6c8bd7ceb4eb3b
7
+ data.tar.gz: 9b7e5b5a16f21d256c44f8a491b6f4bc0b60cc507d9124b49b12d6da9c2e487f64b0f2388ecdc4e0d24e10eb4b4f2fd69f5ca190eb5a4f51af9aba7a1123d6ea
data/README.md CHANGED
@@ -8,6 +8,12 @@ The BUY/SELL signals that it generates are part of a game. **DO NOT USE** when
8
8
 
9
9
  I'm making use of lots of gems which may not be part of the gemspec at this time. I will be adding them as they make the final cut as to fitness for the intended function. Some gems are configurable. For example the default for the plotting library is `gruff`. There are several available that the `daru` gem can use.
10
10
 
11
+ ### DARU or RedAmber
12
+
13
+ I'm just really using `daru` for its data frame object; However, I just learned about the RedAmber data frame object in Ruby based off of Apache Arrow. I'm going to look at that product since it is actively maintained.
14
+
15
+ https://github.com/red-data-tools/red_amber
16
+
11
17
  ## Installation
12
18
 
13
19
  Install the gem and add to the application's Gemfile by executing:
@@ -0,0 +1 @@
1
+ 2df18c06074d6725d838fcda7a72d5053859cc677898f799215a223720eadfc6eb393ab765b074926040b7509b6bb8e0a0b13e1181b0d1713951445a87ac7a6e
@@ -1,28 +1,105 @@
1
1
  # lib/sqa/data_frame/yahoo_finance.rb
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'faraday'
5
+ require 'nokogiri'
6
+
4
7
  class SQA::DataFrame < Daru::DataFrame
5
8
  class YahooFinance
6
- def self.load(filename, options={}, &block)
7
- df = SQA::DataFrame.load(filename, options={}, &block)
9
+ CONNECTION = Faraday.new(url: 'https://finance.yahoo.com')
10
+ HEADERS = %i[
11
+ timestamp # 0
12
+ open_price # 1
13
+ high_price # 2
14
+ low_price # 3
15
+ close_price # 4
16
+ adj_close_price # 5
17
+ volume # 6
18
+ ]
8
19
 
9
- # ASSUMPTION: This is the column headers from Yahoo Finance for
10
- # CSV files. If the file type is something different from the
11
- # same source, they may not be the same.
20
+ # The Yahoo Finance Headers are being remapped so that
21
+ # the header can be used as a method name to access the
22
+ # vector.
12
23
  #
13
- new_names = {
14
- "Date" => :timestamp,
15
- "Open" => :open_price,
16
- "High" => :high_price,
17
- "Low" => :low_price,
18
- "Close" => :close_price,
19
- "Adj Close" => :adj_close_price,
20
- "Volume" => :volume
24
+ HEADER_MAPPING = {
25
+ "Date" => HEADERS[0],
26
+ "Open" => HEADERS[1],
27
+ "High" => HEADERS[2],
28
+ "Low" => HEADERS[3],
29
+ "Close" => HEADERS[4],
30
+ "Adj Close" => HEADERS[5],
31
+ "Volume" => HEADERS[6]
21
32
  }
22
33
 
23
- df.rename_vectors(new_names)
34
+ ################################################################
35
+ def self.load(filename, options={}, &block)
36
+ df = SQA::DataFrame.load(filename, options={}, &block)
37
+
38
+ headers = df.vectors
39
+
40
+ if headers.first == HEADERS.first.to_s
41
+ a_hash = {}
42
+ HEADERS.each {|k| a_hash[k.to_s] = k}
43
+ df.rename_vectors(a_hash)
44
+ else
45
+ df.rename_vectors(HEADER_MAPPING)
46
+ end
24
47
 
25
48
  df
26
49
  end
50
+
51
+
52
+ # Scrape the Yahoo Finance website to get recent
53
+ # historical prices for a specific ticker
54
+ #
55
+ # ticker String the security to retrieve
56
+ # returns a DataFrame
57
+ #
58
+ def self.recent(ticker)
59
+ response = CONNECTION.get("/quote/#{ticker.upcase}/history")
60
+ doc = Nokogiri::HTML(response.body)
61
+ table = doc.css('table').first
62
+ rows = table.css('tbody tr')
63
+
64
+ data = []
65
+
66
+ rows.each do |row|
67
+ cols = row.css('td').map{|c| c&.text}
68
+ next if cols[1]&.include?("Dividend")
69
+ cols[0] = Date.parse(cols[0]).to_s
70
+ cols[6] = cols[6].tr(',','').to_i
71
+ (1..5).each {|x| cols[x] = cols[x].to_f}
72
+ data << HEADERS.zip(cols).to_h
73
+ end
74
+
75
+ Daru::DataFrame.new(data)
76
+ end
77
+
78
+
79
+ # Append update_df rows to the base_df
80
+ #
81
+ # base_df is ascending on timestamp
82
+ # update_df is descending on timestamp
83
+ #
84
+ # base_df content came from CSV file downloaded
85
+ # from Yahoo Finance.
86
+ #
87
+ # update_df came from scraping the webpage
88
+ # at Yahoo Finance for the recent history.
89
+ #
90
+ # Returns a combined DataFrame.
91
+ #
92
+ def self.append(base_df, updates_df)
93
+ last_timestamp = Date.parse base_df.timestamp.last
94
+ filtered_df = updates_df.filter_rows { |row| Date.parse(row[:timestamp]) > last_timestamp }
95
+
96
+ last_inx = filtered_df.size - 1
97
+
98
+ (0..last_inx).each do |x|
99
+ base_df.add_row filtered_df.row[last_inx-x]
100
+ end
101
+
102
+ base_df
103
+ end
27
104
  end
28
105
  end
@@ -3,7 +3,37 @@
3
3
 
4
4
  require_relative 'data_frame/yahoo_finance'
5
5
 
6
+ class Daru::DataFrame
7
+
8
+ def to_csv(path_to_file, opts={})
9
+ options = {
10
+ converters: :numeric
11
+ }.merge(opts)
12
+
13
+ writer = ::CSV.open(path_to_file, 'wb')
14
+
15
+ writer << vectors.to_a unless options[:headers] == false
16
+
17
+ each_row do |row|
18
+ writer << if options[:convert_comma]
19
+ row.map { |v| v.to_s.tr('.', ',') }
20
+ else
21
+ row.to_a
22
+ end
23
+ end
24
+
25
+ writer.close
26
+ end
27
+ end
28
+
29
+
30
+
31
+
6
32
  class SQA::DataFrame < Daru::DataFrame
33
+
34
+
35
+ #################################################
36
+
7
37
  def self.path(filename)
8
38
  Pathname.new SQA.config.data_dir + filename
9
39
  end
data/lib/sqa/stock.rb CHANGED
@@ -8,10 +8,24 @@ class SQA::Stock
8
8
  def initialize(ticker:, source: :yahoo_finance, type: :csv)
9
9
  @ticker = ticker.downcase
10
10
  @company_name = "Company Name"
11
- klass = "SQA::DataFrame::#{source.to_s.camelize}".constantize
12
- filename = "#{@ticker}.#{type}"
13
- @df = klass.send(:load, filename)
14
- @df[:ticker] = ticker
11
+ @klass = "SQA::DataFrame::#{source.to_s.camelize}".constantize
12
+ @type = type
13
+ @filename = "#{@ticker}.#{type}"
14
+
15
+ update_the_dataframe
16
+ end
17
+
18
+
19
+ def update_the_dataframe
20
+ df1 = @klass.load(@filename)
21
+ df2 = @klass.recent(@ticker)
22
+ @df = @klass.append(df1, df2)
23
+
24
+ unless @df.size == df1.size
25
+ @df.send("to_#{@type}", SQA::DataFrame.path(@filename))
26
+ end
27
+
28
+ @df[:ticker] = @ticker
15
29
  end
16
30
 
17
31
  def to_s
data/lib/sqa/version.rb CHANGED
@@ -4,7 +4,7 @@ require 'sem_version'
4
4
  require 'sem_version/core_ext'
5
5
 
6
6
  module SQA
7
- VERSION = "0.0.9"
7
+ VERSION = "0.0.10"
8
8
 
9
9
  class << self
10
10
  def version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-08 00:00:00.000000000 Z
11
+ date: 2023-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -278,6 +278,7 @@ files:
278
278
  - Rakefile
279
279
  - bin/sqa
280
280
  - checksums/sqa-0.0.1.gem.sha512
281
+ - checksums/sqa-0.0.10.gem.sha512
281
282
  - checksums/sqa-0.0.2.gem.sha512
282
283
  - checksums/sqa-0.0.3.gem.sha512
283
284
  - checksums/sqa-0.0.4.gem.sha512