sqa 0.0.31 → 0.0.32
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 +4 -4
- data/CHANGELOG.md +13 -0
- data/CLAUDE.md +21 -0
- data/README.md +56 -32
- data/docs/api/dataframe.md +0 -1
- data/docs/assets/images/sqa.jpg +0 -0
- data/docs/concepts/index.md +2 -10
- data/docs/data_frame.md +0 -1
- data/docs/getting-started/index.md +0 -16
- data/docs/getting-started/installation.md +2 -2
- data/docs/getting-started/quick-start.md +4 -4
- data/docs/index.md +0 -2
- data/docs/strategies/bollinger-bands.md +1 -1
- data/docs/strategies/rsi.md +1 -1
- data/examples/sinatra_app/Gemfile +20 -0
- data/examples/sinatra_app/Gemfile.lock +268 -0
- data/examples/sinatra_app/QUICKSTART.md +13 -3
- data/examples/sinatra_app/README.md +12 -2
- data/examples/sinatra_app/RUNNING_WITHOUT_TALIB.md +90 -0
- data/examples/sinatra_app/TROUBLESHOOTING.md +95 -0
- data/examples/sinatra_app/app.rb +85 -25
- data/examples/sinatra_app/public/css/style.css +101 -37
- data/examples/sinatra_app/public/debug_macd.html +82 -0
- data/examples/sinatra_app/start.sh +53 -0
- data/examples/sinatra_app/views/dashboard.erb +558 -146
- data/examples/sinatra_app/views/layout.erb +2 -2
- data/lib/sqa/data_frame/alpha_vantage.rb +13 -3
- data/lib/sqa/data_frame.rb +21 -15
- data/lib/sqa/indicator.rb +17 -4
- data/lib/sqa/stock.rb +73 -11
- data/lib/sqa/ticker.rb +9 -2
- data/lib/sqa/version.rb +1 -1
- data/lib/sqa.rb +12 -4
- data/mkdocs.yml +4 -40
- metadata +7 -21
- data/docs/alpha_vantage_technical_indicators.md +0 -62
- data/docs/average_true_range.md +0 -9
- data/docs/bollinger_bands.md +0 -15
- data/docs/candlestick_pattern_recognizer.md +0 -4
- data/docs/donchian_channel.md +0 -5
- data/docs/double_top_bottom_pattern.md +0 -3
- data/docs/exponential_moving_average.md +0 -19
- data/docs/fibonacci_retracement.md +0 -30
- data/docs/head_and_shoulders_pattern.md +0 -3
- data/docs/market_profile.md +0 -4
- data/docs/momentum.md +0 -19
- data/docs/moving_average_convergence_divergence.md +0 -23
- data/docs/peaks_and_valleys.md +0 -11
- data/docs/relative_strength_index.md +0 -6
- data/docs/simple_moving_average.md +0 -8
- data/docs/stochastic_oscillator.md +0 -4
- data/docs/ta_lib.md +0 -160
- data/docs/true_range.md +0 -12
- data/docs/true_strength_index.md +0 -46
- data/docs/weighted_moving_average.md +0 -48
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>SQA - Stock Analysis Platform</title>
|
|
7
7
|
|
|
8
|
-
<!--
|
|
9
|
-
<script src="https://cdn.
|
|
8
|
+
<!-- ApexCharts for charts -->
|
|
9
|
+
<script src="https://cdn.jsdelivr.net/npm/apexcharts@3.45.1/dist/apexcharts.min.js"></script>
|
|
10
10
|
|
|
11
11
|
<!-- Custom CSS -->
|
|
12
12
|
<link rel="stylesheet" href="/css/style.css">
|
|
@@ -35,9 +35,14 @@ class SQA::DataFrame
|
|
|
35
35
|
|
|
36
36
|
################################################################
|
|
37
37
|
|
|
38
|
-
# Get recent data from
|
|
38
|
+
# Get recent data from Alpha Vantage API
|
|
39
|
+
#
|
|
39
40
|
# ticker String the security to retrieve
|
|
40
|
-
#
|
|
41
|
+
# full Boolean whether to fetch full history or compact (last 100 days)
|
|
42
|
+
# from_date Date optional date to fetch data after (for incremental updates)
|
|
43
|
+
#
|
|
44
|
+
# Returns: SQA::DataFrame sorted in ASCENDING order (oldest to newest)
|
|
45
|
+
# Note: Alpha Vantage returns data newest-first, but we sort ascending for TA-Lib compatibility
|
|
41
46
|
def self.recent(ticker, full: false, from_date: nil)
|
|
42
47
|
response = CONNECTION.get(
|
|
43
48
|
"/query?" +
|
|
@@ -67,7 +72,8 @@ class SQA::DataFrame
|
|
|
67
72
|
# Handle date criteria if applicable
|
|
68
73
|
if from_date
|
|
69
74
|
# Use Polars.col() to create an expression for filtering
|
|
70
|
-
|
|
75
|
+
# Use > (not >=) to exclude the from_date itself and prevent duplicates
|
|
76
|
+
df = df.filter(Polars.col("timestamp") > from_date.to_s)
|
|
71
77
|
end
|
|
72
78
|
|
|
73
79
|
# Wrap in SQA::DataFrame with proper transformers
|
|
@@ -80,6 +86,10 @@ class SQA::DataFrame
|
|
|
80
86
|
sqa_df.data["close_price"].alias("adj_close_price")
|
|
81
87
|
)
|
|
82
88
|
|
|
89
|
+
# Sort data in ascending chronological order (oldest to newest) for TA-Lib compatibility
|
|
90
|
+
# Alpha Vantage returns data newest-first, but TA-Lib expects oldest-first
|
|
91
|
+
sqa_df.data = sqa_df.data.sort("timestamp", reverse: false)
|
|
92
|
+
|
|
83
93
|
sqa_df
|
|
84
94
|
end
|
|
85
95
|
end
|
data/lib/sqa/data_frame.rb
CHANGED
|
@@ -18,13 +18,6 @@ class SQA::DataFrame
|
|
|
18
18
|
def initialize(raw_data = nil, mapping: {}, transformers: {})
|
|
19
19
|
@data = Polars::DataFrame.new(raw_data || [])
|
|
20
20
|
|
|
21
|
-
debug_me{[
|
|
22
|
-
:raw_data,
|
|
23
|
-
:mapping,
|
|
24
|
-
:transformers,
|
|
25
|
-
'@data'
|
|
26
|
-
]}
|
|
27
|
-
|
|
28
21
|
# IMPORTANT: Rename columns FIRST, then apply transformers
|
|
29
22
|
# Transformers expect renamed column names
|
|
30
23
|
rename_columns!(mapping) unless mapping.empty?
|
|
@@ -77,6 +70,27 @@ class SQA::DataFrame
|
|
|
77
70
|
end
|
|
78
71
|
alias concat! append!
|
|
79
72
|
|
|
73
|
+
# Concatenate another DataFrame, remove duplicates, and sort
|
|
74
|
+
# This is the preferred method for updating CSV data to prevent duplicates
|
|
75
|
+
#
|
|
76
|
+
# @param other_df [SQA::DataFrame] DataFrame to append
|
|
77
|
+
# @param sort_column [String] Column to use for deduplication and sorting (default: "timestamp")
|
|
78
|
+
# @param descending [Boolean] Sort order - false for ascending (oldest first, TA-Lib compatible), true for descending
|
|
79
|
+
def concat_and_deduplicate!(other_df, sort_column: "timestamp", descending: false)
|
|
80
|
+
# Concatenate the dataframes
|
|
81
|
+
@data = if @data.shape[0] == 0
|
|
82
|
+
other_df.data
|
|
83
|
+
else
|
|
84
|
+
@data.vstack(other_df.data)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Remove duplicates based on sort_column, keeping first occurrence
|
|
88
|
+
@data = @data.unique(subset: [sort_column], keep: "first")
|
|
89
|
+
|
|
90
|
+
# Sort by the specified column (Polars uses 'reverse' for descending)
|
|
91
|
+
@data = @data.sort(sort_column, reverse: descending)
|
|
92
|
+
end
|
|
93
|
+
|
|
80
94
|
def columns
|
|
81
95
|
@data.columns
|
|
82
96
|
end
|
|
@@ -196,14 +210,6 @@ class SQA::DataFrame
|
|
|
196
210
|
|
|
197
211
|
|
|
198
212
|
def from_csv_file(source, mapping: {}, transformers: {})
|
|
199
|
-
debug_me do
|
|
200
|
-
%i[
|
|
201
|
-
source
|
|
202
|
-
mapping
|
|
203
|
-
transformers
|
|
204
|
-
]
|
|
205
|
-
end
|
|
206
|
-
|
|
207
213
|
df = Polars.read_csv(source)
|
|
208
214
|
new(df, mapping: mapping, transformers: transformers)
|
|
209
215
|
end
|
data/lib/sqa/indicator.rb
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
# lib/sqa/indicator.rb
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
# Try to load TA-Lib indicators, but make them optional
|
|
5
|
+
# This allows the library to work without TA-Lib installed for basic data loading
|
|
6
|
+
begin
|
|
7
|
+
require 'sqa/tai'
|
|
5
8
|
|
|
6
|
-
# Use SQA::TAI directly for all technical analysis indicators
|
|
7
|
-
# SQAI is a shortcut alias for SQA::TAI
|
|
8
|
-
SQAI = SQA::TAI
|
|
9
|
+
# Use SQA::TAI directly for all technical analysis indicators
|
|
10
|
+
# SQAI is a shortcut alias for SQA::TAI
|
|
11
|
+
SQAI = SQA::TAI
|
|
12
|
+
rescue LoadError, Fiddle::DLError => e
|
|
13
|
+
# TA-Lib not available - define a stub that gives helpful errors
|
|
14
|
+
warn "Warning: TA-Lib not available (#{e.class}: #{e.message}). Technical indicators will not work." if $VERBOSE
|
|
15
|
+
|
|
16
|
+
module SQAI
|
|
17
|
+
def self.method_missing(method, *args, &block)
|
|
18
|
+
raise "Technical indicators require TA-Lib to be installed. Please install libta-lib system library. Visit: http://ta-lib.org/hdr_dw.html"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/sqa/stock.rb
CHANGED
|
@@ -11,11 +11,16 @@ class SQA::Stock
|
|
|
11
11
|
@ticker = ticker.downcase
|
|
12
12
|
@source = source
|
|
13
13
|
|
|
14
|
-
raise "Invalid Ticker #{ticker}" unless SQA::Ticker.valid?(ticker)
|
|
15
|
-
|
|
16
14
|
@data_path = SQA.data_dir + "#{@ticker}.json"
|
|
17
15
|
@df_path = SQA.data_dir + "#{@ticker}.csv"
|
|
18
16
|
|
|
17
|
+
# Validate ticker if validation data is available and cached data doesn't exist
|
|
18
|
+
unless @data_path.exist? && @df_path.exist?
|
|
19
|
+
unless SQA::Ticker.valid?(ticker)
|
|
20
|
+
warn "Warning: Ticker #{ticker} could not be validated. Proceeding anyway." if $VERBOSE
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
19
24
|
@klass = "SQA::DataFrame::#{@source.to_s.camelize}".constantize
|
|
20
25
|
@transformers = "SQA::DataFrame::#{@source.to_s.camelize}::TRANSFORMERS".constantize
|
|
21
26
|
|
|
@@ -27,8 +32,14 @@ class SQA::Stock
|
|
|
27
32
|
if @data_path.exist?
|
|
28
33
|
@data = SQA::DataFrame::Data.new(JSON.parse(@data_path.read))
|
|
29
34
|
else
|
|
35
|
+
# Create minimal data structure
|
|
30
36
|
create_data
|
|
37
|
+
|
|
38
|
+
# Try to fetch overview data, but don't fail if we can't
|
|
39
|
+
# This is optional metadata - we can work with just price data
|
|
31
40
|
update
|
|
41
|
+
|
|
42
|
+
# Save whatever data we have (even if overview fetch failed)
|
|
32
43
|
save_data
|
|
33
44
|
end
|
|
34
45
|
end
|
|
@@ -38,7 +49,13 @@ class SQA::Stock
|
|
|
38
49
|
end
|
|
39
50
|
|
|
40
51
|
def update
|
|
41
|
-
|
|
52
|
+
begin
|
|
53
|
+
merge_overview
|
|
54
|
+
rescue => e
|
|
55
|
+
# Log warning but don't fail - overview data is optional
|
|
56
|
+
# Common causes: rate limits, network issues, API errors
|
|
57
|
+
warn "Warning: Could not fetch overview data for #{@ticker} (#{e.class}: #{e.message}). Continuing without it."
|
|
58
|
+
end
|
|
42
59
|
end
|
|
43
60
|
|
|
44
61
|
def save_data
|
|
@@ -82,27 +99,72 @@ class SQA::Stock
|
|
|
82
99
|
@df.to_csv(@df_path) if migrated
|
|
83
100
|
else
|
|
84
101
|
# Fetch fresh data from source (applies transformers and mapping)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
102
|
+
begin
|
|
103
|
+
@df = @klass.recent(@ticker, full: true)
|
|
104
|
+
@df.to_csv(@df_path)
|
|
105
|
+
return
|
|
106
|
+
rescue => e
|
|
107
|
+
# If we can't fetch data, raise a more helpful error
|
|
108
|
+
raise "Unable to fetch data for #{@ticker}. Please ensure API key is set or provide cached CSV file at #{@df_path}. Error: #{e.message}"
|
|
109
|
+
end
|
|
88
110
|
end
|
|
89
111
|
|
|
90
112
|
update_dataframe_with_recent_data
|
|
91
113
|
end
|
|
92
114
|
|
|
93
115
|
def update_dataframe_with_recent_data
|
|
94
|
-
|
|
95
|
-
df2 = @klass.recent(@ticker, from_date: from_date)
|
|
116
|
+
return unless should_update?
|
|
96
117
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
@df.
|
|
118
|
+
begin
|
|
119
|
+
# CSV is sorted ascending (oldest first, TA-Lib compatible), so .last gets the most recent date
|
|
120
|
+
from_date = Date.parse(@df["timestamp"].to_a.last)
|
|
121
|
+
df2 = @klass.recent(@ticker, from_date: from_date)
|
|
122
|
+
|
|
123
|
+
if df2 && (df2.size > 0)
|
|
124
|
+
# Use concat_and_deduplicate! to prevent duplicate timestamps and maintain ascending sort
|
|
125
|
+
@df.concat_and_deduplicate!(df2)
|
|
126
|
+
@df.to_csv(@df_path)
|
|
127
|
+
end
|
|
128
|
+
rescue => e
|
|
129
|
+
# Log warning but don't fail - we have cached data
|
|
130
|
+
# Common causes: rate limits, network issues, API errors
|
|
131
|
+
warn "Warning: Could not update #{@ticker} from API (#{e.class}: #{e.message}). Using cached data."
|
|
100
132
|
end
|
|
101
133
|
end
|
|
102
134
|
|
|
135
|
+
def should_update?
|
|
136
|
+
# Don't update if we're in lazy update mode
|
|
137
|
+
return false if SQA.config.lazy_update
|
|
138
|
+
|
|
139
|
+
# Don't update if we don't have an API key (only relevant for Alpha Vantage)
|
|
140
|
+
if @source == :alpha_vantage
|
|
141
|
+
begin
|
|
142
|
+
SQA.av_api_key
|
|
143
|
+
rescue
|
|
144
|
+
return false
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Don't update if CSV data is already current (last timestamp is today or later)
|
|
149
|
+
# This prevents unnecessary API calls when we already have today's data
|
|
150
|
+
if @df && @df.size > 0
|
|
151
|
+
begin
|
|
152
|
+
last_timestamp = Date.parse(@df["timestamp"].to_a.last)
|
|
153
|
+
return false if last_timestamp >= Date.today
|
|
154
|
+
rescue => e
|
|
155
|
+
# If we can't parse the date, assume we need to update
|
|
156
|
+
warn "Warning: Could not parse last timestamp for #{@ticker} (#{e.message}). Will attempt update." if $VERBOSE
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
true
|
|
161
|
+
end
|
|
162
|
+
|
|
103
163
|
def to_s
|
|
104
164
|
"#{ticker} with #{@df.size} data points from #{@df["timestamp"].to_a.first} to #{@df["timestamp"].to_a.last}"
|
|
105
165
|
end
|
|
166
|
+
# Note: CSV data is stored in ascending chronological order (oldest to newest)
|
|
167
|
+
# This ensures compatibility with TA-Lib indicators which expect arrays in this order
|
|
106
168
|
alias_method :inspect, :to_s
|
|
107
169
|
|
|
108
170
|
def merge_overview
|
data/lib/sqa/ticker.rb
CHANGED
|
@@ -36,14 +36,21 @@ class SQA::Ticker
|
|
|
36
36
|
until(found || tries >= 3) do
|
|
37
37
|
files = Pathname.new(SQA.config.data_dir).children.select{|c| c.basename.to_s.start_with?(FILENAME_PREFIX)}.sort
|
|
38
38
|
if files.empty?
|
|
39
|
-
|
|
39
|
+
begin
|
|
40
|
+
download
|
|
41
|
+
rescue => e
|
|
42
|
+
warn "Warning: Could not download ticker list: #{e.message}" if $VERBOSE
|
|
43
|
+
end
|
|
40
44
|
tries += 1
|
|
41
45
|
else
|
|
42
46
|
found = true
|
|
43
47
|
end
|
|
44
48
|
end
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
if files.empty?
|
|
51
|
+
warn "Warning: No ticker validation data available. Proceeding without validation." if $VERBOSE
|
|
52
|
+
return {}
|
|
53
|
+
end
|
|
47
54
|
|
|
48
55
|
load_from_csv files.last
|
|
49
56
|
end
|
data/lib/sqa/version.rb
CHANGED
data/lib/sqa.rb
CHANGED
|
@@ -20,13 +20,21 @@ if defined?(DebugMe)
|
|
|
20
20
|
unless respond_to?(:debug_me)
|
|
21
21
|
include DebugMe
|
|
22
22
|
end
|
|
23
|
+
$DEBUG_ME = true
|
|
23
24
|
else
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
begin
|
|
26
|
+
require 'debug_me'
|
|
27
|
+
include DebugMe
|
|
28
|
+
$DEBUG_ME = true
|
|
29
|
+
rescue LoadError
|
|
30
|
+
# debug_me is optional - define a no-op if not available
|
|
31
|
+
def debug_me(tag = nil, &block)
|
|
32
|
+
# No-op when debug_me gem is not available
|
|
33
|
+
end
|
|
34
|
+
$DEBUG_ME = false
|
|
35
|
+
end
|
|
26
36
|
end
|
|
27
37
|
|
|
28
|
-
$DEBUG_ME = true
|
|
29
|
-
|
|
30
38
|
#############################################
|
|
31
39
|
## Additional Libraries
|
|
32
40
|
|
data/mkdocs.yml
CHANGED
|
@@ -179,42 +179,18 @@ nav:
|
|
|
179
179
|
- getting-started/index.md
|
|
180
180
|
- Installation: getting-started/installation.md
|
|
181
181
|
- Quick Start: getting-started/quick-start.md
|
|
182
|
-
- Configuration: getting-started/configuration.md
|
|
183
|
-
- Console Usage: getting-started/console-usage.md
|
|
184
182
|
|
|
185
183
|
- Core Concepts:
|
|
186
184
|
- concepts/index.md
|
|
187
|
-
- Stock Objects: concepts/stock.md
|
|
188
185
|
- DataFrames: data_frame.md
|
|
189
|
-
- Technical Indicators:
|
|
186
|
+
- Technical Indicators: indicators/index.md
|
|
190
187
|
- Trading Strategies: strategy.md
|
|
191
188
|
|
|
192
189
|
- Technical Indicators:
|
|
193
190
|
- indicators/index.md
|
|
194
191
|
- Overview: indicators.md
|
|
195
|
-
-
|
|
196
|
-
|
|
197
|
-
- Exponential Moving Average: exponential_moving_average.md
|
|
198
|
-
- Weighted Moving Average: weighted_moving_average.md
|
|
199
|
-
- Momentum Indicators:
|
|
200
|
-
- RSI (Relative Strength Index): relative_strength_index.md
|
|
201
|
-
- Momentum: momentum.md
|
|
202
|
-
- Stochastic Oscillator: stochastic_oscillator.md
|
|
203
|
-
- True Strength Index: true_strength_index.md
|
|
204
|
-
- Volatility Indicators:
|
|
205
|
-
- Bollinger Bands: bollinger_bands.md
|
|
206
|
-
- Average True Range: average_true_range.md
|
|
207
|
-
- True Range: true_range.md
|
|
208
|
-
- Donchian Channel: donchian_channel.md
|
|
209
|
-
- Trend Indicators:
|
|
210
|
-
- MACD: moving_average_convergence_divergence.md
|
|
211
|
-
- Market Profile: market_profile.md
|
|
212
|
-
- Pattern Recognition:
|
|
213
|
-
- Fibonacci Retracement: fibonacci_retracement.md
|
|
214
|
-
- Peaks and Valleys: peaks_and_valleys.md
|
|
215
|
-
- Candlestick Patterns: candlestick_pattern_recognizer.md
|
|
216
|
-
- Double Top/Bottom: double_top_bottom_pattern.md
|
|
217
|
-
- Head and Shoulders: head_and_shoulders_pattern.md
|
|
192
|
+
- sqa-tai Gem: https://github.com/MadBomber/sqa-tai
|
|
193
|
+
- TA-Lib Documentation: https://ta-lib.org/
|
|
218
194
|
|
|
219
195
|
- Trading Strategies:
|
|
220
196
|
- strategies/index.md
|
|
@@ -249,25 +225,17 @@ nav:
|
|
|
249
225
|
|
|
250
226
|
- AI & Machine Learning:
|
|
251
227
|
- ai_and_ml.md
|
|
228
|
+
- Mean Reversion: mean_reversion.md
|
|
252
229
|
- Predict Next Value: predict_next_value.md
|
|
253
230
|
- Identify Wave Condition: identify_wave_condition.md
|
|
254
231
|
- LIBSVM Format: libsvm_file_format.md
|
|
255
232
|
|
|
256
233
|
- API Reference:
|
|
257
234
|
- api/index.md
|
|
258
|
-
- SQA Module: api/sqa.md
|
|
259
|
-
- Stock Class: api/stock.md
|
|
260
235
|
- DataFrame Class: api/dataframe.md
|
|
261
|
-
- Strategy Framework: api/strategy.md
|
|
262
|
-
- Portfolio Class: api/portfolio.md
|
|
263
|
-
- Backtest Class: api/backtest.md
|
|
264
|
-
- Stream Class: api/stream.md
|
|
265
236
|
|
|
266
237
|
- Data Sources:
|
|
267
238
|
- data-sources/index.md
|
|
268
|
-
- Alpha Vantage: alpha_vantage_technical_indicators.md
|
|
269
|
-
- Data Format: data-sources/format.md
|
|
270
|
-
- Custom Data: data-sources/custom.md
|
|
271
239
|
|
|
272
240
|
- Resources:
|
|
273
241
|
- Tags: tags.md
|
|
@@ -276,13 +244,9 @@ nav:
|
|
|
276
244
|
- Trading Ideas: i_gotta_an_idea.md
|
|
277
245
|
- Factor Analysis: factors_that_impact_price.md
|
|
278
246
|
- External Tools:
|
|
279
|
-
- TA-Lib: ta_lib.md
|
|
280
247
|
- FinViz: finviz.md
|
|
281
248
|
- FX Pro Bit: fx_pro_bit.md
|
|
282
249
|
- Options Trading: options.md
|
|
283
250
|
|
|
284
251
|
- Contributing:
|
|
285
252
|
- contributing/index.md
|
|
286
|
-
- Development Setup: contributing/setup.md
|
|
287
|
-
- Testing: contributing/testing.md
|
|
288
|
-
- Code Style: contributing/style.md
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sqa
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.32
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dewayne VanHoozer
|
|
@@ -411,47 +411,32 @@ files:
|
|
|
411
411
|
- docs/advanced/strategy-generator.md
|
|
412
412
|
- docs/advanced/streaming.md
|
|
413
413
|
- docs/ai_and_ml.md
|
|
414
|
-
- docs/alpha_vantage_technical_indicators.md
|
|
415
414
|
- docs/api/dataframe.md
|
|
416
415
|
- docs/api/index.md
|
|
417
416
|
- docs/assets/css/custom.css
|
|
417
|
+
- docs/assets/images/sqa.jpg
|
|
418
418
|
- docs/assets/js/mathjax.js
|
|
419
|
-
- docs/average_true_range.md
|
|
420
|
-
- docs/bollinger_bands.md
|
|
421
|
-
- docs/candlestick_pattern_recognizer.md
|
|
422
419
|
- docs/concepts/index.md
|
|
423
420
|
- docs/contributing/index.md
|
|
424
421
|
- docs/data-sources/index.md
|
|
425
422
|
- docs/data_frame.md
|
|
426
|
-
- docs/donchian_channel.md
|
|
427
|
-
- docs/double_top_bottom_pattern.md
|
|
428
|
-
- docs/exponential_moving_average.md
|
|
429
423
|
- docs/factors_that_impact_price.md
|
|
430
|
-
- docs/fibonacci_retracement.md
|
|
431
424
|
- docs/finviz.md
|
|
432
425
|
- docs/fx_pro_bit.md
|
|
433
426
|
- docs/genetic_programming.md
|
|
434
427
|
- docs/getting-started/index.md
|
|
435
428
|
- docs/getting-started/installation.md
|
|
436
429
|
- docs/getting-started/quick-start.md
|
|
437
|
-
- docs/head_and_shoulders_pattern.md
|
|
438
430
|
- docs/i_gotta_an_idea.md
|
|
439
431
|
- docs/identify_wave_condition.md
|
|
440
432
|
- docs/index.md
|
|
441
433
|
- docs/indicators.md
|
|
442
434
|
- docs/indicators/index.md
|
|
443
435
|
- docs/libsvm_file_format.md
|
|
444
|
-
- docs/market_profile.md
|
|
445
436
|
- docs/mean_reversion.md
|
|
446
|
-
- docs/momentum.md
|
|
447
|
-
- docs/moving_average_convergence_divergence.md
|
|
448
437
|
- docs/options.md
|
|
449
|
-
- docs/peaks_and_valleys.md
|
|
450
438
|
- docs/predict_next_value.md
|
|
451
|
-
- docs/relative_strength_index.md
|
|
452
439
|
- docs/requirements.md
|
|
453
|
-
- docs/simple_moving_average.md
|
|
454
|
-
- docs/stochastic_oscillator.md
|
|
455
440
|
- docs/strategies/bollinger-bands.md
|
|
456
441
|
- docs/strategies/consensus.md
|
|
457
442
|
- docs/strategies/custom.md
|
|
@@ -466,12 +451,8 @@ files:
|
|
|
466
451
|
- docs/strategies/stochastic.md
|
|
467
452
|
- docs/strategies/volume-breakout.md
|
|
468
453
|
- docs/strategy.md
|
|
469
|
-
- docs/ta_lib.md
|
|
470
454
|
- docs/tags.md
|
|
471
455
|
- docs/terms_of_use.md
|
|
472
|
-
- docs/true_range.md
|
|
473
|
-
- docs/true_strength_index.md
|
|
474
|
-
- docs/weighted_moving_average.md
|
|
475
456
|
- examples/README.md
|
|
476
457
|
- examples/advanced_features_example.rb
|
|
477
458
|
- examples/fpop_analysis_example.rb
|
|
@@ -504,12 +485,17 @@ files:
|
|
|
504
485
|
- examples/rails_app/config/routes.rb
|
|
505
486
|
- examples/realtime_stream_example.rb
|
|
506
487
|
- examples/sinatra_app/Gemfile
|
|
488
|
+
- examples/sinatra_app/Gemfile.lock
|
|
507
489
|
- examples/sinatra_app/QUICKSTART.md
|
|
508
490
|
- examples/sinatra_app/README.md
|
|
491
|
+
- examples/sinatra_app/RUNNING_WITHOUT_TALIB.md
|
|
492
|
+
- examples/sinatra_app/TROUBLESHOOTING.md
|
|
509
493
|
- examples/sinatra_app/app.rb
|
|
510
494
|
- examples/sinatra_app/config.ru
|
|
511
495
|
- examples/sinatra_app/public/css/style.css
|
|
496
|
+
- examples/sinatra_app/public/debug_macd.html
|
|
512
497
|
- examples/sinatra_app/public/js/app.js
|
|
498
|
+
- examples/sinatra_app/start.sh
|
|
513
499
|
- examples/sinatra_app/views/analyze.erb
|
|
514
500
|
- examples/sinatra_app/views/backtest.erb
|
|
515
501
|
- examples/sinatra_app/views/dashboard.erb
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# Alpha Vantage
|
|
2
|
-
## Technical Indicators
|
|
3
|
-
|
|
4
|
-
The following technical indicators are available from Alpha Vantage
|
|
5
|
-
using a free API key.
|
|
6
|
-
|
|
7
|
-
| Acronym | Indicator Description |
|
|
8
|
-
|-----------|----------------------------------------------------------|
|
|
9
|
-
| AD | Accumulation/Distribution |
|
|
10
|
-
| ADOSC | Accumulation/Distribution Oscillator |
|
|
11
|
-
| ADX | Average Directional Index |
|
|
12
|
-
| ADXR | Average Directional Movement Rating |
|
|
13
|
-
| APO | Absolute Price Oscillator |
|
|
14
|
-
| AROON | Aroon Indicator |
|
|
15
|
-
| AROONOSC | Aroon Oscillator |
|
|
16
|
-
| ATR | Average True Range |
|
|
17
|
-
| BBANDS | Bollinger Bands |
|
|
18
|
-
| BOP | Balance of Power |
|
|
19
|
-
| CCI | Commodity Channel Index |
|
|
20
|
-
| CMO | Chande Momentum Oscillator |
|
|
21
|
-
| DEMA | Double Exponential Moving Average |
|
|
22
|
-
| DX | Directional Movement Index |
|
|
23
|
-
| EMA | Exponential Moving Average |
|
|
24
|
-
| HT_DCPERIOD | Hilbert Transform - Dominant Cycle Period |
|
|
25
|
-
| HT_DCPHASE | Hilbert Transform - Dominant Cycle Phase |
|
|
26
|
-
| HT_PHASOR | Hilbert Transform - Phasor Components |
|
|
27
|
-
| HT_SINE | Hilbert Transform - SineWave |
|
|
28
|
-
| HT_TRENDLINE | Hilbert Transform - Instantaneous Trendline |
|
|
29
|
-
| HT_TRENDMODE | Hilbert Transform - Trend vs Cycle Mode |
|
|
30
|
-
| KAMA | Kaufman Adaptive Moving Average |
|
|
31
|
-
| MACD | Moving Average Convergence Divergence |
|
|
32
|
-
| MACDEXT | MACD with controllable MA type |
|
|
33
|
-
| MAMA | MESA Adaptive Moving Average |
|
|
34
|
-
| MFI | Money Flow Index |
|
|
35
|
-
| MIDPOINT | MidPoint over period |
|
|
36
|
-
| MIDPRICE | Midpoint Price over period |
|
|
37
|
-
| MINUS_DI | Minus Directional Indicator |
|
|
38
|
-
| MINUS_DM | Minus Directional Movement |
|
|
39
|
-
| MOM | Momentum |
|
|
40
|
-
| NATR | Normalized Average True Range |
|
|
41
|
-
| OBV | On Balance Volume |
|
|
42
|
-
| PLUS_DI | Plus Directional Indicator |
|
|
43
|
-
| PLUS_DM | Plus Directional Movement |
|
|
44
|
-
| PPO | Percentage Price Oscillator |
|
|
45
|
-
| ROC | Rate of Change |
|
|
46
|
-
| ROCR | Rate of Change Ratio |
|
|
47
|
-
| RSI | Relative Strength Index |
|
|
48
|
-
| SAR | Parabolic SAR |
|
|
49
|
-
| SMA | Simple Moving Average |
|
|
50
|
-
| STOCH | Stochastic Oscillator |
|
|
51
|
-
| STOCHF | Stochastic Fast |
|
|
52
|
-
| STOCHRSI | Stochastic Relative Strength Index |
|
|
53
|
-
| T3 | Triple Exponential Moving Average (T3) |
|
|
54
|
-
| TEMA | Triple Exponential Moving Average |
|
|
55
|
-
| TRANGE | True Range |
|
|
56
|
-
| TRIMA | Triangular Moving Average |
|
|
57
|
-
| TRIX | 1-day Rate of Change of a Triple Smooth EMA |
|
|
58
|
-
| ULTOSC | Ultimate Oscillator |
|
|
59
|
-
| VWAP | Volume Weighted Average Price |
|
|
60
|
-
| WILLR | Williams' %R |
|
|
61
|
-
| WMA | Weighted Moving Average |
|
|
62
|
-
|
data/docs/average_true_range.md
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Average True Range (ATR)
|
|
2
|
-
|
|
3
|
-
See: https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/atr
|
|
4
|
-
|
|
5
|
-
The ATR 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 ATR 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.
|
data/docs/bollinger_bands.md
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
# Bollinger Bands
|
|
4
|
-
|
|
5
|
-
This method takes in an array of historical prices for a stock, a period (the number of days to calculate the moving average and standard deviation over), and the number of standard deviations to use for the upper and lower Bollinger Bands. It uses the `moving_averages` method to calculate the moving average for the given period, and then calculates the standard deviation of the closing prices for each window of the given period. Finally, it calculates the upper and lower Bollinger Bands based on the moving average and standard deviation, and returns an array containing the upper and lower bands.
|
|
6
|
-
|
|
7
|
-
The `num_std_dev` parameter in the Bollinger Bands method specifies the number of standard deviations to use for the upper and lower bands. The default value for this parameter can depend on the specific security being analyzed and the time period being used.
|
|
8
|
-
|
|
9
|
-
A common default value for `num_std_dev` is 2, which corresponds to the standard deviation of the price data over the given time period. Using a value of 2 for `num_std_dev` will result in the upper and lower bands being placed at a distance of two standard deviations from the moving average.
|
|
10
|
-
|
|
11
|
-
However, the optimal value for `num_std_dev` can vary depending on the volatility of the security being analyzed. For highly volatile securities, a larger value for `num_std_dev` may be more appropriate, while for less volatile securities, a smaller value may be more appropriate.
|
|
12
|
-
|
|
13
|
-
Ultimately, the best default value for `num_std_dev` will depend on the specific use case and should be chosen based on the characteristics of the security being analyzed and the preferences of the analyst.
|
|
14
|
-
|
|
15
|
-
The difference between the upper and lower bands can be an indicator of how volatile the stock is.
|
data/docs/donchian_channel.md
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
# Donchian Channel
|
|
2
|
-
|
|
3
|
-
In the domain of computer programming, a Donchian Channel is a technical analysis indicator used to identify potential breakouts and trend reversals in financial markets. It consists of three lines: the upper channel line, the lower channel line, and the middle line.
|
|
4
|
-
|
|
5
|
-
The upper channel line is calculated by finding the highest high over a specified period of time, while the lower channel line is calculated by finding the lowest low over the same period. The middle line is simply the average of the upper and lower channel lines.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# Exponential Moving Average (EMA)
|
|
2
|
-
|
|
3
|
-
In financial analysis, the Exponential Moving Average (EMA) is a commonly used technical indicator that helps identify trends and smooth out price data. It is a type of moving average that gives more weight to recent prices, making it more responsive to recent price changes compared to other moving averages.
|
|
4
|
-
|
|
5
|
-
The EMA is calculated by applying a smoothing factor (often represented as a percentage) to the previous EMA value and adding a weighted average of the current price. The smoothing factor determines the weight given to the most recent price data, with higher values giving more weight to recent prices.
|
|
6
|
-
|
|
7
|
-
The EMA is used for various purposes in financial analysis, including:
|
|
8
|
-
|
|
9
|
-
1. Trend Identification: The EMA is often used to identify the direction and strength of a trend. When the current price is above the EMA, it suggests an uptrend, while a price below the EMA suggests a downtrend. Traders and investors may use the EMA crossover (when the price crosses above or below the EMA) as a signal to enter or exit positions.
|
|
10
|
-
|
|
11
|
-
2. Support and Resistance Levels: The EMA can act as dynamic support or resistance levels. In an uptrend, the EMA may provide support, and in a downtrend, it may act as resistance. Traders may use the EMA as a reference point for setting stop-loss orders or profit targets.
|
|
12
|
-
|
|
13
|
-
3. Price Reversals: The EMA can help identify potential price reversals. When the price deviates significantly from the EMA, it may indicate an overbought or oversold condition, suggesting a potential reversal in the near future. Traders may use this information to anticipate price reversals and adjust their trading strategies accordingly.
|
|
14
|
-
|
|
15
|
-
4. Volatility Assessment: The EMA can be used to assess market volatility. When the EMA is relatively flat, it suggests low volatility, while a steeply sloping EMA indicates higher volatility. Traders may adjust their trading strategies based on the level of volatility indicated by the EMA.
|
|
16
|
-
|
|
17
|
-
It's important to note that the EMA is just one of many technical indicators used in financial analysis. It is often used in combination with other indicators, such as the Simple Moving Average (SMA), to gain a more comprehensive understanding of market trends and price movements.
|
|
18
|
-
|
|
19
|
-
Traders and investors should consider their own trading strategies, risk tolerance, and timeframes when using the EMA or any other technical indicator for financial analysis. It's also recommended to backtest and validate any trading strategies before applying them in real-time trading.
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# Fibonacci Retracement
|
|
2
|
-
|
|
3
|
-
Fibonacci retracement is a popular technical analysis tool used to identify potential levels of support and resistance in a financial market. It is based on the theory that markets tend to move in a series of retracements and expansions, which follow a specific mathematical ratio derived from the Fibonacci sequence.
|
|
4
|
-
|
|
5
|
-
### How it's Used
|
|
6
|
-
|
|
7
|
-
Traders and analysts use Fibonacci retracement levels to determine potential areas where the price of an asset may reverse or continue its existing trend. The most commonly used Fibonacci retracement levels are 23.6%, 38.2%, 50%, 61.8%, and 78.6%.
|
|
8
|
-
|
|
9
|
-
When a market is trending, a trader would plot the Fibonacci retracement levels on the chart to identify potential areas where the price may pull back and find support (in an uptrend) or resistance (in a downtrend).
|
|
10
|
-
|
|
11
|
-
If the price retraces to one of these levels and finds support or resistance, it can be seen as an opportunity to enter a trade in the direction of the prevailing trend. Traders often use other technical analysis tools, such as trend lines, moving averages, or candlestick patterns, in combination with Fibonacci retracement to confirm potential trade setups.
|
|
12
|
-
|
|
13
|
-
### How it's Calculated
|
|
14
|
-
|
|
15
|
-
The calculation of Fibonacci retracement levels involves using the Fibonacci ratio of 0.236, 0.382, 0.500, 0.618, and 0.786.
|
|
16
|
-
|
|
17
|
-
To plot Fibonacci retracement levels, two points on a chart are required: a swing high and a swing low. A swing high is a peak in an uptrend, while a swing low is a trough in a downtrend.
|
|
18
|
-
|
|
19
|
-
The retracement levels are calculated by subtracting the percentage ratios (23.6%, 38.2%, etc.) from the difference between the swing high and the swing low. The resulting levels are then plotted on the chart.
|
|
20
|
-
|
|
21
|
-
For example, to calculate the 38.2% retracement level, the formula would be:
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
Retracement Level = (Swing High - Swing Low) * 0.382 + Swing Low
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Traders commonly use charting software or online tools that automatically calculate and plot Fibonacci retracement levels. This makes it easier for traders to visualize and analyze potential trading opportunities based on these levels.
|
|
28
|
-
|
|
29
|
-
Overall, Fibonacci retracement is a valuable technical analysis technique that can assist traders in identifying key support and resistance levels in a trending market. By understanding and correctly utilizing this tool, traders can enhance their decision-making process and potentially improve their trading outcomes.
|
|
30
|
-
|