sqa 0.0.1 → 0.0.2

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/docs/average_true_range.md +9 -0
  3. data/docs/data_frame.md +164 -0
  4. data/docs/fibonacci_retracement.md +30 -0
  5. data/docs/identify_wave_condition.md +14 -0
  6. data/docs/peaks_and_valleys.md +11 -0
  7. data/docs/stochastic_oscillator.md +4 -0
  8. data/lib/sqa/cli.rb +1 -1
  9. data/lib/sqa/data_frame/yahoo_finance.rb +24 -0
  10. data/lib/sqa/data_frame.rb +11 -0
  11. data/lib/sqa/indicator/average_true_range.rb +22 -9
  12. data/lib/sqa/indicator/bollinger_bands.rb +2 -2
  13. data/lib/sqa/indicator/candlestick_pattern_recognizer.rb +1 -1
  14. data/lib/sqa/indicator/donchian_channel.rb +1 -1
  15. data/lib/sqa/indicator/double_top_bottom_pattern.rb +1 -1
  16. data/lib/sqa/indicator/elliott_wave_theory.rb +57 -0
  17. data/lib/sqa/indicator/exponential_moving_average.rb +25 -0
  18. data/lib/sqa/indicator/exponential_moving_average_trend.rb +36 -0
  19. data/lib/sqa/indicator/fibonacci_retracement.rb +5 -7
  20. data/lib/sqa/indicator/head_and_shoulders_pattern.rb +1 -1
  21. data/lib/sqa/indicator/{classify_market_profile.rb → market_profile.rb} +7 -8
  22. data/lib/sqa/indicator/mean_reversion.rb +1 -1
  23. data/lib/sqa/indicator/momentum.rb +9 -7
  24. data/lib/sqa/indicator/moving_average_convergence_divergence.rb +1 -1
  25. data/lib/sqa/indicator/peaks_and_valleys.rb +29 -0
  26. data/lib/sqa/indicator/{relative_strength_index.md.rb → relative_strength_index.rb} +2 -2
  27. data/lib/sqa/indicator/simple_moving_average.rb +6 -3
  28. data/lib/sqa/indicator/simple_moving_average_trend.rb +15 -14
  29. data/lib/sqa/indicator/stochastic_oscillator.rb +32 -3
  30. data/lib/sqa/indicator/true_range.rb +14 -12
  31. data/lib/sqa/indicator.rb +4 -4
  32. data/lib/sqa/stock.rb +6 -13
  33. data/lib/sqa/version.rb +1 -1
  34. data/lib/sqa.rb +27 -6
  35. metadata +30 -29
  36. data/lib/sqa/datastore/active_record.rb +0 -89
  37. data/lib/sqa/datastore/csv/yahoo_finance.rb +0 -51
  38. data/lib/sqa/datastore/csv.rb +0 -93
  39. data/lib/sqa/datastore/sqlite.rb +0 -7
  40. data/lib/sqa/datastore.rb +0 -6
  41. data/lib/sqa/indicator/average_true_range.md +0 -9
  42. data/lib/sqa/indicator/ema_analysis.rb +0 -70
  43. data/lib/sqa/indicator/fibonacci_retracement.md +0 -3
  44. data/lib/sqa/indicator/identify_wave_condition.md +0 -6
  45. data/lib/sqa/indicator/identify_wave_condition.rb +0 -40
  46. data/lib/sqa/indicator/stochastic_oscillator.md +0 -5
  47. /data/{lib/sqa/indicator → docs}/README.md +0 -0
  48. /data/{lib/sqa/indicator → docs}/bollinger_bands.md +0 -0
  49. /data/{lib/sqa/indicator → docs}/candlestick_pattern_recognizer.md +0 -0
  50. /data/{lib/sqa/indicator → docs}/donchian_channel.md +0 -0
  51. /data/{lib/sqa/indicator → docs}/double_top_bottom_pattern.md +0 -0
  52. /data/{lib/sqa/indicator/ema_analysis.md → docs/exponential_moving_average.md} +0 -0
  53. /data/{lib/sqa/indicator → docs}/head_and_shoulders_pattern.md +0 -0
  54. /data/{lib/sqa/indicator/classify_market_profile.md → docs/market_profile.md} +0 -0
  55. /data/{lib/sqa/indicator → docs}/mean_reversion.md +0 -0
  56. /data/{lib/sqa/indicator → docs}/momentum.md +0 -0
  57. /data/{lib/sqa/indicator → docs}/moving_average_convergence_divergence.md +0 -0
  58. /data/{lib/sqa/indicator → docs}/relative_strength_index.md +0 -0
  59. /data/{lib/sqa/indicator → docs}/simple_moving_average.md +0 -0
  60. /data/{lib/sqa/indicator → docs}/true_range.md +0 -0
@@ -1,12 +1,12 @@
1
1
  # lib/sqa/indicator/relative_strength_index.rb
2
2
 
3
- module SQA::Indicator; class << self
3
+ class SQA::Indicator; class << self
4
4
 
5
5
  def relative_strength_index(
6
6
  prices, # Array of prices
7
7
  period, # Integer how many to consider at a time
8
8
  over_sold = 30.0, # Float break over point in trend
9
- over_boufht = 70.0 # Float break over point in trend
9
+ over_bought = 70.0 # Float break over point in trend
10
10
  )
11
11
  gains = []
12
12
  losses = []
@@ -1,6 +1,6 @@
1
1
  # lib/sqa/indicator/simple_moving_average.rb
2
2
 
3
- module SQA::Indicator; class << self
3
+ class SQA::Indicator; class << self
4
4
 
5
5
  def simple_moving_average(
6
6
  prices, # Array of prices
@@ -8,9 +8,12 @@ module SQA::Indicator; class << self
8
8
  )
9
9
  moving_averages = []
10
10
 
11
+ (0..period-2).to_a.each do |x|
12
+ moving_averages << prices[0..x].mean
13
+ end
14
+
11
15
  prices.each_cons(period) do |window|
12
- moving_average = window.sum / period.to_f
13
- moving_averages << moving_average
16
+ moving_averages << window.mean
14
17
  end
15
18
 
16
19
  moving_averages # Array
@@ -1,28 +1,29 @@
1
1
  # lib/sqa/indicator/simple_moving_average_trend.rb
2
2
 
3
- module SQA::Indicator; class << self
3
+ class SQA::Indicator; class << self
4
4
 
5
5
  def simple_moving_average_trend(
6
- closing_prices, # Array of closing prices
6
+ prices, # Array of prices
7
7
  period, # Integer number of entries to consider
8
- delta = 0.0005 # Float defines a :nutria trend range.
8
+ delta = 1.0 # Float defines the angle range(+/-) for :neutral trend
9
9
  )
10
- sma = simple_moving_average(closing_prices, period)
10
+ sma = simple_moving_average(prices, period)
11
11
  last_sma = sma.last
12
- prev_sma = sma[-2]
12
+ prev_sma = sma.last(period).first
13
13
  angle = Math.atan((last_sma - prev_sma) / period) * (180 / Math::PI)
14
14
 
15
- if angle > 0.0
16
- trend = :up
17
- elsif angle < 0.0
18
- trend = :down
19
- else
20
- trend = :neutral
21
- end
15
+ trend = if angle > delta
16
+ :up
17
+ elsif angle < -delta
18
+ :down
19
+ else
20
+ :neutral
21
+ end
22
22
 
23
23
  {
24
- trend: trend, # Symbol :up, :down, :neutral
25
- angle: angle # Float how step the trend
24
+ sma: sma, # Array
25
+ trend: trend, # Symbol :up, :down, :neutral
26
+ angle: angle # Float how step the trend
26
27
  }
27
28
  end
28
29
  alias_method :sma_trend, :simple_moving_average_trend
@@ -1,6 +1,6 @@
1
1
  # lib/sqa/indicator/stochastic_oscillator.rb
2
2
 
3
- module SQA::Indicator; class << self
3
+ class SQA::Indicator; class << self
4
4
 
5
5
  # @param high_prices [Array]
6
6
  # @param low_prices [Array]
@@ -20,10 +20,10 @@ module SQA::Indicator; class << self
20
20
  k_values = []
21
21
  d_values = []
22
22
 
23
- closing_prices.each_cons(period) do |closing_prices_subset|
23
+ closing_prices.each_cons(period) do |window|
24
24
  highest_high = high_prices.max(period)
25
25
  lowest_low = low_prices.min(period)
26
- current_close = closing_prices_subset.last
26
+ current_close = window.last
27
27
  k_values << (current_close - lowest_low) / (highest_high - lowest_low) * 100 # Calculate the k_value
28
28
  end
29
29
 
@@ -35,5 +35,34 @@ module SQA::Indicator; class << self
35
35
  end
36
36
  alias_method :so, :stochastic_oscillator
37
37
 
38
+
39
+ def stochastic_oscillator2(
40
+ prices, # Array of prices
41
+ period # Integer number of events to consider
42
+ )
43
+ k_values = []
44
+ d_values = []
45
+
46
+ prices.each_cons(period) do |window|
47
+ low = window.min # Lowest price in the period
48
+ high = window.max # Highest price in the period
49
+ current_price = window.last # Current closing price
50
+
51
+ k_values << (current_price - low) * 100 / (high - low)
52
+ end
53
+
54
+ k_values.each_cons(period) do |window|
55
+ d_values << window.mean
56
+ end
57
+
58
+ {
59
+ k: k_values,
60
+ d: d_values
61
+ }
62
+ end
63
+ alias_method :so2, :stochastic_oscillator2
64
+
65
+
66
+
38
67
  end; end
39
68
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  # See Also: average_true_range
4
4
 
5
- module SQA::Indicator; class << self
5
+ class SQA::Indicator; class << self
6
6
 
7
7
  # @param high_prices [Array]
8
8
  # @param low_prices [Array]
@@ -13,21 +13,23 @@ module SQA::Indicator; class << self
13
13
  def true_range(
14
14
  high_prices, # Array of high prices
15
15
  low_prices, # Array of low prices
16
- previous_closes # Array of previous closing prices
16
+ closing_prices # Array of closing prices
17
17
  )
18
18
  true_ranges = []
19
19
 
20
20
  high_prices.each_with_index do |high, index|
21
- low = low_prices[index]
22
- previous_close = previous_closes[index]
23
-
24
- true_range = [
25
- high - low,
26
- (high - previous_close).abs,
27
- (low - previous_close).abs
28
- ].max
29
-
30
- true_ranges << true_range
21
+ if index > 0
22
+ low = low_prices[index]
23
+ previous_close = closing_prices[index - 1]
24
+
25
+ true_range = [
26
+ high - low,
27
+ (high - previous_close).abs,
28
+ (low - previous_close).abs
29
+ ].max
30
+
31
+ true_ranges << true_range
32
+ end
31
33
  end
32
34
 
33
35
  true_ranges # Array of True Range values
data/lib/sqa/indicator.rb CHANGED
@@ -1,11 +1,11 @@
1
- # lib/sqa/indicators.rb
1
+ # lib/sqa/indicator.rb
2
2
 
3
- module SQA::Indicator
3
+ class SQA::Indicator
4
4
  end
5
5
 
6
6
  # setup a shortcut for the namespace
7
7
  SQAI = SQA::Indicator
8
8
 
9
- Dir["indicator/*.rb"].each do |file|
10
- require_relative file
9
+ Dir[__dir__ + "/indicator/*.rb"].each do |file|
10
+ load file
11
11
  end
data/lib/sqa/stock.rb CHANGED
@@ -1,26 +1,19 @@
1
1
  # lib/sqa/stock.rb
2
2
 
3
- require_relative 'indicators'
4
- require_relative 'datastore'
5
-
6
- class SQA::Stock < ActiveRecord::Base
7
- include SQA::Indicators
8
-
9
- # has_many :activities using ticker as the foreign key
10
- # primary id is ticker it is unique
11
-
3
+ class SQA::Stock
12
4
  attr_accessor :company_name
13
- attr_accessor :data
5
+ attr_accessor :df # The DataFrane
14
6
  attr_accessor :ticker
15
7
 
16
- def initialize(ticker, datastore = SQA::Datastore::CSV)
8
+ def initialize(ticker:, source: :yahoo_finance, type: :csv)
17
9
  @ticker = ticker
18
10
  @company_name = "Company Name"
19
- @data = datastore.new(ticker)
11
+ klass = "SQA::DataFrame::#{source.to_s.camelize}".constantize
12
+ @df = klass.send("from_#{type.downcase}", ticker)
20
13
  end
21
14
 
22
15
  def to_s
23
- "#{ticker} with #{@data.size} data points."
16
+ "#{ticker} with #{@df.size} data points from #{@df.timestamp.first} to #{@df.timestamp.last}"
24
17
  end
25
18
  end
26
19
 
data/lib/sqa/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SQA
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
  end
data/lib/sqa.rb CHANGED
@@ -1,12 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module SQA
4
- end
5
-
6
- require 'csv'
3
+ require 'active_support'
4
+ require 'active_support/core_ext/string'
5
+ require 'daru'
7
6
  require 'date'
8
- require 'json'
7
+
8
+ require 'debug_me'
9
+ include DebugMe
10
+
11
+ require 'descriptive_statistics'
12
+ require 'mixlib/config'
13
+ require 'nenv'
9
14
  require 'pathname'
10
15
 
11
- require_relative "sqa/version"
16
+ unless defined?(HOME)
17
+ HOME = Pathname.new(Nenv.home)
18
+ end
19
+
20
+ module SQA
21
+ module Config
22
+ extend Mixlib::Config
23
+ config_strict_mode true
24
+
25
+ default :data_dir, HOME + "sqa_data"
26
+ end
27
+ end
28
+
29
+ require_relative "sqa/data_frame"
12
30
  require_relative "sqa/errors"
31
+ require_relative "sqa/indicator"
32
+ require_relative "sqa/stock"
33
+ require_relative "sqa/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.1
4
+ version: 0.0.2
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-08-12 00:00:00.000000000 Z
11
+ date: 2023-08-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Simplistic playpen (e.g. not for serious use) for doing technical analysis
14
14
  of stock prices.
@@ -26,52 +26,53 @@ files:
26
26
  - Rakefile
27
27
  - bin/sqa
28
28
  - checksums/sqa-0.0.1.gem.sha512
29
+ - docs/README.md
30
+ - docs/average_true_range.md
31
+ - docs/bollinger_bands.md
32
+ - docs/candlestick_pattern_recognizer.md
33
+ - docs/data_frame.md
34
+ - docs/donchian_channel.md
35
+ - docs/double_top_bottom_pattern.md
36
+ - docs/exponential_moving_average.md
37
+ - docs/fibonacci_retracement.md
38
+ - docs/head_and_shoulders_pattern.md
39
+ - docs/identify_wave_condition.md
40
+ - docs/market_profile.md
41
+ - docs/mean_reversion.md
42
+ - docs/momentum.md
43
+ - docs/moving_average_convergence_divergence.md
44
+ - docs/peaks_and_valleys.md
45
+ - docs/relative_strength_index.md
29
46
  - docs/requirements.md
47
+ - docs/simple_moving_average.md
48
+ - docs/stochastic_oscillator.md
49
+ - docs/true_range.md
30
50
  - lib/sqa.rb
31
51
  - lib/sqa/activity.rb
32
52
  - lib/sqa/cli.rb
33
- - lib/sqa/datastore.rb
34
- - lib/sqa/datastore/active_record.rb
35
- - lib/sqa/datastore/csv.rb
36
- - lib/sqa/datastore/csv/yahoo_finance.rb
37
- - lib/sqa/datastore/sqlite.rb
53
+ - lib/sqa/data_frame.rb
54
+ - lib/sqa/data_frame/yahoo_finance.rb
38
55
  - lib/sqa/errors.rb
39
56
  - lib/sqa/indicator.rb
40
- - lib/sqa/indicator/README.md
41
- - lib/sqa/indicator/average_true_range.md
42
57
  - lib/sqa/indicator/average_true_range.rb
43
- - lib/sqa/indicator/bollinger_bands.md
44
58
  - lib/sqa/indicator/bollinger_bands.rb
45
- - lib/sqa/indicator/candlestick_pattern_recognizer.md
46
59
  - lib/sqa/indicator/candlestick_pattern_recognizer.rb
47
- - lib/sqa/indicator/classify_market_profile.md
48
- - lib/sqa/indicator/classify_market_profile.rb
49
- - lib/sqa/indicator/donchian_channel.md
50
60
  - lib/sqa/indicator/donchian_channel.rb
51
- - lib/sqa/indicator/double_top_bottom_pattern.md
52
61
  - lib/sqa/indicator/double_top_bottom_pattern.rb
53
- - lib/sqa/indicator/ema_analysis.md
54
- - lib/sqa/indicator/ema_analysis.rb
55
- - lib/sqa/indicator/fibonacci_retracement.md
62
+ - lib/sqa/indicator/elliott_wave_theory.rb
63
+ - lib/sqa/indicator/exponential_moving_average.rb
64
+ - lib/sqa/indicator/exponential_moving_average_trend.rb
56
65
  - lib/sqa/indicator/fibonacci_retracement.rb
57
- - lib/sqa/indicator/head_and_shoulders_pattern.md
58
66
  - lib/sqa/indicator/head_and_shoulders_pattern.rb
59
- - lib/sqa/indicator/identify_wave_condition.md
60
- - lib/sqa/indicator/identify_wave_condition.rb
61
- - lib/sqa/indicator/mean_reversion.md
67
+ - lib/sqa/indicator/market_profile.rb
62
68
  - lib/sqa/indicator/mean_reversion.rb
63
- - lib/sqa/indicator/momentum.md
64
69
  - lib/sqa/indicator/momentum.rb
65
- - lib/sqa/indicator/moving_average_convergence_divergence.md
66
70
  - lib/sqa/indicator/moving_average_convergence_divergence.rb
67
- - lib/sqa/indicator/relative_strength_index.md
68
- - lib/sqa/indicator/relative_strength_index.md.rb
69
- - lib/sqa/indicator/simple_moving_average.md
71
+ - lib/sqa/indicator/peaks_and_valleys.rb
72
+ - lib/sqa/indicator/relative_strength_index.rb
70
73
  - lib/sqa/indicator/simple_moving_average.rb
71
74
  - lib/sqa/indicator/simple_moving_average_trend.rb
72
- - lib/sqa/indicator/stochastic_oscillator.md
73
75
  - lib/sqa/indicator/stochastic_oscillator.rb
74
- - lib/sqa/indicator/true_range.md
75
76
  - lib/sqa/indicator/true_range.rb
76
77
  - lib/sqa/protfolio.rb
77
78
  - lib/sqa/stock.rb
@@ -1,89 +0,0 @@
1
- # lib/sqa/datastore/active_record.rb
2
-
3
-
4
- require 'active_record'
5
- require 'sqlite3'
6
-
7
-
8
- module SQA::Datastore
9
- class ActiveRecord
10
- def initialize(ticker); end
11
- end
12
- end
13
-
14
-
15
- __END__
16
-
17
- # An example of how to use active record with sqlite3 ...
18
-
19
- #!/usr/bin/env ruby
20
- # See: https://gist.github.com/unnitallman/944011
21
-
22
- require 'active_record'
23
- require 'sqlite3'
24
-
25
- ActiveRecord::Base.logger = Logger.new(STDERR)
26
- # TDV ActiveRecord::Base.colorize_logging = false
27
-
28
- ActiveRecord::Base.establish_connection(
29
- adapter: "sqlite3",
30
- database: './database.db'
31
- )
32
-
33
- ActiveRecord::Schema.define do
34
- create_table :albums do |table|
35
- table.column :title, :string
36
- table.column :performer, :string
37
- end
38
-
39
- create_table :tracks do |table|
40
- table.column :album_id, :integer
41
- table.column :track_number, :integer
42
- table.column :title, :string
43
- end
44
- end
45
-
46
- class Album < ActiveRecord::Base
47
- has_many :tracks
48
- end
49
-
50
- class Track < ActiveRecord::Base
51
- belongs_to :album
52
- end
53
-
54
- album = Album.create(:title => 'Black and Blue',
55
- :performer => 'The Rolling Stones')
56
- album.tracks.create(:track_number => 1, :title => 'Hot Stuff')
57
- album.tracks.create(:track_number => 2, :title => 'Hand Of Fate')
58
- album.tracks.create(:track_number => 3, :title => 'Cherry Oh Baby ')
59
- album.tracks.create(:track_number => 4, :title => 'Memory Motel ')
60
- album.tracks.create(:track_number => 5, :title => 'Hey Negrita')
61
- album.tracks.create(:track_number => 6, :title => 'Fool To Cry')
62
- album.tracks.create(:track_number => 7, :title => 'Crazy Mama')
63
- album.tracks.create(:track_number => 8,
64
- :title => 'Melody (Inspiration By Billy Preston)')
65
-
66
- album = Album.create(:title => 'Sticky Fingers',
67
- :performer => 'The Rolling Stones')
68
- album.tracks.create(:track_number => 1, :title => 'Brown Sugar')
69
- album.tracks.create(:track_number => 2, :title => 'Sway')
70
- album.tracks.create(:track_number => 3, :title => 'Wild Horses')
71
- album.tracks.create(:track_number => 4,
72
- :title => 'Can\'t You Hear Me Knocking')
73
- album.tracks.create(:track_number => 5, :title => 'You Gotta Move')
74
- album.tracks.create(:track_number => 6, :title => 'Bitch')
75
- album.tracks.create(:track_number => 7, :title => 'I Got The Blues')
76
- album.tracks.create(:track_number => 8, :title => 'Sister Morphine')
77
- album.tracks.create(:track_number => 9, :title => 'Dead Flowers')
78
- album.tracks.create(:track_number => 10, :title => 'Moonlight Mile')
79
-
80
- puts Album.find(1).tracks.length
81
- puts Album.find(2).tracks.length
82
-
83
- puts Album.find_by_title('Sticky Fingers').title
84
- puts Track.find_by_title('Fool To Cry').album_id
85
-
86
-
87
-
88
-
89
-
@@ -1,51 +0,0 @@
1
- # lib/sqa/datastore/csv/yahoo_finance.rb
2
-
3
- # processes a CSV file downloaded from finance.yahoo.com
4
- # Date,Open,High,Low,Close,Adj Close,Volume
5
-
6
- require 'csv-importer'
7
-
8
- class SQA::Datastore::CSV::YahooFinance
9
- include CSVImporter
10
-
11
- model ::SQA::Activity # an active record like model
12
-
13
- column :date, to: ->(x) { Date.parse(x)}, required: true
14
- column :open, to: ->(x) {x.to_f}, required: true
15
- column :high, to: ->(x) {x.to_f}, required: true
16
- column :low, to: ->(x) {x.to_f}, required: true
17
- column :close, to: ->(x) {x.to_f}, required: true
18
- column :adj_close, to: ->(x) {x.to_f}, required: true
19
- column :volumn, to: ->(x) {x.to_i}, required: true
20
-
21
- # TODO: make the identifier compound [ticker, date]
22
- # so we can put all the data into a single table.
23
-
24
- identifier :date
25
-
26
- when_invalid :skip # or :abort
27
-
28
-
29
- column :email, to: ->(email) { email.downcase }, required: true
30
- column :first_name, as: [ /first.?name/i, /pr(é|e)nom/i ]
31
- column :last_name, as: [ /last.?name/i, "nom" ]
32
- column :published, to: ->(published, user) { user.published_at = published ? Time.now : nil }
33
-
34
-
35
-
36
-
37
- def self.load(ticker)
38
- import = new(file: "#{ticker.upcase}.csv")
39
-
40
- import.valid_header? # => false
41
- import.report.message # => "The following columns are required: email"
42
-
43
- # Assuming the header was valid, let's run the import!
44
-
45
- import.run!
46
- import.report.success? # => true
47
- import.report.message # => "Import completed. 4 created, 2 updated, 1 failed to update" end
48
-
49
- end
50
- end
51
-
@@ -1,93 +0,0 @@
1
- # lib/sqa/datastore/csv.rb
2
-
3
- require 'csv'
4
- require 'forwardable'
5
-
6
- module SQA::Datastore
7
- class CSV
8
- extend Forwardable
9
- def_delegators :@data, :first, :last, :size, :empty?, :[], :map, :select, :reject
10
-
11
- SOURCE_DOMAIN = "https://query1.finance.yahoo.com/v7/finance/download/"
12
- # curl -o AAPL.csv -L --url "https://query1.finance.yahoo.com/v7/finance/download/AAPL?period1=345427200&period2=1691712000&interval=1d&events=history&includeAdjustedClose=true"
13
-
14
-
15
- attr_accessor :ticker
16
- attr_accessor :data
17
-
18
- def initialize(ticker, adapter = YahooFinance)
19
- @ticker = ticker
20
- @data_path = Pathname.pwd + "#{ticker.downcase}.csv"
21
- @adapter = adapter
22
- @data = adapter.load(ticker)
23
- end
24
-
25
-
26
- #######################################################################
27
- # Read the CSV file associated with the give ticker symbol
28
- #
29
- # def read_csv_data
30
- # download_historical_prices unless @data_path.exist?
31
-
32
- # csv_data = []
33
-
34
- # ::CSV.foreach(@data_path, headers: true) do |row|
35
- # csv_data << row.to_h
36
- # end
37
-
38
- # csv_data
39
- # end
40
-
41
- #######################################################################
42
- # download a CSV file from https://query1.finance.yahoo.com
43
- # given a stock ticker symbol as a String
44
- # start and end dates
45
- #
46
- # For ticker "aapl" the downloaded file will be named "aapl.csv"
47
- # That filename will be renamed to "aapl_YYYYmmdd.csv" where the
48
- # date suffix is the end_date of the historical data.
49
- #
50
- # def download_historical_prices(
51
- # start_date: Date.new(2019, 1, 1),
52
- # end_date: previous_dow(:friday, Date.today)
53
- # )
54
-
55
- # start_timestamp = start_date.to_time.to_i # Convert to unix timestamp
56
- # end_timestamp = end_date.to_time.to_i
57
-
58
- # user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0"
59
-
60
- # # TODO: replace curl with Faraday
61
-
62
- # `curl -A "#{user_agent}" --cookie-jar cookies.txt -o #{@data_path} -L --url "#{SOURCE_DOMAIN}/#{ticker.upcase}?period1=#{start_timestamp}&period2=#{end_timestamp}&interval=1d&events=history&includeAdjustedClose=true"`
63
-
64
- # check_csv_file
65
- # end
66
-
67
-
68
- # def check_csv_file
69
- # f = File.open(@data_path, 'r')
70
- # c1 = f.read(1)
71
-
72
- # if '{' == c1
73
- # error_msg = JSON.parse("#{c1}#{f.read}")
74
- # raise "Not OK: #{error_msg}"
75
- # end
76
- # end
77
- end
78
- end
79
-
80
- __END__
81
-
82
- {
83
- "finance": {
84
- "error": {
85
- "code": "Unauthorized",
86
- "description": "Invalid cookie"
87
- }
88
- }
89
- }
90
-
91
-
92
-
93
-
@@ -1,7 +0,0 @@
1
- # lib/sqa/datastore/sqlite.rb
2
-
3
- module Datastore
4
- class Sqlite
5
- def initialize(ticker); end
6
- end
7
- end
data/lib/sqa/datastore.rb DELETED
@@ -1,6 +0,0 @@
1
- # lib/sqa/datastore.rb
2
-
3
- require_relative 'datastore/csv'
4
- require_relative 'datastore/active_record'
5
-
6
- # require_relative 'datastore/sqlite'
@@ -1,9 +0,0 @@
1
- # Average True Range
2
-
3
- Calculates the Average True Range (ATR) for a given set of price data.
4
-
5
- The Average True Range is an indicator that calculates the average of the True Range values over a specified period. It provides a measure of the average volatility of a security over that period.
6
-
7
- The ATR is commonly used to assess the volatility of a security, identify potential trend reversals, and determine appropriate stop-loss levels. Higher ATR values indicate higher volatility, while lower ATR values indicate lower volatility.
8
-
9
- For example, a 14-day Average True Range would calculate the average of the True Range values over the past 14 trading days. Traders and analysts may use this indicator to set stop-loss levels based on the average volatility of the security.