Alapaca 交易自动化

高级

这是一个Crypto Trading领域的自动化工作流,包含 19 个节点。主要使用 Code、Wait、Merge、SplitOut、HttpRequest 等节点。 AI驱动的自动化股票交易:集成Alpaca和Google Sheets

前置要求
  • 可能需要目标 API 的认证凭证
  • Google Sheets API 凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "6Bn6KSpg1le9mG4Y",
  "meta": {
    "instanceId": "34d07950904120624117fd89d9d9b4f13d9fa466720a0972ac5aa843f9eb8cb8",
    "templateCredsSetupCompleted": true
  },
  "name": "Alapaca 交易自动化",
  "tags": [],
  "nodes": [
    {
      "id": "1311dd64-4b51-4e2e-ab20-9621e3b41e03",
      "name": "Alpaca-获取账户信息",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -140,
        680
      ],
      "parameters": {
        "url": "https://paper-api.alpaca.markets/v2/account",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth",
        "queryParameters": {
          "parameters": [
            {}
          ]
        }
      },
      "credentials": {
        "httpQueryAuth": {
          "id": "p1dJbEo98pH5SVih",
          "name": "Query Auth account"
        },
        "httpCustomAuth": {
          "id": "cY4cJyCzDnwhbKkw",
          "name": "Custom Auth account"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "1aa8a8aa-b765-4674-9177-15167da914be",
      "name": "Alpaca-提交卖出订单",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1620,
        580
      ],
      "parameters": {
        "url": "=https://paper-api.alpaca.markets/v2/positions/{{$json.asset_id}}",
        "method": "DELETE",
        "options": {},
        "sendBody": true,
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {}
          ]
        },
        "genericAuthType": "httpCustomAuth",
        "queryParameters": {
          "parameters": [
            {}
          ]
        },
        "headerParameters": {
          "parameters": [
            {}
          ]
        }
      },
      "credentials": {
        "httpQueryAuth": {
          "id": "p1dJbEo98pH5SVih",
          "name": "Query Auth account"
        },
        "httpCustomAuth": {
          "id": "cY4cJyCzDnwhbKkw",
          "name": "Custom Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "0d966c99-bf41-4cc6-82de-217e25a7fcf2",
      "name": "Alpaca-提交买入订单",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1620,
        780
      ],
      "parameters": {
        "url": "https://paper-api.alpaca.markets/v2/orders",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "symbol",
              "value": "={{ $json.symbol }}"
            },
            {
              "name": "notional",
              "value": "={{ $json.market_value_per_symbol.toFixed(2) }}"
            },
            {
              "name": "side",
              "value": "buy"
            },
            {
              "name": "type",
              "value": "market"
            },
            {
              "name": "time_in_force",
              "value": "day"
            }
          ]
        },
        "genericAuthType": "httpCustomAuth",
        "queryParameters": {
          "parameters": [
            {}
          ]
        },
        "headerParameters": {
          "parameters": [
            {}
          ]
        }
      },
      "credentials": {
        "httpQueryAuth": {
          "id": "p1dJbEo98pH5SVih",
          "name": "Query Auth account"
        },
        "httpCustomAuth": {
          "id": "cY4cJyCzDnwhbKkw",
          "name": "Custom Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "60ba11a2-065f-453a-b310-4cc65f3b726d",
      "name": "筛选最高情感得分",
      "type": "n8n-nodes-base.code",
      "position": [
        520,
        680
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\n// Sort the array by sentimentScore in descending order\nconst sortedItems = $input.all().sort((a, b) => b.json.sentimentScore - a.json.sentimentScore);\n\n// Get the top 4 items\nconst top4Items = sortedItems.slice(0, 4);\n\n// Return the result in the n8n expected format\nreturn top4Items\n\n\n"
      },
      "typeVersion": 2
    },
    {
      "id": "6f876b15-aeb6-4def-96f1-3ec20b8e4919",
      "name": "读取今日情感得分",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        300,
        680
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{$today}}\n",
              "lookupColumn": "date"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww/edit#gid=0",
          "cachedResultName": "sentiments"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww/edit?usp=drivesdk",
          "cachedResultName": "Stock Sentiment"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "Bpltco7Lqc7P73Qp",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "c4ce7556-5966-493e-8017-0377c2bcd2be",
      "name": "记录今日账户余额",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        80,
        680
      ],
      "parameters": {
        "columns": {
          "value": {
            "date": "={{$today}}\n",
            "change": "={{($json.equity- $json.last_equity)/ $json.last_equity}}",
            "balance": "={{ $json.equity }}"
          },
          "schema": [
            {
              "id": "date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "balance",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "balance",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "change",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "change",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "date"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "useAppend": true
        },
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 449152551,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww/edit#gid=449152551",
          "cachedResultName": "balance"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww/edit?usp=drivesdk",
          "cachedResultName": "Stock Sentiment"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "Bpltco7Lqc7P73Qp",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "657726f0-38f0-4863-b911-1050cf345d84",
      "name": "Alpaca_获取未平仓头寸",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        740,
        680
      ],
      "parameters": {
        "url": "https://paper-api.alpaca.markets/v2/positions",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth",
        "queryParameters": {
          "parameters": [
            {}
          ]
        }
      },
      "credentials": {
        "httpQueryAuth": {
          "id": "p1dJbEo98pH5SVih",
          "name": "Query Auth account"
        },
        "httpCustomAuth": {
          "id": "cY4cJyCzDnwhbKkw",
          "name": "Custom Auth account"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "7d04afeb-3b24-4c96-9cf9-16999a14fec4",
      "name": "创建待平仓头寸和两个待开仓头寸",
      "type": "n8n-nodes-base.code",
      "position": [
        960,
        680
      ],
      "parameters": {
        "jsCode": "// Accessing data from the previous nodes\nconst openPositions = $('Alpaca_get_open_positions').all();\nconst topSentiment = $(\"filter_top_sentiment_score\").all();\n\n// Extracting the symbols for easier comparison\nconst openPositionSymbols = openPositions.map(pos => pos.json.symbol);\nconst topSentimentSymbols = topSentiment.map(sen => sen.json.stock);\n\n// Table 1: Open positions not in the top sentiment filter\nconst positionsNotInTopSentiment = openPositions\n  .filter(pos => !topSentimentSymbols.includes(pos.json.symbol))\n  .map(pos => ({\n    symbol: pos.json.symbol,\n    market_value: pos.json.market_value,\n    qty: pos.json.qty,\n    asset_id : pos.json.asset_id\n  }));\n\n// Table 2: Symbols from top sentiment not in open positions\nconst symbolsNotInOpenPositions = topSentiment\n  .filter(sen => !openPositionSymbols.includes(sen.json.stock))\n  .map(sen => ({\n    symbol: sen.json.stock,\n  }));\n\n// Calculate the total market value of the first table\nconst totalMarketValue = positionsNotInTopSentiment.reduce((sum, pos) => {\n  return sum + parseFloat(pos.market_value);\n}, 0);\n\n// Calculate the value to be assigned to each symbol in the second table\nconst valuePerSymbol = symbolsNotInOpenPositions.length > 0\n  ? totalMarketValue / symbolsNotInOpenPositions.length\n  : 0;\n\n// Add the calculated value to each symbol in the second table\nconst symbolsWithMarketValue = symbolsNotInOpenPositions.map(item => ({\n  ...item,\n  market_value_per_symbol: valuePerSymbol,\n}));\n\n// Returning the two tables as separate outputs\nreturn [\n  {\n    json: {\n      positions_not_in_top_sentiment: positionsNotInTopSentiment,\n    \n    symbols_not_in_open_positions: symbolsWithMarketValue,\n    \n  }}\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "1e846978-377d-477f-9e62-5ae465066315",
      "name": "待开仓头寸",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1180,
        780
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "symbols_not_in_open_positions"
      },
      "typeVersion": 1
    },
    {
      "id": "a8bbdca1-d531-4384-bde9-8c1bf0979677",
      "name": "待平仓头寸",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1400,
        580
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "positions_not_in_top_sentiment"
      },
      "typeVersion": 1
    },
    {
      "id": "a6175bb8-d92e-4c36-9f70-9411567f80c8",
      "name": "合并订单以写入表格",
      "type": "n8n-nodes-base.merge",
      "position": [
        1840,
        680
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "d74f036b-e085-43d4-a47d-82820e68bbed",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -920,
        380
      ],
      "parameters": {
        "width": 400,
        "height": 380,
        "content": "## Alpaca 交易 📈"
      },
      "typeVersion": 1
    },
    {
      "id": "61a3c87f-00f1-4dad-94c1-bd9ef1a9c906",
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2060,
        680
      ],
      "parameters": {
        "columns": {
          "value": {
            "date": "={{ $today }}",
            "order": "={{ $json.side }}",
            "value": "={{ $if( $json.side == \"buy\",$json.notional,$('positions_to_close').item.json.market_value) }}",
            "symbol": "={{ $json.symbol }}"
          },
          "schema": [
            {
              "id": "date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "symbol",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "symbol",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "order",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "order",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "value",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "value",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "date"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 486231870,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww/edit#gid=486231870",
          "cachedResultName": "positions"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tQDBVDqn5v08GOsjupjV8o3Jzqd4-fKoSoGhWLEOTww/edit?usp=drivesdk",
          "cachedResultName": "Stock Sentiment"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "Bpltco7Lqc7P73Qp",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "22e12a7a-0a3d-46d7-a103-648e9628f3c4",
      "name": "等待",
      "type": "n8n-nodes-base.wait",
      "position": [
        1400,
        780
      ],
      "webhookId": "3d1031f5-7a20-4c3a-8791-748e93830402",
      "parameters": {
        "unit": "minutes",
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "ea31c298-b298-4e59-8057-a582a9fed462",
      "name": "由 Github 模型提供支持",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -360,
        680
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 16,
              "triggerAtMinute": 45
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "2b54791d-fec9-47f4-bf86-4e967884c5c0",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -400,
        380
      ],
      "parameters": {
        "color": 6,
        "width": 620,
        "height": 560,
        "content": "## 1. 每日触发和账户快照 📈"
      },
      "typeVersion": 1
    },
    {
      "id": "a2bc2441-e498-4de4-9d5e-b4af8fa1d5d4",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        260,
        380
      ],
      "parameters": {
        "width": 620,
        "height": 560,
        "content": "## 2. 基于情感的股票选择 👍👎"
      },
      "typeVersion": 1
    },
    {
      "id": "e80a7608-0850-4da6-af19-a2d271a6960c",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        920,
        100
      ],
      "parameters": {
        "color": 3,
        "width": 840,
        "height": 840,
        "content": "## 3. 交易逻辑与执行 ⚙️"
      },
      "typeVersion": 1
    },
    {
      "id": "d824c44b-d4c3-4334-b563-f0390541c2e8",
      "name": "便签5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1800,
        420
      ],
      "parameters": {
        "color": 4,
        "width": 520,
        "height": 520,
        "content": "## 4. 记录与记账 📝"
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "timezone": "Asia/Jerusalem",
    "callerPolicy": "workflowsFromSameOwner",
    "executionOrder": "v1"
  },
  "versionId": "83841c35-e0c9-4cee-86c2-e8bc1ae465bb",
  "connections": {
    "Wait": {
      "main": [
        [
          {
            "node": "Alpaca-post-order-buy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Alpaca-get-account-info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "positions_to_open": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "positions_to_close": {
      "main": [
        [
          {
            "node": "Alpaca-post-order-sell",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alpaca-post-order-buy": {
      "main": [
        [
          {
            "node": "merge_orders_to_write_to_sheets",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Alpaca-post-order-sell": {
      "main": [
        [
          {
            "node": "merge_orders_to_write_to_sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alpaca-get-account-info": {
      "main": [
        [
          {
            "node": "write_account_balace_today",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alpaca_get_open_positions": {
      "main": [
        [
          {
            "node": "create_positions_to_close_and_positions_two_open",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "filter_top_sentiment_score": {
      "main": [
        [
          {
            "node": "Alpaca_get_open_positions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "write_account_balace_today": {
      "main": [
        [
          {
            "node": "read_sentiments_score_today",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "read_sentiments_score_today": {
      "main": [
        [
          {
            "node": "filter_top_sentiment_score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "merge_orders_to_write_to_sheets": {
      "main": [
        [
          {
            "node": "Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "create_positions_to_close_and_positions_two_open": {
      "main": [
        [
          {
            "node": "positions_to_close",
            "type": "main",
            "index": 0
          },
          {
            "node": "positions_to_open",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

这是一个高级难度的工作流,适用于Crypto Trading等场景。适合高级用户,包含 16+ 个节点的复杂工作流

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量19
分类1
节点类型8
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
Raz Hadas

Raz Hadas

@raz-hadas

Co-founder of buildmyflow, on a mission to create powerful and easy-to-use n8n automation templates. With a background in AI and a passion for social impact as the co-founder of TovTech, I'm dedicated to building a community-focused resource for free and premium workflows that save you time and unlock new possibilities. Let's automate together! https://www.linkedin.com/in/raz-hadas/

外部链接
在 n8n.io 上查看 →

分享此工作流