taylortrader 0.1.0__tar.gz

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.
Files changed (148) hide show
  1. taylortrader-0.1.0/.env.example +23 -0
  2. taylortrader-0.1.0/.github/dependabot.yml +14 -0
  3. taylortrader-0.1.0/.github/workflows/ci.yml +37 -0
  4. taylortrader-0.1.0/.github/workflows/package.yml +53 -0
  5. taylortrader-0.1.0/.github/workflows/release.yml +57 -0
  6. taylortrader-0.1.0/.gitignore +45 -0
  7. taylortrader-0.1.0/CONTRIBUTING.md +39 -0
  8. taylortrader-0.1.0/LICENSE.md +105 -0
  9. taylortrader-0.1.0/PKG-INFO +265 -0
  10. taylortrader-0.1.0/README.md +230 -0
  11. taylortrader-0.1.0/SECURITY.md +20 -0
  12. taylortrader-0.1.0/assets/logo.svg +7 -0
  13. taylortrader-0.1.0/config.example.toml +129 -0
  14. taylortrader-0.1.0/dashboard/index.html +14 -0
  15. taylortrader-0.1.0/dashboard/package-lock.json +924 -0
  16. taylortrader-0.1.0/dashboard/package.json +24 -0
  17. taylortrader-0.1.0/dashboard/public/favicon.svg +7 -0
  18. taylortrader-0.1.0/dashboard/src/App.tsx +103 -0
  19. taylortrader-0.1.0/dashboard/src/advice.tsx +45 -0
  20. taylortrader-0.1.0/dashboard/src/api.ts +464 -0
  21. taylortrader-0.1.0/dashboard/src/components/AIFields.tsx +63 -0
  22. taylortrader-0.1.0/dashboard/src/components/AIGrades.tsx +139 -0
  23. taylortrader-0.1.0/dashboard/src/components/EquityChart.tsx +207 -0
  24. taylortrader-0.1.0/dashboard/src/components/ErrorBoundary.tsx +26 -0
  25. taylortrader-0.1.0/dashboard/src/components/Header.tsx +246 -0
  26. taylortrader-0.1.0/dashboard/src/components/InvestCard.tsx +62 -0
  27. taylortrader-0.1.0/dashboard/src/components/Keys.tsx +76 -0
  28. taylortrader-0.1.0/dashboard/src/components/ModeDialog.tsx +57 -0
  29. taylortrader-0.1.0/dashboard/src/components/Panels.tsx +451 -0
  30. taylortrader-0.1.0/dashboard/src/components/Sell.tsx +84 -0
  31. taylortrader-0.1.0/dashboard/src/components/StrategyEditor.tsx +299 -0
  32. taylortrader-0.1.0/dashboard/src/components/TradeChart.tsx +392 -0
  33. taylortrader-0.1.0/dashboard/src/components/WhatIf.tsx +165 -0
  34. taylortrader-0.1.0/dashboard/src/components/forms.tsx +163 -0
  35. taylortrader-0.1.0/dashboard/src/format.ts +58 -0
  36. taylortrader-0.1.0/dashboard/src/main.tsx +15 -0
  37. taylortrader-0.1.0/dashboard/src/pages/GuidePage.tsx +189 -0
  38. taylortrader-0.1.0/dashboard/src/pages/InvestPage.tsx +395 -0
  39. taylortrader-0.1.0/dashboard/src/pages/Overview.tsx +70 -0
  40. taylortrader-0.1.0/dashboard/src/pages/SettingsPage.tsx +407 -0
  41. taylortrader-0.1.0/dashboard/src/pages/SetupPage.tsx +102 -0
  42. taylortrader-0.1.0/dashboard/src/pages/SignInPage.tsx +46 -0
  43. taylortrader-0.1.0/dashboard/src/pages/StrategiesPage.tsx +83 -0
  44. taylortrader-0.1.0/dashboard/src/settings.ts +38 -0
  45. taylortrader-0.1.0/dashboard/src/styles.css +812 -0
  46. taylortrader-0.1.0/dashboard/src/useChartWidth.ts +14 -0
  47. taylortrader-0.1.0/dashboard/src/usePoll.ts +70 -0
  48. taylortrader-0.1.0/dashboard/tsconfig.json +17 -0
  49. taylortrader-0.1.0/dashboard/vite.config.ts +12 -0
  50. taylortrader-0.1.0/docs/images/ai-decisions.png +0 -0
  51. taylortrader-0.1.0/docs/images/overview.png +0 -0
  52. taylortrader-0.1.0/docs/images/phone.png +0 -0
  53. taylortrader-0.1.0/docs/images/strategies.png +0 -0
  54. taylortrader-0.1.0/docs/images/trade-chart.gif +0 -0
  55. taylortrader-0.1.0/docs/images/what-if.png +0 -0
  56. taylortrader-0.1.0/docs/proposals/investing.md +154 -0
  57. taylortrader-0.1.0/pyproject.toml +72 -0
  58. taylortrader-0.1.0/scripts/build-release.sh +26 -0
  59. taylortrader-0.1.0/scripts/githooks/pre-commit +4 -0
  60. taylortrader-0.1.0/src/taylortrader/__init__.py +6 -0
  61. taylortrader-0.1.0/src/taylortrader/alerts.py +121 -0
  62. taylortrader-0.1.0/src/taylortrader/app.py +124 -0
  63. taylortrader-0.1.0/src/taylortrader/backtest.py +179 -0
  64. taylortrader-0.1.0/src/taylortrader/broker.py +343 -0
  65. taylortrader-0.1.0/src/taylortrader/chart.py +133 -0
  66. taylortrader-0.1.0/src/taylortrader/cli.py +660 -0
  67. taylortrader-0.1.0/src/taylortrader/config.py +444 -0
  68. taylortrader-0.1.0/src/taylortrader/criteria.py +135 -0
  69. taylortrader-0.1.0/src/taylortrader/data.py +244 -0
  70. taylortrader-0.1.0/src/taylortrader/executor.py +136 -0
  71. taylortrader-0.1.0/src/taylortrader/grading.py +195 -0
  72. taylortrader-0.1.0/src/taylortrader/guardrails/__init__.py +22 -0
  73. taylortrader-0.1.0/src/taylortrader/guardrails/engine.py +106 -0
  74. taylortrader-0.1.0/src/taylortrader/guardrails/invest.py +34 -0
  75. taylortrader-0.1.0/src/taylortrader/guardrails/limits.py +54 -0
  76. taylortrader-0.1.0/src/taylortrader/guardrails/models.py +53 -0
  77. taylortrader-0.1.0/src/taylortrader/home.py +80 -0
  78. taylortrader-0.1.0/src/taylortrader/indicators.py +90 -0
  79. taylortrader-0.1.0/src/taylortrader/invest.py +352 -0
  80. taylortrader-0.1.0/src/taylortrader/journal.py +305 -0
  81. taylortrader-0.1.0/src/taylortrader/launchd.py +146 -0
  82. taylortrader-0.1.0/src/taylortrader/llm.py +286 -0
  83. taylortrader-0.1.0/src/taylortrader/logging_setup.py +59 -0
  84. taylortrader-0.1.0/src/taylortrader/mcp_server.py +391 -0
  85. taylortrader-0.1.0/src/taylortrader/replay.py +191 -0
  86. taylortrader-0.1.0/src/taylortrader/report.py +259 -0
  87. taylortrader-0.1.0/src/taylortrader/search.py +312 -0
  88. taylortrader-0.1.0/src/taylortrader/secrets.py +206 -0
  89. taylortrader-0.1.0/src/taylortrader/secretscan.py +126 -0
  90. taylortrader-0.1.0/src/taylortrader/service.py +597 -0
  91. taylortrader-0.1.0/src/taylortrader/stats.py +139 -0
  92. taylortrader-0.1.0/src/taylortrader/strategies/__init__.py +7 -0
  93. taylortrader-0.1.0/src/taylortrader/strategies/ai.py +253 -0
  94. taylortrader-0.1.0/src/taylortrader/strategies/base.py +83 -0
  95. taylortrader-0.1.0/src/taylortrader/strategies/builtin.py +267 -0
  96. taylortrader-0.1.0/src/taylortrader/strategies/registry.py +33 -0
  97. taylortrader-0.1.0/src/taylortrader/strategies/rule.py +49 -0
  98. taylortrader-0.1.0/src/taylortrader/web/__init__.py +0 -0
  99. taylortrader-0.1.0/src/taylortrader/web/api.py +978 -0
  100. taylortrader-0.1.0/src/taylortrader/web/remote.py +142 -0
  101. taylortrader-0.1.0/src/taylortrader/web/runtime.py +80 -0
  102. taylortrader-0.1.0/src/taylortrader/web/static/assets/index-CT_-f4CD.js +9 -0
  103. taylortrader-0.1.0/src/taylortrader/web/static/assets/index-DSHKlv3w.css +1 -0
  104. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-cyrillic-400-normal-BCR-5knY.woff2 +0 -0
  105. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-cyrillic-400-normal-Br6HGNtH.woff +0 -0
  106. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-cyrillic-600-normal-BK9F1QH4.woff2 +0 -0
  107. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-cyrillic-600-normal-DfZOe4kq.woff +0 -0
  108. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-latin-400-normal-DM4nBGIh.woff +0 -0
  109. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-latin-400-normal-DZsjfPjH.woff2 +0 -0
  110. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-latin-600-normal-BlUmYrg6.woff2 +0 -0
  111. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-latin-600-normal-CDEEqth2.woff +0 -0
  112. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-latin-ext-400-normal-CBFElp5P.woff +0 -0
  113. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-latin-ext-400-normal-CqsZQCXg.woff2 +0 -0
  114. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-latin-ext-600-normal-B7SJLXMk.woff2 +0 -0
  115. taylortrader-0.1.0/src/taylortrader/web/static/assets/martian-mono-latin-ext-600-normal-DcTSv0-g.woff +0 -0
  116. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-400-normal-BkiRe4WW.woff +0 -0
  117. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-400-normal-DPhJBilQ.woff2 +0 -0
  118. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-600-normal-BieE9YjJ.woff +0 -0
  119. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-600-normal-Czv9Obfv.woff2 +0 -0
  120. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-800-normal-CIaq-TR1.woff2 +0 -0
  121. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-800-normal-Dl5-MP1T.woff +0 -0
  122. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-ext-400-normal-DHVTfbSM.woff2 +0 -0
  123. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-ext-400-normal-DUPvg9bQ.woff +0 -0
  124. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-ext-600-normal-C5pQPdUJ.woff2 +0 -0
  125. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-ext-600-normal-DQsnXf5q.woff +0 -0
  126. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-ext-800-normal-CZWJQj-F.woff2 +0 -0
  127. taylortrader-0.1.0/src/taylortrader/web/static/assets/schibsted-grotesk-latin-ext-800-normal-DS3YHxa9.woff +0 -0
  128. taylortrader-0.1.0/src/taylortrader/web/static/favicon.svg +7 -0
  129. taylortrader-0.1.0/src/taylortrader/web/static/index.html +15 -0
  130. taylortrader-0.1.0/src/taylortrader/whatif.py +92 -0
  131. taylortrader-0.1.0/tests/__init__.py +0 -0
  132. taylortrader-0.1.0/tests/test_ai.py +267 -0
  133. taylortrader-0.1.0/tests/test_cli.py +125 -0
  134. taylortrader-0.1.0/tests/test_data_feeds.py +124 -0
  135. taylortrader-0.1.0/tests/test_grading.py +180 -0
  136. taylortrader-0.1.0/tests/test_guardrails.py +85 -0
  137. taylortrader-0.1.0/tests/test_invest.py +405 -0
  138. taylortrader-0.1.0/tests/test_launchd.py +61 -0
  139. taylortrader-0.1.0/tests/test_mcp.py +194 -0
  140. taylortrader-0.1.0/tests/test_replay.py +117 -0
  141. taylortrader-0.1.0/tests/test_search.py +196 -0
  142. taylortrader-0.1.0/tests/test_secrets.py +207 -0
  143. taylortrader-0.1.0/tests/test_service.py +887 -0
  144. taylortrader-0.1.0/tests/test_stats.py +38 -0
  145. taylortrader-0.1.0/tests/test_strategies_and_backtest.py +237 -0
  146. taylortrader-0.1.0/tests/test_web.py +657 -0
  147. taylortrader-0.1.0/tests/test_whatif.py +65 -0
  148. taylortrader-0.1.0/uv.lock +1888 -0
@@ -0,0 +1,23 @@
1
+ # Copy to .env (git-ignored) or, better, store these in the macOS Keychain:
2
+ # security add-generic-password -s taylortrader -a ALPACA_PAPER_KEY_ID -w
3
+ # (-w with no value prompts for it, so the secret never lands in shell history)
4
+ #
5
+ # Lookup order for each name: environment variable, then .env, then Keychain (service "taylortrader").
6
+
7
+ ALPACA_PAPER_KEY_ID=
8
+ ALPACA_PAPER_SECRET_KEY=
9
+
10
+ # Live keys are only read when config mode = "live" AND TAYLORTRADER_ALLOW_LIVE=1 (the dashboard sets it when you type GO LIVE).
11
+ ALPACA_LIVE_KEY_ID=
12
+ ALPACA_LIVE_SECRET_KEY=
13
+ # TAYLORTRADER_ALLOW_LIVE=1
14
+
15
+ # Alerts (optional)
16
+ NTFY_TOPIC=
17
+ EMAIL_PASSWORD=
18
+ HEALTHCHECK_URL=
19
+
20
+ # AI strategy (optional): the key for the provider set in [ai] in config.toml.
21
+ # A local model (Ollama, LM Studio) needs no key: set [ai] endpoint instead.
22
+ ANTHROPIC_API_KEY=
23
+ OPENAI_API_KEY=
@@ -0,0 +1,14 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ - package-ecosystem: uv
8
+ directory: /
9
+ schedule:
10
+ interval: weekly
11
+ - package-ecosystem: npm
12
+ directory: /dashboard
13
+ schedule:
14
+ interval: weekly
@@ -0,0 +1,37 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ test:
12
+ strategy:
13
+ matrix:
14
+ os: [macos-latest, ubuntu-latest]
15
+ runs-on: ${{ matrix.os }}
16
+ steps:
17
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
18
+ - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
19
+ - run: uv sync --locked
20
+ - run: uv run ruff check src tests
21
+ - run: uv run pytest -q
22
+ # The same secret scan the pre-commit hook runs, over every tracked file.
23
+ - run: uv run python -m taylortrader.secretscan
24
+
25
+ dashboard:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
29
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
30
+ with:
31
+ node-version: 22
32
+ cache: npm
33
+ cache-dependency-path: dashboard/package-lock.json
34
+ - run: npm ci
35
+ working-directory: dashboard
36
+ - run: npx tsc --noEmit -p . && npm run build
37
+ working-directory: dashboard
@@ -0,0 +1,53 @@
1
+ # Builds the package people install and tests it with the newest dependencies allowed, not uv.lock:
2
+ # that's what a new user gets. Runs weekly so a breaking dependency update shows up here first.
3
+ name: Package
4
+ on:
5
+ schedule:
6
+ - cron: "17 13 * * 1"
7
+ workflow_dispatch:
8
+ workflow_call:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ build:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
18
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
19
+ with:
20
+ node-version: 22
21
+ # No caches in the build that releases ship from: a poisoned cache can't reach a release.
22
+ - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
23
+ with:
24
+ enable-cache: false
25
+ # Also fails if the dashboard is missing or a file that must never ship got in.
26
+ - run: bash scripts/build-release.sh
27
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
28
+ with:
29
+ name: dist
30
+ path: dist/
31
+ if-no-files-found: error
32
+
33
+ test:
34
+ needs: build
35
+ strategy:
36
+ fail-fast: false
37
+ matrix:
38
+ os: [macos-latest, ubuntu-latest]
39
+ python: ["3.12", "3.14"]
40
+ runs-on: ${{ matrix.os }}
41
+ steps:
42
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
43
+ - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
44
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
45
+ with:
46
+ name: dist
47
+ path: dist/
48
+ - run: uv venv --python ${{ matrix.python }} fresh
49
+ - run: uv pip install --python fresh --only-binary ":all:" dist/*.whl pytest httpx
50
+ - name: Tests run against the installed package
51
+ run: |
52
+ fresh/bin/python -c "import taylortrader, sys; assert 'site-packages' in taylortrader.__file__, taylortrader.__file__"
53
+ fresh/bin/python -m pytest -q
@@ -0,0 +1,57 @@
1
+ # Push a tag like v0.1.0 to publish. See CONTRIBUTING.md.
2
+ name: Release
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ version:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
15
+ with:
16
+ fetch-depth: 0
17
+ - name: The tagged commit is on main
18
+ run: git merge-base --is-ancestor "$GITHUB_SHA" origin/main
19
+ - name: The tag matches the version in the code
20
+ run: |
21
+ want="${GITHUB_REF_NAME#v}"
22
+ grep -qx "version = \"$want\"" pyproject.toml
23
+ grep -qx "__version__ = \"$want\"" src/taylortrader/__init__.py
24
+
25
+ package:
26
+ needs: version
27
+ uses: ./.github/workflows/package.yml
28
+
29
+ pypi:
30
+ needs: package
31
+ runs-on: ubuntu-latest
32
+ environment: pypi
33
+ permissions:
34
+ id-token: write # Trusted Publishing: a short-lived login from GitHub, no stored token
35
+ steps:
36
+ - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
37
+ with:
38
+ enable-cache: false
39
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
40
+ with:
41
+ name: dist
42
+ path: dist/
43
+ - run: uv publish --trusted-publishing always
44
+
45
+ github-release:
46
+ needs: pypi
47
+ runs-on: ubuntu-latest
48
+ permissions:
49
+ contents: write
50
+ steps:
51
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
52
+ with:
53
+ name: dist
54
+ path: dist/
55
+ - run: gh release create "$GITHUB_REF_NAME" dist/* --repo "$GITHUB_REPOSITORY" --generate-notes
56
+ env:
57
+ GH_TOKEN: ${{ github.token }}
@@ -0,0 +1,45 @@
1
+ # --- Secrets: never commit ---
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+ *.pem
6
+ *.key
7
+ secrets/
8
+ # Local config may hold account-specific settings; commit config.example.toml instead
9
+ config.toml
10
+
11
+ # --- Runtime data: market data cache, trade journal, logs ---
12
+ var/
13
+ *.db
14
+ *.sqlite
15
+ *.sqlite3
16
+ *.parquet
17
+ *.log
18
+ cache/
19
+ logs/
20
+
21
+ # --- Python ---
22
+ __pycache__/
23
+ *.py[cod]
24
+ .venv/
25
+ .pytest_cache/
26
+ .ruff_cache/
27
+ dist/
28
+ build/
29
+ *.egg-info/
30
+
31
+ # --- Dashboard ---
32
+ node_modules/
33
+ src/taylortrader/web/static/
34
+
35
+ # --- OS / editors ---
36
+ .DS_Store
37
+ .idea/
38
+ .vscode/
39
+
40
+ # Local notes
41
+ docs/journal/
42
+ config.toml.bak
43
+ config.tmp
44
+ *.toml.tmp
45
+ *.bak
@@ -0,0 +1,39 @@
1
+ # Contributing
2
+
3
+ Bug reports, ideas and fixes are welcome. For anything large, open an issue first so we can agree on
4
+ the approach before you spend time on it.
5
+
6
+ ## Setup
7
+
8
+ ```sh
9
+ uv sync
10
+ git config core.hooksPath scripts/githooks # scans each commit for secrets
11
+ uv run pytest -q
12
+ uv run ruff check src tests
13
+ ```
14
+
15
+ The hooks setting turns on the pre-commit secret scan, which catches keys before they get into a commit. Run the
16
+ tests and the linter before you open a pull request; CI runs both.
17
+
18
+ The dashboard is in `dashboard/` (`npm install`, then `npm run build`).
19
+
20
+ ## Ground rules
21
+
22
+ - Safety first: every strategy buy has a stop-loss held at the broker, and nothing goes around the guardrails.
23
+ - Never commit keys, account numbers or real trading records.
24
+ - New behavior comes with tests. Anything that claims a strategy works needs the holdout and luck test.
25
+ - Use your own paper account, never live, while developing.
26
+
27
+ ## Your contribution
28
+
29
+ By submitting a contribution, you confirm it's your own work, and you agree that it's licensed under
30
+ this project's [license](LICENSE.md) and that the project's owner may also use, relicense and sell it
31
+ as part of TaylorTrader, including in paid versions. You keep the copyright to your work.
32
+
33
+ ## Releasing (maintainer)
34
+ 1. Set the same new version in `pyproject.toml` and `src/taylortrader/__init__.py`, and commit.
35
+ 2. `git tag v0.1.0 && git push origin v0.1.0`
36
+
37
+ The Release workflow builds the package with the dashboard inside, installs it fresh, runs the tests,
38
+ publishes to PyPI and creates a GitHub Release. PyPI versions can't be reused, so a bad release gets
39
+ a new version number. Publishing uses PyPI Trusted Publishing, so there's no token to store.
@@ -0,0 +1,105 @@
1
+ # Functional Source License, Version 1.1, ALv2 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-ALv2
6
+
7
+ ## Notice
8
+
9
+ Copyright 2026 Brandon Taylor
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
@@ -0,0 +1,265 @@
1
+ Metadata-Version: 2.5
2
+ Name: taylortrader
3
+ Version: 0.1.0
4
+ Summary: A safety-first trading bot and scheduled long-term investing for Alpaca, with a local dashboard.
5
+ Project-URL: Homepage, https://github.com/brandonmtaylor/taylor-trader
6
+ Project-URL: Source, https://github.com/brandonmtaylor/taylor-trader
7
+ Project-URL: Issues, https://github.com/brandonmtaylor/taylor-trader/issues
8
+ Project-URL: Releases, https://github.com/brandonmtaylor/taylor-trader/releases
9
+ Project-URL: Security, https://github.com/brandonmtaylor/taylor-trader/security/policy
10
+ Author: Brandon Taylor
11
+ License-Expression: FSL-1.1-ALv2
12
+ License-File: LICENSE.md
13
+ Keywords: alpaca,backtesting,investing,trading,trading-bot
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: End Users/Desktop
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Office/Business :: Financial :: Investment
22
+ Requires-Python: >=3.12
23
+ Requires-Dist: alpaca-py==0.44.0
24
+ Requires-Dist: anthropic<3,>=2.4
25
+ Requires-Dist: fastapi<1,>=0.115
26
+ Requires-Dist: mcp<3,>=2.3
27
+ Requires-Dist: numpy<3,>=2.0
28
+ Requires-Dist: openai<4,>=1.50
29
+ Requires-Dist: pandas<4,>=2.2
30
+ Requires-Dist: pyarrow>=17
31
+ Requires-Dist: pydantic<3,>=2.7
32
+ Requires-Dist: uvicorn<1,>=0.32
33
+ Requires-Dist: yfinance==1.7.0
34
+ Description-Content-Type: text/markdown
35
+
36
+ # TaylorTrader
37
+
38
+ **Set your strategies once, and let the bot watch the market for you.** TaylorTrader runs on your own
39
+ computer and trades your [Alpaca](https://alpaca.markets) account automatically: it checks prices all
40
+ day, buys and sells when your strategies say so, protects those trades with stop-losses, and tells you
41
+ what it did. Mix short-term trading strategies, an AI that makes the calls, and long-term investing on
42
+ a schedule. No staring at charts.
43
+
44
+ ![The TaylorTrader dashboard: account value, the bot's heartbeat, and growth of $100 against SPY](https://raw.githubusercontent.com/brandonmtaylor/taylor-trader/main/docs/images/overview.png)
45
+
46
+ - **Runs on its own.** Once it's set up, it trades and invests by itself during market hours, checks
47
+ that every position is protected, and sends you a summary after each close. You step in only when
48
+ you want to.
49
+ - **Talk to it from Claude.** Describe an idea in plain English and Claude turns it into rules,
50
+ backtests them against buying and holding, and adds the strategy when you say so. Ask how it's
51
+ doing, pause it, or move a stock to another strategy, all in conversation.
52
+ - **An AI strategy that shows its work.** A language model decides buy, sell or hold, and explains
53
+ every call with its confidence, pros and cons. A report card grades each call against what happened next.
54
+ - **Strategies without code.** Pick a built-in, or write rules like `close > ma_50 and rsi < 40`, and
55
+ backtest them in a click.
56
+ - **Scheduled investing.** Put a set amount into a mix of funds every week or month, kept in balance,
57
+ and see first how that plan would have done over the last 10 years.
58
+ - **On your phone.** Open the dashboard from your phone on your Wi-Fi, and get alerts for every buy,
59
+ sell and problem.
60
+ - **Safety first.** Stop-losses held at Alpaca, limits on every order, and paper trading until you
61
+ choose otherwise.
62
+
63
+ > **Not financial advice.** It trades on **paper** (simulated money) until you switch to live yourself.
64
+ > Trading can lose money, and you're responsible for every order it places. Provided as is, with no
65
+ > warranty (see the [license](https://github.com/brandonmtaylor/taylor-trader/blob/main/LICENSE.md)).
66
+
67
+ **Status:** early, and in a paper-trading trial.
68
+
69
+ ## A quick tour
70
+
71
+ **Ask Claude.** With the MCP server connected, for example:
72
+ ```text
73
+ You: Add a strategy for NVDA and AMD: buy when they pull back to the 50-day average with RSI
74
+ under 40, sell when RSI goes over 70.
75
+ Claude: Writes the rules, backtests them on both stocks against buying and holding, shows you
76
+ the results, and adds the strategy once you say so.
77
+ ```
78
+
79
+ **Every trade on the chart.** Each buy and sell, the stop-loss, and how much of the move each sell kept.
80
+ Hover for any bar's price, and add moving averages, RSI and MACD.
81
+
82
+ ![The trade chart: hovering shows each bar's price; the 20-bar average, RSI and MACD are switched on, then the range changes to 3 months](https://raw.githubusercontent.com/brandonmtaylor/taylor-trader/main/docs/images/trade-chart.gif)
83
+
84
+ **The AI's reasoning, call by call.**
85
+
86
+ ![AI decisions: each call with its confidence and a one-line reason](https://raw.githubusercontent.com/brandonmtaylor/taylor-trader/main/docs/images/ai-decisions.png)
87
+
88
+ **What if you'd started 10 years ago?** Your investing plan, run on real past prices for each mix.
89
+
90
+ ![What if you'd started 10 years ago: $200 a month in each ready-made mix, run on real past prices](https://raw.githubusercontent.com/brandonmtaylor/taylor-trader/main/docs/images/what-if.png)
91
+
92
+ <table>
93
+ <tr>
94
+ <td width="62%"><img alt="The Strategies page: strategy, symbols, bar size, position size, stop-loss and a one-click backtest" src="https://raw.githubusercontent.com/brandonmtaylor/taylor-trader/main/docs/images/strategies.png"></td>
95
+ <td width="38%"><img alt="The dashboard on a phone, over the home Wi-Fi" src="https://raw.githubusercontent.com/brandonmtaylor/taylor-trader/main/docs/images/phone.png"></td>
96
+ </tr>
97
+ <tr>
98
+ <td>Set up strategies and backtest them against buying and holding, without code.</td>
99
+ <td>Open it from your phone on the same Wi-Fi, with a passcode.</td>
100
+ </tr>
101
+ </table>
102
+
103
+ ## Install
104
+ **Platforms:** macOS is fully supported. Linux runs the dashboard, backtests and a foreground
105
+ `taylortrader run`, with keys in a `.env` file; running in the background is set up for macOS only so
106
+ far. Windows isn't supported.
107
+
108
+ You need a free [Alpaca](https://app.alpaca.markets/signup) paper account (email only, no money).
109
+ ```bash
110
+ curl -LsSf https://astral.sh/uv/install.sh | sh # once, if you don't have uv
111
+ uv tool install taylortrader
112
+ taylortrader # opens the dashboard and walks you through setup
113
+ ```
114
+ Setup takes about ten minutes: connect your Alpaca paper keys, pick a strategy and backtest it, check
115
+ the safety limits, optionally add phone or email alerts, and start the bot in **dry run** (it decides
116
+ and alerts, but places no orders). Then switch between Dry run, Paper and Live at the top of the page.
117
+
118
+ Settings, the trade journal and logs live in `~/Library/Application Support/TaylorTrader` on macOS
119
+ (`~/.local/share/taylortrader` on Linux). Update with `uv tool upgrade taylortrader`. The dashboard's
120
+ **Guide** page explains everything in plain language.
121
+
122
+ ### Does my computer need to stay on?
123
+ The bot only checks prices while your computer is awake, so a Mac that stays on (a Mac mini, or a
124
+ laptop left plugged in and open) works best. On a laptop that sleeps:
125
+ - Your stop-losses keep protecting open positions, because they're held at Alpaca, not on your computer.
126
+ - Strategies on daily bars miss little; ones on 1- to 15-minute bars miss whatever happens while it sleeps.
127
+ - The invest plan catches up: a buy that comes due while the laptop is asleep goes in when it wakes.
128
+ - The watchdog may send a "not running" alert after the laptop wakes up.
129
+
130
+ ### From your phone
131
+ `taylortrader wifi on` prints a passcode and the address to open (`http://<your-mac>.local:8787`).
132
+ Each device signs in once and stays signed in for 30 days. Going live, changing API keys, and turning
133
+ real-money buying back on after a pause only work on the Mac itself. It's plain http, so use it on a
134
+ home network you trust; for anywhere else, put the Mac and phone on [Tailscale](https://tailscale.com).
135
+ `wifi off` closes it again.
136
+
137
+ ## Talk to it from Claude (MCP)
138
+ TaylorTrader includes an MCP server, so Claude Code or the Claude desktop app can check on the bot and
139
+ adjust it: "how did the AI strategy do this week?", "move PLTR to macd_rsi", "backtest rsi_14 on NVDA
140
+ hourly", or describe an idea and let Claude write the rules and test it. It's optional; the bot runs
141
+ the same without it.
142
+
143
+ - **Claude Code:** [install it](https://claude.com/claude-code), then run once:
144
+ ```bash
145
+ claude mcp add taylortrader --scope user -- taylortrader mcp
146
+ ```
147
+ - **Claude desktop app:** Settings, then Developer, then Edit Config. Add this to the file (merge it if
148
+ it already has `mcpServers`) and reopen the app:
149
+ ```json
150
+ { "mcpServers": { "taylortrader": { "command": "/full/path/to/taylortrader", "args": ["mcp"] } } }
151
+ ```
152
+ The desktop app needs the full path (`which taylortrader` prints it).
153
+
154
+ The dashboard's **Settings** page, under Claude, shows both filled in for your computer, with copy
155
+ buttons. Then ask Claude "how's my trading bot doing?" to check it's connected. The dashboard doesn't
156
+ need to be open.
157
+
158
+ It uses the same rules as the dashboard: every change is checked, hard limits still apply, and changes
159
+ are logged as coming from Claude. It can't go live, read or change keys, loosen limits on a live
160
+ account, or turn buying back on after you pause it. Selling on a live account is off unless you turn
161
+ on **Let Claude sell on a live account** in Settings, on your Mac.
162
+
163
+ ## AI strategy (experimental)
164
+ `ai` asks a language model whether to buy, sell or hold, using your plain-English instructions, recent
165
+ bars, indicators, and optionally the last 3 days of news. It works with:
166
+ - **Your Claude subscription** through [Claude Code](https://claude.com/claude-code) (`claude -p`, with
167
+ no tools and none of your own settings). No API key; calls count toward your plan.
168
+ - **The Claude API**, billed per call. The sturdier choice for running unattended.
169
+ - **Any OpenAI-compatible API**: OpenAI, OpenRouter, Groq, or a free local model through Ollama or
170
+ LM Studio.
171
+
172
+ The model only proposes. Position size, the stop-loss and every limit still apply, and an error, an
173
+ off-menu answer or low confidence means hold. A daily call limit caps cost.
174
+
175
+ It can't be backtested honestly, so the backtester refuses it: try it in dry run, then on paper.
176
+ `taylortrader replay` tests it on past bars with each stock disguised, so the model can't recall what
177
+ happened next.
178
+
179
+ ## Strategies
180
+ Built-ins: `macd_rsi`, `macd`, `ma_20`, `rsi_14`, `ma_20_rsi`, `ma_200_rsi`, `ma_20_over_200_rsi`,
181
+ `chaikin`, `pullback`. Each symbol belongs to one strategy, so
182
+ it's always clear who manages a position.
183
+
184
+ Or write your own with `rule`: a buy rule and a sell rule, like `close > ma_50 and rsi < 40` or
185
+ `close > prev_high_20`. Rules can use price, volume, MACD and Chaikin, plus these at any length up to
186
+ 250 bars: `ma_N`, `ema_N`, `high_N`, `low_N`, `change_N` (percent), `avg_volume_N`, `rsi_N`, `atr_N`.
187
+ Rules are parsed, never run as code.
188
+
189
+ **Test an idea before trusting it.** The backtester always compares against buying and holding.
190
+ `taylortrader search` goes further: it tunes on older data, then tests once on held-back data, and
191
+ checks the result against random entries, so luck doesn't pass for skill.
192
+
193
+ ## Long-term investing
194
+ An **invest plan** puts a set amount into a fixed mix of funds on a schedule (say $200 a month into US
195
+ stocks, international stocks and bonds) and holds it.
196
+ - Each contribution goes to whatever is furthest under its target first, so new money keeps the mix
197
+ balanced without selling. Fractional shares, so any amount splits exactly.
198
+ - A period is never bought twice, even across restarts: each buy is recorded first and carries an
199
+ order id Alpaca won't accept twice.
200
+ - It invests cash already in your Alpaca account; it can't move money from your bank.
201
+ - Start in preview: it alerts what it would buy and places nothing. Buying for real asks you to type
202
+ the amount and schedule.
203
+
204
+ The ready-made mixes are examples, not recommendations. What's built and what's planned is in the
205
+ [investing proposal](https://github.com/brandonmtaylor/taylor-trader/blob/main/docs/proposals/investing.md).
206
+
207
+ ## Safety limits
208
+ - **Stop-losses live at the broker.** Every strategy buy is a bracket order with a stop-loss held by
209
+ Alpaca, so the stop still works if TaylorTrader or your computer stops. A stop limits losses but can
210
+ fill below its price when a stock gaps down or moves fast. (The invest plan doesn't use stops: holding
211
+ through dips is its point.)
212
+ - **Every order is checked** against position size, total exposure, daily loss, buys per day, stop
213
+ width, and a pause switch. Settings can tighten the built-in hard limits but never loosen them.
214
+ Sells are never blocked.
215
+ - **It only manages what it bought.** Shares you already owned aren't touched, even if you add the
216
+ symbol to a strategy.
217
+ - **Keys stay secret.** They live in the macOS Keychain (or a private `.env` file elsewhere), are
218
+ masked in logs, and the dashboard never shows them again. Config files with secret-looking values
219
+ are rejected.
220
+ - **Real money needs two steps:** live keys that open an active account, and typing `GO LIVE` in the
221
+ dashboard on your Mac.
222
+ - **It tells you when something's wrong:** a missing stop, a refused order, prices that stopped
223
+ arriving, a strategy that hasn't traded in two weeks, or the bot itself going quiet.
224
+
225
+ ## Command line
226
+ Everything the dashboard does also works from a terminal:
227
+ ```bash
228
+ taylortrader doctor # settings, credentials (found or missing), secret scan
229
+ taylortrader strategies # what you can pick
230
+ taylortrader backtest VRT --strategy macd_rsi --timeframe 5Min --days 365
231
+ taylortrader account # read-only: positions, stops, positions it doesn't manage
232
+ taylortrader alerts-test # push and email test
233
+ taylortrader run --dry-run --once # one check: decides and alerts, places no orders
234
+ taylortrader kill on # pause new buys; sells and stops keep working
235
+ taylortrader journal # recent orders and the heartbeat
236
+ taylortrader dashboard --background # keep the dashboard running (also --restart, --stop)
237
+ taylortrader wifi on # open it to your phone on the same Wi-Fi
238
+ ```
239
+ Settings live in `config.toml` with no secrets in it;
240
+ [config.example.toml](https://github.com/brandonmtaylor/taylor-trader/blob/main/config.example.toml)
241
+ explains each one. The bot notices a saved change and restarts itself with it, and a file with a
242
+ mistake in it is reported and ignored.
243
+
244
+ **Price data:** `feed = "yahoo"` (the default) covers every exchange and is current, but unofficial;
245
+ the bot switches to Alpaca IEX on its own if Yahoo fails or falls behind. `"iex"` is Alpaca, real
246
+ time, one exchange. Backtests use Alpaca's full-market (SIP) history.
247
+
248
+ ## From source
249
+ ```bash
250
+ git clone https://github.com/brandonmtaylor/taylor-trader && cd taylor-trader
251
+ uv sync
252
+ cd dashboard && npm install && npm run build && cd .. # once, and after UI changes
253
+ uv run taylortrader # uses this folder for settings and data
254
+ ```
255
+ In a checkout, put `uv run` in front of every command above. See
256
+ [CONTRIBUTING.md](https://github.com/brandonmtaylor/taylor-trader/blob/main/CONTRIBUTING.md) to help
257
+ out, and [SECURITY.md](https://github.com/brandonmtaylor/taylor-trader/blob/main/SECURITY.md) to report
258
+ a problem privately.
259
+
260
+ ## License
261
+ Source-available under the [Functional Source License 1.1, Apache 2.0 future
262
+ license](https://github.com/brandonmtaylor/taylor-trader/blob/main/LICENSE.md) (FSL-1.1-ALv2). Use it,
263
+ change it, run it for yourself, learn from it, contribute: all free. What it doesn't allow is selling
264
+ it, or a product built from it that does the same job, in competition with TaylorTrader. Each version
265
+ becomes plain Apache 2.0 two years after it's released.