# DBL Mid (04/17)
###### tags: `DBL`
---
[TOC]
---
<style>
.markdown-body
{
max-width: 960px !important;
}
</style>
## 飆股九陰真經
### ==股價資訊用於日後的數據分析==
- **均線、K線**
### ==K 線==

### ==兩日 K 線漲跌類型==
- **上漲(下跌)**:**前一日收盤價低於今日收盤價**即今日上漲,反之則為下跌
- **完全上漲(下跌)**:符合以下以條件為完全上漲,反之為完全下跌
- 今日**最高點**高於昨日**最高點**
- 今日**最低點**高於昨日**最低點**
- 今日**開盤價**高於昨日**開盤價**
- 今日**收盤價**高於昨日**收盤價**
- **跳空上漲(下跌)**:前一日與今日**整個 K 線均無重疊**,即**今日最低點高於昨日最高點**,因此兩個K線無重疊,即為跳空上漲,反之為跳空下跌
### ==MA 指標(Moving Average)==
- **簡單移動平均線(SMA)**:過去 N 天的**收盤價**加總再除以 N ,得到第 N 天的算術平均線數值
$$\text{MA}_N = \frac{\sum^N_{i=T-N}{C_i}}{N}$$
- 運用:
- 支撐與阻力
- **黃金交叉**:短均線向上突破長均線
- **死亡交叉**:短均線向下突破長均線
### ==MA 趨勢分析==
- **多頭排列**:強勢的上升趨勢,均線以 5-10-20-30-60 由上至下排列
- **空頭排列**:強勢的下降趨勢,均線以 60-30-20-10-5 由上至下排列
### K 線的波動範圍
- **臺股限制漲跌幅度須在 $\pm$ 10% 以內**
- 範圍可由使用者自己訂定:
- **長紅/長黑**:上漲/下跌幅度 > 3.6%
- **中紅/中黑**:上漲/下跌幅度介於 1.6% ~ 3.5%
- **小紅/小黑**:上漲/下跌幅度介於 0.6% ~ 1.5%
- **極小紅/極小黑**:上漲/下跌幅度約在 0.5%
- **十字線**:上漲/下跌幅度 < 0.5%
### ==二日 K 線型態==
- **遭遇線**(反攻線):

- 長黑棒與長紅棒**收盤價**相同
- **懷抱線**(母子線):

- 後者實體被前者實體全部包含
- 後者交易區間被前者交易區間全部包含
- **插入線**:

- 前者實體被後者實體吃掉一半以上
- **吞噬線**:

- 前者實體被後者實體全部包含
- 前者交易區間被後者交易區間全部包含
## SQL 奇技淫巧
### `SELECT` 組成部分邏輯執行順序
1. `FROM`
2. `WHERE`
3. `GROUP BY`
4. `HAVING`
5. `SELECT`
6. `DISTINCT`
7. `ORDER BY`
8. `TOP/FETCH/OFFSET`
### ==`JOIN`==
- 必須指定 **`ON`** 條件
### ==`EXISTS` vs. `IN`==
```sql=
SELECT ... WHERE EXISTS (SELECT ...);
SELECT ... WHERE col IN (SELECT ...);
```
- `EXISTS`:用集合比較後過濾掉不需要的資訊
- `IN`:逐行比較,**效能較差**
### `YEAR(date)`:從 `DATE` 中取得年份數字
```sql=
YEAR(a_date);
YEAR('2023-04-11');
```
### `STRING_AGG(str, delim)`:彙總函式,彙總時連接所有字串
```sql=
SELECT STRING_AGG(a_col, ',')
FROM a_table
GROUP BY a_cat;
```
### 字面資料表值
```sql=
SELECT * FROM (VALUES (1, 2), (3, 4)) AS t (a, b);
```
### ==Stored Procedure & User Defined Function==
| | Stored Procedure | User Defined Function |
|:--------------:|:----------------:|:---------------------:|
| **回傳值需求** | 不一定需要 | 需要 |
| **回傳值數量** | 0 ~ 多個 | 一個純量或 Table |
| **互相嵌套** | 可使用 SP 與 UDF | 不可使用 SP,可用 UDF |
| **更改資料庫** | 可 | 不可 |
#### Stored Procedure
- 一或多個 Transact-SQL 陳述式(具有批次與區塊特性的SQL指令集合)的群組
- 優點:
- 減少伺服器/用戶端網路流量
- 更強的安全性
- 重複使用程式碼
- 維護更簡易
- 提升效能(重複使用執行計畫)
- 缺點:
- 不推薦使用在套入 SQL 指令中
- 輸出類型:
- `SELECT` 回傳 **`TABLE`**
- Output Parameter 回傳**參數**
- `RETURN` 回傳一個 **`INT`**
#### User Defined Function
- 可接受參數、執行動作 (如複雜計算) 以及傳回該動作所得值的常式
- 優點:
- 可進行模組化的程式撰寫
- 可加快執行速度
- 可降低網路傳輸量
- 相比 SP 較適合套入 SQL 指令中執行
- 類型:
- **純量函式**:`RETURN` 回傳單一資料值
- **資料表值函式**:回傳 `TABLE`
- **系統函式**:SQL Server 系統函數,不能修改
- ==**兩種回傳資料表方式**==:
- 差別在於**宣告 TABLE 變數的方式不同**,而這也影響了**回傳 table 的方式**
1. 嵌入資料表值函式
```sql=
CREATE FUNCTION ... (...)
RETURNS TABLE
AS
RETURN
(
... -- SELECT 回傳
)
```
2. 多重陳述式資料表值函式
```sql=
CREATE FUNCTION ... (...)
RETURNS @table TABLE
(
...
)
AS
BEGIN
... -- 插入 @table 回傳
END
```
### `IIF(condition, true_then, false_then)`:判斷並回傳值
```sql=
SELECT ... WHERE IIF(@cond = 1, col_a, col_b) = 2;
```
### `DATEDIFF(diff_type, date_from, date_to)`:計算日期間格時間
```sql=
SELECT ... WHERE DATEDIFF(DAY, date_a, date_b) < 10;
```
### `CAST(value AS type)`:轉型
```sql=
SELECT ... OFFSET CAST(@a_bit AS INT) ROWS;
```
### `OFFSET`
```sql=
SELECT ... OFFSET 3 ROWS;
```
### `FETCH FIRST`
```sql=
SELECT ... FETCH FIRST 3 ROWS ONLY;
```
### `LIKE`
```sql=
SELECT ... WHERE a_col LIKE 'str%';
```
### `MAX(col)`:取最大值
```sql=
SELECT MAX(a_col) ...;
```
### `AVG(value)`:取平均值
```sql=
SELECT AVG(a_col) ...;
```
### `INSERT`
```sql=
INSERT INTO a_table
SELECT ...;
```
### `UPDATE`
```sql=
UPDATE a_table
SET col_a = 3, col_b = 'hello'
WHERE col_c = 5;
```
### `DELETE`
```sql=
DELETE a_table
WHERE id = 3;
```
### ==`CURSOR` & `WHILE`==
```sql=
DECLARE cur CURSOR LOCAL FOR
SELECT col_a, col_b
FROM a_table;
OPEN cur;
DECLARE @var_a INT, @var_b INT;
FETCH NEXT FROM cur INTO @var_a, @var_b;
WHILE @@FETCH_STATUS = 0
BEGIN
-- ... do something ...
FETCH NEXT FROM cur INTO @var_a, @var_b;
END
CLOSE cur;
DEALLOCATE cur;
```
### ==動態 SQL==
```sql=
DECLARE @statement VARCHAR(MAX) = 'SELECT ...;';
EXECUTE (@statemnt);
```
### ==`sp_executesql`:動態 SQL==
```sql=
DECLARE @statement NVARCHAR(MAX) = N'SELECT ...;';
DECLARE @param_def NVARCHAR(MAX) = N'@var_a INT, @var_b DATE';
EXECUTE SP_EXECUTESQL @statement, @param_def, @var_a_in, @var_b_in;
```
- 優點:建立一個可以重複使用的 sql 指令
- 缺點:較難以測試與 debug、**無法在 UDF 中使用**
- 相比直接 `EXEC` 的優點:
- 效能更好
- 簡化回傳值的方式
- 可以傳參數
- 結構比較嚴謹
### ==臨時 `TABLE`==
```sql=
CREATE TABLE #table
(
id INT IDENTITY(1, 1),
a_date DATE NOT NULL
);
```
### ==State Table==
- 管理者要**修改條件值**的時候**只要修改 state table** 就好,不用動到 function 本身
### `@@CURSOR_ROWS`:取得最新 `CURSOR` 目前的取得列數
```sql=
IF @@CURSOR_ROWS = 1
SELECT ...;
```
### `ABS(value)`:取絕對值
```sql=
SELECT ... WHERE ABS(a_col)
```
## Python 葵花寶典
### `bs4`:(BeautifulSoup)靜態網頁爬蟲
```python=
res = requests.get("... url ...")
soup = BeautifulSoup(res.text, "html.parser")
result = soup.select("... CSS selector ...")
result.text # text content (containS sub-elements' texts)
result.find_next("... filter ...") # Find next elements appears later
result.find_all("... filter ...") # Find all sub-elements
```
### ==`selenium`:動態網頁爬蟲==
- ==**動態網站**==:HTML 本身是不具備資料
- 等使用者進入網站後,才會利用後端**程式載入資料**,因此我們選用selenium能使網站**先載入完成才抓取**
```python=
options = EdgeOptions()
options.add_argument("--headless") # No showing browser
options.add_argument("--disable-notifications") # No notifications
options.add_argument("blink-settings=imagesEnabled=false") # No loading images
options.add_argument("--no-sandbox") # Highest permissions
options.add_argument("--window-size=1440,900") # Specify window's size
try:
with webdriver.Edge(EdgeChromiumDriverManager().install(), options=options) as edge:
edge.get("... url ...")
# Wait until all needed elements are visible or 100 seconds passed
WebDriverWait(edge, 100)\
.until(EC.visibility_of_all_elements_located((By.XPATH, "XPath str ...")))
result = edge.find_elements(By.XPATH, "XPath str ...")
# Other finding methods:
# By.CLASS_NAME, By.ID, By.TAG_NAME, By.CSS_SELECTOR
input_block = edge.find_element(By.CSS_SELECTOR, "input")
input_block.send_keys("... something ...")
input_block.send_keys(Keys.ENTER)
except TimeoutException as e:
print(e)
```
### `requests`
```python=
from fake_useragent import UserAgent
res = requests.get("... url ...", headers={"User-Agent": UserAgent().random})
result = json.loads(res.text) # type: dict[str]
```
### `pymssql`
```python=
db_settings = {
"host": "127.0.0.1",
"user": "... user ...",
"password": "... pwd ...",
"database": "... db ...",
"charset": "utf8"
}
try:
with pymssql.connect(**db_settings) as conn:
with conn.cursor() as cursor:
cursor.execute("... sql (%s, %d) ...", a_tuple)
cursor.executemany("... sql (%s, %d) ...", a_list_of_tuples)
cursor.rowcount # Get affected row count
conn.commit()
except Exception as e:
print(e)
```
### `concurrent.futures.ThreadPoolExecutor`
```python=
with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor:
results = executor.map(lambda p: func(**p), params_list)
results = [*results]
```
### `apscheduler.schedulers.blocking.BlockingScheduler`
```python=
# Possible to be combined with Windwos 工作排程器
now = datetime.datetime.today()
end = datetime.datetime.combine(datetime.date.today(), datetime.time(hour=14))
scheduler.add_job(func, "interval",
minutes=5, start_date=now, end_date=end, next_run_time=now)
scheduler.start()
```
### `datetime`
```python=
datetime.date(2023, 12, 31)
datetime.datetime(2023, 12, 31, hour=14)
datetime.time(hour=14)
datetime.timedelta(days=1)
datetime.date.fromisoformat("2023-04-10")
datetime.datetime.fromisoformat("20230410")
datetime.date.today()
datetime.datetime.today()
a_date.strftime("%Y-%m-%d")
a_datetime.strftime("%Y-%m-%d %H:%M:%S")
datetime.datetime.combine(a_date, a_time)
```
### `mplfinance`
==TODO==
## Others
### ==HTML 架構分析==
- **id**:獨一的標籤,整個網頁只會有一個
- **class**:群組標籤,通常會是排版的標籤或是一個內容群組
- **tag name**:架構的標籤
- **text**:顧名思義文字,就是一個架構中純文字的部分
- **attribute**:除了特定的屬性(class、id...),其他都為 attribute