-
Notifications
You must be signed in to change notification settings - Fork 332
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add KdCrossOver, MAGoldenDeathCrossOver, InstitutionalInvestors…
…OverBuy, ShortSaleMarginPurchaseRatio (#277) * featL add KdCrossOver * feat: add MAGoldenDeathCrossOver * feat: add auto add _additional_dataset * feat: add short_sale_margin_purchase_ratio
- Loading branch information
Showing
14 changed files
with
572 additions
and
154 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,29 @@ | ||
from FinMind.indicators.kd import add_kd_indicators | ||
from FinMind.indicators.bias import add_bias_indicators | ||
from FinMind.indicators.continue_holding import add_continue_holding_indicators | ||
from FinMind.indicators.institutional_investors_follower import ( | ||
add_institutional_investors_follower, | ||
) | ||
from FinMind.indicators.institutional_investors_over_buy import ( | ||
add_institutional_investors_over_buy_indicators, | ||
) | ||
from FinMind.indicators.kd import add_kd_indicators | ||
from FinMind.indicators.kd_crossover import ( | ||
add_kd_golden_death_cross_over_indicators, | ||
) | ||
from FinMind.indicators.ma_cross_orver import ( | ||
add_ma_golden_death_cross_orver_indicators, | ||
) | ||
from FinMind.indicators.short_sale_margin_purchase_ratio import ( | ||
add_short_sale_margin_purchase_ratio_indicators, | ||
) | ||
|
||
INDICATORS_MAPPING = dict( | ||
KD=add_kd_indicators, | ||
BIAS=add_bias_indicators, | ||
ContinueHolding=add_continue_holding_indicators, | ||
InstitutionalInvestorsFollower=add_institutional_investors_follower, | ||
KDGoldenDeathCrossOver=add_kd_golden_death_cross_over_indicators, | ||
MAGoldenDeathCrossOver=add_ma_golden_death_cross_orver_indicators, | ||
InstitutionalInvestorsOverBuy=add_institutional_investors_over_buy_indicators, | ||
ShortSaleMarginPurchaseRatio=add_short_sale_margin_purchase_ratio_indicators, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import numpy as np | ||
import pandas as pd | ||
|
||
from FinMind.schema.data import Dataset | ||
|
||
|
||
def _taiwan_stock_institutional_investors_buy_sell_group_by( | ||
taiwan_stock_institutional_investors_buy_sell: pd.DataFrame, | ||
) -> pd.DataFrame: | ||
taiwan_stock_institutional_investors_buy_sell[["sell", "buy"]] = ( | ||
taiwan_stock_institutional_investors_buy_sell[["sell", "buy"]] | ||
.fillna(0) | ||
.astype(int) | ||
) | ||
taiwan_stock_institutional_investors_buy_sell = ( | ||
taiwan_stock_institutional_investors_buy_sell.groupby( | ||
["date", "stock_id"], as_index=False | ||
).agg({"buy": np.sum, "sell": np.sum}) | ||
) | ||
taiwan_stock_institutional_investors_buy_sell[ | ||
"InstitutionalInvestorsOverBuy" | ||
] = ( | ||
taiwan_stock_institutional_investors_buy_sell["buy"] | ||
- taiwan_stock_institutional_investors_buy_sell["sell"] | ||
) | ||
return taiwan_stock_institutional_investors_buy_sell | ||
|
||
|
||
def add_institutional_investors_over_buy_indicators( | ||
stock_price: pd.DataFrame, additional_dataset_obj, **kwargs | ||
) -> pd.DataFrame: | ||
""" | ||
url: "https://blog.above.tw/2018/08/15/%E7%B1%8C%E7%A2%BC%E9%9D%A2%E7%9A%84%E9%97%9C%E9%8D%B5%E6%8C%87%E6%A8%99%E6%9C%89%E5%93%AA%E4%BA%9B%EF%BC%9F/" | ||
summary: | ||
策略概念:法人買超股票會上漲, 反之亦然 | ||
策略規則: 法人買超, 買 | ||
法人賣超, 賣 | ||
""" | ||
stock_price = stock_price.sort_values("date") | ||
taiwan_stock_institutional_investors_buy_sell = getattr( | ||
additional_dataset_obj, Dataset.TaiwanStockInstitutionalInvestorsBuySell | ||
) | ||
taiwan_stock_institutional_investors_buy_sell = ( | ||
_taiwan_stock_institutional_investors_buy_sell_group_by( | ||
taiwan_stock_institutional_investors_buy_sell | ||
) | ||
) | ||
stock_price = pd.merge( | ||
stock_price, | ||
taiwan_stock_institutional_investors_buy_sell[ | ||
["stock_id", "date", "InstitutionalInvestorsOverBuy"] | ||
], | ||
on=["stock_id", "date"], | ||
how="left", | ||
).fillna(0) | ||
return stock_price |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import numpy as np | ||
import pandas as pd | ||
from ta.momentum import StochasticOscillator | ||
|
||
|
||
def add_kd_golden_death_cross_over_indicators( | ||
stock_price: pd.DataFrame, k_days: int = 9, **kwargs | ||
) -> pd.DataFrame: | ||
""" | ||
url: "http://smart.businessweekly.com.tw/Reading/WebArticle.aspx?id=68129&p=2" | ||
summary: 日KD黃金交叉和死亡交叉 | ||
日K線 < 日D線,翻轉成,日K線 > 日D線 稱為黃金交叉 | ||
日K線 > 日D線,翻轉成,日K線 < 日D線 稱為死亡交叉 | ||
黃金交叉進場,死亡交叉出場 | ||
""" | ||
stock_price = stock_price.sort_values("date") | ||
kd = StochasticOscillator( | ||
high=stock_price["max"], | ||
low=stock_price["min"], | ||
close=stock_price["close"], | ||
n=k_days, | ||
) | ||
rsv_ = kd.stoch().fillna(50) | ||
_k = np.zeros(stock_price.shape[0]) | ||
_d = np.zeros(stock_price.shape[0]) | ||
for i, r in enumerate(rsv_): | ||
if i == 0: | ||
_k[i] = 50 | ||
_d[i] = 50 | ||
else: | ||
_k[i] = _k[i - 1] * 2 / 3 + r / 3 | ||
_d[i] = _d[i - 1] * 2 / 3 + _k[i] / 3 | ||
stock_price["K"] = _k | ||
stock_price["D"] = _d | ||
stock_price.index = range(len(stock_price)) | ||
stock_price["diff"] = stock_price["K"] - stock_price["D"] | ||
stock_price.loc[(stock_price.index < k_days), "diff"] = np.nan | ||
stock_price["diff_sign"] = stock_price["diff"].map( | ||
lambda x: 1 if x >= 0 else (-1 if x < 0 else 0) | ||
) | ||
stock_price["diff_sign_yesterday"] = ( | ||
stock_price["diff_sign"].shift(1).fillna(0).astype(int) | ||
) | ||
stock_price["KDGoldenDeathCrossOver"] = 0 | ||
stock_price.loc[ | ||
( | ||
(stock_price["diff_sign"] > 0) | ||
& (stock_price["diff_sign_yesterday"] < 0) | ||
), | ||
"KDGoldenDeathCrossOver", | ||
] = 1 | ||
stock_price.loc[ | ||
( | ||
(stock_price["diff_sign"] < 0) | ||
& (stock_price["diff_sign_yesterday"] > 0) | ||
), | ||
"KDGoldenDeathCrossOver", | ||
] = -1 | ||
stock_price = stock_price.drop( | ||
["diff", "diff_sign", "diff_sign_yesterday"], axis=1 | ||
) | ||
return stock_price |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import pandas as pd | ||
from ta.trend import SMAIndicator | ||
|
||
|
||
def add_ma_golden_death_cross_orver_indicators( | ||
stock_price: pd.DataFrame, | ||
ma_short_term_days: int = 10, | ||
ma_long_term_days: int = 30, | ||
**kwargs, | ||
) -> pd.DataFrame: | ||
""" | ||
url: | ||
"https://www.cmoney.tw/learn/course/technicalanalysisfast/topic/1811" | ||
summary: | ||
均線黃金交叉 | ||
以短線操作來說,當 5日均線 向上突破 20日均線 | ||
也就是短期的平均買進成本大於長期平均成本 | ||
代表短期買方的力道較大,市場上大多數人獲利 | ||
市場易走出「多頭」的趨勢,進而帶動長期均線向上,讓股價上漲機率較大 | ||
短期線 突破 長期線(黃金交叉),進場 | ||
長期線 突破 短期線(死亡交叉),出場 | ||
""" | ||
stock_price = stock_price.sort_values("date") | ||
stock_price[f"ma{ma_short_term_days}"] = SMAIndicator( | ||
stock_price["close"], ma_short_term_days | ||
).sma_indicator() | ||
stock_price[f"ma{ma_long_term_days}"] = SMAIndicator( | ||
stock_price["close"], ma_long_term_days | ||
).sma_indicator() | ||
stock_price["ma_diff"] = ( | ||
stock_price[f"ma{ma_short_term_days}"] | ||
- stock_price[f"ma{ma_long_term_days}"] | ||
) | ||
stock_price["bool_signal"] = stock_price["ma_diff"].map( | ||
lambda x: 1 if x > 0 else -1 | ||
) | ||
stock_price["bool_signal_shift1"] = ( | ||
stock_price["bool_signal"].shift(1).fillna(0) | ||
) | ||
stock_price["bool_signal_shift1"] = stock_price[ | ||
"bool_signal_shift1" | ||
].astype(int) | ||
stock_price["MAGoldenDeathCrossOver"] = 0 | ||
stock_price.loc[ | ||
( | ||
(stock_price["bool_signal"] > 0) | ||
& (stock_price["bool_signal_shift1"] < 0) | ||
), | ||
"MAGoldenDeathCrossOver", | ||
] = 1 | ||
stock_price.loc[ | ||
( | ||
(stock_price["bool_signal"] < 0) | ||
& (stock_price["bool_signal_shift1"] > 0) | ||
), | ||
"MAGoldenDeathCrossOver", | ||
] = -1 | ||
stock_price = stock_price.drop( | ||
[ | ||
"ma_diff", | ||
"bool_signal", | ||
"bool_signal_shift1", | ||
f"ma{ma_short_term_days}", | ||
f"ma{ma_long_term_days}", | ||
], | ||
axis=1, | ||
) | ||
return stock_price |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import numpy as np | ||
import pandas as pd | ||
|
||
from FinMind.schema.data import Dataset | ||
|
||
|
||
def _create_short_sale_margin_purchase_today_ratio( | ||
taiwan_stock_margin_purchase_shortSale: pd.DataFrame, | ||
) -> pd.DataFrame: | ||
taiwan_stock_margin_purchase_shortSale[ | ||
["ShortSaleTodayBalance", "MarginPurchaseTodayBalance"] | ||
] = taiwan_stock_margin_purchase_shortSale[ | ||
["ShortSaleTodayBalance", "MarginPurchaseTodayBalance"] | ||
].astype( | ||
int | ||
) | ||
taiwan_stock_margin_purchase_shortSale["ShortSaleMarginPurchaseRatio"] = ( | ||
taiwan_stock_margin_purchase_shortSale["ShortSaleTodayBalance"] | ||
/ taiwan_stock_margin_purchase_shortSale["MarginPurchaseTodayBalance"] | ||
) | ||
return taiwan_stock_margin_purchase_shortSale | ||
|
||
|
||
def add_short_sale_margin_purchase_ratio_indicators( | ||
stock_price: pd.DataFrame, additional_dataset_obj, **kwargs | ||
) -> pd.DataFrame: | ||
""" | ||
url: "https://blog.above.tw/2018/08/15/%E7%B1%8C%E7%A2%BC%E9%9D%A2%E7%9A%84%E9%97%9C%E9%8D%B5%E6%8C%87%E6%A8%99%E6%9C%89%E5%93%AA%E4%BA%9B%EF%BC%9F/" | ||
summary: | ||
策略概念: 券資比越高代表散戶看空,這時候賣可以跟大部分散戶進行相反的操作,反之亦然 | ||
策略規則: 券資比>=30%, 賣 | ||
券資比<30%, 買 | ||
""" | ||
stock_price = stock_price.sort_values("date") | ||
taiwan_stock_margin_purchase_shortSale = getattr( | ||
additional_dataset_obj, Dataset.TaiwanStockMarginPurchaseShortSale | ||
) | ||
taiwan_stock_margin_purchase_shortSale = ( | ||
_create_short_sale_margin_purchase_today_ratio( | ||
taiwan_stock_margin_purchase_shortSale | ||
) | ||
) | ||
stock_price = pd.merge( | ||
stock_price, | ||
taiwan_stock_margin_purchase_shortSale[ | ||
["stock_id", "date", "ShortSaleMarginPurchaseRatio"] | ||
], | ||
on=["stock_id", "date"], | ||
how="left", | ||
).fillna(0) | ||
return stock_price |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.