timescaledb 0.2.6 → 0.2.7
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/lib/timescaledb/acts_as_hypertable/core.rb +1 -1
- data/lib/timescaledb/database/quoting.rb +12 -0
- data/lib/timescaledb/database/schema_statements.rb +168 -0
- data/lib/timescaledb/database/types.rb +17 -0
- data/lib/timescaledb/database.rb +11 -0
- data/lib/timescaledb/toolkit/time_vector.rb +41 -4
- data/lib/timescaledb/version.rb +1 -1
- metadata +6 -95
- data/.github/workflows/ci.yml +0 -72
- data/.gitignore +0 -12
- data/.rspec +0 -3
- data/.ruby-version +0 -1
- data/.tool-versions +0 -1
- data/.travis.yml +0 -9
- data/CODE_OF_CONDUCT.md +0 -74
- data/Fastfile +0 -17
- data/Gemfile +0 -8
- data/Gemfile.lock +0 -75
- data/Gemfile.scenic +0 -7
- data/Gemfile.scenic.lock +0 -119
- data/README.md +0 -490
- data/Rakefile +0 -21
- data/bin/console +0 -28
- data/bin/setup +0 -13
- data/docs/command_line.md +0 -178
- data/docs/img/lttb_example.png +0 -0
- data/docs/img/lttb_sql_vs_ruby.gif +0 -0
- data/docs/img/lttb_zoom.gif +0 -0
- data/docs/index.md +0 -72
- data/docs/migrations.md +0 -76
- data/docs/models.md +0 -78
- data/docs/toolkit.md +0 -507
- data/docs/toolkit_lttb_tutorial.md +0 -557
- data/docs/toolkit_lttb_zoom.md +0 -357
- data/docs/toolkit_ohlc.md +0 -315
- data/docs/videos.md +0 -16
- data/examples/all_in_one/all_in_one.rb +0 -94
- data/examples/all_in_one/benchmark_comparison.rb +0 -108
- data/examples/all_in_one/caggs.rb +0 -93
- data/examples/all_in_one/query_data.rb +0 -78
- data/examples/ranking/.gitattributes +0 -7
- data/examples/ranking/.gitignore +0 -29
- data/examples/ranking/.ruby-version +0 -1
- data/examples/ranking/Gemfile +0 -33
- data/examples/ranking/Gemfile.lock +0 -189
- data/examples/ranking/README.md +0 -166
- data/examples/ranking/Rakefile +0 -6
- data/examples/ranking/app/controllers/application_controller.rb +0 -2
- data/examples/ranking/app/controllers/concerns/.keep +0 -0
- data/examples/ranking/app/jobs/application_job.rb +0 -7
- data/examples/ranking/app/models/application_record.rb +0 -3
- data/examples/ranking/app/models/concerns/.keep +0 -0
- data/examples/ranking/app/models/game.rb +0 -2
- data/examples/ranking/app/models/play.rb +0 -7
- data/examples/ranking/bin/bundle +0 -114
- data/examples/ranking/bin/rails +0 -4
- data/examples/ranking/bin/rake +0 -4
- data/examples/ranking/bin/setup +0 -33
- data/examples/ranking/config/application.rb +0 -39
- data/examples/ranking/config/boot.rb +0 -4
- data/examples/ranking/config/credentials.yml.enc +0 -1
- data/examples/ranking/config/database.yml +0 -86
- data/examples/ranking/config/environment.rb +0 -5
- data/examples/ranking/config/environments/development.rb +0 -60
- data/examples/ranking/config/environments/production.rb +0 -75
- data/examples/ranking/config/environments/test.rb +0 -53
- data/examples/ranking/config/initializers/cors.rb +0 -16
- data/examples/ranking/config/initializers/filter_parameter_logging.rb +0 -8
- data/examples/ranking/config/initializers/inflections.rb +0 -16
- data/examples/ranking/config/initializers/timescale.rb +0 -2
- data/examples/ranking/config/locales/en.yml +0 -33
- data/examples/ranking/config/puma.rb +0 -43
- data/examples/ranking/config/routes.rb +0 -6
- data/examples/ranking/config/storage.yml +0 -34
- data/examples/ranking/config.ru +0 -6
- data/examples/ranking/db/migrate/20220209120747_create_games.rb +0 -10
- data/examples/ranking/db/migrate/20220209120910_create_plays.rb +0 -19
- data/examples/ranking/db/migrate/20220209143347_create_score_per_hours.rb +0 -5
- data/examples/ranking/db/schema.rb +0 -47
- data/examples/ranking/db/seeds.rb +0 -7
- data/examples/ranking/db/views/score_per_hours_v01.sql +0 -7
- data/examples/ranking/lib/tasks/.keep +0 -0
- data/examples/ranking/log/.keep +0 -0
- data/examples/ranking/public/robots.txt +0 -1
- data/examples/ranking/storage/.keep +0 -0
- data/examples/ranking/tmp/.keep +0 -0
- data/examples/ranking/tmp/pids/.keep +0 -0
- data/examples/ranking/tmp/storage/.keep +0 -0
- data/examples/ranking/vendor/.keep +0 -0
- data/examples/toolkit-demo/compare_volatility.rb +0 -104
- data/examples/toolkit-demo/lttb/README.md +0 -15
- data/examples/toolkit-demo/lttb/lttb.rb +0 -92
- data/examples/toolkit-demo/lttb/lttb_sinatra.rb +0 -139
- data/examples/toolkit-demo/lttb/lttb_test.rb +0 -21
- data/examples/toolkit-demo/lttb/views/index.erb +0 -27
- data/examples/toolkit-demo/lttb-zoom/README.md +0 -13
- data/examples/toolkit-demo/lttb-zoom/lttb_zoomable.rb +0 -90
- data/examples/toolkit-demo/lttb-zoom/views/index.erb +0 -33
- data/examples/toolkit-demo/ohlc.rb +0 -175
- data/mkdocs.yml +0 -34
- data/timescaledb.gemspec +0 -40
@@ -1,139 +0,0 @@
|
|
1
|
-
# ruby lttb.rb postgres://user:pass@host:port/db_name
|
2
|
-
require 'bundler/inline' #require only what you need
|
3
|
-
|
4
|
-
gemfile(true) do
|
5
|
-
gem 'timescaledb', path: '../../..'
|
6
|
-
gem 'pry'
|
7
|
-
gem 'sinatra', require: false
|
8
|
-
gem 'sinatra-reloader', require: false
|
9
|
-
gem 'sinatra-cross_origin', require: false
|
10
|
-
gem 'chartkick'
|
11
|
-
end
|
12
|
-
|
13
|
-
require 'timescaledb/toolkit'
|
14
|
-
require 'sinatra'
|
15
|
-
require 'sinatra/json'
|
16
|
-
require 'sinatra/cross_origin'
|
17
|
-
require 'chartkick'
|
18
|
-
require_relative 'lttb'
|
19
|
-
|
20
|
-
PG_URI = ARGV.last
|
21
|
-
|
22
|
-
VALID_SIZES = %i[small med big]
|
23
|
-
def download_weather_dataset size: :small
|
24
|
-
unless VALID_SIZES.include?(size)
|
25
|
-
fail "Invalid size: #{size}. Valids are #{VALID_SIZES}"
|
26
|
-
end
|
27
|
-
url = "https://timescaledata.blob.core.windows.net/datasets/weather_#{size}.tar.gz"
|
28
|
-
puts "fetching #{size} weather dataset..."
|
29
|
-
system "wget \"#{url}\""
|
30
|
-
puts "done!"
|
31
|
-
end
|
32
|
-
|
33
|
-
def setup size: :small
|
34
|
-
file = "weather_#{size}.tar.gz"
|
35
|
-
download_weather_dataset(size: size) unless File.exists? file
|
36
|
-
puts "extracting #{file}"
|
37
|
-
system "tar -xvzf #{file} "
|
38
|
-
puts "creating data structures"
|
39
|
-
system "psql #{PG_URI} < weather.sql"
|
40
|
-
system %|psql #{PG_URI} -c "\\COPY locations FROM weather_#{size}_locations.csv CSV"|
|
41
|
-
system %|psql #{PG_URI} -c "\\COPY conditions FROM weather_#{size}_conditions.csv CSV"|
|
42
|
-
end
|
43
|
-
|
44
|
-
ActiveRecord::Base.establish_connection(PG_URI)
|
45
|
-
class Location < ActiveRecord::Base
|
46
|
-
self.primary_key = "device_id"
|
47
|
-
|
48
|
-
has_many :conditions, foreign_key: "device_id"
|
49
|
-
end
|
50
|
-
|
51
|
-
class Condition < ActiveRecord::Base
|
52
|
-
acts_as_hypertable time_column: "time"
|
53
|
-
acts_as_time_vector value_column: "temperature", segment_by: "device_id"
|
54
|
-
|
55
|
-
belongs_to :location, foreign_key: "device_id"
|
56
|
-
end
|
57
|
-
|
58
|
-
# Setup Hypertable as in a migration
|
59
|
-
ActiveRecord::Base.connection.instance_exec do
|
60
|
-
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
61
|
-
|
62
|
-
unless Condition.table_exists?
|
63
|
-
setup size: :big
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
require 'sinatra/reloader'
|
68
|
-
require 'sinatra/contrib'
|
69
|
-
register Sinatra::Reloader
|
70
|
-
register Sinatra::Contrib
|
71
|
-
include Chartkick::Helper
|
72
|
-
|
73
|
-
set :bind, '0.0.0.0'
|
74
|
-
set :port, 9999
|
75
|
-
|
76
|
-
def conditions
|
77
|
-
device_ids = (1..9).map{|i|"weather-pro-00000#{i}"}
|
78
|
-
Condition
|
79
|
-
.where(device_id: device_ids.first)
|
80
|
-
.order('time')
|
81
|
-
end
|
82
|
-
|
83
|
-
def threshold
|
84
|
-
params[:threshold]&.to_i || 50
|
85
|
-
end
|
86
|
-
|
87
|
-
configure do
|
88
|
-
enable :cross_origin
|
89
|
-
end
|
90
|
-
before do
|
91
|
-
response.headers['Access-Control-Allow-Origin'] = '*'
|
92
|
-
end
|
93
|
-
|
94
|
-
# routes...
|
95
|
-
options "*" do
|
96
|
-
response.headers["Allow"] = "GET, PUT, POST, DELETE, OPTIONS"
|
97
|
-
response.headers["Access-Control-Allow-Headers"] = "Authorization,
|
98
|
-
Content-Type, Accept, X-User-Email, X-Auth-Token"
|
99
|
-
response.headers["Access-Control-Allow-Origin"] = "*"
|
100
|
-
200
|
101
|
-
end
|
102
|
-
|
103
|
-
get '/' do
|
104
|
-
headers 'Access-Control-Allow-Origin' => 'https://cdn.jsdelivr.net/'
|
105
|
-
|
106
|
-
erb :index
|
107
|
-
end
|
108
|
-
|
109
|
-
get '/lttb_ruby' do
|
110
|
-
payload = conditions
|
111
|
-
.pluck(:device_id, :time, :temperature)
|
112
|
-
.group_by(&:first)
|
113
|
-
.map do |device_id, data|
|
114
|
-
data.each(&:shift)
|
115
|
-
{
|
116
|
-
name: device_id,
|
117
|
-
data: Lttb.downsample(data, threshold)
|
118
|
-
}
|
119
|
-
end
|
120
|
-
json payload
|
121
|
-
end
|
122
|
-
|
123
|
-
get "/lttb_sql" do
|
124
|
-
downsampled = conditions
|
125
|
-
.lttb(threshold: threshold)
|
126
|
-
.map do |device_id, data|
|
127
|
-
{
|
128
|
-
name: device_id,
|
129
|
-
data: data.sort_by(&:first)
|
130
|
-
}
|
131
|
-
end
|
132
|
-
json downsampled
|
133
|
-
end
|
134
|
-
|
135
|
-
|
136
|
-
get '/all_data' do
|
137
|
-
data = conditions.pluck(:time, :temperature)
|
138
|
-
json [ { name: "All data", data: data} ]
|
139
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require_relative 'lttb'
|
2
|
-
require 'pp'
|
3
|
-
require 'date'
|
4
|
-
|
5
|
-
data = [
|
6
|
-
['2020-1-1', 10],
|
7
|
-
['2020-1-2', 21],
|
8
|
-
['2020-1-3', 19],
|
9
|
-
['2020-1-4', 32],
|
10
|
-
['2020-1-5', 12],
|
11
|
-
['2020-1-6', 14],
|
12
|
-
['2020-1-7', 18],
|
13
|
-
['2020-1-8', 29],
|
14
|
-
['2020-1-9', 23],
|
15
|
-
['2020-1-10', 27],
|
16
|
-
['2020-1-11', 14]]
|
17
|
-
data.each do |e|
|
18
|
-
e[0] = Time.mktime(*e[0].split('-'))
|
19
|
-
end
|
20
|
-
|
21
|
-
pp Lttb.downsample(data, 5)
|
@@ -1,27 +0,0 @@
|
|
1
|
-
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.1/dist/jquery.min.js"></script>
|
2
|
-
<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8hammerjs@2.0.8"></script>
|
3
|
-
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js"></script>
|
4
|
-
<script src="https://cdn.jsdelivr.net/npm/highcharts@10.2.1/highcharts.min.js"></script>
|
5
|
-
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@1.0.0/dist/chartjs-adapter-moment.min.js"></script>
|
6
|
-
<script src="https://cdn.jsdelivr.net/npm/chartkick@4.2.0/dist/chartkick.min.js"></script>
|
7
|
-
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@1.2.1/dist/chartjs-plugin-zoom.min.js"></script>
|
8
|
-
<h3>Downsampling <%= conditions.count %> records to
|
9
|
-
<select value="<%= threshold %>" onchange="location.href=`/?threshold=${this.value}`">
|
10
|
-
<option><%= threshold %></option>
|
11
|
-
<option value="50">50</option>
|
12
|
-
<option value="100">100</option>
|
13
|
-
<option value="500">500</option>
|
14
|
-
<option value="1000">1000</option>
|
15
|
-
<option value="5000">5000</option>
|
16
|
-
</select> points.
|
17
|
-
</h3>
|
18
|
-
|
19
|
-
<h3>SQL</h3>
|
20
|
-
<%= line_chart("/lttb_sql?threshold=#{threshold}",
|
21
|
-
loading: "dowsampled data from SQL") %>
|
22
|
-
<h3>Ruby</h3>
|
23
|
-
<%= line_chart("/lttb_ruby?threshold=#{threshold}",
|
24
|
-
library: {chart: {zoomType: 'x'}},
|
25
|
-
points: true, loading: "downsampled data from Ruby") %>
|
26
|
-
<!--%= line_chart("/all_data", loading: "Loading all data") %-->
|
27
|
-
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# LTTB examples
|
2
|
-
|
3
|
-
This folder contains an example to explore the a dynamic reloading of downsampled data.
|
4
|
-
|
5
|
-
It keeps the same amount of data and refresh the data with a higher resolution
|
6
|
-
as you keep zooming in.
|
7
|
-
There is a [./lttb_zoomable.rb](./lttb_zoomable.rb) file is a small webserver that compares
|
8
|
-
the SQL vs Ruby implementation. It also uses the [./views](./views) folder which
|
9
|
-
contains the view with the rendering and javascript part.
|
10
|
-
|
11
|
-
You can learn more by reading the [LTTB Zoom tutorial](https://jonatas.github.io/timescaledb/toolkit_lttb_zoom/).
|
12
|
-
|
13
|
-
|
@@ -1,90 +0,0 @@
|
|
1
|
-
# ruby lttb_zoomable.rb postgres://user:pass@host:port/db_name
|
2
|
-
require 'bundler/inline' #require only what you need
|
3
|
-
|
4
|
-
gemfile(true) do
|
5
|
-
gem 'timescaledb', path: '../../..'
|
6
|
-
gem 'pry'
|
7
|
-
gem 'sinatra', require: false
|
8
|
-
gem 'sinatra-reloader'
|
9
|
-
gem 'sinatra-cross_origin'
|
10
|
-
end
|
11
|
-
|
12
|
-
require 'timescaledb/toolkit'
|
13
|
-
require 'sinatra'
|
14
|
-
require 'sinatra/json'
|
15
|
-
require 'sinatra/contrib'
|
16
|
-
|
17
|
-
register Sinatra::Reloader
|
18
|
-
register Sinatra::Contrib
|
19
|
-
|
20
|
-
PG_URI = ARGV.last
|
21
|
-
|
22
|
-
VALID_SIZES = %i[small med big]
|
23
|
-
def download_weather_dataset size: :small
|
24
|
-
unless VALID_SIZES.include?(size)
|
25
|
-
fail "Invalid size: #{size}. Valids are #{VALID_SIZES}"
|
26
|
-
end
|
27
|
-
url = "https://timescaledata.blob.core.windows.net/datasets/weather_#{size}.tar.gz"
|
28
|
-
puts "fetching #{size} weather dataset..."
|
29
|
-
system "wget \"#{url}\""
|
30
|
-
puts "done!"
|
31
|
-
end
|
32
|
-
|
33
|
-
def setup size: :small
|
34
|
-
file = "weather_#{size}.tar.gz"
|
35
|
-
download_weather_dataset(size: size) unless File.exists? file
|
36
|
-
puts "extracting #{file}"
|
37
|
-
system "tar -xvzf #{file} "
|
38
|
-
puts "creating data structures"
|
39
|
-
system "psql #{PG_URI} < weather.sql"
|
40
|
-
system %|psql #{PG_URI} -c "\\COPY locations FROM weather_#{size}_locations.csv CSV"|
|
41
|
-
system %|psql #{PG_URI} -c "\\COPY conditions FROM weather_#{size}_conditions.csv CSV"|
|
42
|
-
end
|
43
|
-
|
44
|
-
ActiveRecord::Base.establish_connection(PG_URI)
|
45
|
-
|
46
|
-
class Condition < ActiveRecord::Base
|
47
|
-
acts_as_hypertable time_column: "time"
|
48
|
-
acts_as_time_vector value_column: "temperature", segment_by: "device_id"
|
49
|
-
end
|
50
|
-
|
51
|
-
# Setup Hypertable as in a migration
|
52
|
-
ActiveRecord::Base.connection.instance_exec do
|
53
|
-
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
54
|
-
|
55
|
-
if !Condition.table_exists? || Condition.count.zero?
|
56
|
-
|
57
|
-
setup size: :big
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
|
-
def filter_by_request_params
|
63
|
-
filter= {device_id: "weather-pro-000001"}
|
64
|
-
if params[:filter] && params[:filter] != "null"
|
65
|
-
from, to = params[:filter].split(",").map(&Time.method(:parse))
|
66
|
-
filter[:time] = from..to
|
67
|
-
end
|
68
|
-
filter
|
69
|
-
end
|
70
|
-
|
71
|
-
def conditions
|
72
|
-
Condition.where(filter_by_request_params).order('time')
|
73
|
-
end
|
74
|
-
|
75
|
-
def threshold
|
76
|
-
params[:threshold]&.to_i || 50
|
77
|
-
end
|
78
|
-
|
79
|
-
configure do
|
80
|
-
enable :cross_origin
|
81
|
-
end
|
82
|
-
|
83
|
-
get '/' do
|
84
|
-
erb :index
|
85
|
-
end
|
86
|
-
|
87
|
-
get "/lttb_sql" do
|
88
|
-
downsampled = conditions.lttb(threshold: threshold, segment_by: nil)
|
89
|
-
json downsampled
|
90
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
<head>
|
2
|
-
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.1/dist/jquery.min.js"></script>
|
3
|
-
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
|
4
|
-
</head>
|
5
|
-
|
6
|
-
<h3>Downsampling <%= conditions.count %> records to
|
7
|
-
<select value="<%= threshold %>" onchange="location.href=`/?threshold=${this.value}`">
|
8
|
-
<option><%= threshold %></option>
|
9
|
-
<option value="50">50</option>
|
10
|
-
<option value="100">100</option>
|
11
|
-
<option value="500">500</option>
|
12
|
-
<option value="1000">1000</option>
|
13
|
-
<option value="5000">5000</option>
|
14
|
-
</select> points.
|
15
|
-
</h3>
|
16
|
-
<div id='container'></div>
|
17
|
-
<script>
|
18
|
-
let chart = document.getElementById('container');
|
19
|
-
function fetch(filter) {
|
20
|
-
$.ajax({
|
21
|
-
url: `/lttb_sql?threshold=<%= threshold %>&filter=${filter}`,
|
22
|
-
success: function(result) {
|
23
|
-
let x = result.map((e) => e[0]);
|
24
|
-
let y = result.map((e) => parseFloat(e[1]));
|
25
|
-
Plotly.newPlot(chart, [{x, y,"mode": "markers", "type": "scatter"}]);
|
26
|
-
chart.on('plotly_relayout',
|
27
|
-
function(eventdata){
|
28
|
-
fetch([eventdata['xaxis.range[0]'],eventdata['xaxis.range[1]']]);
|
29
|
-
});
|
30
|
-
}});
|
31
|
-
}
|
32
|
-
fetch(null);
|
33
|
-
</script>
|
@@ -1,175 +0,0 @@
|
|
1
|
-
# ruby ohlc.rb postgres://user:pass@host:port/db_name
|
2
|
-
# @see https://jonatas.github.io/timescaledb/ohlc_tutorial
|
3
|
-
|
4
|
-
require 'bundler/inline' #require only what you need
|
5
|
-
|
6
|
-
gemfile(true) do
|
7
|
-
gem 'timescaledb', path: '../..'
|
8
|
-
gem 'pry'
|
9
|
-
end
|
10
|
-
|
11
|
-
ActiveRecord::Base.establish_connection ARGV.last
|
12
|
-
|
13
|
-
# Compare ohlc processing in Ruby vs SQL.
|
14
|
-
class Tick < ActiveRecord::Base
|
15
|
-
acts_as_hypertable time_column: "time"
|
16
|
-
acts_as_time_vector segment_by: "symbol", value_column: "price"
|
17
|
-
end
|
18
|
-
require "active_support/concern"
|
19
|
-
|
20
|
-
module Ohlc
|
21
|
-
extend ActiveSupport::Concern
|
22
|
-
|
23
|
-
included do
|
24
|
-
%w[open high low close].each do |name|
|
25
|
-
attribute name, :decimal
|
26
|
-
attribute "#{name}_time", :time
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
scope :attributes, -> do
|
31
|
-
select("symbol, time,
|
32
|
-
toolkit_experimental.open(ohlc),
|
33
|
-
toolkit_experimental.high(ohlc),
|
34
|
-
toolkit_experimental.low(ohlc),
|
35
|
-
toolkit_experimental.close(ohlc),
|
36
|
-
toolkit_experimental.open_time(ohlc),
|
37
|
-
toolkit_experimental.high_time(ohlc),
|
38
|
-
toolkit_experimental.low_time(ohlc),
|
39
|
-
toolkit_experimental.close_time(ohlc)")
|
40
|
-
end
|
41
|
-
|
42
|
-
scope :rollup, -> (timeframe: '1h') do
|
43
|
-
select("symbol, time_bucket('#{timeframe}', time) as time,
|
44
|
-
toolkit_experimental.rollup(ohlc) as ohlc")
|
45
|
-
.group(1,2)
|
46
|
-
end
|
47
|
-
|
48
|
-
def readonly?
|
49
|
-
true
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
class_methods do
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
class Ohlc1m < ActiveRecord::Base
|
58
|
-
self.table_name = 'ohlc_1m'
|
59
|
-
include Ohlc
|
60
|
-
end
|
61
|
-
|
62
|
-
class Ohlc1h < ActiveRecord::Base
|
63
|
-
self.table_name = 'ohlc_1h'
|
64
|
-
include Ohlc
|
65
|
-
end
|
66
|
-
|
67
|
-
class Ohlc1d < ActiveRecord::Base
|
68
|
-
self.table_name = 'ohlc_1d'
|
69
|
-
include Ohlc
|
70
|
-
end
|
71
|
-
=begin
|
72
|
-
scope :ohlc_ruby, -> (
|
73
|
-
timeframe: 1.hour,
|
74
|
-
segment_by: segment_by_column,
|
75
|
-
time: time_column,
|
76
|
-
value: value_column) {
|
77
|
-
ohlcs = Hash.new() {|hash, key| hash[key] = [] }
|
78
|
-
|
79
|
-
key = tick.send(segment_by)
|
80
|
-
candlestick = ohlcs[key].last
|
81
|
-
if candlestick.nil? || candlestick.time + timeframe > tick.time
|
82
|
-
ohlcs[key] << Candlestick.new(time $, price)
|
83
|
-
end
|
84
|
-
find_all do |tick|
|
85
|
-
symbol = tick.symbol
|
86
|
-
|
87
|
-
if previous[symbol]
|
88
|
-
delta = (tick.price - previous[symbol]).abs
|
89
|
-
volatility[symbol] += delta
|
90
|
-
end
|
91
|
-
previous[symbol] = tick.price
|
92
|
-
end
|
93
|
-
volatility
|
94
|
-
}
|
95
|
-
=end
|
96
|
-
|
97
|
-
ActiveRecord::Base.connection.add_toolkit_to_search_path!
|
98
|
-
|
99
|
-
|
100
|
-
ActiveRecord::Base.connection.instance_exec do
|
101
|
-
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
102
|
-
|
103
|
-
unless Tick.table_exists?
|
104
|
-
hypertable_options = {
|
105
|
-
time_column: 'time',
|
106
|
-
chunk_time_interval: '1 week',
|
107
|
-
compress_segmentby: 'symbol',
|
108
|
-
compress_orderby: 'time',
|
109
|
-
compression_interval: '1 month'
|
110
|
-
}
|
111
|
-
create_table :ticks, hypertable: hypertable_options, id: false do |t|
|
112
|
-
t.column :time , 'timestamp with time zone'
|
113
|
-
t.string :symbol
|
114
|
-
t.decimal :price
|
115
|
-
t.integer :volume
|
116
|
-
end
|
117
|
-
|
118
|
-
options = {
|
119
|
-
with_data: false,
|
120
|
-
refresh_policies: {
|
121
|
-
start_offset: "INTERVAL '1 month'",
|
122
|
-
end_offset: "INTERVAL '1 minute'",
|
123
|
-
schedule_interval: "INTERVAL '1 minute'"
|
124
|
-
}
|
125
|
-
}
|
126
|
-
create_continuous_aggregate('ohlc_1m', Tick._ohlc(timeframe: '1m'), **options)
|
127
|
-
|
128
|
-
execute "CREATE VIEW ohlc_1h AS #{ Ohlc1m.rollup(timeframe: '1 hour').to_sql}"
|
129
|
-
execute "CREATE VIEW ohlc_1d AS #{ Ohlc1h.rollup(timeframe: '1 day').to_sql}"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
if Tick.count.zero?
|
134
|
-
ActiveRecord::Base.connection.execute(<<~SQL)
|
135
|
-
INSERT INTO ticks
|
136
|
-
SELECT time, 'SYMBOL', 1 + (random()*30)::int, 100*(random()*10)::int
|
137
|
-
FROM generate_series(TIMESTAMP '2022-01-01 00:00:00',
|
138
|
-
TIMESTAMP '2022-02-01 00:01:00',
|
139
|
-
INTERVAL '1 second') AS time;
|
140
|
-
SQL
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
# Fetch attributes
|
145
|
-
Ohlc1m.attributes
|
146
|
-
|
147
|
-
# Rollup demo
|
148
|
-
|
149
|
-
# Attributes from rollup
|
150
|
-
Ohlc1m.attributes.from(Ohlc1m.rollup(timeframe: '1 day'))
|
151
|
-
|
152
|
-
|
153
|
-
# Nesting several levels
|
154
|
-
Ohlc1m.attributes.from(
|
155
|
-
Ohlc1m.rollup(timeframe: '1 week').from(
|
156
|
-
Ohlc1m.rollup(timeframe: '1 day')
|
157
|
-
)
|
158
|
-
)
|
159
|
-
Ohlc1m.attributes.from(
|
160
|
-
Ohlc1m.rollup(timeframe: '1 month').from(
|
161
|
-
Ohlc1m.rollup(timeframe: '1 week').from(
|
162
|
-
Ohlc1m.rollup(timeframe: '1 day')
|
163
|
-
)
|
164
|
-
)
|
165
|
-
)
|
166
|
-
|
167
|
-
Pry.start
|
168
|
-
|
169
|
-
=begin
|
170
|
-
TODO: implement the ohlc_ruby
|
171
|
-
Benchmark.bm do |x|
|
172
|
-
x.report("ruby") { Tick.ohlc_ruby }
|
173
|
-
x.report("sql") { Tick.ohlc.map(&:attributes) }
|
174
|
-
end
|
175
|
-
=end
|
data/mkdocs.yml
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
site_name: The Timescaledb gem
|
2
|
-
repo_url: https://github.com/jonatas/timescaledb
|
3
|
-
edit_uri: edit/master/docs/
|
4
|
-
extra:
|
5
|
-
analytics:
|
6
|
-
provider: google
|
7
|
-
property: G-9B2BMB0TNQ
|
8
|
-
theme:
|
9
|
-
name: material
|
10
|
-
palette:
|
11
|
-
primary: indigo
|
12
|
-
accent: pink
|
13
|
-
markdown_extensions:
|
14
|
-
- admonition
|
15
|
-
- codehilite:
|
16
|
-
guess_lang: false
|
17
|
-
- toc:
|
18
|
-
permalink: true
|
19
|
-
- pymdownx.highlight:
|
20
|
-
anchor_linenums: true
|
21
|
-
- pymdownx.inlinehilite
|
22
|
-
- pymdownx.snippets
|
23
|
-
- pymdownx.superfences
|
24
|
-
|
25
|
-
nav:
|
26
|
-
- Introduction: index.md
|
27
|
-
- Migrations: migrations.md
|
28
|
-
- Models: models.md
|
29
|
-
- Toolkit Integration: toolkit.md
|
30
|
-
- Toolkit LTTB Tutorial: toolkit_lttb_tutorial.md
|
31
|
-
- Zooming with High Resolution: toolkit_lttb_zoom.md
|
32
|
-
- Toolkit OHLC: toolkit_ohlc.md
|
33
|
-
- Command Line: command_line.md
|
34
|
-
- Videos: videos.md
|
data/timescaledb.gemspec
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require_relative 'lib/timescaledb/version'
|
2
|
-
|
3
|
-
Gem::Specification.new do |spec|
|
4
|
-
spec.name = "timescaledb"
|
5
|
-
spec.version = Timescaledb::VERSION
|
6
|
-
spec.authors = ["Jônatas Davi Paganini"]
|
7
|
-
spec.email = ["jonatasdp@gmail.com"]
|
8
|
-
|
9
|
-
spec.summary = %q{TimescaleDB helpers for Ruby ecosystem.}
|
10
|
-
spec.description = %q{Functions from timescaledb available in the ActiveRecord models.}
|
11
|
-
spec.homepage = "https://github.com/jonatas/timescaledb"
|
12
|
-
spec.license = "MIT"
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
14
|
-
|
15
|
-
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
16
|
-
|
17
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
-
#spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
19
|
-
#spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
20
|
-
|
21
|
-
# Specify which files should be added to the gem when it is released.
|
22
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
-
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
24
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
-
end
|
26
|
-
spec.bindir = "bin"
|
27
|
-
spec.executables = spec.files.grep(%r{^bin/tsdb}) { |f| File.basename(f) }
|
28
|
-
spec.require_paths = ["lib"]
|
29
|
-
|
30
|
-
spec.add_dependency "pg", "~> 1.2"
|
31
|
-
spec.add_dependency "activerecord"
|
32
|
-
spec.add_dependency "activesupport"
|
33
|
-
|
34
|
-
spec.add_development_dependency "pry"
|
35
|
-
spec.add_development_dependency "rspec-its"
|
36
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
37
|
-
spec.add_development_dependency "dotenv"
|
38
|
-
spec.add_development_dependency "rake", "~> 12.0"
|
39
|
-
spec.add_development_dependency "database_cleaner-active_record"
|
40
|
-
end
|