{
  "schemaVersion": "1.0",
  "item": {
    "slug": "portfolio-trader",
    "name": "Portfolio Trader",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/brendanwood/portfolio-trader",
    "canonicalUrl": "https://clawhub.ai/brendanwood/portfolio-trader",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/portfolio-trader",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=portfolio-trader",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "requirements.txt",
      "references/connection-portal.md",
      "references/webhooks.md",
      "references/getting-started.md",
      "references/api-reference.md",
      "scripts/snaptrade_portal.py"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/portfolio-trader"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/portfolio-trader",
    "agentPageUrl": "https://openagent3.xyz/skills/portfolio-trader/agent",
    "manifestUrl": "https://openagent3.xyz/skills/portfolio-trader/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/portfolio-trader/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Overview",
        "body": "Connect brokerage accounts through SnapTrade and generate a daily total-value report. This skill uses the official SnapTrade Python SDK (snaptrade_client) with request signing handled automatically."
      },
      {
        "title": "2d) Place buy/sell orders (stocks/ETFs)",
        "body": "Run:\n\npython3 scripts/snaptrade_order.py buy|sell TICKER UNITS --account-id <ACCOUNT_ID> [--order-type market|limit] [--limit-price <PRICE>] [--tif Day|GTC|IOC|FOK]\n\nDefaults:\n\norder type: market\ntime in force: Day\nlimit price: only required for limit orders\n\nOptional monitoring (poll recent orders):\n\npython3 scripts/snaptrade_order.py buy|sell TICKER UNITS --account-id <ACCOUNT_ID> --watch\n\npolls every 10s for up to 120s by default\nadjust with --watch-interval and --watch-seconds\n\nWatch an existing order by ID:\n\npython3 scripts/snaptrade_watch_order.py --account-id <ACCOUNT_ID> --order-id <BROKERAGE_ORDER_ID>\n\nsame 10s/120s defaults, adjustable with --watch-interval and --watch-seconds\n\nUse account orders endpoint to confirm fills and report open orders to the user when asked."
      },
      {
        "title": "0) Create a SnapTrade account + API keys",
        "body": "You need a SnapTrade account to connect brokerages. Create a free account at https://snaptrade.com, generate your Client ID and Consumer Key, then add them to the skill config."
      },
      {
        "title": "1) Install dependencies",
        "body": "pip3 install -r requirements.txt"
      },
      {
        "title": "2) Configure credentials (one-time)",
        "body": "Store credentials in a local config file (not committed). user_id is generated automatically on first run:\n\n/home/openclaw/.openclaw/workspace/secrets/snaptrade.json\n\nExample:\n\n{\n  \"client_id\": \"YOUR_CLIENT_ID\",\n  \"consumer_key\": \"YOUR_CONSUMER_KEY\",\n  \"user_id\": \"<auto-generated-uuid>\"\n}"
      },
      {
        "title": "2) Register user + generate connection portal link",
        "body": "Run:\n\npython3 scripts/snaptrade_portal.py\n\nThis will:\n\nregister the user if user_secret is missing\nstore user_secret back into the config file\nprint a connection portal URL the user must open to link accounts"
      },
      {
        "title": "2b) Reconnect a disabled connection",
        "body": "Run:\n\npython3 scripts/snaptrade_reconnect.py [brokerage-name]\n\nThis will:\n\nlist disabled connections\ngenerate a reconnect link (optionally match by brokerage name)\nprint a reconnect URL for the user to re‑enable the connection"
      },
      {
        "title": "2c) List available brokerages (allowed connections)",
        "body": "Run:\n\npython3 scripts/snaptrade_brokers.py\n\nThis calls /snaptrade/partners and returns the allowed_brokerages list (display names)."
      },
      {
        "title": "3) Pull total portfolio value",
        "body": "Run:\n\npython3 scripts/snaptrade_total.py\n\nOutput is JSON like:\n\n{\"total_value\": 123456.78, \"currency\": \"CAD\"}"
      },
      {
        "title": "3b) Per-broker totals (converted currency)",
        "body": "Run:\n\npython3 scripts/snaptrade_broker_totals.py --currency CAD\n\nOutput JSON includes per-broker totals in the chosen currency and the FX rates used.\n\nImplementation notes: Avoid get_user_holdings when possible. Prefer get_user_account_positions (positions endpoint) for holdings/positions data. Only use balances/cash from holdings if explicitly required by the user; otherwise do not call holdings."
      },
      {
        "title": "4) Schedule daily report",
        "body": "Use cron to call snaptrade_total.py, format a concise WhatsApp message, then send it to the user. Only the total value is required."
      },
      {
        "title": "Scripts",
        "body": "scripts/snaptrade_common.py — config load/save + client creation\nscripts/snaptrade_portal.py — register user + generate connection portal link\nscripts/snaptrade_reconnect.py — generate reconnect link for disabled connections\nscripts/snaptrade_brokers.py — list allowed brokerages for this client\nscripts/snaptrade_order.py — place buy/sell orders (market/limit) with optional monitoring\nscripts/snaptrade_watch_order.py — watch an existing order by ID for fills\nscripts/snaptrade_total.py — compute total value across all accounts\nscripts/snaptrade_broker_totals.py — per-broker totals with FX conversion"
      },
      {
        "title": "Notes",
        "body": "Request signing is handled by the SDK via request_after_hook using consumer_key.\nThe total is computed by summing each account’s account.balance.total from holdings; this avoids errors when accounts are added or removed.\nIf multiple currencies are present, the script uses the first currency encountered.\nKeep secrets in the local config file with chmod 600 permissions."
      }
    ],
    "body": "SnapTrade Portfolio\nOverview\n\nConnect brokerage accounts through SnapTrade and generate a daily total-value report. This skill uses the official SnapTrade Python SDK (snaptrade_client) with request signing handled automatically.\n\nWorkflow\n2d) Place buy/sell orders (stocks/ETFs)\n\nRun:\n\npython3 scripts/snaptrade_order.py buy|sell TICKER UNITS --account-id <ACCOUNT_ID> [--order-type market|limit] [--limit-price <PRICE>] [--tif Day|GTC|IOC|FOK]\n\n\nDefaults:\n\norder type: market\ntime in force: Day\nlimit price: only required for limit orders\n\nOptional monitoring (poll recent orders):\n\npython3 scripts/snaptrade_order.py buy|sell TICKER UNITS --account-id <ACCOUNT_ID> --watch\n\npolls every 10s for up to 120s by default\nadjust with --watch-interval and --watch-seconds\n\nWatch an existing order by ID:\n\npython3 scripts/snaptrade_watch_order.py --account-id <ACCOUNT_ID> --order-id <BROKERAGE_ORDER_ID>\n\nsame 10s/120s defaults, adjustable with --watch-interval and --watch-seconds\n\nUse account orders endpoint to confirm fills and report open orders to the user when asked.\n\n0) Create a SnapTrade account + API keys\n\nYou need a SnapTrade account to connect brokerages. Create a free account at https://snaptrade.com, generate your Client ID and Consumer Key, then add them to the skill config.\n\n1) Install dependencies\npip3 install -r requirements.txt\n\n2) Configure credentials (one-time)\n\nStore credentials in a local config file (not committed). user_id is generated automatically on first run:\n\n/home/openclaw/.openclaw/workspace/secrets/snaptrade.json\n\n\nExample:\n\n{\n  \"client_id\": \"YOUR_CLIENT_ID\",\n  \"consumer_key\": \"YOUR_CONSUMER_KEY\",\n  \"user_id\": \"<auto-generated-uuid>\"\n}\n\n2) Register user + generate connection portal link\n\nRun:\n\npython3 scripts/snaptrade_portal.py\n\n\nThis will:\n\nregister the user if user_secret is missing\nstore user_secret back into the config file\nprint a connection portal URL the user must open to link accounts\n2b) Reconnect a disabled connection\n\nRun:\n\npython3 scripts/snaptrade_reconnect.py [brokerage-name]\n\n\nThis will:\n\nlist disabled connections\ngenerate a reconnect link (optionally match by brokerage name)\nprint a reconnect URL for the user to re‑enable the connection\n2c) List available brokerages (allowed connections)\n\nRun:\n\npython3 scripts/snaptrade_brokers.py\n\n\nThis calls /snaptrade/partners and returns the allowed_brokerages list (display names).\n\n3) Pull total portfolio value\n\nRun:\n\npython3 scripts/snaptrade_total.py\n\n\nOutput is JSON like:\n\n{\"total_value\": 123456.78, \"currency\": \"CAD\"}\n\n3b) Per-broker totals (converted currency)\n\nRun:\n\npython3 scripts/snaptrade_broker_totals.py --currency CAD\n\n\nOutput JSON includes per-broker totals in the chosen currency and the FX rates used.\n\nImplementation notes: Avoid get_user_holdings when possible. Prefer get_user_account_positions (positions endpoint) for holdings/positions data. Only use balances/cash from holdings if explicitly required by the user; otherwise do not call holdings.\n\n4) Schedule daily report\n\nUse cron to call snaptrade_total.py, format a concise WhatsApp message, then send it to the user. Only the total value is required.\n\nScripts\nscripts/snaptrade_common.py — config load/save + client creation\nscripts/snaptrade_portal.py — register user + generate connection portal link\nscripts/snaptrade_reconnect.py — generate reconnect link for disabled connections\nscripts/snaptrade_brokers.py — list allowed brokerages for this client\nscripts/snaptrade_order.py — place buy/sell orders (market/limit) with optional monitoring\nscripts/snaptrade_watch_order.py — watch an existing order by ID for fills\nscripts/snaptrade_total.py — compute total value across all accounts\nscripts/snaptrade_broker_totals.py — per-broker totals with FX conversion\nNotes\nRequest signing is handled by the SDK via request_after_hook using consumer_key.\nThe total is computed by summing each account’s account.balance.total from holdings; this avoids errors when accounts are added or removed.\nIf multiple currencies are present, the script uses the first currency encountered.\nKeep secrets in the local config file with chmod 600 permissions."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/brendanwood/portfolio-trader",
    "publisherUrl": "https://clawhub.ai/brendanwood/portfolio-trader",
    "owner": "brendanwood",
    "version": "1.1.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/portfolio-trader",
    "downloadUrl": "https://openagent3.xyz/downloads/portfolio-trader",
    "agentUrl": "https://openagent3.xyz/skills/portfolio-trader/agent",
    "manifestUrl": "https://openagent3.xyz/skills/portfolio-trader/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/portfolio-trader/agent.md"
  }
}