# 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