尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
ระบบแจ้งเตือนราคาหุ้น US แตะ แนวรับ ผ่าน LINE OA — คำนวณแนวรับอัตโนมัติจากราคาย้อนหลัง (ไม่ต้องตั้งเอง) ออกแบบมาสำหรับติดตามพอร์ตส่วนตัว (เช่น AMD, NVDA, PLTR, TSM, AVGO) และรันบน free tier ทั้งหมด สารบัญ 1. สูตรคำนวณแนวรับ 2. กติกาการแจ้งเตือน 3. เหตุผลที่เลือก Data Source / Database 4. Setup ทีละขั้น 5. โครงสร้างโค้ด 6. Environment variables 7. Push ขึ้น GitHub ใช้ข้อมูลแท่งเทียนรายวัน (~260 แท่ง ≈ 1 ปี) เฉพาะ session ที่ปิดแล้ว (แท่งวันนี้ที่ยังไม่จบถูกตัดทิ้ง) แล้วรวบรวมแนวรับ เชิงโครงสร้าง 3 วิธี กรองเฉพาะระดับที่ ต่ำกว่าราคาปิดล่าสุด ก่อนจัดลำดับ檢視完整 README ↗
ระบบแจ้งเตือนราคาหุ้น US แตะ แนวรับ ผ่าน LINE OA — คำนวณแนวรับอัตโนมัติจากราคาย้อนหลัง (ไม่ต้องตั้งเอง) ออกแบบมาสำหรับติดตามพอร์ตส่วนตัว (เช่น AMD, NVDA, PLTR, TSM, AVGO) และรันบน free tier ทั้งหมด
GitHub Actions (cron) ──POST──▶ Vercel (Next.js API) ──▶ Twelve Data (ราคา/OHLC)
│ ▲
▼ │
Postgres (Supabase) LINE Push API ──▶ มือถือคุณ
▲
LINE webhook (follow) ─┘ หน้าเว็บ: จัดการหุ้น / แนวรับ / ประวัติ
ใช้ข้อมูลแท่งเทียนรายวัน (~260 แท่ง ≈ 1 ปี) เฉพาะ session ที่ปิดแล้ว (แท่งวันนี้ที่ยังไม่จบถูกตัดทิ้ง) แล้วรวบรวมแนวรับ เชิงโครงสร้าง 3 วิธี กรองเฉพาะระดับที่ ต่ำกว่าราคาปิดล่าสุด ก่อนจัดลำดับ
| วิธี | สูตร | บทบาท |
|---|---|---|
| Swing Low (โซน) | จุด low ที่ต่ำกว่า low ของ 5 แท่งซ้าย-ขวา (fractal) ภายใน 250 แท่ง แล้วรวมจุดที่ห่างกันไม่เกิน 1.5% เป็นโซนเดียว นับว่าราคาเคยเด้งในโซนนั้นกี่ครั้ง · ระดับ = ขอบบนของโซน (ถ้าราคาอยู่ในโซนแล้ว ใช้ขอบล่าง) | ราคาที่ผู้ซื้อเคยเข้ามาจริง ยิ่งเด้งหลายครั้งยิ่งมีน้ำหนัก |
| Moving Average | SMA 50 และ SMA 200 ของราคาปิด | แนวรับเชิงแนวโน้มระยะกลาง/ยาว — MA200 คือเส้นที่สถาบันดู |
| Fibonacci Retracement | ขาขึ้นล่าสุด: high สูงสุดใน 120 แท่ง และ low ต่ำสุดก่อนหน้า high นั้น → level = High − r·(High−Low), r = 38.2%, 50%, 61.8% | จุดพักตัวมาตรฐานของแนวโน้มขาขึ้น (ข้ามไปถ้า range < 10% หรือไม่มีขาขึ้น) |
เอา Pivot Point รายวันออกแล้ว: Pivot คำนวณจากแท่งเทียนของเมื่อวานแท่งเดียว จึงเปลี่ยนทุกวันและเลื่อนตามราคาลงไปเรื่อย ๆ — ราคาวันนี้ก็คือ "แนวรับ" ของเมื่อวาน ซึ่งแปลว่าไม่มีแนวรับจริง และ backtest พบว่าการแตะ Pivot ไม่ได้ดีกว่าการซื้อวันสุ่ม
| ระดับ | วิธีที่เข้าเกณฑ์ | กติกาเลือก |
|---|---|---|
| แนวรับแรก (Minor) | Swing Low, MA50, Fib 38.2%, Fib 50% | อันที่ ใกล้ราคาปัจจุบันที่สุด |
| แนวรับถัดไป (Intermediate) | Swing Low, Fib 50%, MA50, Fib 38.2% | อันที่สูงสุดที่ยังต่ำกว่า Minor อย่างน้อย 1% |
| แนวรับสำคัญ (Major) | MA200, Fib 61.8% (สำรอง: โซน Swing Low ที่เด้ง ≥2 ครั้ง) | อันที่สูงสุดที่ยังต่ำกว่า Intermediate อย่างน้อย 1% |
ทำไมออกแบบแบบนี้
ทุกวันหลังคำนวณแนวรับ ระบบเล่นวิธีคำนวณปัจจุบันซ้ำกับราคาย้อนหลัง ~5 ปีของหุ้นตัวนั้น ทีละวันโดยไม่แอบดูอนาคต (src/lib/support/track.ts) ทุกครั้งที่ราคาแตะระดับ จะจำราคาระดับนั้นไว้ แล้วดูว่าเกิดอะไรก่อนภายใน 20 วันทำการ:
track.test.ts)โค้ดอยู่ที่ src/lib/support/ (pure functions มี unit test ครบ)
⚠️ แนวรับเป็นเครื่องมือประกอบการตัดสินใจ ไม่ใช่คำแนะนำการลงทุน
แจ้งเตือนเฉพาะ "แนวรับสำคัญ" (ค่าเริ่มต้น) เพื่อลดจำนวนข้อความ (≈ 1 ข้อความต่อเดือน) — backtest ยังไม่พบว่าระดับใดดีกว่าการซื้อวันสุ่มอย่างมีนัยสำคัญ ดูหัวข้อ Backtest — ตั้ง ALERT_TIERS=minor,intermediate,major ถ้าต้องการแจ้งทุกระดับ ระดับอื่นยังแสดงบนหน้าเว็บและในคำสั่ง "ขอแนวรับ" ตามปกติ
State machine แยกตาม (หุ้น, ระดับ) — ดู src/lib/alerts/evaluate.ts
src/lib/alerts/lateCheck.ts) ถ้าราคาแตะหลังรอบเช็กและยังไม่ได้แจ้ง จะส่ง "แตะ … หลังรอบเช็ก" ถ้าราคาปิดต่ำกว่าแนวรับ (หรือต่ำกว่าขอบล่างของโซน) จะส่ง "หลุด …" พร้อมบอกระดับใหม่ที่ใช้แทน แทนที่จะเปลี่ยนเงียบ ๆ ใช้ข้อมูลที่ดึงมาอยู่แล้ว ไม่เปลืองโควตา API เพิ่ม และส่งเฉพาะระดับใน ALERT_TIERSตัวอย่างข้อความ:
🔔 แจ้งเตือนแนวรับหุ้น US
NVDA แตะ "แนวรับสำคัญ"
• ราคาปัจจุบัน: $158.20
• แนวรับ: $158.50 (MA200)
• ห่างจากแนวรับ: -0.19%
ต่ำกว่า 1024px แถบบนมีแค่ไอคอน ชื่อ และปุ่มแฮมเบอร์เกอร์ (เส้นสามเส้นที่หมุนเป็นกากบาทตอนเปิด) กดแล้วเมนูเลื่อนออกมาเป็นลิ้นชักด้านซ้าย: ปิดได้ด้วยแตะพื้นหลัง กด Esc หรือเลือกเมนู (ลิ้นชักปิดเองหลังหน้าใหม่พร้อม ระหว่างรอมีวงกลมหมุนที่รายการที่กด) ตอนเปิดหน้าด้านหลังจะเลื่อนไม่ได้ และ Tab วนอยู่ในเมนู — src/components/Nav.tsx ตั้งแต่ 1024px ขึ้นไปเป็นเมนูแนวนอนเหมือนเดิม
npm run backtest เดินย้อนหลังทีละวัน (5.5 ปี, หุ้นที่ track) ด้วยโค้ดตัวจริงของระบบ แล้วเทียบผลหลังแตะแนวรับกับวันอื่น ๆ ของหุ้นตัวเดียวกัน (ปีเดียวกัน ที่เพิ่งลงใกล้เคียงกัน) — วิธีและข้อจำกัดเต็ม ๆ อยู่ที่ docs/backtest-report.md
set -a; source .env.local; set +a
npm run backtest # ใช้แคชข้อมูลราคาถ้ามี (ครั้งแรกใช้ ~1 credit ต่อหุ้น)
npm run backtest -- --refresh # ดาวน์โหลดราคาใหม่
รันบน GitHub ได้ที่ workflow Deploy steps (ติ๊กเฉพาะ backtest) — รายงานเต็มอยู่ในหน้าสรุปของรอบนั้นและไฟล์แนบ
สรุปจากการรันวันที่ 2026-09-30 (แนวรับเชิงโครงสร้าง, หุ้น 11 ตัว, 2,468 ครั้งที่แตะ, ธ.ค. 2021 – ก.ย. 2026):
ทั้งหมดนี้ไม่ใช่คำแนะนำการลงทุน ผลในอดีตไม่รับประกันอนาคต และมี survivorship bias (หุ้นที่ track คือตัวที่โตมาแล้ว)
กดปุ่มเดียว ระบบส่งหุ้นทุกตัวที่ track ไปให้ AI จัดอันดับ ตัวที่ควรดูต่อสูงสุด 5 ตัว ตามเป้าหมายที่เลือก (เติบโต · ปันผล · ราคาไม่แพง · ความเสี่ยงต่ำ · จังหวะใกล้แนวรับ เลือกได้หลายข้อ ไม่เลือกคือดูภาพรวมสมดุล) — src/lib/jobs/analysis.ts
AI_DAILY_LIMIT (ค่าเริ่มต้น 10) นับเฉพาะครั้งที่ได้ผลลัพธ์ ครั้งที่จบด้วย error ทุกแบบ (key/โมเดลผิด, โควตาหมด, ผู้ให้บริการขัดข้อง, หมดเวลา, อ่านคำตอบไม่ได้) ไม่ถูกนับ — ระบบจองสิทธิ์ไว้ก่อนเรียก (กดพร้อมกันหลายครั้งก็ไม่เกินเพดาน) แล้วคืนให้เมื่อ error · โควตาของผู้ให้บริการเองยังอาจถูกใช้ในบางกรณี (เช่นหมดเวลา) ดูได้ที่หน้า Usage ของผู้ให้บริการAI_MODEL ได้หลายตัวคั่นด้วยจุลภาค เช่น gemini-3.8-flash,gemini-3.5-flash-lite ตัวแรกคือโมเดลหลัก ถ้าใช้ไม่ได้ (โควตารายวันหมด 429, โมเดลถูกยกเลิก 404/400, ตอบว่างเปล่า) ระบบสลับไปตัวถัดไปเอง ถ้าเซิร์ฟเวอร์ขัดข้อง/คนใช้เยอะ (5xx) ลองซ้ำโมเดลเดิม 1 ครั้งหลังรอ 2 วินาทีก่อนสลับ ทั้งหมดใช้งบเวลาเดียวกัน (AI_TIMEOUT_SECONDS) และถ้า key ผิด (401/403) หยุดทันที เพราะทุกโมเดลจะล้มแบบเดียวกัน ผลลัพธ์จะบอกว่าใช้โมเดลไหนและตัวไหนถูกข้ามเพราะอะไร · ถ้ามีมากกว่า 1 โมเดล หน้าเว็บมีช่องเลือกโมเดล (เลือกได้เฉพาะที่อยู่ใน AI_MODEL) · Google แยกโควตาตามโมเดล การมีตัวสำรองจึงช่วยเมื่อตัวหลักหมดโควตาของวันsrc/lib/analysis/factors.ts) ให้ทุกตัว พร้อมอันดับในกลุ่ม (percentile 0–100): ผลตอบแทน 1/3/6/12 เดือน, ความผันผวนจริง, ห่างจุดสูง/ต่ำ 52 สัปดาห์, ลงลึกสุด, P/E, กำไรที่คาดว่าจะโต (P/E ÷ P/E ปีหน้า), รายได้โต, อัตรากำไร, ปันผล, Beta, ขนาดบริษัท, อัพไซด์ถึงราคาเป้า, สัดส่วนแนะนำซื้อ, จำนวนนักวิเคราะห์, ห่างแนวรับแรก, แนวรับดีกว่าระดับสุ่ม, ทิศทางข่าว — คำนวณจากข้อมูลในระบบ (ราคาย้อนหลัง price_history ฯลฯ) ไม่ใช้ API เพิ่มตั้งค่า (Vercel → Settings → Environment Variables, Production แล้ว Redeploy) — ใช้ผู้ให้บริการใดก็ได้ที่รองรับรูปแบบ OpenAI …/chat/completions:
| ตัวแปร | ชนิด | ค่า |
|---|---|---|
AI_API_KEY | Secret | key จากผู้ให้บริการ |
AI_MODEL | Config | ชื่อโมเดล หรือหลายชื่อคั่นด้วยจุลภาค (ตัวแรก = หลัก ที่เหลือ = สำรอง) |
AI_BASE_URL | Config (ไม่บังคับ) | ค่าเริ่มต้น https://openrouter.ai/api/v1 |
ตัวอย่างค่า (ชื่อโมเดล/โควตาฟรีเปลี่ยนบ่อย ตรวจที่หน้าของผู้ให้บริการก่อน):
| ผู้ให้บริการ | AI_BASE_URL | AI_MODEL (ตัวอย่าง) |
|---|---|---|
| OpenRouter (รวมหลายโมเดล มีตัวฟรี) | https://openrouter.ai/api/v1 | ชื่อจากหน้า Models เช่น …:free |
| Google Gemini (AI Studio) | https://generativelanguage.googleapis.com/v1beta/openai | เช่น gemini-3.8-flash, gemini-3.5-flash-lite (รุ่น 2.5 ปิดรับผู้ใช้ใหม่แล้ว) |
| Groq | https://api.groq.com/openai/v1 | โมเดล Llama ที่ Groq เปิดให้ |
| OpenAI | https://api.openai.com/v1 | ตามบัญชี |
ไม่บังคับ: AI_DAILY_LIMIT (ครั้ง/วัน) · AI_TIMEOUT_SECONDS (ค่าเริ่มต้นและสูงสุด 280 = เวลารวมของทุกโมเดลและการลองซ้ำ; ฟังก์ชันนี้ตั้งให้รันได้ 300 วินาทีตามเพดานของ Vercel แบบ Fluid compute โดยเผื่อเวลาดึงราคาและฐานข้อมูล — ตั้งน้อยกว่านี้ได้ถ้าไม่อยากรอนาน) · AI_TEMPERATURE (ส่งไปเฉพาะเมื่อตั้ง บางโมเดลไม่รับค่าอื่นนอกจากค่าเริ่มต้นของมัน)
⚠️ ข้อมูลหุ้นที่ติดตามจะถูกส่งไปผู้ให้บริการ AI — แพ็กเกจฟรีของบางเจ้าอาจนำข้อมูลไปปรับปรุงโมเดลได้ ตรวจเงื่อนไขก่อนใช้ (ข้อมูลนี้ไม่มีความลับ แต่บอกว่าคุณสนใจหุ้นอะไร) · โมเดลฟรีมักช้า ถูกจำกัดบ่อย และทำตามรูปแบบ JSON ไม่เสถียร ถ้าเจอ "อ่านคำตอบของ AI ไม่ได้" บ่อย ให้ลองโมเดลอื่น
src/components/PriceChart.tsx): ราคาปิดรายวัน (5Y เป็นรายสัปดาห์) + เส้นประแนวรับปัจจุบันตามสีระดับ + จุดที่ราคาเคยแตะแนวรับจาก backtest (จุดเขียว = รับได้, วงแดง = หลุด) · ช่วง 3M · 6M (เริ่มต้น) · 1Y · 5Y ผู้เยี่ยมชมเลือกช่วงได้ (เป็นการดูอย่างเดียว) · ช่วงยาวแสดงเฉพาะจุดของระดับที่สำคัญกว่า (1Y: แนวรับถัดไป+สำคัญ, 5Y: แนวรับสำคัญ) ไม่ให้จุดของแนวรับแรกที่แตะบ่อยบังหมด · วาดด้วย SVG เอง (ไม่มี library) ตามความกว้างจริงของการ์ด ตัวเลขจึงอ่านได้ทุกขนาดจอ · โหลดเมื่อกางรายละเอียดเท่านั้นsrc/components/AnalystPanel.tsx): แถบสีซื้อ/ถือ/ขาย (Finnhub ฟรี ทุก 3 วัน) และแถบช่วงราคาเป้าหมาย 12 เดือน ต่ำสุด–เฉลี่ย–สูงสุด พร้อมจุดราคาตอนนี้และขีดแนวรับในแถบเดียว (เห็นทั้งระยะลงถึงแนวรับและระยะขึ้นถึงเป้า) · ราคาเป้าหมายดึงจาก Nasdaq (api.nasdaq.com ไม่เป็นทางการ ฟรี ไม่ต้องมี key) เพราะ Finnhub แผนฟรีไม่ให้ · ถ้า Nasdaq ล้ม ค่าเดิมยังอยู่ แต่จะไม่แสดงเมื่อเก่ากว่า 14 วัน · ETF ไม่มีราคาเป้า · ไม่มีป้าย "แนะนำซื้อ" และมีคำเตือนว่าเป็นความเห็นที่มักมองบวกเกินจริงprice_history (ราคาปิดย้อนหลังประมาณ 5 ปี) บันทึกโดยงานคำนวณแนวรับรายวันจากราคาที่ดึงอยู่แล้ว ไม่ใช้เครดิต API เพิ่ม · API สาธารณะ GET /api/history/<SYMBOL>?range=6m (src/lib/chart/series.ts เลือกช่วง ย่อรายสัปดาห์ เลือกจุด) · เติมย้อนหลังทันทีโดยไม่รอรอบรายวัน: set -a; source .env.local; set +a; npm run backfill:prices (1 เครดิต Twelve Data ต่อหุ้น ไม่คำนวณแนวรับใหม่ ไม่ส่ง LINE)src/proxy.ts ให้ทุกคนใช้ได้แค่ GET/HEAD คำขอที่แก้ข้อมูล (POST/PUT/PATCH/DELETE) ต้องมีเซสชันเจ้าของ ไม่มีจะได้ 401 · ปุ่มรีเฟรชราคา (/api/prices?force=1) ข้าม cache ได้เฉพาะเจ้าของ ผู้เยี่ยมชมใช้ cache ร่วม 5 นาที จึงไม่ทำให้เรียก API ราคาถี่ขึ้น · หน้าแต่ละหน้าเช็กสิทธิ์ด้วย src/lib/viewer.tssrc/lib/recipients.ts): สำหรับผู้เยี่ยมชม server ตัด LINE user id (แสดง U••••••••) ชื่อจาก LINE และชื่อเรียกออกก่อนส่งไปเบราว์เซอร์ จึงไม่อยู่ใน HTML ด้วย แสดงเป็น "ผู้รับ #1" พร้อม "✓ ดึงชื่อและรูปโปรไฟล์จาก LINE แล้ว" เป็นหลักฐานว่าดึงข้อมูลได้จริง · รูปโปรไฟล์แสดงเฉพาะคนที่เจ้าของเปิดสวิตช์ "แสดงรูปบนหน้าสาธารณะ" ในหน้าผู้รับ (ตั้งใจไว้สำหรับบัญชีของเจ้าของเอง ค่าเริ่มต้นปิดทุกคน) คนอื่นเป็นไอคอนเงาให้ Google ค้นเจอ (SEO)
src/app/robots.ts → /robots.txt อนุญาตทุกหน้า ยกเว้น /api/ และ /login และชี้ไปที่ sitemapsrc/app/sitemap.ts → /sitemap.xml รายการหน้าสาธารณะทั้ง 6 หน้า (จาก PUBLIC_PAGES ใน src/lib/site.ts)src/app/layout.tsx → title/description, Open Graph (ตัวอย่างลิงก์เวลาแชร์), canonical URL · แต่ละหน้ามี metadata ของตัวเอง (ชื่อหน้า + คำอธิบาย) · หน้า login ตั้ง noindexSITE_URL ถ้าตั้ง (เช่นเมื่อมีโดเมนของตัวเอง) ไม่อย่างนั้นใช้ VERCEL_PROJECT_PRODUCTION_URL ที่ Vercel ให้มาเองhttps://stock-support-alert.vercel.app → ยืนยันด้วย HTML tag (คัดลอกค่า content มาใส่ verification: { google: "…" } ใน metadata ของ src/app/layout.tsx แล้ว deploy) → เมนู Sitemaps ใส่ sitemap.xml → Submitระบบเก็บข่าวฟรีทุกชั่วโมง แล้วให้ AI สรุปทุกวันทำการก่อนตลาดเปิด ว่าข่าวกระทบตลาดและหุ้นที่ track แต่ละตัวอย่างไร (หรือกด "สรุปข่าวตอนนี้" เองได้) — src/lib/jobs/news.ts
company-news ของหุ้นทุกตัว และ news?category=general (ข่าวตลาด ส่วนใหญ่เป็นพาดหัว Reuters) ใช้ FINNHUB_API_KEY ตัวเดิม ประมาณ 21 ครั้งต่อรอบ เว้นช่วง 1.2 วินาทีเพื่อไม่ชนเพดาน 60 ครั้ง/นาทีที่ใช้ร่วมกับราคาสดNEWS_PER_STOCK ข่าวต่อหุ้น (ค่าเริ่มต้น 6) + ข่าวตลาด 15 ข่าว · เนื้อหารวมไม่เกิน NEWS_PROMPT_MAX_CHARS ตัวอักษร (ค่าเริ่มต้น 160,000 ≈ 40k token)AI_API_KEY, AI_MODEL, สลับโมเดลสำรองเหมือนกัน) จำกัด NEWS_DAILY_LIMIT ครั้งต่อวัน (ค่าเริ่มต้น 3 รวมรอบอัตโนมัติ นับเฉพาะครั้งที่สำเร็จ) · prompt ใหญ่ (หลายหมื่น token) เหมาะกับ Gemini/OpenRouter ถ้าใช้ Groq แบบฟรีให้ลด NEWS_PROMPT_MAX_CHARSnews_articles (เนื้อข่าวเต็มเก็บแค่ 7 วันเพื่อใช้สรุป แถวทั้งหมดลบเมื่อครบ 30 วัน) และ news_briefs (สรุปที่ได้ เก็บเฉพาะพาดหัว แหล่ง และลิงก์ ไม่เก็บเนื้อข่าว)ทุกตัวเลขมีคำอธิบายภาษาคนต่อท้ายว่าหมายความว่าอะไร — src/lib/profile/describe.ts (เกณฑ์เป็นค่าประมาณทั่วไป ระบบไม่เขียนว่า "ควรซื้อ" หรือ "ราคาถูก")
| ข้อมูล | แปลว่า | ที่มา |
|---|---|---|
| P/E (และปีหน้า) | จ่ายกี่ดอลลาร์ต่อกำไร $1 ต่อปี เทียบช่วงทั่วไปของตลาดสหรัฐ (~15–25) และนักวิเคราะห์คาดว่ากำไรจะเพิ่ม/ลด | Finnhub |
| รายได้เทียบปีก่อน | ธุรกิจหด / โตช้า / ปานกลาง / เร็ว / เร็วมาก | Finnhub |
| อัตรากำไรสุทธิ | ขายได้ $100 เหลือกำไรเท่าไร | Finnhub |
| ผลตอบแทนปันผล | ถือหุ้นมูลค่า $100 ได้ปันผลกี่ดอลลาร์ต่อปี (ไม่แสดงถ้าไม่มีตัวเลข = ไม่จ่ายหรือไม่ทราบ) | Finnhub |
| Beta | ถ้าตลาดลง 10% หุ้นนี้ลงโดยเฉลี่ยกี่ % | Finnhub |
| เทียบจุดสูงสุด 52 สัปดาห์ | ราคาอยู่ตรงไหนของรอบปี (ใช้ราคาบนการ์ด) | ราคาย้อนหลัง |
| ลงลึกสุดในอดีต | ช่วง ~5 ปี เคยร่วงจากจุดสูงสุดกี่ % เมื่อไหร่ ถ้าซื้อที่จุดสูงสุดเงิน $100 จะเหลือเท่าไร และกลับมาได้หรือยัง | ราคาย้อนหลัง |
| ประกาศงบครั้งถัดไป | อีกกี่วัน (ภายใน 7 วันจะเตือนสีเหลือง เพราะราคามักแกว่งแรง) | Finnhub |
| คำแนะนำนักวิเคราะห์ | กี่คนแนะนำ ซื้อ/ถือ/ขาย (เดือนล่าสุด) — บอกด้วยว่าคำแนะนำ "ซื้อ" เป็นเรื่องปกติของโบรกเกอร์ จึงไม่ใช่สัญญาณแรง; เตือนเมื่อมีคนแนะนำขายมากผิดปกติ | Finnhub (ฟรี) |
| ราคาเป้าหมายนักวิเคราะห์ | ค่าเฉลี่ยเป้า 12 เดือน (ต่ำสุด–สูงสุด) เทียบราคาตอนนี้ — ราคาเป้าหมายมักมองบวกเกินจริง | Finnhub (อาจต้องแพ็กเกจจ่ายเงิน ถ้าไม่ได้จะไม่แสดง) |
stock_profiles หน้าเว็บอ่านจากฐานข้อมูลอย่างเดียว; หุ้นที่เพิ่มใหม่ได้ข้อมูลทันทีตอนเพิ่มset -a; source .env.local; set +a; npm run refresh:profilesดึง ครั้งเดียวตอนเพิ่มหุ้น แล้วเก็บ ตัวไฟล์รูปไว้ในฐานข้อมูลของเรา (คอลัมน์ symbols.logo_*) หน้าเว็บแสดงผ่าน /api/logo/<symbol> ของเราเอง จึงไม่ต่อเว็บอื่นตอนใช้งาน (ทั้งหน้าแนวรับและหน้าจัดการหุ้น) และไม่ขึ้นกับว่า Finnhub ตอบหรือไม่
FINNHUB_API_KEY) → Twelve Data (STOCK_API_KEY) → ถ้าไม่มีเลยแสดงตัวอักษรย่อของ tickerset -a; source .env.local; set +a
npm run seed:logos # เติมตัวที่ยังไม่มี (ข้ามตัวที่ลองไปไม่เกิน 7 วัน)
npm run seed:logos -- --retry # ลองตัวที่ยังไม่มีอีกครั้งทันที
src/lib/stock/logo.ts, src/lib/jobs/logos.tsMAX_PUSH_RECIPIENTS คน (ค่าเริ่มต้น 5) เพราะโควตาของ LINE นับ "ต่อผู้รับ" — ระบบตรวจเพดานฝั่งเซิร์ฟเวอร์ ไม่ให้เกินแม้กดพร้อมกันขอแนวรับ ถามได้ ซึ่งตอบด้วย reply message ที่ไม่นับโควตา pushLINE_ALLOWED_USER_IDS ที่เคยใช้ เลิกใช้แล้ว (ลบออกจาก Vercel ได้ ปล่อยไว้ก็ไม่มีผล)ตอนมีคนแอด OA ระบบส่งข้อความต้อนรับที่บอกวิธีใช้ทันที (พร้อมตัวอย่างจากหุ้นที่ติดตามอยู่จริง) และพิมพ์ วิธีใช้ (หรือ help, ช่วยเหลือ, เมนู) เพื่อขอดูอีกครั้งได้ทุกเมื่อ — src/lib/line/guide.ts
แนะนำให้ปิด Greeting message เริ่มต้นของ LINE ใน OA Manager (Settings → Response settings) ไม่ให้ซ้ำกับของระบบ
หน้า แนวรับปัจจุบัน ดึงราคาสดมาแสดงเมื่อเปิดหน้า และมีปุ่ม "รีเฟรชราคา" — ใช้ Finnhub (ตั้ง FINNHUB_API_KEY) → ถ้าไม่ได้ตั้ง key หรือดึงไม่ได้จะลอง Yahoo (ไม่เป็นทางการ อาจถูกบล็อก) → ถ้ายังไม่ได้จะใช้ราคาที่เก็บไว้ตอนรอบเช็ค Twelve Data
live_quotes) 5 นาที ใช้ร่วมกันทุกคนและทุกเซิร์ฟเวอร์ — โหลดหน้ารัว ๆ หรือหลายคนใช้พร้อมกัน ก็ยิง Finnhub/Yahoo ไม่เกิน 1 ครั้งต่อหุ้นต่อ 5 นาที (หุ้น 20 ตัว ≈ 4 ครั้ง/นาที เทียบเพดานฟรี 60 ครั้ง/นาที) ปรับได้ด้วย LIVE_PRICE_TTL_SECONDSLIVE_PRICE_MIN_REFRESH_SECONDS) และคำขอที่ซ้อนกันในเซิร์ฟเวอร์เดียวกันใช้การดึงเดียวกันLIVE_PRICE_DEADLINE_MS) ตัวที่ไม่ทันจะใช้ราคาเก่าล่าสุดของ live (ติดป้าย "ค่าเก่า") แล้วค่อยใช้ราคาจากรอบเช็ก Twelve Datasrc/lib/stock/live.ts, src/lib/jobs/livePrices.ts, /api/pricesSMOKE_USERNAME=<ชื่อผู้ใช้> SMOKE_PASSWORD=<รหัส> npm run smoke -- https://<โดเมน-vercel>
ทดสอบโหลดทุกหน้า/API พร้อมกัน 18 คำขอ × 3 รอบ (แบบเดียวกับที่เบราว์เซอร์โหลดเมนูล่วงหน้า) — เป็นการอ่านอย่างเดียวพิมพ์หา OA ได้เลย (ตอบด้วย reply message ฟรี ไม่กินโควตา push และอ่านจากข้อมูลที่ cache ไว้ ไม่เรียก Stock API):
ขอแนวรับ → แนวรับของ ทุกตัวที่ track ในหน้าเว็บขอแนวรับ NVDA, ขอแนวรับของ NVDA หรือ ขอแนวรับ nvda amd → เฉพาะตัวที่ระบุ (ตัวที่ไม่ได้ track จะแจ้งว่าไม่พบ)เพื่อนทุกคนสั่งได้ — src/lib/line/supportCommand.ts
หน้า แนวรับปัจจุบัน: กดค้างที่ปุ่มจุด 6 จุดมุมการ์ดแล้วลากเพื่อจัดลำดับ (ใช้ได้ทั้งเมาส์ ทัชสกรีน และคีย์บอร์ด: Space หยิบ → ลูกศรย้าย → Space วาง)
ลำดับถูกบันทึกในคอลัมน์ symbols.position และใช้ร่วมกันทั้งเว็บและคำตอบ ขอแนวรับ ใน LINE หุ้นที่เพิ่มใหม่จะต่อท้ายสุด ถ้ายังไม่เคยจัดลำดับจะเรียง A→Z
ส่วนหน้า ประวัติแจ้งเตือน เรียงตามเวลาล่าสุดก่อน
เพื่อประหยัดโควตา workflow เรียก /api/cron/check?mode=daily วันละ 2 รอบ: 10:30 น. นิวยอร์ก (1 ชม. หลังเปิด = 21:30 น. ไทยช่วง EDT / 22:30 น. ช่วง EST) และ 13:30 น. นิวยอร์ก (00:30 / 01:30 น. ไทย) รอบแรกให้ทันดูก่อนนอนและจับช่วงเปิดตลาดที่แกว่งแรงที่สุด ระดับที่แจ้งไปแล้วจะไม่แจ้งซ้ำในรอบที่สองจนกว่าราคาจะเด้งขึ้นก่อน
เหลือเวลาตัดสินใจซื้อทัน โหมดนี้ต่างจากโหมดถี่ตรงที่ นับ "ราคาต่ำสุดของวัน" เป็นการแตะด้วย (ไม่งั้นถ้าแตะตอนเช้าแล้วเด้งกลับจะพลาด) และข้อความแจ้งเตือนจะมีบรรทัด "ต่ำสุดวันนี้"
job_runs (แยกต่อรอบ) cron อีกตัวของรอบเดียวกัน (ที่ตั้งไว้เผื่อ EDT/EST) จึงข้ามเอง (ถ้าดึงราคาไม่ครบ จะไม่บันทึก และลองใหม่ได้ โดยไม่ส่งแจ้งเตือนซ้ำ)*/30 13-20 * * 1-5 + 0 21 * * 1-5 และเรียก /api/cron/check (ไม่ใส่ mode) — endpoint รองรับทั้งสองโหมดGitHub cron เป็น UTC และไม่รู้จัก DST จึงตั้งให้ครอบคลุมทั้งเวลา EDT/EST แล้วให้ endpoint ตัดสินเองด้วย
America/New_York ผ่าน Intl (ไม่ hardcode offset) รวมวันหยุด NYSE (Good Friday, Juneteenth ฯลฯ) และวัน early close 13:00
— src/lib/market/calendar.ts
| ตัวเลือก | ราคา real-time | OHLC ย้อนหลัง | ข้อสรุป |
|---|---|---|---|
| Twelve Data | ✅ /quote | ✅ /time_series 1day ได้ถึง 5,000 แท่ง | เลือก — ฟรี 800 credit/วัน, 8/นาที, batch หลาย symbol ในคำขอเดียว, ใช้ API key |
| Finnhub | ✅ ฟรี | ❌ candle ย้อนหลังเป็น premium | ใช้คำนวณแนวรับไม่ได้ |
| Alpha Vantage | ✅ | ⚠️ ฟรีแค่ 25 คำขอ/วัน และ full history เป็น premium | ไม่พอสำหรับ MA200 + เช็คทุก 30 นาที |
| Yahoo (unofficial) | ✅ | ✅ | ไม่มี SLA, มักบล็อก IP ของ Vercel/GitHub, ไม่มี key |
ออกแบบให้ประหยัด rate limit
/quote 1 คำขอ (5 credits) ต่อรอบ — โหมดวันละครั้ง ≈ 5 credits/วัน (โหมดทุก 30 นาที ≈ 70/วัน) จาก 800quotes (TTL 5 นาที) — รันซ้ำ/กดเรียกมือไม่ยิง API ซ้ำsupport_levels และคำนวณใหม่วันละครั้ง (ข้ามถ้าข้อมูลของ session ล่าสุดมีอยู่แล้ว)MAX_TRACKED_SYMBOLS, ค่าเริ่มต้น 20) ภายใต้ limit 8 credits/นาที โดยแต่ละงานดึงครั้งละไม่เกิน 8 ตัว (API_CREDITS_PER_MINUTE)
แล้ว workflow วนเรียกซ้ำโดยเว้น 61 วินาที จนครบ — 20 ตัว = 3 ชุด ใช้เวลาเพิ่มราว 2 นาทีต่อรอบ (ทำเป็นหลายการเรียกสั้น ๆ เพื่อไม่ชนเพดาน 60 วินาทีของ Vercel ฟรี)
/api/cron/quotes อุ่น cache ทีละชุด แล้ว /api/cron/check อ่านจาก cache ทั้งหมด (ไม่เรียก API)/api/cron/recalculate ทำทีละชุดและตอบ remaining กลับมาStockDataProvider (src/lib/stock/types.ts)เช็ค limit ล่าสุดของ free plan ที่ https://twelvedata.com/pricing
เป็น Postgres ธรรมดา ใช้ผ่าน DATABASE_URL เดียว (ไม่ผูก SDK) ย้ายไป Neon / Vercel Postgres ได้โดยเปลี่ยนแค่ connection string
ตาราง: symbols, support_levels, quotes, alert_state, alert_history, line_users — src/lib/db/schema.sql
git clone https://github.com/extratha/stock-support-alert.git
cd stock-support-alert
npm install
cp .env.example .env.local
สมัครฟรีที่ https://twelvedata.com → Dashboard → API Keys → ใส่ใน STOCK_API_KEY
DATABASE_URL
(ถ้ามี ?sslmode=require ก็ใส่ต่อท้าย)npm run db:migrate # อ่าน DATABASE_URL จาก environment
หรือ set -a; source .env.local; set +a; npm run db:migrate
หลังจากนั้น Vercel รัน migrate ให้เองทุกครั้งที่ deploy production (script vercel-build = db:migrate แล้ว next build) ใช้ DATABASE_URL จาก env ของ Vercel — schema เป็นแบบรันซ้ำได้ (เพิ่มเฉพาะที่ยังไม่มี) ถ้าต่อฐานข้อมูลไม่ได้ build จะล้มและเวอร์ชันเดิมยังออนไลน์อยู่ · preview deployment ไม่แตะฐานข้อมูล
เมื่อวิธีคำนวณแนวรับเปลี่ยน (SUPPORT_LOGIC_VERSION) รอบคำนวณถัดไปจะคำนวณใหม่ทุกตัวเอง ไม่ต้องรอวันทำการใหม่LINE_CHANNEL_SECRETLINE_CHANNEL_ACCESS_TOKENhttps://<โดเมน-vercel-ของคุณ>/api/line/webhook → Verify → เปิด Use webhook
(ทำหลัง deploy ข้อ 5)userId ของคุณอัตโนมัติ (event follow)⚠️ โควตา push: แผน Free ของ LINE OA ส่งได้จำกัด (ประมาณ 200 ข้อความ/เดือน ดูแผนล่าสุดในประเทศคุณ) ระบบจึงรวมหลายแจ้งเตือนในรอบเดียวเป็นข้อความเดียว
openssl rand -hex 32 # รันสองครั้ง: ผลแรกเป็น CRON_SECRET ผลที่สองเป็น SESSION_SECRET
ADMIN_USERNAME (ไม่ตั้ง = admin) และ ADMIN_PASSWORD (รหัสผ่านที่ยาวพอ) ใช้เข้าหน้าเว็บผ่านหน้า loginSESSION_SECRET ใช้เซ็น cookie เซสชัน (ยาวอย่างน้อย 16 ตัวอักษร) — ถ้าไม่ตั้งบน production เว็บจะตอบ 503 (ไม่เปิดโล่ง)การ login: เซสชันเป็น cookie ที่เซ็นลายเซ็น (HttpOnly, Secure, SameSite=Lax) อายุ 7 วัน ไม่เก็บอะไรใน DB กดปุ่ม "ออกจากระบบ" เพื่อล้าง cookie
เปลี่ยน ADMIN_USERNAME / ADMIN_PASSWORD / SESSION_SECRET อย่างใดอย่างหนึ่งแล้ว Redeploy = ทุกเครื่องถูกบังคับ login ใหม่
ข้อจำกัด: ไม่มีระบบล็อกเมื่อเดารหัสผิดหลายครั้ง (มีแค่หน่วง 0.5 วินาทีต่อครั้งที่ผิด) จึงควรตั้งรหัสให้ยาวและเดายาก
/api/cron/* (bearer CRON_SECRET) และ /api/line/webhook (ลายเซ็น LINE) ไม่ผ่านหน้า login
extratha/stock-support-alerthttps://stock-support-alert.vercel.appAMD, NVDA, PLTR, TSM, AVGO (ระบบคำนวณแนวรับให้ทันที และใช้ตรวจว่า symbol ถูกต้อง) → กด ส่งข้อความทดสอบทำไมไม่ใช้ GitHub Actions อย่างเดียว: งานตามเวลาของ GitHub เริ่มช้ากว่ากำหนด 5–7 ชั่วโมงเป็นประจำ (วัดจริงช่วง 30 ก.ย.–5 ต.ค. 2026: รอบเช็กระหว่างวันเกือบทุกรอบไปเริ่มหลังตลาดปิดแล้ว) จึงใช้ cron-job.org (ฟรี ตรงเวลาระดับนาที เลือก timezone ได้) เป็นตัวหลัก และเก็บ workflow ของ GitHub ไว้เป็นสำรอง — ส่งซ้ำไม่ได้ เพราะแต่ละรอบบันทึกไว้ใน job_runs และแจ้งเตือนถูก claim ไว้
endpoint ทำงานทั้งหมดในการเรียกครั้งเดียว (ดึงราคา/คำนวณทีละชุด 8 ตัว ห่างกัน 1 นาทีเอง) และ ?async=1 ตอบ 202 ทันทีแล้วทำงานต่อเบื้องหลัง (cron-job.org รอคำตอบได้ไม่นาน) ผลลัพธ์ดูได้ที่ Vercel → Logs
สมัคร cron-job.org แล้วสร้าง 3 งาน (Create cronjob) ทุกงานตั้ง:
POST · Headers: Authorization = Bearer <ค่า CRON_SECRET> (แท็บ Advanced)America/New_York (DST จัดการให้เอง ไม่ต้องมีรอบเผื่อ) · วัน: จันทร์–ศุกร์ (วันหยุดตลาด endpoint ข้ามเอง)| งาน | URL | เวลา (นิวยอร์ก) |
|---|---|---|
| เช็กรอบเช้า | https://<APP_URL>/api/cron/check?mode=daily&async=1 | 10:31 (= 21:31 / 22:31 น. ไทย) |
| เช็กรอบบ่าย | https://<APP_URL>/api/cron/check?mode=daily&async=1 | 13:31 (= 00:31 / 01:31 น. ไทย) |
| คำนวณแนวรับ + สรุปหลังปิด | https://<APP_URL>/api/cron/recalculate?async=1 | 18:05 |
| เก็บข่าว | https://<APP_URL>/api/cron/news?async=1 | ทุกชั่วโมง นาทีที่ 15 (ทุกวัน รวมเสาร์–อาทิตย์ เพื่อเก็บข่าวสุดสัปดาห์) |
| สรุปข่าวก่อนตลาดเปิด | https://<APP_URL>/api/cron/news?mode=brief&async=1 | 08:30 (= 19:30 / 20:30 น. ไทย) จันทร์–ศุกร์ |
ทดสอบ: กด "Test run" ในงานแรก ควรได้ 202 {"accepted":true} (ถ้าได้ 401 แปลว่า header ผิด) แล้วดูใน Vercel → Logs ว่ามีบรรทัด check (async)
ที่ repo → Settings → Secrets and variables → Actions → New repository secret
| Secret | ค่า |
|---|---|
APP_URL | https://stock-support-alert.vercel.app (ไม่ต้องมี / ท้าย) |
CRON_SECRET | ค่าเดียวกับที่ตั้งใน Vercel |
หรือใช้ CLI:
gh secret set APP_URL --repo extratha/stock-support-alert
gh secret set CRON_SECRET --repo extratha/stock-support-alert
| Workflow | เวลา (UTC) | ทำอะไร |
|---|---|---|
check-alerts.yml | 14:30, 15:30, 17:30, 18:30 จันทร์–ศุกร์ (= 10:30 และ 13:30 น. นิวยอร์ก ทั้งช่วง EDT/EST) | เช็คราคา วันละ 2 รอบ เทียบแนวรับ (รวมราคาต่ำสุดของวัน) ส่ง LINE — แต่ละรอบทำงานครั้งเดียว อีกตัวข้ามเอง |
recalculate-supports.yml | 22:00 จันทร์–ศุกร์ | คำนวณแนวรับใหม่หลังตลาดปิด |
maintenance.yml | กดรันเอง | ขั้นตอนหลังอัปเดต: (1) db:migrate (2) คำนวณแนวรับใหม่ทุกตัวทันที (3) backtest แล้วแนบรายงานไว้กับรอบนั้น — ต้องมี secret DATABASE_URL และ STOCK_API_KEY เพิ่มจาก APP_URL/CRON_SECRET |
ทดสอบมือ: แท็บ Actions → เลือก workflow → Run workflow (ติ๊กช่อง "Ignore the market-hours / time-window check" เพื่อข้ามการเช็คเวลาตลาด — ช่องนี้ข้ามแค่เรื่องเวลา ไม่ได้บังคับให้ส่งแจ้งเตือน)
หมายเหตุ GitHub: cron อาจล่าช้าได้หลายนาทีช่วงคนใช้เยอะ · และ workflow ตามเวลาจะถูกปิดอัตโนมัติถ้า repo ไม่มี activity 60 วัน (เข้าไปกด enable ใหม่ได้)
npm run dev # http://localhost:3000 (ไม่มี ADMIN_PASSWORD = ไม่ต้อง login ใน dev)
npm test # unit tests
npm run typecheck && npm run lint
# เรียก job มือ:
curl -X POST -H "Authorization: Bearer $CRON_SECRET" "http://localhost:3000/api/cron/recalculate?force=1"
curl -X POST -H "Authorization: Bearer $CRON_SECRET" "http://localhost:3000/api/cron/check?force=1"
ทดสอบ webhook ตอน dev ด้วย tunnel เช่น cloudflared tunnel --url http://localhost:3000
src/
lib/
support/ คำนวณแนวรับ (pure, มี test) movingAverage · swing (โซน) · fibonacci · calculate (จัดระดับ) · track (รับได้/หลุด ย้อนหลัง)
market/ ปฏิทิน NYSE + timezone/DST
alerts/ evaluate (state machine) · format (ข้อความ LINE)
ai/ ตัวเรียก AI (OpenAI-compatible, ไม่ retry)
analysis/ เป้าหมาย · prompt · ตรวจคำตอบ AI (หน้า "วิเคราะห์ด้วย AI")
viewer.ts เจ้าของหรือผู้เยี่ยมชม · recipients.ts ปิดข้อมูลผู้รับสำหรับผู้เยี่ยมชม · site.ts ที่อยู่เว็บ/หน้าสาธารณะ
news/ ข่าว Finnhub · อ่านเนื้อข่าว (Readability) · จับคู่ข่าวกับหุ้น · prompt · ตรวจคำตอบ AI (หน้า "ข่าว")
stock/ StockDataProvider interface + Twelve Data adapter
line/ signature verify · push/reply client
db/ postgres client · schema.sql · repositories
jobs/ recalculateSupports · checkAlerts · quotes cache · notify ← orchestration
auth.ts cron bearer / admin basic auth
app/
page.tsx, symbols/, history/ หน้าเว็บ
api/cron/* endpoint สำหรับ GitHub Actions
api/line/webhook รับ follow/unfollow
api/symbols เพิ่ม/ลบหุ้น
proxy.ts อ่านได้ทุกคน (GET) · แก้ข้อมูลต้องมีเซสชันเจ้าของ (cookie)
.github/workflows/ cron + CI
scripts/migrate.ts สร้างตาราง
ชั้น support/, market/, alerts/ ไม่แตะ DB/network เลย จึงเทสต์ง่ายและเปลี่ยนกติกาได้โดยไม่กระทบส่วนอื่น
| ตัวแปร | จำเป็น | คำอธิบาย |
|---|---|---|
LINE_CHANNEL_SECRET | ✅ | verify signature ของ webhook |
LINE_CHANNEL_ACCESS_TOKEN | ✅ | ส่ง push/reply |
STOCK_API_KEY | ✅ | Twelve Data API key |
DATABASE_URL | ✅ | Postgres connection string |
ADMIN_USERNAME | – | ชื่อผู้ใช้หน้าเว็บ ค่าเริ่มต้น admin |
ADMIN_PASSWORD | ✅ (production) | รหัสผ่านเจ้าของ (ผู้เยี่ยมชมดูได้โดยไม่ต้องมี) — ถ้าไม่ตั้งใน production เว็บจะตอบ 503 |
SITE_URL | – | ที่อยู่เว็บสำหรับ sitemap/ลิงก์แชร์ ตั้งเฉพาะเมื่อใช้โดเมนของตัวเอง (ไม่ตั้ง = ใช้ที่อยู่ production ของ Vercel) |
SESSION_SECRET | ✅ (production) | คีย์เซ็น cookie login (อย่างน้อย 16 ตัวอักษร) — ถ้าไม่ตั้งใน production เว็บจะตอบ 503 |
CRON_SECRET | ✅ | bearer token ของ /api/cron/* — ถ้าไม่ตั้งจะปฏิเสธทุกคำขอ |
MAX_PUSH_RECIPIENTS | – | จำนวนเพื่อนสูงสุดที่รับ push ค่าเริ่มต้น 5 (ดูหัวข้อ "ผู้รับแจ้งเตือน") |
ALERT_TIERS | – | ระดับที่ส่งแจ้งเตือน LINE ค่าเริ่มต้น major (แนวรับสำคัญ) · minor,intermediate,major = ทุกระดับ |
AI_API_KEY, AI_MODEL | – | แท็บ "วิเคราะห์ด้วย AI" (ดูหัวข้อ "วิเคราะห์ด้วย AI") — ถ้าไม่ตั้ง หน้านั้นบอกว่ายังไม่ได้ตั้งค่า ส่วนอื่นของระบบไม่กระทบ |
AI_BASE_URL, AI_DAILY_LIMIT, AI_TIMEOUT_SECONDS, AI_TEMPERATURE | – | ไม่บังคับ ดูหัวข้อ "วิเคราะห์ด้วย AI" |
NEWS_DAILY_LIMIT, NEWS_PER_STOCK, NEWS_PROMPT_MAX_CHARS | – | แท็บ "ข่าว": สรุปได้กี่ครั้ง/วัน (3) · ข่าวต่อหุ้น (6) · ขนาดเนื้อหาที่ส่งให้ AI (160000 ตัวอักษร) |
FINNHUB_API_KEY | – | key ฟรีจาก finnhub.io สำหรับราคาสดบนหน้าเว็บ (ไม่ตั้ง = ใช้ Yahoo แล้วราคาจากรอบเช็ก) |
Repo นี้ตั้ง origin = https://github.com/extratha/stock-support-alert.git ไว้แล้ว
# 1) login (ครั้งแรก) — ต้องเป็นบัญชีที่มีสิทธิ์เขียน repo ของ extratha
gh auth login # เลือก GitHub.com → HTTPS → Login with a web browser
gh auth status # ตรวจว่า active account ถูกต้อง
# 2) สร้าง public repo (ข้ามถ้ามีอยู่แล้ว)
gh repo create extratha/stock-support-alert --public --source=. --remote=origin --description "US stock support-level alerts via LINE"
# 3) push
git push -u origin main
ถ้า gh login เป็นบัญชีอื่น (ไม่ใช่ extratha) จะสร้าง/push ไม่ได้ ให้ gh auth login ใหม่ด้วยบัญชี extratha
หรือเพิ่มบัญชีนั้นเป็น collaborator ของ repo ก่อน
ai_analyses เปิดหน้าใหม่ก็ยังเห็นset -a; source .env.local; set +a; npm run news (เก็บข่าว) · npm run news -- brief (เก็บข่าว + สรุป ใช้ AI 1 ครั้ง)LIVE_PRICE_TTL_SECONDS / LIVE_PRICE_MIN_REFRESH_SECONDS / LIVE_PRICE_DEADLINE_MS | – | แคชราคาสด (300 วินาที) / ระยะห่างขั้นต่ำของปุ่มรีเฟรช (30 วินาที) / เพดานเวลาต่อคำขอ (12000 มิลลิวินาที) |
MAX_TRACKED_SYMBOLS | – | ค่าเริ่มต้น 20 |
API_CREDITS_PER_MINUTE | – | จำนวนหุ้นต่อการเรียก API หนึ่งครั้ง ค่าเริ่มต้น 8 (ตาม free plan ของ Twelve Data) |
QUOTE_CACHE_TTL_MINUTES | – | ค่าเริ่มต้น 5 |