sqa 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc +4 -0
  3. data/CHANGELOG.md +5 -0
  4. data/LICENSE +21 -0
  5. data/README.md +29 -0
  6. data/Rakefile +4 -0
  7. data/bin/sqa +6 -0
  8. data/checksums/sqa-0.0.1.gem.sha512 +1 -0
  9. data/docs/requirements.md +40 -0
  10. data/lib/sqa/activity.rb +10 -0
  11. data/lib/sqa/cli.rb +310 -0
  12. data/lib/sqa/datastore/active_record.rb +89 -0
  13. data/lib/sqa/datastore/csv/yahoo_finance.rb +51 -0
  14. data/lib/sqa/datastore/csv.rb +93 -0
  15. data/lib/sqa/datastore/sqlite.rb +7 -0
  16. data/lib/sqa/datastore.rb +6 -0
  17. data/lib/sqa/errors.rb +5 -0
  18. data/lib/sqa/indicator/README.md +33 -0
  19. data/lib/sqa/indicator/average_true_range.md +9 -0
  20. data/lib/sqa/indicator/average_true_range.rb +30 -0
  21. data/lib/sqa/indicator/bollinger_bands.md +15 -0
  22. data/lib/sqa/indicator/bollinger_bands.rb +28 -0
  23. data/lib/sqa/indicator/candlestick_pattern_recognizer.md +4 -0
  24. data/lib/sqa/indicator/candlestick_pattern_recognizer.rb +60 -0
  25. data/lib/sqa/indicator/classify_market_profile.md +4 -0
  26. data/lib/sqa/indicator/classify_market_profile.rb +33 -0
  27. data/lib/sqa/indicator/donchian_channel.md +5 -0
  28. data/lib/sqa/indicator/donchian_channel.rb +29 -0
  29. data/lib/sqa/indicator/double_top_bottom_pattern.md +3 -0
  30. data/lib/sqa/indicator/double_top_bottom_pattern.rb +34 -0
  31. data/lib/sqa/indicator/ema_analysis.md +19 -0
  32. data/lib/sqa/indicator/ema_analysis.rb +70 -0
  33. data/lib/sqa/indicator/fibonacci_retracement.md +3 -0
  34. data/lib/sqa/indicator/fibonacci_retracement.rb +25 -0
  35. data/lib/sqa/indicator/head_and_shoulders_pattern.md +3 -0
  36. data/lib/sqa/indicator/head_and_shoulders_pattern.rb +26 -0
  37. data/lib/sqa/indicator/identify_wave_condition.md +6 -0
  38. data/lib/sqa/indicator/identify_wave_condition.rb +40 -0
  39. data/lib/sqa/indicator/mean_reversion.md +8 -0
  40. data/lib/sqa/indicator/mean_reversion.rb +37 -0
  41. data/lib/sqa/indicator/momentum.md +19 -0
  42. data/lib/sqa/indicator/momentum.rb +26 -0
  43. data/lib/sqa/indicator/moving_average_convergence_divergence.md +23 -0
  44. data/lib/sqa/indicator/moving_average_convergence_divergence.rb +25 -0
  45. data/lib/sqa/indicator/relative_strength_index.md +6 -0
  46. data/lib/sqa/indicator/relative_strength_index.md.rb +47 -0
  47. data/lib/sqa/indicator/simple_moving_average.md +8 -0
  48. data/lib/sqa/indicator/simple_moving_average.rb +21 -0
  49. data/lib/sqa/indicator/simple_moving_average_trend.rb +31 -0
  50. data/lib/sqa/indicator/stochastic_oscillator.md +5 -0
  51. data/lib/sqa/indicator/stochastic_oscillator.rb +39 -0
  52. data/lib/sqa/indicator/true_range.md +12 -0
  53. data/lib/sqa/indicator/true_range.rb +37 -0
  54. data/lib/sqa/indicator.rb +11 -0
  55. data/lib/sqa/protfolio.rb +8 -0
  56. data/lib/sqa/stock.rb +29 -0
  57. data/lib/sqa/version.rb +5 -0
  58. data/lib/sqa.rb +12 -0
  59. metadata +105 -0
@@ -0,0 +1,25 @@
1
+ # lib/sqa/indicator/moving_average_convergence_divergence.rb
2
+
3
+ module SQA::Indicator; class << self
4
+
5
+ def moving_average_convergence_divergence(
6
+ prices,
7
+ short_period,
8
+ long_period,
9
+ signal_period
10
+ )
11
+
12
+ short_ma = simple_moving_average(prices, short_period)
13
+ long_ma = simple_moving_average(prices, long_period)
14
+ macd_line = short_ma.last - long_ma.last
15
+ signal_line = simple_moving_average(short_ma, signal_period).last
16
+
17
+ {
18
+ macd: macd_line, # Array
19
+ signal: signal_line # Array
20
+ }
21
+ end
22
+ alias_method :macd, :moving_average_convergence_divergence
23
+
24
+ end; end
25
+
@@ -0,0 +1,6 @@
1
+ # Relative Strength Index (RSI)
2
+
3
+ This method takes in an array of historical prices for a stock and a period (the number of days to calculate the RSI over). It uses the `each_cons` method to iterate over a sliding window of closing prices and calculate the gains and losses for each window. Then, it calculates the average gain and average loss for the time period and uses these values to calculate the RSI. The method returns the RSI value for the given period.
4
+
5
+ * over_bought if rsi >= 70
6
+ * over_sold if rsi <= 30
@@ -0,0 +1,47 @@
1
+ # lib/sqa/indicator/relative_strength_index.rb
2
+
3
+ module SQA::Indicator; class << self
4
+
5
+ def relative_strength_index(
6
+ prices, # Array of prices
7
+ period, # Integer how many to consider at a time
8
+ over_sold = 30.0, # Float break over point in trend
9
+ over_boufht = 70.0 # Float break over point in trend
10
+ )
11
+ gains = []
12
+ losses = []
13
+
14
+ prices.each_cons(2) do |pair|
15
+ change = pair[1] - pair[0]
16
+
17
+ if change > 0
18
+ gains << change
19
+ losses << 0
20
+ else
21
+ gains << 0
22
+ losses << change.abs
23
+ end
24
+ end
25
+
26
+ avg_gain = gains.last(period).sum / period.to_f
27
+ avg_loss = losses.last(period).sum / period.to_f
28
+ rs = avg_gain / avg_loss
29
+ rsi = 100 - (100 / (1 + rs))
30
+
31
+ trend = if rsi >= over_bought
32
+ :over_bought
33
+ elsif rsi <= over_sold
34
+ :over_sold
35
+ else
36
+ :normal
37
+ end
38
+
39
+ {
40
+ rsi: rsi, # Float
41
+ trend: trend # Symbol :normal, :over_bought, :over+sold
42
+ }
43
+ end
44
+ alias_method :rsi, :relative_strength_index
45
+
46
+ end; end
47
+
@@ -0,0 +1,8 @@
1
+ # Simple Moving Average (SMA)
2
+
3
+ This method takes in an array of historical prices for a stock and a period (the number of days to calculate the moving average over). It uses the `each_cons` method to iterate over a sliding window of closing prices and calculate the moving average for each window. The method returns an array of the moving averages for each windo
4
+
5
+ # Simple Moving Average Trend
6
+
7
+ Up or down with angle to indicate how steep the movement is.
8
+
@@ -0,0 +1,21 @@
1
+ # lib/sqa/indicator/simple_moving_average.rb
2
+
3
+ module SQA::Indicator; class << self
4
+
5
+ def simple_moving_average(
6
+ prices, # Array of prices
7
+ period # Integer how many to consider at a time
8
+ )
9
+ moving_averages = []
10
+
11
+ prices.each_cons(period) do |window|
12
+ moving_average = window.sum / period.to_f
13
+ moving_averages << moving_average
14
+ end
15
+
16
+ moving_averages # Array
17
+ end
18
+ alias_method :sma, :simple_moving_average
19
+
20
+ end; end
21
+
@@ -0,0 +1,31 @@
1
+ # lib/sqa/indicator/simple_moving_average_trend.rb
2
+
3
+ module SQA::Indicator; class << self
4
+
5
+ def simple_moving_average_trend(
6
+ closing_prices, # Array of closing prices
7
+ period, # Integer number of entries to consider
8
+ delta = 0.0005 # Float defines a :nutria trend range.
9
+ )
10
+ sma = simple_moving_average(closing_prices, period)
11
+ last_sma = sma.last
12
+ prev_sma = sma[-2]
13
+ angle = Math.atan((last_sma - prev_sma) / period) * (180 / Math::PI)
14
+
15
+ if angle > 0.0
16
+ trend = :up
17
+ elsif angle < 0.0
18
+ trend = :down
19
+ else
20
+ trend = :neutral
21
+ end
22
+
23
+ {
24
+ trend: trend, # Symbol :up, :down, :neutral
25
+ angle: angle # Float how step the trend
26
+ }
27
+ end
28
+ alias_method :sma_trend, :simple_moving_average_trend
29
+
30
+ end; end
31
+
@@ -0,0 +1,5 @@
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.
@@ -0,0 +1,39 @@
1
+ # lib/sqa/indicator/stochastic_oscillator.rb
2
+
3
+ module SQA::Indicator; class << self
4
+
5
+ # @param high_prices [Array]
6
+ # @param low_prices [Array]
7
+ # @param close_prices [Array]
8
+ # @param period [Integer]
9
+ # @param smoothing_period [Integer]
10
+ #
11
+ # @return [Array] An array of %K and %D values.
12
+ #
13
+ def stochastic_oscillator(
14
+ high_prices, # Array of high prices
15
+ low_prices, # Array of low prices
16
+ closing_prices, # Array of closing prices
17
+ period, # Integer The period for calculating the Stochastic Oscillator
18
+ smoothing_period # Integer The smoothing period for %K line
19
+ )
20
+ k_values = []
21
+ d_values = []
22
+
23
+ closing_prices.each_cons(period) do |closing_prices_subset|
24
+ highest_high = high_prices.max(period)
25
+ lowest_low = low_prices.min(period)
26
+ current_close = closing_prices_subset.last
27
+ k_values << (current_close - lowest_low) / (highest_high - lowest_low) * 100 # Calculate the k_value
28
+ end
29
+
30
+ k_values.each_cons(smoothing_period) do |k_values_subset|
31
+ d_values << k_values_subset.sum / smoothing_period.to_f # Calculate the d_value
32
+ end
33
+
34
+ [k_values, d_values]
35
+ end
36
+ alias_method :so, :stochastic_oscillator
37
+
38
+ end; end
39
+
@@ -0,0 +1,12 @@
1
+ # True Range
2
+
3
+ Calculates the True Range (TR) for a given set of price data.
4
+
5
+ The True Range is a measure of the price volatility of a security over a given period. It is calculated as the greatest of the following three values:
6
+
7
+ * The difference between the current high and the current low.
8
+ * The absolute value of the difference between the current high and the previous close.
9
+ * The absolute value of the difference between the current low and the previous close.
10
+
11
+ The True Range helps to capture the true extent of price movement, taking into account potential gaps or price jumps between periods. It is often used as a component in calculating other indicators, such as the Average True Range.
12
+
@@ -0,0 +1,37 @@
1
+ # lib/sqa/indicator/true_range.rb
2
+
3
+ # See Also: average_true_range
4
+
5
+ module SQA::Indicator; class << self
6
+
7
+ # @param high_prices [Array]
8
+ # @param low_prices [Array]
9
+ # @param previous_closes [Array]
10
+ #
11
+ # @return [Array]
12
+ #
13
+ def true_range(
14
+ high_prices, # Array of high prices
15
+ low_prices, # Array of low prices
16
+ previous_closes # Array of previous closing prices
17
+ )
18
+ true_ranges = []
19
+
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
31
+ end
32
+
33
+ true_ranges # Array of True Range values
34
+ end
35
+ alias_method :tr, :true_range
36
+
37
+ end; end
@@ -0,0 +1,11 @@
1
+ # lib/sqa/indicators.rb
2
+
3
+ module SQA::Indicator
4
+ end
5
+
6
+ # setup a shortcut for the namespace
7
+ SQAI = SQA::Indicator
8
+
9
+ Dir["indicator/*.rb"].each do |file|
10
+ require_relative file
11
+ end
@@ -0,0 +1,8 @@
1
+ # lib/sqa/portfolio.rb
2
+
3
+ # A collection of stocks
4
+ # primary id is ticker its unique
5
+
6
+ class SQA::Portfolio < ActiveRecord::Base
7
+ has_many :stocks # use ticker as the foreign key
8
+ end
data/lib/sqa/stock.rb ADDED
@@ -0,0 +1,29 @@
1
+ # lib/sqa/stock.rb
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
+
12
+ attr_accessor :company_name
13
+ attr_accessor :data
14
+ attr_accessor :ticker
15
+
16
+ def initialize(ticker, datastore = SQA::Datastore::CSV)
17
+ @ticker = ticker
18
+ @company_name = "Company Name"
19
+ @data = datastore.new(ticker)
20
+ end
21
+
22
+ def to_s
23
+ "#{ticker} with #{@data.size} data points."
24
+ end
25
+ end
26
+
27
+ __END__
28
+
29
+ aapl = Stock.new('aapl', SQA::Datastore::CSV)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SQA
4
+ VERSION = "0.0.1"
5
+ end
data/lib/sqa.rb ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SQA
4
+ end
5
+
6
+ require 'csv'
7
+ require 'date'
8
+ require 'json'
9
+ require 'pathname'
10
+
11
+ require_relative "sqa/version"
12
+ require_relative "sqa/errors"
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sqa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dewayne VanHoozer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-08-12 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Simplistic playpen (e.g. not for serious use) for doing technical analysis
14
+ of stock prices.
15
+ email:
16
+ - dvanhoozer@gmail.com
17
+ executables:
18
+ - sqa
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".envrc"
23
+ - CHANGELOG.md
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - bin/sqa
28
+ - checksums/sqa-0.0.1.gem.sha512
29
+ - docs/requirements.md
30
+ - lib/sqa.rb
31
+ - lib/sqa/activity.rb
32
+ - 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
38
+ - lib/sqa/errors.rb
39
+ - lib/sqa/indicator.rb
40
+ - lib/sqa/indicator/README.md
41
+ - lib/sqa/indicator/average_true_range.md
42
+ - lib/sqa/indicator/average_true_range.rb
43
+ - lib/sqa/indicator/bollinger_bands.md
44
+ - lib/sqa/indicator/bollinger_bands.rb
45
+ - lib/sqa/indicator/candlestick_pattern_recognizer.md
46
+ - 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
+ - lib/sqa/indicator/donchian_channel.rb
51
+ - lib/sqa/indicator/double_top_bottom_pattern.md
52
+ - 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
56
+ - lib/sqa/indicator/fibonacci_retracement.rb
57
+ - lib/sqa/indicator/head_and_shoulders_pattern.md
58
+ - 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
62
+ - lib/sqa/indicator/mean_reversion.rb
63
+ - lib/sqa/indicator/momentum.md
64
+ - lib/sqa/indicator/momentum.rb
65
+ - lib/sqa/indicator/moving_average_convergence_divergence.md
66
+ - 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
70
+ - lib/sqa/indicator/simple_moving_average.rb
71
+ - lib/sqa/indicator/simple_moving_average_trend.rb
72
+ - lib/sqa/indicator/stochastic_oscillator.md
73
+ - lib/sqa/indicator/stochastic_oscillator.rb
74
+ - lib/sqa/indicator/true_range.md
75
+ - lib/sqa/indicator/true_range.rb
76
+ - lib/sqa/protfolio.rb
77
+ - lib/sqa/stock.rb
78
+ - lib/sqa/version.rb
79
+ homepage: https://github.com/MadBomber/sqa
80
+ licenses:
81
+ - MIT
82
+ metadata:
83
+ allowed_push_host: https://rubygems.org
84
+ homepage_uri: https://github.com/MadBomber/sqa
85
+ source_code_uri: https://github.com/MadBomber/sta
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '2.7'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.4.18
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: sqa - Stock Qualitative Analysis
105
+ test_files: []