L allgemeine, có 2 loại investor trên thế giới. Fundamental investor xem fundamental metrics như business model, revenues, earnings, cashflows, valuation hiện tại, risks, growth prospects khi quyết định invest vào công ty. Warren Buffett nổi tiếng và thành một trong người giàu nhất thế giới bằng cách tìm công ty undervalued qua fundamental research.
Mặt khác, technical investors ít hoặc không chú ý fundamentals công ty, thay vào đó focus attention vào derive buy, sell, hold signals từ hàng trăm technical indicators. Các technical investors trade trên cơ sở daily, weekly, monthly.
Tôi không tranh luận cho hoặc chống investing styles nào. Nhưng cả fundamental và technical investors study, analyze, quyết định dựa trên hàng trăm, nếu không phải hàng nghìn data sources.
Fundamental investors study balance sheets, income statements, cash flow statements, demographic trends, thematic trends, social trends across thousands companies và hundreds industries globally. Họ build financial models hoặc analytics trên data đó để hiểu trajectory của companies và growth prospects.
Technical investors nhìn hàng trăm technical indicators trên cơ sở hourly/daily để derive investing signals. Investors rely trên technical indicators phải deal với vast array data across multiple time frames để build trading strategies. Họ cần query vast số indicators và require virtually instant answers. Họ cần quickly adapt algorithms và trading strategies cho fast-changing markets. Redis Enterprise giải quyết tất cả challenges này.
Gần đây, tôi viết về tại sao Redis Enterprise là essential tool cho financial industry. Bài này sẽ show cách RedisTimeSeries dùng store, aggregate, query stock prices và technical indicators. Các nguyên tắc outlined cũng dùng store/query financial information từ companies hoặc bất kỳ time-series data nào fundamental investors dùng.
Module RedisTimeSeries ingest và query millions events, samples, pricing data. RedisTimeSeries best suited cho storing related pairs của times và values để spot trends trong use cases từ IoT đến healthcare đến finance. RedisTimeSeries cung cấp aggregations như average, sum, minimum, maximum, standard deviation, range, etc. giúp easily analyze data và make decisions.
Tracking stock prices với RedisTimeSeries
Bài này illustrate model dùng RedisTimeSeries store stock prices và technical indicators. Sẽ cover tạo various time series cho prices và indicators, show cách tạo aggregations trên raw time series, và demo cách dễ dàng bulk time series ingested và queried dùng various RedisTimeSeries commands. Cung cấp sample code Python làm starting point cho use case của bạn.
Đúng hay sai, nhiều người coi Dow Jones Industrial Average (DJIA) là bellwether cho US economy. Tôi muốn track technical indicator của all 30 stocks trong DJIA cùng price và trading volume. Khởi động bằng track stock prices của Dow-component Goldman Sachs và một technical indicator cho stock đó. Technical indicator yêu thích của tôi là Relative Strength Index (RSI). RSI là momentum indicator đo lường stock có thể overbought hoặc oversold. Khi RSI near hoặc below 30, stock có thể oversold và present buying opportunity. Tương tự, khi RSI above 70, có thể entering overbought territory signal good time to sell.
Relative Strength Index cho Goldman Sachs Group
Trong trading hours, RSI, như any technical indicator, varies khi trades executed dựa trên demand và supply Goldman Sachs shares. Chúng ta dùng RedisTimeSeries module giúp trả lời các câu hỏi then chốt:
- Minimum và maximum value cho technical indicator cho mỗi specified time interval?
- Cho phép quickly spot entry/exit points cho trade.
- Range và standard deviation cho stock price trong specified time interval?
- Range và standard deviation là indicators của volatility của underlying stock price.
- Có thể profitable entry/exit prices cho trades stock này?
- Value của technical indicator across all stocks trong specified time interval?
Chúng ta dùng RedisTimeSeries queries programmatically identify min/max RSI values và stock prices trong designated time period. Ví dụ, nếu muốn tìm min/max RSI numbers trong mỗi 15-minute period của trading day? Khi RSI at/near 30, tôi muốn generate alert, place trade, hoặc kickoff complex trading workflow analyze other technical indicators trước buy/sell. Bất cứ điều gì bạn muốn đều easily modeled trong RedisTimeSeries database.
Data model cho stock prices và technical indicators
Cách dễ nhất hands-on RedisTimeSeries là chạy Docker image cho RedisTimeSeries.
Chạy lệnh sau pull và run Docker image:
docker run -p 6379:6379 -it --rm redis/redistimeseries
Redis team quyết định thiết kế deliberate cho RedisTimeSeries module hold single metric trong mỗi time series. Simplicity trong data model làm insertion và retrieval data super fast. Bạn add new time series as needed mà không lo break existing application. Nghĩa là bạn add new data sources dễ dàng không lo break database schema hoặc application.
Khi đã RedisTimeSeries container up and running, connect đến server (đảm bảo đúng IP/hostname) dùng Python:
from redistimeseries.client import Client rts = Client(host='127.0.0.1', port=6379)
Với design principle hold single metric mỗi time series, chúng ta store intraday stock price và RSI cho mỗi DJIA stock trong own time series. Dưới, tôi tạo time series cho Goldman Sachs Group, Inc. (NYSE: GS). Tôi đặt tên intraday RSI cho Goldman Sachs là ‘DAILYRSI:GS’ và apply various labels cho mỗi time series—labeling time series cho phép query across all keys dùng label.
rts.create('DAILYRSI:GS', labels={ 'SYMBOL': 'GS' , 'DESC':'RELATIVE_STRENGTH_INDEX' , 'INDEX' :'DJIA' , 'TIMEFRAME': '1_DAY' , 'INDICATOR':'RSI' , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'})
Tôi tạo time series cho intraday stock prices Goldman Sachs tên ‘INTRADAYPRICES:GS’:
rts.create('INTRADAYPRICES:GS', labels={ 'SYMBOL': 'GS' , 'DESC':'SHARE_PRICE' , 'INDEX' :'DJIA' , 'PRICETYPE':'INTRADAY' , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'})
Tiếp, tạo various aggregations trên RSI data trong 15-minute timeframes. (Có thể tạo aggregations longer/shorter time frames phù hợp trading needs.) Aggregations này let us look at first, last, min, max, range values cho RSI. Tạo aggregation, trước tạo time series lưu aggregation, sau tạo rule populate time series với aggregated value. Trong case này, tạo time series ‘DAILYRSI15MINRNG:GS’ lưu range cho RSI trong 15-minute time frame. ‘createrule’ apply range function trên raw data (‘DAILYRSI:GS’) mỗi 15-minute time frame và aggregate vào ‘DAILYRSI15MINRNG:GS’.
rts.create('DAILYRSI15MINRNG:GS', labels={ 'SYMBOL': 'GS' , 'DESC':'RELATIVE_STRENGTH_INDEX' , 'INDEX' :'DJIA' , 'TIMEFRAME': '15_MINUTES' , 'AGGREGATION': 'RANGE' , 'INDICATOR':'RSI' , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'}) rts.createrule('DAILYRSI:GS', 'DAILYRSI15MINRNG:GS', 'range', 900)
Tôi tạo couple rules calculate range và standard deviation cho Goldman Sachs stock price mỗi 15-minute interval trading day:
rts.create('INTRADAYPRICES15MINRNG:GS' , labels={ 'SYMBOL': 'GS' , 'DESC':'SHARE_PRICE' , 'INDEX' :'DJIA' , 'PRICETYPE':'RANGE' , 'AGGREGATION': 'RANGE' , 'DURATION':'15_MINUTES' , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'}) rts.createrule('INTRADAYPRICES:GS’ ,'INTRADAYPRICES15MINRNG:GS' ,'range', 900) rts.create('INTRADAYPRICES15MINSTDP:GS' , labels={ 'SYMBOL': 'GS' , 'DESC':'SHARE_PRICE' , 'INDEX' :'DJIA' , 'PRICETYPE':'STDDEV' , 'AGGREGATION': 'STDDEV' , 'DURATION':'15_MINUTES' , 'COMPANYNAME': 'GOLDMAN_SACHS_GROUP'}) rts.createrule( 'INTRADAYPRICES:GS' , 'INTRADAYPRICES15MINSTDP:GS' , 'std.p', 900)
Bạn tạo time series cho all 30 stocks trong Dow Jones Industrial Average (DJIA) tương tự.
Data ingestion methods
Có 2 cách ingest data vào RedisTimeSeries. Lệnh TS.ADD cho phép add mỗi stock price/technical indicator vào time series. Vì data financial market produced gần như continuously và bạn cần add multiple samples, tốt hơn dùng method TS.MADD. MADD function takes list of tuples as argument. Mỗi tuple lấy tên time-series key, timestamp, value:
Bạn dùng Python command sau insert data vào time-series key:
rts.madd(<RSIIndicatorList>)
Querying RedisTimeSeries
Như most things RedisTimeSeries, query database dễ dàng. Range và standard deviation cho stock price/technical indicator là indication của volatility. Query sau let you see price range và standard deviation cho Goldman Sachs stock price trong every 15-minute interval:
rts.range( 'INTRADAYPRICES15MINRNG:GS' , from_time = 1603704600 , to_time = 1603713600)
Query range aggregation cho result set:
[(1603704600, 1.75999999999999), (1603705500, 0.775000000000006), (1603706400, 0.730000000000018), (1603707300, 0.449999999999989), (1603708200, 0.370000000000005), (1603709100, 1.01000000000002), (1603710000, 0.490000000000009), (1603710900, 0.89500000000001), (1603711800, 0.629999999999995), (1603712700, 0.490000000000009), (1603713600, 0.27000000000001)]
Như result cho thấy, tại start trading day 9:30 a.m. Oct 26, 2020 ET (integer timestamp = 1603704600) Goldman Sachs stock volatile, trading với range $1.75. So sánh next 15 minutes, 9:45 a.m. (timestamp = 1603705500), volatility dropped với range $0.77. Range prices tiếp tục drop subsequent intervals và không bao giờ quay lại levels opening interval.
Data từ RedisTimeSeries dễ visualize trong dashboards và charts. Charts dưới show Goldman Sachs price range 15-minute intervals:
Chart dưới show same data line chart format, chỉ price range Goldman Sachs trades tighter as time progresses through day (chart show integer timestamps x-axis):
Bạn làm similar query với measure volatility khác—standard deviation—as aggregation function:
rts.range( 'INTRADAYPRICES15MINSTDP:GS' , from_time = 1603704600 , to_time = 1603713600)
[(1603704600, 0.54657783830434), (1603705500, 0.23201149395202), (1603706400, 0.196072381345986), (1603707300, 0.160267138157647), (1603708200, 0.116990621700049), (1603709100, 0.28043101744222), (1603710000, 0.144379900126934), (1603710900, 0.327611558618967), (1603711800, 0.163118915546951), (1603712700, 0.151417199675549), (1603713600, 0.0963889432843203)]
Điều này mở nhiều intriguing possibilities. Giả sử bạn muốn biết price Goldman Sachs stock khi intraday RSI value between 30 và 40. Bạn query time series RSI và time series stock prices identify profitable entry points cho trade.
Ở đây, tôi query RSI value Goldman Sachs tại time frame giữa 1605260100 (9:35 a.m. ET Nov 13, 2020) và 1605260940 (9:49 a.m. ngày đó).
dailyGSRSIValue = rts.range( 'DAILYRSI:GS' , from_time = 1605260100 , to_time = 1605260940)
Query tìm RSI value 34.2996427544861 tại 1605260820 (9:47 a.m. ET).
[(1605260100, 75.0305441024708), (1605260160, 81.6673948350152), (1605260220, 83.8852225932517), (1605260280, 85.9469082344746), (1605260340, 94.3803586011592), (1605260400, 92.2412262502652), (1605260460, 85.6867329371465), (1605260520, 87.9557361513823), (1605260580, 89.9407873066781), (1605260640, 57.1512452602676), (1605260700, 50.5638232111769), (1605260760, 35.2804436894564), (1605260820, 34.2996427544861), (1605260880, 54.5486275202972), (1605260940, 64.7593307385219)]
Bây giờ query Goldman Sachs intraday prices cho same interval as RSI query, hoặc change query programmatically reflect khi RSI value at 34.29. Example dùng same time frame as RSI query.
dailyGSPrice = rts.range( 'INTRADAYPRICES:GS' , from_time = 1605260100 , to_time = 1605260940)
Query return Goldman Sachs stock prices cho specified range: Tại 1605260820 (9:47 a.m. ET Nov 13, 2020) price $217.18.
[(1605260100, 216.57), (1605260160, 216.73), (1605260220, 217.08), (1605260280, 217.17), (1605260340, 217.87), (1605260400, 218.05), (1605260460, 217.91), (1605260520, 218.0), (1605260580, 218.11), (1605260640, 218.02), (1605260700, 217.72), (1605260760, 217.22), (1605260820, 217.18), (1605260880, 217.46), (1605260940, 217.61)]
RedisTimeSeries cung cấp powerful way query across multiple time series at once. Lệnh TS.MGET cho phép query across multiple time series dùng filters. Chúng ta đã tạo various time series và attach labels. Giờ labels those act as filters query across time series.
Python code sau apply 2 filters based trên labels: "DESC" và "TIMEFRAME". Parameter “with_labels=False” cho result set return without labels cho mỗi value:
allRSIValues = rts.mget(filters=['DESC=RELATIVE_STRENGTH_INDEX','TIMEFRAME=1_DAY'], with_labels=False)
Query present result similar như dưới, return last RSI values across số stocks:
[{'DAILYRSI:BA': [{}, 1605261060, 62.2048922111768]}, {'DAILYRSI:CAT': [{}, 1605261060, 68.3834400302296]}, {'DAILYRSI:CRM': [{}, 1605261060, 59.2107333830133]}, {'DAILYRSI:CSCO': [{}, 1605261060, 52.7011052724688]}, {'DAILYRSI:CVX': [{}, 1605261060, 62.9890368832232]}, {'DAILYRSI:DOW': [{}, 1605261060, 73.597680480764]}, {'DAILYRSI:GS': [{}, 1605283140, 41.182852552541]}, {'DAILYRSI:IBM': [{}, 1605261060, 65.3742140862697]}, {'DAILYRSI:JPM': [{}, 1605261060, 77.7760292843745]}, {'DAILYRSI:KO': [{}, 1605261060, 26.8638381005608]}, {'DAILYRSI:MMM': [{}, 1605261060, 65.7852833683174]}, {'DAILYRSI:MRK': [{}, 1605261060, 38.9991886598036]}, {'DAILYRSI:UNH': [{}, 1605261060, 74.2672428885775]}, {'DAILYRSI:VZ': [{}, 1605261060, 33.177554436462]}, {'DAILYRSI:WBA': [{}, 1605261060, 47.3877762365391]}]
Nếu set “with_labels=True”, result include all labels trên mỗi time series, như dưới:
[{'DAILYRSI:BA': [{'SYMBOL': 'BA', 'DESC': 'RELATIVE_STRENGTH_INDEX', 'INDEX': 'DJIA', 'TIMEFRAME': '1_DAY', 'INDICATOR': 'RSI', 'COMPANYNAME': 'BOEING'}, 1605261060, 62.2048922111768]}, {'DAILYRSI:CAT': [{'SYMBOL': 'CAT', 'DESC': 'RELATIVE_STRENGTH_INDEX', 'INDEX': 'DJIA', 'TIMEFRAME': '1_DAY', 'INDICATOR': 'RSI', 'COMPANYNAME': 'CATERPILLAR'}, 1605261060, 68.3834400302296]}, {'DAILYRSI:CRM': [{'SYMBOL': 'CRM', 'DESC': 'RELATIVE_STRENGTH_INDEX', 'INDEX': 'DJIA', 'TIMEFRAME': '1_DAY', 'INDICATOR': 'RSI', 'COMPANYNAME': 'SALESFORCE'}, 1605261060, 59.2107333830133]}]
Kết luận
Bài viết illustrate một số commands RedisTimeSeries để flexibly build financial application dependent on time-series data. Stock traders, ví dụ, cần make high-stakes decisions real-time dựa trên dozens variables. RedisTimeSeries schemaless, nghĩa là load data không define schema, add new fields on the fly, hoặc change data model nếu business circumstances change. Real-time performance và simple developer experience makes it fun working with time-series data!
Sample code bài viết trên GitHub tại đây. Tìm hiểu thêm RedisTimeSeries tại đây.