๐ TODAY'S GOAL๐
๐ ์ฃผ์ ๋งค๋งค ์ ๋ต์ ์ธ์ฐ๊ณ ,
๐ ๋งค์ผ ์ ํด์ง ์๊ฐ์ ์ฃผ์์ (๊ฐ์์ผ๋ก) ๋งค๋งคํ๊ณ ,
๐ ๋งค๋งคํ ๋ด์ฉ์ ๋ํด์ ๊ธฐ๋กํ๊ณ ,
๐ ์๋ฆผ ์ค์
๐ณ STEP 0 ๐ณ readstock ๋ช ๋ น์ ๋ค์์ฒ๋ผ ์ ๋ฐ์ดํธ
def generate(self):
url = self.url.format(self.code)
self.logger.info("Generating event with code %s" % (self.code))
with urlopen(url) as doc:
content = doc.read()
content = content.decode('utf-8', 'ignore')
soup = BeautifulSoup(content, 'lxml')
cur_price = soup.find('strong', id='_nowVal').text.replace(",", "")
cur_rate = soup.find('strong', id='_rate').text.strip()
cur_time = soup.find('span', id='time').text.strip()
#stock = soup.find('title')
stock_name = self.code
raw = {"price": cur_price, "rate": cur_rate, "code":stock_name, "time":cur_time }
yield {'_time': time.time(), '_raw': raw}
๐ณ STEP 0 ๐ณ Phase 10์ ML์ ์นดํ
๊ณ ๋ฆฌ ์ ์ ์๊ณ ๋ฆฌ์ฆ์์
๊ฐ ์์ธก ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋ณ๊ฒฝ
index="kospi" code="$code$.KS" earliest=0
| sort _time
| `mylag(Close, 10)`
| table _time, Close, lag_*
| where isnotnull(lag_9)
| fit StandardScaler "lag_0" "lag_1" "lag_2" "lag_3" "lag_4" "lag_5" "lag_6" "lag_7" "lag_8" "lag_9" "Close" with_mean=true with_std=true into "model_stock_predict_SS_$code$"
| fit RandomForestRegressor "SS_Close" from "SS_lag_0" "SS_lag_1" "SS_lag_2" "SS_lag_3" "SS_lag_4" "SS_lag_5" "SS_lag_6" "SS_lag_7" "SS_lag_8" "SS_lag_9" into "model_stock_predict_RF_$code$"
์ด๋ฅผ apply ํ๋ ๋ฐฉ๋ฒ์ "predict_stock_with_ml: ML์ ์ด์ฉํ ์์ธก" ๋ฅผ ์ฐธ์กฐํ์.
ํด๋น savedsearch ๋ ์์ ๋ง๋ค๊ณ linux cron ์ ์ด์ฉํด ๋งค ์ฃผ ํ๋ฒ ์คํํด์ ๋ชจ๋ธ์ ์ ๋ฐ์ดํธ ํ๋ค.
โ
$ vi run_build_model.sh
#!/bin/sh
home=/data/prj/stock
curl -k -u admin:changeme https://localhost:8089/servicesNS/admin/stock/search/jobs/export -d search="| inputlookup my_stock | table code" -d "output_mode=csv" -o "${home}/mystock.csv"
while read line; do
code=${line}
if [ ${code} != "code" ]; then
curl -k -u admin:changeme https://localhost:8089/servicesNS/admin/stock/search/jobs/export -d search="savedsearch make_ml_model%20code%3D$code" >> ${home}/logs/buildmodel_`date '+%y%m%d'`.log
fi
done < ${home}/mystock.csv
๐ณ STEP 1 ๐ณ Key-Value Store ์ถ๊ฐ
๋จผ์ ์๋ฎฌ๋ ์ดํฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์ ๋ฐ์ดํธ ํ ๊ณต๊ฐ์ ๋ง๋ค์ด ์ค๋ค.
Lookup ์์ "key-value" ์คํ ์ด๋ฅผ ์ ์ํด ์ฃผ์๋ค. (3์ฅ ์ฐธ์กฐ)
$ vi $SPLUNK_HOME/etc/apps/stock/local/collections.conf
[my_asset_history]
๐ณ my_asset_history ๐ณ
ํต์ฅ๊ณผ ๋น์ทํ ์ญํ ๋ก ํ์ฌ ๊ณ์ข์ ์๋ ํ๊ธ๊ณผ ์ฃผ์ ๋งค๋งค์ ๋งค๋งค๋ ๋ด์ญ์ ํ์ธํ ์ ์๋ ์คํ ์ด
๐น date: ๊ฑฐ๋ ๋ ์๊ฐ
๐น balance: ๊ณ์ข ์์ก
๐นcode: ์ฃผ์ ์ฝ๋
๐น method: "BUY or SELL" ๊ธฐ๋ก
๐น count: ๋งค๋งคํ ์ฃผ์ ๊ฐฏ์
๐น cost: ๋งค๋งคํ ๊ฑฐ๋ ์ก์
๐ณ my_stock ๐ณ
ํ์ฌ ์ฃผ์ ๋ณด์ ์๋ ๋ฐ ๋ชฉํ ๊ธฐ๋ก
๐นcode: ์ฃผ์ ์ฝ๋
๐น interest: "0 or 1" ๊ด์ฌ ์ข ๋ชฉ ํ๋๊ทธ
๐น share: ๋ณด์ ์ฃผ์ ์
๐น target: ๋ชฉํ ์ฃผ์ ๋น์จ (ํฌํธํด๋ฆฌ์ค ์์ฑ ์ ๊ฒฐ์ )
๐ณ stock_ml_predict ๐ณ
ML์ ํตํ ์ฃผ์ ์์ธก(10์ฅ ์ฐธ์กฐ)
๐นdate: ์์ธก ์คํํ ๋ ์ง
๐นcode: ์ฃผ์ ์ฝ๋
๐นclose: ์์ธกํ ์์ ์ ์ข ๊ฐ
๐นpredict: ์์ธก ๊ฐ๊ฒฉ
๐ณ stock_predict ๐ณ
predict ๋ฌธ์ ํตํ ์ฃผ์ ์์ธก (5์ฅ ์ฐธ์กฐ)
๐นdate: ์์ธก ์คํํ ๋ ์ง
๐นcode: ์ฃผ์ ์ฝ๋
๐นprice: ์์ธกํ ์์ ์ ์ข ๊ฐ
๐นpredict: ์์ธก ๊ฐ๊ฒฉ
๐นexpected_value: 5์ผ ํ ๊น์ง ์์๋๋ ๊ฐ๊ฒฉ ๋ณํ์จ
๐ณ stock_statics_predict ๐ณ
์ผ์ค์ฐฝ์ ํตํ ์ฃผ์ ์์ธก (9์ฅ ์ฐธ์กฐ)
๐นdate: ์์ธก ์คํํ ๋ ์ง
๐นcode: ์ฃผ์ ์ฝ๋
๐นclose: ์์ธกํ ์์ ์ ์ข ๊ฐ
๐นstep1: 1 ์ฐฝ์ ํตํ ์ ๋ต
๐นstep2: 2 ์ฐฝ์ ํตํ ์ ๋ต
๐นstep3: 3 ์ฐฝ์ ํตํ ์ ๋ต
๐นslow_d: ๋จ๊ธฐ ํ์ฌ ๊ฐ๊ฒฉ ํ๊ฐ ์ง์
๐ณ today_target ๐ณ
์ค๋ ๋ชฉํ ์ ๋ต
๐นcode: ์ฃผ์ ์ฝ๋
๐นbuy: ๋งค๋งคํ ๋ชฉํ ์ฃผ์ ์ (BUY/SELL)
๐นpredict: ๊ธ์ผ ๋ชฉํ ์์ ์ฃผ๊ฐ
๐ณ STEP 2๐ณ ์์ธก ๋ด์ฉ ์ ์ฅ ์ค์ผ์ฅด ๋ง๋ค๊ธฐ
savedsearch๋ฅผ ๋ง๋ค๊ณ ์ด๋ฅผ ์ค์ผ์ฅด๋ง์ ๋ฑ๋กํด ๋งค์ผ ์๋ก์ด ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค๋๋ก ํ๋ค.
๐ณ stock_predict ๐ณ
predict ๋ฌธ์ ํตํ ์ฃผ์ ์์ธก (5์ฅ ์ฐธ์กฐ)
| inputlookup my_stock | map search="
| search index=kospi code=$code$.ks earliest=-365d
| sort _time
| predict "Close" as prediction algorithm=LLT future_timespan=5 upper95=upper95 lower95=lower95
| eventstats latest(Close) as f_close, latest(Date) as f_date, latest(code) as code
| stats latest(f_date) as date, latest(f_close) as Close, latest(prediction) as predict by code
| eval predict = round(predict, 0)
| eval expected_value = round(((predict - Close) / Close)* 100, 2)
"
| rex field=code "^(?<code>\d+).KS"
| eval _key = date + "_" + code
| rename Close as price
| table _key, date, code, price, predict, expected_value
| outputlookup stock_predict append=true override_if_empty=true
์ด ๊ฒฐ๊ณผ๋ฅผ predict_stock์ด๋ผ๋ ์ ๋ชฉ์ ๋ฆฌํฌํธ๋ก ์ ์ฅ
๐ณ predict_stock_with_ml ๐ณ
ML์ ํตํ ์ฃผ์ ์์ธก(10์ฅ ์ฐธ์กฐ)
10์ฅ์ ์๋ ML์ ์นดํ ๊ณ ๋ฆฌ ์ ์ ์๊ณ ๋ฆฌ์ฆ์์ ๊ฐ ์์ธก ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋ณ๊ฒฝํ์๋ค.
MLTK์ Experiment ํด๋ฆญ > Predict Numeric Fields ํด๋ฆญ > Create New Experiement
Experiment Title ์์ฑ ํ Create ํด๋ฆญ
index="kospi" code="068270.KS" earliest=0
| sort _time
| `mylag(Close, 10)`
| table _time, Close, lag_*
| where isnotnull(lag_9)
search ์ฐฝ์ ์์ ๊ฒ์์ด ์ ๋ ฅ ํ ๋๋ณด๊ธฐ ํด๋ฆญ
์์ ๊ฐ์ด ์ค์ ํ Apply
์์ ๊ฐ์ด ์ค์ ํ Fit Model ํด๋ฆญ > Save && Show SPL
์์ ์์ฑ๋ SEARCH COMMAND ๋ณต์ฌ ํ stock ์ฑ์ ๊ฒ์ ์ฐฝ์์ ์๋์ ๊ฐ์ด ์์ ํ ๊ฒ์
| inputlookup my_stock
| map search="
| search index="kospi" code="$code$.KS" earliest=0
| sort _time
| `mylag(Close, 10)`
| table _time, Close, lag_*
| where isnotnull(lag_9)
| fit StandardScaler "lag_0" "lag_1" "lag_2" "lag_3" "lag_4" "lag_5" "lag_6" "lag_7" "lag_8" "lag_9" "Close" with_mean=true with_std=true into "model_stock_predict_SS_$code$"
| fit RandomForestRegressor "SS_Close" from "SS_lag_0" "SS_lag_1" "SS_lag_2" "SS_lag_3" "SS_lag_4" "SS_lag_5" "SS_lag_6" "SS_lag_7" "SS_lag_8" "SS_lag_9" into "model_stock_predict_RF_$code$"
์ด ๋ถ๋ถ์ SAVEDSEARCH๋ก ์ ์ฅํ๋ค.
์ดํ ์ค์ ์์ ๊ฒ์/๋ฆฌํฌํธ/์๋์ ๋ค์ด๊ฐ์ ์ฟผ๋ฆฌ๋ฅผ ๋ค์์ฒ๋ผ ์์ ํด
ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด ๋ชจ๋ธ์ ์์ฑํ ์ ์๋๋ก ๋ง๋ค์ด ์ค๋ค.
index="kospi" code="$code$.KS" earliest=0
| sort _time
| `mylag(Close, 10)`
| table _time, Close, lag_*
| where isnotnull(lag_9)
| fit StandardScaler "Close" "lag_0" "lag_1" "lag_2" "lag_3" "lag_4" "lag_5" "lag_6" "lag_7" "lag_8" "lag_9" with_mean=true with_std=true into "model_stock_predict_SS_$code$"
| fit RandomForestRegressor "SS_Close" from "SS_lag_0" "SS_lag_1" "SS_lag_2" "SS_lag_3" "SS_lag_4" "SS_lag_5" "SS_lag_6" "SS_lag_7" "SS_lag_8" "SS_lag_9" into "model_stock_predict_RF_$code$"
์ฑ๊ณต
| inputlookup my_stock
| map search="
| search index=kospi code=$code$.KS earliest=-20d
| sort _time
| `mylag2(Close, 10, true)`
| table _time, code, Date, Close, lag_*
| eventstats latest(Date) as evaluate_date
| where Date = evaluate_date
| apply model_stock_predict_SS_$code$
| apply model_stock_predict_RF_$code$
| rename predicted(SS_Close) as predict
| append [ | summary model_stock_predict_SS_$code$ | where fields = \"Close\"]
| eventstats max(\"mean\") as ss_mean, max(var) as ss_var
| eval predict = predict * sqrt(ss_var) + ss_mean
| table Date, code, Close, predict"
| where isnotnull(Date)
| rex field=code \"^(?<code>\d+).KS\"
| rename Date as date, Close as close
| eval _key = date + "_" + code
| table _key, date, code, close, predict
| outputlookup stock_ml_predict append=true override_if_empty=true
์ด ๊ฒฐ๊ณผ๋ฅผ predict_stock_with_ml์ด๋ผ๋ ์ ๋ชฉ์ ๋ฆฌํฌํธ๋ก ์ ์ฅ
๐ณ predict_stock_with_statics ๐ณ
์ผ์ค์ฐฝ์ ์ด์ฉํ ์์ธก (9์ฅ ์ฐธ์กฐ)
| inputlookup my_stock |map search="| search index=kospi code=$code$.KS earliest=-360d
| sort _time
| trendline ema130(Close) as ema130, ema5(Close) as ema5
| table _time, Date, code, Close, ema130, ema5
| join _time [ | search index=kospi code=$code$.KS earliest=-360d
| sort _time
| streamstats window=14 current=true max(High) as ndays_high, min(Low) as ndays_low
| eval fast_k = (Close - ndays_low) / (ndays_high - ndays_low) * 100
| streamstats window=3 avg(fast_k) as slow_d
| table _time, fast_k, slow_d ]
| where isnotnull(ema130)
| table _time, Date, code, Close ema130, ema5, slow_d
| streamstats window=2 list(ema130) as ema130_list, list(ema5) as ema5_list, list(slow_d) as slow_d_list
| eventstats latest(Date) as evaluate_date
| where Date = evaluate_date "
| eval ema130_pre = tonumber(mvindex(ema130_list, 0)), ema130_cur = tonumber(mvindex(ema130_list, 1))
| eval ema5_pre = tonumber(mvindex(ema5_list, 0)), ema5_cur = tonumber(mvindex(ema5_list, 1))
| eval slow_d_pre = tonumber(mvindex(slow_d_list, 0)), slow_d_cur = tonumber(mvindex(slow_d_list, 1))
| eval step1 = if(ema130_pre > ema130_cur, -1, 1)
| eval step2_pre = if(slow_d_pre > slow_d_cur, -1, 1)
| eval step3_pre = if(ema5_pre > ema5_cur, -1, 1)
| eval step2 = case(step1 > 0 AND slow_d > 20, 1, step1 < 0 AND slow_d > 80, -1, 1=1, 0)
| eval step3 = case(step2_pre < 0 AND step3_pre > 0, 1, step2_pre > 0 AND step3_pre < 0, -1, 1 = 1, 0)
| rex field=code "^(?<code>\d+).KS"
| rename Date as date, Close as close
| eval _key = date + "_" + code
| table date, code, ,close, step1, step2, step3, slow_d
| outputlookup stock_statics_predict append=true override_if_empty=true
์ด ๊ฒฐ๊ณผ๋ฅผ predict_stock_with_statics์ด๋ผ๋ ์ ๋ชฉ์ ๋ฆฌํฌํธ๋ก ์ ์ฅ
์ด๋ค์ ๊ฐ๊ฐ ๋ค์์ฒ๋ผ ์ค์ผ์ฅด๋ง ํ๋ค.
๐ณ STEP 3๐ณ ๋งค๋งค ์ ๋ต ์ธ์ฐ๊ธฐ
๋งค๋งค ์ ๋ต์ ๊ฒฐ๊ตญ์ ์ฌ๋ฌ ๋ถ์์ ํตํด์
๋ช ์ฃผ๋ฅผ ์ผ๋ง์ ๊ตฌ๋งคํ ๊ฒ์ธ๊ฐ๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ผ๋ก ๊ฐ์ธ๋ง๋ค ๋ ธํ์ฐ๊ฐ ๊ฐ๊ฐ ๋ค๋ฅผ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ , ์๋ฎฌ๋ ์ด์ ์ด ์งํ๋๊ณ , ์์ต๋ฅ ์ ๋ฐ๋ผ์ ๋งค๋งค์ ๋ต์ ์ํฉ์ ๋ง๊ฒ ๋ฐ๊ฟ์ ์ ์ฉํ๊ฒ ๋๋ค.
| inputlookup stock_predict
| eval _time = strptime(date, "%Y-%m-%d")
| eventstats latest(date) as f_date
| where date = f_date
| rex field=code "^(?<code>\d+).KS"
| eval p_score = case(expected_value >= 20 , 3, expected_value < 20 AND expected_value >= 10, 2, expected_value < 10 AND expected_value >= 1, 1,
expected_value <= -1 AND expected_value > -10, -1, expected_value <= -10 AND expected_value > 20, -2, expected_value <= -20 , -3, 1=1, 0)
| table date, code, p_score
| append
[| inputlookup stock_ml_predict
| eval _time = strptime(date, "%Y-%m-%d")
| eventstats latest(date) as f_date
| where date = f_date
| rex field=code "^(?<code>\d+).KS"
| eval expected_value = (predict - close) * 100 / close
| eval m_score = case(expected_value >= 10 , 2, expected_value < 10 AND expected_value >= 1, 1,
expected_value <= -1 AND expected_value > -10, -1, expected_value <= -10 , -2, 1=1, 0)
| table date, code, m_score, close, predict]
| append
[| inputlookup stock_statics_predict
| eval _time = strptime(date, "%Y-%m-%d")
| eventstats latest(date) as f_date
| rex field=code "^(?<code>\d+).KS"
| eval s_score = case(step1 > 0 AND slow_d < 20, 5, step1 > 0 AND slow_d < 40, 4, step1 < 0 AND slow_d > 80, -5, step1 < 0 AND slow_d > 60, -4, 1= 1, 0)
| table date, code, s_score]
| stats max(p_score) as p_score, max(m_score) as m_score, max(s_score) as s_score, max(close) as close, max(predict) as predict by date, code
| eval score = p_score + m_score + s_score
| append
[| inputlookup my_stock]
| stats max(score) as score, max(share) as share, max(target) as target, max(close) as close, max(predict) as predict by code
| append
[| inputlookup my_asset_history
| eval _time = strptime(date,"%Y-%m-%d %H:%M:%S")
| stats latest(balance) as balance ]
| eval asset = close * share
| eventstats max(balance) as balance, sum(asset) as total
| eval my_total_asset = balance + total
| eval rate = (asset / my_total_asset) * 100, share_rate = (asset / total) * 100
| eval target_count = round(( round(my_total_asset * (target / 100)) - asset ) / close)
| where isnotnull(code)
| eval BUY = if(score > 0, target_count * (score /10), 0), SELL = if(score < 0, share * (abs(score)/10), 0)
| eval BUY = if(BUY > 0, round(BUY), 0), SELL = if(SELL > 0, round(SELL), 0)
| eval buy = BUY - SELL
| lookup kospi_200 code OUTPUT name
| eval predict = round(predict)
| eval rate = round(rate, 2), share_rate = round(share_rate, 2)
| eval _key = code
| table _key, code, name, buy, predict
| outputlookup today_target
์ฝ๋๋ถ์
1๏ธโฃ ์ฐ์ ์์ธก๋ ๋ด์ฉ์ ์ต์ ๋ ์ง๋ฅผ ๊ธฐ์ค์ผ๋ก key-value ์คํ ์ด์์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ ๋ชจ์๋ค.
| inputlookup stock_predict
| eval _time = strptime(date, "%Y-%m-%d")
| eventstats latest(date) as f_date
| where date = f_date
...
| append [ | inputlookup stock_ml_predict
| eval _time = strptime(date, "%Y-%m-%d")
| eventstats latest(date) as f_date
| where date = f_date
...]
| append [ | inputlookup stock_statics_predict
| eval _time = strptime(date, "%Y-%m-%d")
| eventstats latest(date) as f_date
...]
2๏ธโฃ ๊ฐ ์์ธก๋ณ๋ก Max ์ ์๋ก ๊ฐ์ค์น๋ฅผ ๋์๋ค.
์ผ์ค์ฐฝ ๋ฐฉ๋ฒ์ 5~4์ , ์๊ฐ ์์ธก์ 3~1 ์ , ML์ 2~1 ์ ์ฌ์ด๋ก ์ ์๋ฅผ ๋งค๊ธฐ๊ณ ,
+ ์ ์์ด๋ฉด BUY, - ์ ์์ด๋ฉด SELL ์ ํ๋๋ก ํ๋ค.
predict ์ค์ฝ์ด ๊ฒฐ์ ์
5์ผ ํ ์์๋๋ ๊ฐ๊ฒฉ ๋ณ๋์ด 20% ์ด์์ด๋ฉด 3์
10~20% ์ด๋ฉด 2์
1~10% ์ด๋ฉด 1์
๊ทธ ์ธ์๋ 0์ ์ด๊ณ , ๋ฐ๋๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค.
..
| eval p_score = case(expected_value >= 20 , 3, expected_value < 20 AND expected_value >= 10, 2, expected_value < 10 AND expected_value >= 1, 1,
expected_value <= -1 AND expected_value > -10, -1, expected_value <= -10 AND expected_value > 20, -2, expected_value <= -20 , -3, 1=1, 0)
...
- ์ฌ๊ธฐ์ expected_value๊ฐ ๊ฐ๊ฒฉ ๋ณ๋ ๊ฐ์ด๋ค.
ML ์ค์ฝ์ด ๋ ๋น์ทํ ํํ๋ก ์ ๋ ฅ๋๋ค.
...
| eval m_score = case(expected_value >= 10 , 2, expected_value < 10 AND expected_value >= 1, 1,
expected_value <= -1 AND expected_value > -10, -1, expected_value <= -10 , -2, 1=1, 0)
...
์ผ์ค์ฐฝ ์ค์ฝ์ด๋ ๋ค์๊ณผ ๊ฐ๋ค.
...
| eval s_score = case(step1 > 0 AND slow_d < 20, 5, step1 > 0 AND slow_d < 40, 4, step1 < 0 AND slow_d > 80, -5, step1 < 0 AND slow_d > 60, -4, 1= 1, 0)
...
์ฌ๋ฌ ์๊ณ ๋ฆฌ์ฆ์ ๋์ค๋ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ง๊ณ ์ค์ฝ์ด๋ฅผ ์ด๋ป๊ฒ ์ฃผ๋๊ฒ ๊ฐ์ฅ ์์ต๋ฅ ์ด ์ข์๊ฐ์ ๋ํ ML ๋๋ DL์ ๋ง๋๋ ๊ฒ์ด ์ฌ์ค ๊ฐ์ฅ ์ค์ํ๊ณ AI ํธ๋ ์ด๋ฉ์ ํต์ฌ์ด ๋ ๊ฒ์ด๋ค. (์ด ๋ถ๋ถ์ ์คํ๋ ํฌ scope์ ๋์ด๊ฐ๊ธฐ ๋๋ฌธ์ ...)
3๏ธโฃ ์ดํ ๊ฐ ์ค์ฝ์ด๋ฅผ ๋ํด์ ์ต์ข ์์ธก ์ค์ฝ์ด๋ฅผ ๋ง๋ ๋ค.
...
| stats max(p_score) as p_score, max(m_score) as m_score, max(s_score) as s_score, max(close) as close, max(predict) as predict by date, code
| eval score = p_score + m_score + s_score
...
4๏ธโฃ ํฌํธํด๋ฆฌ์ค ๊ตฌ์ถ ๊ณํ์ ๊ธฐ๋ฐ์ผ๋ก ๋ด ์์ฐ์ผ๋ก ๊ตฌ๋งคํ ์ ์๋ ๊ฐ ์ฃผ์์ ์ต๋ ์ฃผ์ ์๋ฅผ ๊ตฌํ๋ค.
...
| append [ | inputlookup my_stock]
| stats max(score) as score, max(share) as share, max(target) as target, max(close) as close, max(predict) as predict by code
| append [ | inputlookup my_asset_history
| eval _time = strptime(date,"%Y-%m-%d %H:%M:%S")
| stats latest(balance) as balance ]
| eval asset = close * share
| eventstats max(balance) as balance, sum(asset) as total
| eval rate = (asset / balance) * 100, share_rate = (asset / total) * 100
| eval target_count = round(balance * (target / 100) / close) - share
...
5๏ธโฃ ์ค์ฝ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฃผ์์ ์ผ๋ง๋ ์ด์ง/ํ์ง๋ฅผ ๊ฒฐ์ ํ๋ค.
...
| eval BUY = if(score > 0, target_count * (score /10), 0), SELL = if(score < 0, share * (abs(score)/10), 0)
| eval BUY = if(BUY > 0, round(BUY), 0), SELL = if(SELL > 0, round(SELL), 0)
...
์ด ์ฟผ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ์ ๋ต์ด ๋ง๋ค์ด์ง๋ค.
๋ค๋ฅธ๊ฑด ๋ชจ๋ฅด๊ฒ ๊ณ Cellirion ํ๋ผ๋ ๊ตฌ๋ง!ใ ใ ใ
๐ณ STEP 4๐ณ ๋งค๋งค ์คํํ๊ธฐ
์ ๋ต์ด ๋ง๋ค์ด์ก์ผ๋ฉด ์ด์ ์ค์ ๋งค๋งค๋ฅผ ์ํํ๋ ์๋ฎฌ๋ ์ด์ ์ ๋ง๋ ๋ค.
์ฌ์ค ๋ณต์กํ ์ฒด๊ฒฐ๊ณผ์ ๋ ์๊ณ ์์๋ฃ๋ ์๋ค.
์ด์งํผ ์ค์ ๋ก ๋ง๋ค๊ธฐ ์ํด์๋ ์ธ๋ถ ๋งค๋งค ์์คํ ๊ณผ ์ฐ๊ฒฐํด์ผ ํ๋๋ฐ
์ด๋๊น์ง๋ ์ง๊ธ ํฌ์คํ ์ ์คํ๋ ํฌ ํ์ต์ฉ์ด๋ค.
๋ก์ง์ ๊ฐ๋จํ๊ฒ ํ๊ธฐ ์ํด์ ์ฐ์ ์ ํ๋ฒ ์ํ ๋ ๋ ํ๋์ ์ฃผ์๋ง ๊ฑฐ๋๋๊ฒ ํ์๋ค.
์์์ ์ ์ฅํ "today_target" ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ค๋ ๊ฒ์ผ๋ก ์์ํ๋ค.
| inputlookup today_target | where buy != 0 | head 1
| map search="| readstock code=$code$
| spath | eval buy = $buy$ , predict = $predict$
| table code, price, time, buy, predict"
| rex field=time "^(?<online>\d{4}.\d{2}.\d{2}(\s?\d{2}?:\d{2})?)"
| eval online = if(len(time) > 10, 1, 0)
| eval B_DONE = if( buy > 0 AND online == 1, buy, 0) , S_DONE = if( buy < 0 AND online == 1, abs(buy), 0)
| eval outcome = price * B_DONE, income = price * S_DONE
| eval buy = buy - B_DONE + S_DONE
| append [ | inputlookup my_asset_history | eval _time = strptime(date, "%Y-%m-%d %H:%M:%S") | stats latest(balance) as balance ]
| eventstats max(balance) as balance
| eval date=strftime(now(),"%Y-%m-%d %H:%M:%S")
| eval balance = balance - outcome + income, method = case (B_DONE != 0 , "BUY", S_DONE != 0 , "SELL", 1=1, ""), count = B_DONE - S_DONE, cost = income - outcome
| join code [ | inputlookup my_stock ]
| where online = 1
| eval share = share + B_DONE - S_DONE
| eval _key = code
| outputlookup today_target append=true override_if_empty=true
| outputlookup my_stock append=true override_if_empty=true
| eval _key = strftime(_time, "%Y%m%d%H%M%S") + "_" + code
| outputlookup my_asset_history append=true
์ฝ๋๋ถ์
1๏ธโฃ ์ฐ์ "map" ๊ตฌ๋ฌธ๊ณผ 2์ฅ์์ ๋ง๋ "readstock" ๋ช ๋ น์ ์ด์ฉํด ํ์ฌ ์ฃผ์์ ๊ฐ์ ธ์จ๋ค.
| map search="| readstock code=$code$
| spath | eval buy = $buy$ , predict = $predict$
| table code, price, time, buy, predict"
2๏ธโฃ 2์ฅ์ ์๋ ์ฝ๋๋ฅผ ์ฝ๊ฐ ์ ๋ฐ์ดํธ ํด์ ํ์ฌ ์๊ฐ์ ๊ฐ์ ธ์จ๋ค.
...
| rex field=time "^(?<online>\d{4}.\d{2}.\d{2}(\s?\d{2}?:\d{2})?)"
| eval online = if(len(time) > 10, 1, 0)
...
์ด๋ฅผ ํตํด ์ฅ์ค์ธ์ง, ์ฅ๋ง๊ฐ์ด ๋์๋์ง ํ์ธํ๋ค.
ํ์ฌ ํ๊ธ์ด ํ์ฑ์ด ๋์ง ์์์(๋ค์ํ ๋ฐฉ๋ฒ์ผ๋ก ํ ์คํธ ํด๋ดค์ง๋ง ์์ง ํด๊ฒฐ์ด ์๋๋ค. ใ ใ )
์ฅ ์ค์ผ ๋๋ ์๊ฐ๊น์ง ๋์ค๊ณ ์ฅ๋ง๊ฐ์ด๋ฉด ๋ ์ง๋ง ๋์ค๋ ํน์ฑ์ ์ด์ฉํ๊ธฐ๋ก ํ๋ค.
3๏ธโฃ ๊ฑฐ๋ ๋ด์ฉ์ KV_STORE์ ์ ์ฅํด์ค๋ค.
...
| outputlookup today_target append=true override_if_empty=true
| outputlookup my_stock append=true override_if_empty=true
| eval _key = strftime(_time, "%Y%m%d%H%M%S") + "_" + code
| outputlookup my_asset_history append=true
์ฅ ์ค์ผ ๊ฒฝ์ฐ ์ ๋ต์ ๋์จ๋ฐ๋ก ์ฃผ์์ ๊ฑฐ๋ํ๊ณ ๊ฑฐ๋๋ ๋ด์ฉ์,
"my_stock", "today_target", "my_asset_history" ์ ๊ฐ๊ฐ ์ ๋ฐ์ดํธ ํด ์ค๋ค.
์์ง์ buy๊ฐ 0์ด ์๋ ์ฃผ์์ด ๋์ค์ง ์์์ ์ฃผ์์ ๊ตฌ๋งคํ ์๋ ํ ์๋ ์๋ ์ํฉ์ด๋ผ ์คํ๋์ง ์๋๋ค.
๊ทธ๋ผ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ์๋ก ์ ์ฅํ๊ณ ์ด์จ๋ ์ ์ฟผ๋ฆฌ๋ ์ ์ฅํ๊ณ
ํด๋น ๋ถ๋ถ์ alert ์ผ๋ก ๋ง๋ค๊ณ ์ค์ผ์ฅด์ ์คํํ๋ค.
๊ฑฐ๋๊ฐ 1๊ฑด์ด๋ผ๋ ๋ฐ์ํ๋ฉด ์นดํก์ผ๋ก ์๋์ ๋ณด๋ธ๋ค.
๐ซ ์ฃผ์ ๐ซ
ํ
์คํธ์ฉ์ผ๋ก key-value ์คํ ์ด๋ฅผ ์ด์ฉํด ๊ฐ์ข
์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ์์ผ๋,
์ด ๊ณณ์ ์ค์ํ ๋ด์ฉ์ ์ ์ฅํ๋ ๊ฒ์ ๋ฐ๋์งํด ๋ณด์ด์ง ์๋๋ค.
์ค์๋ก "| outpulookup kv-store-name" ์ ์คํํ๊ฒ ๋๋ฉด ์ฌ๊ธฐ ๊ธฐ๋ก๋ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ๋ ์ ๊ฐ๋ค.
๋ณต๊ตฌํ ๋ฐฉ๋ฒ๋ ์๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์, ๋ฐฑ์ ์ผ๋ก ์ ์ฅ๋ ๋ด์ฉ๋ค, ๋ค์ ๋ณต๊ตฌํ ์ ์๋ ๋ด์ฉ์ ๋ํด์๋ง ๊ธฐ๋กํ๋๊ฒ ์ข์๋ณด์ธ๋ค. ์๋๋ฉด ์ฃผ๊ธฐ์ ์ผ๋ก ํ์ผ๋ก ๋ฐฑ์ ์ ํ๋์ง....
key-value ์คํ ์ด์ ๋ํด์ ๊ธฐ๋ณธ์ ์ผ๋ก append=true ์ต์ ์ด ์ ์ฉ๋๋ฉด ์ข์ ๊ฒ ๊ฐ๊ธด ํ๋ฐ...
๋ง์ฝ key-value ์คํ ์ด๋ฅผ ์ด์ฉ์ค์ด๊ณ ์ ๋ฐ์ดํธ๊ฐ ํ์ํ๋ค๋ฉด ๊ผญ ์ ์ต์ ์ ๊น๋จน์ง ๋ง์........
โ