@drico2008/fincli 0.1.2 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -7
- package/fincli/__init__.py +1 -1
- package/fincli/app/analysis/assistant_context.py +27 -1
- package/fincli/app/analysis/indicators.py +1 -1
- package/fincli/app/analysis/market_structure.py +1 -1
- package/fincli/app/cli/commands.py +12 -4
- package/fincli/app/cli/router.py +253 -13
- package/fincli/app/modules/session_history.py +113 -0
- package/fincli/app/providers/ai/anthropic_provider.py +8 -7
- package/fincli/app/providers/ai/gemini_provider.py +8 -7
- package/fincli/app/providers/ai/groq_provider.py +8 -7
- package/fincli/app/providers/ai/http_provider.py +3 -3
- package/fincli/app/providers/ai/huggingface_provider.py +8 -7
- package/fincli/app/providers/ai/openai_provider.py +8 -7
- package/fincli/app/providers/ai/openrouter_provider.py +8 -7
- package/fincli/app/providers/ai/together_provider.py +8 -7
- package/fincli/app/providers/market/custom_provider.py +2 -2
- package/fincli/app/providers/market/finnhub_provider.py +1 -1
- package/fincli/app/providers/market/manager.py +6 -5
- package/fincli/app/providers/market/news_provider.py +4 -4
- package/fincli/app/providers/market/twelvedata_provider.py +1 -1
- package/fincli/app/providers/market/yfinance_provider.py +1 -1
- package/fincli/app/services/web_research.py +267 -0
- package/fincli/app/storage/cache.py +2 -2
- package/fincli/app/storage/config.py +3 -4
- package/fincli/app/storage/config_paths.py +9 -0
- package/fincli/app/storage/database.py +17 -0
- package/fincli/app/storage/secrets.py +104 -0
- package/fincli/app/tui/components.py +1 -1
- package/fincli/app/tui/layout.py +8 -7
- package/fincli/app/tui/market_provider_selector.py +42 -2
- package/fincli/app/tui/model_selector.py +97 -55
- package/fincli/app/utils/formatting.py +50 -0
- package/npm/bin/fincli.js +9 -2
- package/package.json +1 -1
- package/pyproject.toml +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
FinCLI adalah financial CLI/TUI terminal modern untuk memantau market, mengelola watchlist, portfolio, journal, konfigurasi provider, dan menyiapkan integrasi AI market analysis secara modular.
|
|
4
4
|
|
|
5
|
-
Status saat ini:
|
|
5
|
+
Status saat ini: FinCLI MVP aktif dengan TUI, provider chain, AI assistance, web research, portfolio, journal, watchlist, export, dan session history lokal.
|
|
6
6
|
|
|
7
7
|
- Textual TUI satu kolom dengan command palette inline yang bisa discroll; sidebar lama sudah dihapus agar output market lebih lega.
|
|
8
8
|
- Slash command router dengan command wajib FinCLI v0.1.
|
|
@@ -90,6 +90,24 @@ copy .env.example .env
|
|
|
90
90
|
|
|
91
91
|
Isi API key hanya untuk provider yang ingin digunakan. yfinance fallback tidak butuh API key. Config membaca status key tanpa menampilkan secret.
|
|
92
92
|
|
|
93
|
+
Untuk install global lewat npm, user tidak perlu membuka folder package atau mengedit `.env`. Simpan API key lewat command FinCLI:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
/ai_model key groq <api_key>
|
|
97
|
+
/ai_model key openrouter <api_key>
|
|
98
|
+
/news_model key finnhub <api_key>
|
|
99
|
+
/news_model key twelvedata <api_key>
|
|
100
|
+
/news_model key custom <api_key> https://your-market-api.example.com
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Key disimpan lokal di:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
~/.fincli/secrets.env
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
File ini tidak dicetak penuh di output terminal. `/config` dan `/provider key status` hanya menampilkan status/masked key.
|
|
110
|
+
|
|
93
111
|
## Run
|
|
94
112
|
|
|
95
113
|
```bash
|
|
@@ -130,12 +148,17 @@ python -m fincli.app.main
|
|
|
130
148
|
/journal add BTC-USD bullish "Breakout gagal, tunggu konfirmasi"
|
|
131
149
|
/journal stats
|
|
132
150
|
/journal review
|
|
133
|
-
/
|
|
151
|
+
/history
|
|
152
|
+
/history sessions
|
|
153
|
+
/history save "Riset market pagi"
|
|
154
|
+
/quote AAPL
|
|
134
155
|
/technical BTC-USD 1d
|
|
135
156
|
/technical XAUUSD 1d
|
|
136
157
|
/technical EURUSD 1d
|
|
137
158
|
/structure BTC-USD 1d
|
|
138
159
|
/news AAPL
|
|
160
|
+
/web penyebab rupiah melemah hari ini
|
|
161
|
+
/web sources penyebab rupiah melemah hari ini
|
|
139
162
|
/funda MSFT
|
|
140
163
|
/yahoo BBRI history 6mo 1d
|
|
141
164
|
/yahoo BBRI statistics
|
|
@@ -159,7 +182,7 @@ python -m fincli.app.main
|
|
|
159
182
|
/exit
|
|
160
183
|
```
|
|
161
184
|
|
|
162
|
-
Command `/market`, `/
|
|
185
|
+
Command `/market`, `/quote`, `/technical`, `/structure`, `/news`, dan `/funda` sudah memakai provider chain aktif. Command `/ai` dan `/analyze` sudah memakai AI provider aktif dari `/ai_model` dan `.env`. `/analyze` membawa konteks indikator, struktur pasar, news, dan fundamental ringkas ke prompt AI. `/ai` juga mengambil quote, OHLCV/technical, structure, news, dan fundamental saat user menyebut symbol seperti `AAPL`, `EURUSD`, atau `XAUUSD`.
|
|
163
186
|
|
|
164
187
|
## AI Chat UX
|
|
165
188
|
|
|
@@ -189,8 +212,31 @@ AI assistant di dalam FinCLI dipersonalisasi untuk market workflow:
|
|
|
189
212
|
- Boleh free chat untuk pertanyaan umum, market, portfolio, journal, provider, dan risk workflow.
|
|
190
213
|
- Menolak coding/debugging/refactor/pembuatan software di dalam assistant FinCLI agar fokus app tetap jelas.
|
|
191
214
|
- Jika prompt berisi symbol eksplisit, FinCLI menyisipkan market context dari provider chain aktif sebelum memanggil AI provider.
|
|
215
|
+
- Jika prompt membutuhkan info terkini, FinCLI dapat mengambil konteks web publik dan memasukkannya ke AI prompt.
|
|
192
216
|
- Tidak membocorkan API key dan tidak mengklaim realtime jika provider aktif hanya delayed/fallback.
|
|
193
217
|
|
|
218
|
+
Contoh web-aware freechat:
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
apa yang menyebabkan penurunan rupiah terhadap semua mata uang hari ini
|
|
222
|
+
berita terbaru BI rate dan dampaknya ke IHSG
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Untuk web search yang dirangkum oleh AI:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
/web penyebab rupiah melemah hari ini
|
|
229
|
+
/web update harga emas dan dollar index
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Untuk melihat sumber mentah tanpa ringkasan AI:
|
|
233
|
+
|
|
234
|
+
```text
|
|
235
|
+
/web sources penyebab rupiah melemah hari ini
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
FinCLI memakai lightweight HTTP web research, bukan Chrome automation. Ini lebih stabil untuk npm global install dan tidak membuka browser di background. Output tetap harus diverifikasi karena kualitas sumber web bisa berbeda-beda.
|
|
239
|
+
|
|
194
240
|
## Interactive AI Model Selector
|
|
195
241
|
|
|
196
242
|
```text
|
|
@@ -202,6 +248,7 @@ Di TUI, command ini membuka selector seperti modern CLI:
|
|
|
202
248
|
- Select Provider
|
|
203
249
|
- Status provider current/configured
|
|
204
250
|
- Use existing configuration / configure again
|
|
251
|
+
- Configure API key jika provider belum punya key
|
|
205
252
|
- Select Model
|
|
206
253
|
- Search model/provider
|
|
207
254
|
- Navigasi `up/down`, `Enter`, `Tab`, dan `Esc`
|
|
@@ -222,6 +269,7 @@ Di TUI, command ini membuka selector untuk provider market/news dan fallback pri
|
|
|
222
269
|
|
|
223
270
|
- Select Market/News Provider
|
|
224
271
|
- Pilih `Twelve Data`, `Finnhub`, `Custom API`, atau `Yahoo Finance`
|
|
272
|
+
- Masukkan API key langsung dari popup jika provider belum dikonfigurasi
|
|
225
273
|
- Pilih preset fallback: recommended, primary + yfinance, data API priority, atau yfinance only
|
|
226
274
|
- Search provider/preset
|
|
227
275
|
- Navigasi `up/down`, `Enter`, `Tab`, dan `Esc`
|
|
@@ -436,6 +484,7 @@ Contoh:
|
|
|
436
484
|
|
|
437
485
|
```bash
|
|
438
486
|
/ai_model openrouter openai/gpt-4o-mini
|
|
487
|
+
/ai_model key openrouter <api_key>
|
|
439
488
|
/ai jelaskan risiko market NVDA secara singkat
|
|
440
489
|
/analyze AAPL 1d
|
|
441
490
|
```
|
|
@@ -453,7 +502,7 @@ FinCLI memakai yfinance untuk akses saham global yang tersedia di Yahoo Finance.
|
|
|
453
502
|
Command:
|
|
454
503
|
|
|
455
504
|
```text
|
|
456
|
-
/
|
|
505
|
+
/quote BBRI
|
|
457
506
|
/technical BBRI 1d
|
|
458
507
|
/analyze BBRI 1d
|
|
459
508
|
/yahoo BBRI history 6mo 1d
|
|
@@ -496,6 +545,12 @@ Environment variable:
|
|
|
496
545
|
FINNHUB_API_KEY=your-finnhub-key
|
|
497
546
|
```
|
|
498
547
|
|
|
548
|
+
Atau simpan dari FinCLI:
|
|
549
|
+
|
|
550
|
+
```text
|
|
551
|
+
/news_model key finnhub <api_key>
|
|
552
|
+
```
|
|
553
|
+
|
|
499
554
|
Endpoint Finnhub yang dipakai:
|
|
500
555
|
|
|
501
556
|
```text
|
|
@@ -524,6 +579,12 @@ Environment variable:
|
|
|
524
579
|
TWELVE_DATA_API_KEY=your-twelve-data-key
|
|
525
580
|
```
|
|
526
581
|
|
|
582
|
+
Atau simpan dari FinCLI:
|
|
583
|
+
|
|
584
|
+
```text
|
|
585
|
+
/news_model key twelvedata <api_key>
|
|
586
|
+
```
|
|
587
|
+
|
|
527
588
|
Endpoint Twelve Data yang dipakai:
|
|
528
589
|
|
|
529
590
|
```text
|
|
@@ -571,6 +632,12 @@ MARKET_DATA_API_KEY=your-key
|
|
|
571
632
|
MARKET_DATA_BASE_URL=https://your-market-api.example.com
|
|
572
633
|
```
|
|
573
634
|
|
|
635
|
+
Atau simpan dari FinCLI:
|
|
636
|
+
|
|
637
|
+
```text
|
|
638
|
+
/news_model key custom <api_key> https://your-market-api.example.com
|
|
639
|
+
```
|
|
640
|
+
|
|
574
641
|
FinCLI akan memanggil endpoint:
|
|
575
642
|
|
|
576
643
|
```text
|
|
@@ -604,7 +671,14 @@ FinCLI menyimpan data lokal di:
|
|
|
604
671
|
~/.fincli/fincli.log
|
|
605
672
|
```
|
|
606
673
|
|
|
607
|
-
API key tidak disimpan di output terminal
|
|
674
|
+
API key tidak disimpan di output terminal. Untuk install global via npm, jalur utama adalah command FinCLI:
|
|
675
|
+
|
|
676
|
+
```text
|
|
677
|
+
/ai_model key groq <api_key>
|
|
678
|
+
/news_model key twelvedata <api_key>
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
Key disimpan lokal di `~/.fincli/secrets.env`, dipakai otomatis untuk semua session FinCLI berikutnya, dan tidak perlu dikonfigurasi ulang. Jika `.env` lokal berisi nilai kosong, FinCLI tetap memakai secret lokal yang sudah tersimpan.
|
|
608
682
|
|
|
609
683
|
## Test
|
|
610
684
|
|
|
@@ -622,8 +696,8 @@ Hasil terakhir di environment ini:
|
|
|
622
696
|
|
|
623
697
|
- `fincli` tidak dikenali: jalankan `pip install -e .` dari root project.
|
|
624
698
|
- TUI tidak tampil rapi: perbesar terminal desktop.
|
|
625
|
-
- API key tidak terbaca:
|
|
626
|
-
- `/
|
|
699
|
+
- API key tidak terbaca: gunakan `/ai_model key <provider> <api_key>` atau `/news_model key <provider> <api_key>`, lalu cek `/config` atau `/provider key status`.
|
|
700
|
+
- `/quote` gagal karena yfinance belum ada: jalankan `pip install -e ".[dev]"` atau `pip install -r requirements.txt`.
|
|
627
701
|
- Config rusak: hapus `~/.fincli/config.json` untuk kembali ke default.
|
|
628
702
|
|
|
629
703
|
## Roadmap Lanjutan
|
package/fincli/__init__.py
CHANGED
|
@@ -15,6 +15,7 @@ Identity and scope:
|
|
|
15
15
|
|
|
16
16
|
Financial analysis rules:
|
|
17
17
|
- Analyze from provided market context first. Do not invent prices, news, fundamentals, provider status, or certainty.
|
|
18
|
+
- If Web Research Context is provided, use it as current public context, mention source URLs, and separate sourced facts from interpretation.
|
|
18
19
|
- Use probabilistic language: scenario, bias, confirmation, invalidation, risk, caution.
|
|
19
20
|
- Do not promise profit and do not present aggressive entries as guaranteed signals.
|
|
20
21
|
- For technical analysis, weigh trend, momentum, volatility, support/resistance, market structure, and data quality.
|
|
@@ -155,7 +156,32 @@ def build_fincli_assistant_prompt(user_prompt: str, market_context: str = "") ->
|
|
|
155
156
|
f"{user_prompt.strip()}\n\n"
|
|
156
157
|
"Instruction:\n"
|
|
157
158
|
"- Answer the user's prompt directly.\n"
|
|
158
|
-
"- If market context is present, cite provider/data-quality limitations.\n"
|
|
159
|
+
"- If market or web context is present, cite provider/data-quality limitations and source URLs when available.\n"
|
|
159
160
|
"- If market context is missing and the user asks about an instrument, say what data is missing.\n"
|
|
160
161
|
"- Keep the coding boundary enforced.\n"
|
|
161
162
|
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def build_web_research_answer_prompt(user_prompt: str, web_context: str) -> str:
|
|
166
|
+
"""Build a prompt that turns gathered web context into an answer, not a source dump."""
|
|
167
|
+
context = web_context.strip() or "Web Research: no public web context returned."
|
|
168
|
+
return (
|
|
169
|
+
f"{FINCLI_ASSISTANT_SYSTEM_PROMPT}\n\n"
|
|
170
|
+
"Web Search Skill Result:\n"
|
|
171
|
+
f"{context}\n\n"
|
|
172
|
+
"User Prompt:\n"
|
|
173
|
+
f"{user_prompt.strip()}\n\n"
|
|
174
|
+
"Instruction:\n"
|
|
175
|
+
"- You already have web search context above. Do not answer by only listing articles or links.\n"
|
|
176
|
+
"- Synthesize the sources into a useful explanation/summary for the user.\n"
|
|
177
|
+
"- Prioritize facts found in the web context, then clearly label interpretation.\n"
|
|
178
|
+
"- If sources disagree or are thin, say that the evidence is limited.\n"
|
|
179
|
+
"- Use this output structure when relevant:\n"
|
|
180
|
+
" 1. Ringkasan singkat\n"
|
|
181
|
+
" 2. Poin utama/penyebab\n"
|
|
182
|
+
" 3. Dampak atau implikasi\n"
|
|
183
|
+
" 4. Risiko dan hal yang perlu diverifikasi\n"
|
|
184
|
+
" 5. Sumber singkat\n"
|
|
185
|
+
"- Keep source citations compact: source title or URL only where useful.\n"
|
|
186
|
+
"- Do not provide financial advice or certainty about market direction.\n"
|
|
187
|
+
)
|
|
@@ -26,7 +26,7 @@ class TechnicalSummary:
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def phase_one_indicator_status() -> str:
|
|
29
|
-
return "Indicator engine
|
|
29
|
+
return "Indicator engine active: SMA, EMA, RSI, MACD, Bollinger Bands, ATR, volume, support, and resistance."
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def summarize_technical_indicators(candles: list[Candle]) -> TechnicalSummary:
|
|
@@ -20,7 +20,7 @@ class MarketStructureSummary:
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def phase_one_structure_status() -> str:
|
|
23
|
-
return "Market structure
|
|
23
|
+
return "Market structure engine active: HH/HL/LH/LL, BOS, CHoCH, liquidity area, and risk zone."
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def analyze_market_structure(candles: list[Candle], lookback: int = 20) -> MarketStructureSummary:
|
|
@@ -17,9 +17,13 @@ COMMANDS: tuple[CommandSpec, ...] = (
|
|
|
17
17
|
CommandSpec("/help", "Tampilkan bantuan, command list, dan contoh.", "/help"),
|
|
18
18
|
CommandSpec("/dashboard", "Tampilkan dashboard compact FinCLI.", "/dashboard", "General"),
|
|
19
19
|
CommandSpec("/ai_model", "Lihat atau ganti AI provider/model.", "/ai_model openrouter openai/gpt-4o-mini", "AI"),
|
|
20
|
+
CommandSpec("/ai_model key", "Simpan API key AI lokal.", "/ai_model key groq <api_key>", "AI"),
|
|
20
21
|
CommandSpec("/news_model", "Buka selector provider market/news dan fallback.", "/news_model", "Provider"),
|
|
22
|
+
CommandSpec("/news_model key", "Simpan API key market/news lokal.", "/news_model key finnhub <api_key>", "Provider"),
|
|
21
23
|
CommandSpec("/market", "Ringkasan market profesional untuk instrumen.", "/market AAPL 1d", "Market"),
|
|
22
24
|
CommandSpec("/news", "Tampilkan news/fundamental terbaru untuk instrumen.", "/news AAPL", "Market"),
|
|
25
|
+
CommandSpec("/web", "Web search lalu AI merangkum jawaban.", "/web penyebab rupiah melemah hari ini", "Research"),
|
|
26
|
+
CommandSpec("/web sources", "Tampilkan sumber mentah hasil web search.", "/web sources penyebab rupiah melemah hari ini", "Research"),
|
|
23
27
|
CommandSpec("/technical", "Analisis teknikal instrumen.", "/technical BTC-USD 1d", "Analysis"),
|
|
24
28
|
CommandSpec("/structure", "Analisis struktur pasar instrumen.", "/structure BTC-USD 1d", "Analysis"),
|
|
25
29
|
CommandSpec("/funda", "Fundamental ringkas instrumen.", "/funda MSFT", "Market"),
|
|
@@ -39,9 +43,13 @@ COMMANDS: tuple[CommandSpec, ...] = (
|
|
|
39
43
|
CommandSpec("/journal add", "Tambahkan catatan journal singkat.", '/journal add BTC-USD bullish "Breakout gagal, tunggu konfirmasi"', "Journal"),
|
|
40
44
|
CommandSpec("/journal stats", "Tampilkan statistik journal.", "/journal stats", "Journal"),
|
|
41
45
|
CommandSpec("/journal review", "AI review kebiasaan journal.", "/journal review", "Journal"),
|
|
46
|
+
CommandSpec("/history", "Tampilkan command history current session.", "/history", "History"),
|
|
47
|
+
CommandSpec("/history sessions", "Tampilkan daftar session tersimpan.", "/history sessions", "History"),
|
|
48
|
+
CommandSpec("/history show", "Tampilkan detail session tertentu.", "/history show <session_id>", "History"),
|
|
49
|
+
CommandSpec("/history save", "Beri nama current session.", '/history save "Riset IHSG pagi"', "History"),
|
|
50
|
+
CommandSpec("/history delete", "Hapus session tertentu.", "/history delete <session_id>", "History"),
|
|
42
51
|
CommandSpec("/config", "Tampilkan konfigurasi aktif tanpa membocorkan API key.", "/config"),
|
|
43
|
-
CommandSpec("/
|
|
44
|
-
CommandSpec("/quote", "Alias harga/quote instrumen.", "/quote NVDA", "Market"),
|
|
52
|
+
CommandSpec("/quote", "Tampilkan harga/quote instrumen.", "/quote NVDA", "Market"),
|
|
45
53
|
CommandSpec("/scan", "Scanner watchlist dengan filter indikator.", "/scan watchlist rsi<30", "Market"),
|
|
46
54
|
CommandSpec("/calendar", "Economic calendar provider/fallback.", "/calendar week US high", "Market"),
|
|
47
55
|
CommandSpec("/provider status", "Tampilkan status provider aktif.", "/provider status", "Provider"),
|
|
@@ -50,8 +58,8 @@ COMMANDS: tuple[CommandSpec, ...] = (
|
|
|
50
58
|
CommandSpec("/provider key status", "Tampilkan status API key market provider.", "/provider key status", "Provider"),
|
|
51
59
|
CommandSpec("/cache stats", "Tampilkan statistik cache market persistent.", "/cache stats", "System"),
|
|
52
60
|
CommandSpec("/cache clear", "Bersihkan runtime dan persistent market cache.", "/cache clear", "System"),
|
|
53
|
-
CommandSpec("/export journal", "Export journal
|
|
54
|
-
CommandSpec("/export portfolio", "Export portfolio
|
|
61
|
+
CommandSpec("/export journal", "Export journal ke CSV/JSON.", "/export journal csv journal.csv", "Export"),
|
|
62
|
+
CommandSpec("/export portfolio", "Export portfolio ke CSV/JSON.", "/export portfolio json portfolio.json", "Export"),
|
|
55
63
|
CommandSpec("/clear", "Bersihkan output terminal.", "/clear"),
|
|
56
64
|
CommandSpec("/exit", "Keluar dari aplikasi.", "/exit"),
|
|
57
65
|
)
|