sqa 0.0.1 → 0.0.3

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.irbrc +3 -0
  3. data/checksums/sqa-0.0.2.gem.sha512 +1 -0
  4. data/docs/average_true_range.md +9 -0
  5. data/docs/data_frame.md +164 -0
  6. data/docs/fibonacci_retracement.md +30 -0
  7. data/docs/identify_wave_condition.md +14 -0
  8. data/docs/peaks_and_valleys.md +11 -0
  9. data/docs/requirements.md +22 -0
  10. data/docs/stochastic_oscillator.md +4 -0
  11. data/docs/strategy.md +5 -0
  12. data/lib/sqa/cli.rb +1 -1
  13. data/lib/sqa/data_frame/yahoo_finance.rb +24 -0
  14. data/lib/sqa/data_frame.rb +16 -0
  15. data/lib/sqa/indicator/average_true_range.rb +22 -9
  16. data/lib/sqa/indicator/bollinger_bands.rb +2 -2
  17. data/lib/sqa/indicator/candlestick_pattern_recognizer.rb +1 -1
  18. data/lib/sqa/indicator/donchian_channel.rb +1 -1
  19. data/lib/sqa/indicator/double_top_bottom_pattern.rb +1 -1
  20. data/lib/sqa/indicator/elliott_wave_theory.rb +57 -0
  21. data/lib/sqa/indicator/exponential_moving_average.rb +25 -0
  22. data/lib/sqa/indicator/exponential_moving_average_trend.rb +36 -0
  23. data/lib/sqa/indicator/fibonacci_retracement.rb +5 -7
  24. data/lib/sqa/indicator/head_and_shoulders_pattern.rb +1 -1
  25. data/lib/sqa/indicator/{classify_market_profile.rb → market_profile.rb} +7 -8
  26. data/lib/sqa/indicator/mean_reversion.rb +1 -1
  27. data/lib/sqa/indicator/momentum.rb +9 -7
  28. data/lib/sqa/indicator/moving_average_convergence_divergence.rb +7 -3
  29. data/lib/sqa/indicator/peaks_and_valleys.rb +29 -0
  30. data/lib/sqa/indicator/{relative_strength_index.md.rb → relative_strength_index.rb} +2 -2
  31. data/lib/sqa/indicator/simple_moving_average.rb +6 -3
  32. data/lib/sqa/indicator/simple_moving_average_trend.rb +15 -14
  33. data/lib/sqa/indicator/stochastic_oscillator.rb +32 -3
  34. data/lib/sqa/indicator/true_range.rb +14 -12
  35. data/lib/sqa/indicator.rb +4 -4
  36. data/lib/sqa/stock.rb +6 -13
  37. data/lib/sqa/strategy.rb +65 -0
  38. data/lib/sqa/version.rb +3 -1
  39. data/lib/sqa.rb +44 -6
  40. metadata +34 -29
  41. data/lib/sqa/datastore/active_record.rb +0 -89
  42. data/lib/sqa/datastore/csv/yahoo_finance.rb +0 -51
  43. data/lib/sqa/datastore/csv.rb +0 -93
  44. data/lib/sqa/datastore/sqlite.rb +0 -7
  45. data/lib/sqa/datastore.rb +0 -6
  46. data/lib/sqa/indicator/average_true_range.md +0 -9
  47. data/lib/sqa/indicator/ema_analysis.rb +0 -70
  48. data/lib/sqa/indicator/fibonacci_retracement.md +0 -3
  49. data/lib/sqa/indicator/identify_wave_condition.md +0 -6
  50. data/lib/sqa/indicator/identify_wave_condition.rb +0 -40
  51. data/lib/sqa/indicator/stochastic_oscillator.md +0 -5
  52. /data/{lib/sqa/indicator → docs}/README.md +0 -0
  53. /data/{lib/sqa/indicator → docs}/bollinger_bands.md +0 -0
  54. /data/{lib/sqa/indicator → docs}/candlestick_pattern_recognizer.md +0 -0
  55. /data/{lib/sqa/indicator → docs}/donchian_channel.md +0 -0
  56. /data/{lib/sqa/indicator → docs}/double_top_bottom_pattern.md +0 -0
  57. /data/{lib/sqa/indicator/ema_analysis.md → docs/exponential_moving_average.md} +0 -0
  58. /data/{lib/sqa/indicator → docs}/head_and_shoulders_pattern.md +0 -0
  59. /data/{lib/sqa/indicator/classify_market_profile.md → docs/market_profile.md} +0 -0
  60. /data/{lib/sqa/indicator → docs}/mean_reversion.md +0 -0
  61. /data/{lib/sqa/indicator → docs}/momentum.md +0 -0
  62. /data/{lib/sqa/indicator → docs}/moving_average_convergence_divergence.md +0 -0
  63. /data/{lib/sqa/indicator → docs}/relative_strength_index.md +0 -0
  64. /data/{lib/sqa/indicator → docs}/simple_moving_average.md +0 -0
  65. /data/{lib/sqa/indicator → docs}/true_range.md +0 -0
@@ -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.
@@ -1,70 +0,0 @@
1
- # lib/sqa/indicator/ema_analysis.rb
2
-
3
- module SQA::Indicator; class << self
4
-
5
- def ema_analysis(
6
- prices, # Array of prices
7
- period # Integer number of entries to consider
8
- )
9
- return {} if prices.empty? || period <= 0
10
-
11
- ema_values = []
12
- ema_values << prices.first
13
-
14
- multiplier = (2.0 / (period + 1))
15
-
16
- (1...prices.length).each do |i|
17
- ema = (prices[i] - ema_values.last) * multiplier + ema_values.last
18
- ema_values << ema.round(2)
19
- end
20
-
21
- analysis = {}
22
-
23
- analysis[:ema_values] = ema_values
24
- analysis[:trend] = ema_determine_trend(ema_values)
25
- analysis[:support] = ema_determine_support(ema_values)
26
- analysis[:resistance] = ema_determine_resistance(ema_values)
27
-
28
- analysis
29
- end
30
-
31
-
32
- # @param ema_values [Array] An array of EMA values.
33
- # @return [Symbol] The trend: :up, :down, or :sideways.
34
- #
35
- private def ema_determine_trend(ema_values)
36
- return :sideways if ema_values.empty?
37
-
38
- last_ema = ema_values.last
39
- previous_ema = ema_values[-2]
40
-
41
- if last_ema > previous_ema
42
- :up
43
- elsif last_ema < previous_ema
44
- :down
45
- else
46
- :sideways
47
- end
48
- end
49
-
50
-
51
- # @param ema_values [Array] An array of EMA values.
52
- # @return [Float] The support level.
53
- #
54
- private def ema_determine_support(ema_values)
55
- return 0.0 if ema_values.empty?
56
-
57
- ema_values.min
58
- end
59
-
60
-
61
- # @param ema_values [Array] An array of EMA values.
62
- # @return [Float] The resistance level.
63
- private def ema_determine_resistance(ema_values)
64
- return 0.0 if ema_values.empty?
65
-
66
- ema_values.max
67
- end
68
-
69
- end; end
70
-
@@ -1,3 +0,0 @@
1
- # Fibonacci Retracement
2
-
3
- Fibonacci retracement uses Fibonacci ratios to identify potential support and resistance levels based on the price's previous significant moves.
@@ -1,6 +0,0 @@
1
- # Wave Theory
2
-
3
- Wave theory, such as Elliott Wave Theory, suggests that price movements follow repetitive patterns or waves. It aims to identify and predict these patterns to make trading decisions.
4
-
5
- Identifies a wave condition in a stock's price history based on a given price series.
6
-
@@ -1,40 +0,0 @@
1
- # lib/sqa/indicator/identify_wave_condition.rb
2
-
3
- module SQA::Indicator; class << self
4
-
5
- def identify_wave_condition?(
6
- prices, # Array of prices
7
- wave_length, # Integer expected length of a wave pattern
8
- tolerance # Float delta change in price that would indicate a wave
9
- )
10
- return false if prices.length < wave_length
11
-
12
- wave_start = 0
13
- wave_end = wave_length - 1
14
-
15
- while wave_end < prices.length
16
- wave = prices[wave_start..wave_end]
17
-
18
- if wave.length == wave_length &&
19
- wave_pattern?(wave, tolerance)
20
- return true
21
- end
22
-
23
- wave_start += 1
24
- wave_end += 1
25
- end
26
-
27
- false
28
- end
29
-
30
-
31
- private def wave_pattern?(wave, tolerance)
32
- wave.each_cons(2) do |a, b|
33
- return false if (b - a).abs > tolerance
34
- end
35
-
36
- true
37
- end
38
-
39
- end; end
40
-
@@ -1,5 +0,0 @@
1
- # Stochastic Oscillator
2
-
3
- Calculates the Stochastic Oscillator for a given set of price data.
4
-
5
- Stochastic Oscillator: The Stochastic Oscillator compares a security's closing price to its price range over a specified period. It helps identify potential trend reversals and overbought/oversold conditions.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes