---
# System prepended metadata

title: DBL Mid (04/17)
tags: [DBL]

---

# DBL Mid (04/17)
###### tags: `DBL`

---

[TOC]

---

<style>
.markdown-body
{
    max-width: 960px !important;
}
</style>

## 飆股九陰真經
### ==股價資訊用於日後的數據分析==
- **均線、K線**

### ==K 線==
![](https://i.imgur.com/uRFaIW3.png)

### ==兩日 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 線型態==
- **遭遇線**（反攻線）：
    ![](https://i.imgur.com/kzkmICK.png =x250)
    - 長黑棒與長紅棒**收盤價**相同
- **懷抱線**（母子線）：
    ![](https://i.imgur.com/ZWWP1W8.png =x250)
    - 後者實體被前者實體全部包含
    - 後者交易區間被前者交易區間全部包含
- **插入線**：
    ![](https://i.imgur.com/juiujeI.png =x250)
    - 前者實體被後者實體吃掉一半以上
- **吞噬線**：
    ![](https://i.imgur.com/P08Rcmf.png =x250)
    - 前者實體被後者實體全部包含
    - 前者交易區間被後者交易區間全部包含


## 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


