redis - 远程发送买卖信号、本地接收信号处理

我们经常会有这样的场景:想在远程(比如聚宽)是发送买入、卖出信号,比如 时间、买入100股,价格、代码、平安银行,然后在redis本地进行接收,解析,打印并且执行任务(比如QMT、miniQMT进行实盘买入下单)

前一个帖子我们已经知道怎么在windows上搭建redis环境,这个教程我们来学习用python进行发送、接收信号。

目录

一、说明

二、统一消息格式(JSON)

三、sender.py(远端发送)

四、worker.py(本地接收并执行)

五、结语


一、说明

  • sender.py:远端发送买卖信号(入队)

  • worker.py:本地常驻进程,阻塞式取队列、解析、打印并"执行任务"

  • 统一消息格式(JSON)

依赖:
pip install redis

二、统一消息格式(JSON)

复制代码
{
  "type": "BUY",            // BUY 或 SELL
  "symbol": "000001.SZ",    // 证券代码
  "name": "平安银行",        // 可选
  "qty": 100,               // 数量(股/手)
  "price": 12.34,           // 价格,允许 0 表示市价或由执行侧自行决定
  "client_order_id": "...", // 唯一ID(便于去重/追踪)
  "ts": "2025-09-03T17:20:15.123Z"  // ISO时间
}

{

"type": "BUY", // BUY 或 SELL

"symbol": "000001.SZ", // 证券代码

"name": "平安银行", // 可选

"qty": 100, // 数量(股/手)

"price": 12.34, // 价格,允许 0 表示市价或由执行侧自行决定

"client_order_id": "...", // 唯一ID(便于去重/追踪)

"ts": "2025-09-03T17:20:15.123Z" // ISO时间

}

三、sender.py(远端发送)

复制代码
# sender.py
import argparse
import json
import uuid
from datetime import datetime, timezone
import redis
import os

def get_redis():
    r = redis.Redis(
        host=os.getenv("REDIS_HOST", "127.0.0.1"),
        port=int(os.getenv("REDIS_PORT", "6379")),
        password=os.getenv("REDIS_PASSWORD", None),
        db=int(os.getenv("REDIS_DB", "0")),
        decode_responses=True,
        socket_timeout=5
    )
    # 测连通
    r.ping()
    return r

def build_message(side, symbol, qty, price, name=None):
    return {
        "type": side.upper(),             # BUY / SELL
        "symbol": symbol,
        "name": name,
        "qty": int(qty),
        "price": float(price),
        "client_order_id": str(uuid.uuid4()),
        "ts": datetime.now(timezone.utc).isoformat()
    }

def main():
    parser = argparse.ArgumentParser(description="Push trade signal to Redis queue")
    parser.add_argument("--side", choices=["BUY", "SELL"], required=True, help="BUY or SELL")
    parser.add_argument("--symbol", required=True, help="like 000001.SZ")
    parser.add_argument("--qty", type=int, required=True, help="quantity")
    parser.add_argument("--price", type=float, required=True, help="price (0 for market)")
    parser.add_argument("--name", default=None, help="security name, e.g. 平安银行")
    parser.add_argument("--queue", default="trade_queue", help="redis list key")
    args = parser.parse_args()

    r = get_redis()
    msg = build_message(args.side, args.symbol, args.qty, args.price, args.name)
    r.rpush(args.queue, json.dumps(msg, ensure_ascii=False))
    print("Enqueued:", msg)

if __name__ == "__main__":
    main()

使用:

在远程电脑上执行,

环境变量

set REDIS_HOST=你的本地公网IP或内网IP

set REDIS_PASSWORD=123456

然后执行发送代码:【注意,可以等先启动了接收程序再启动发送,这样能看到效果】

python sender.py --side BUY --symbol 000001.SZ --qty 100 --price 12.34 --name 平安银行

注意:macos的话用 export来代替set

四、worker.py(本地接收并执行)

复制代码
# worker.py
import json
import time
import redis
import os
import traceback

QUEUE_KEY = os.getenv("QUEUE_KEY", "trade_queue")
DEAD_KEY  = os.getenv("DEAD_KEY",  "trade_dead")  # 可选死信队列

def get_redis():
    r = redis.Redis(
        host=os.getenv("REDIS_HOST", "127.0.0.1"),
        port=int(os.getenv("REDIS_PORT", "6379")),
        password=os.getenv("REDIS_PASSWORD", None),
        db=int(os.getenv("REDIS_DB", "0")),
        decode_responses=True,
        socket_timeout=10
    )
    r.ping()
    return r

def validate(msg: dict):
    required = ["type", "symbol", "qty", "price", "client_order_id", "ts"]
    for k in required:
        if k not in msg:
            raise ValueError(f"missing field: {k}")
    if msg["type"] not in ("BUY", "SELL"):
        raise ValueError("type must be BUY or SELL")
    if not isinstance(msg["qty"], int) or msg["qty"] <= 0:
        raise ValueError("qty must be positive int")
    # 价格可为0(如表示市价或由执行端决定)
    float(msg["price"])

def execute_trade(msg: dict):
    """
    这里写你的实际执行逻辑(下单、回测接口、模拟撮合、调用券商API等)。
    为了演示,先做个"打印执行"的占位。
    """
    side = msg["type"]
    symbol = msg["symbol"]
    name = msg.get("name") or ""
    qty = msg["qty"]
    price = msg["price"]
    cid = msg["client_order_id"]

    # ===== 在这替换成你的交易执行 =====
    print(f"[EXECUTE] {side} {qty} {symbol} ({name}) @ {price}  CID={cid}")
    # 例如:broker_api.place_order(side=side, symbol=symbol, qty=qty, price=price, tif="GFD")
    # 返回报单号 / 状态,写入日志或回写状态即可。
    # =================================

def main():
    r = get_redis()
    print(f"Worker started. Listening on list: {QUEUE_KEY}")
    while True:
        try:
            # BLPOP: 阻塞等待,timeout=5秒可让我们有机会处理中断/心跳等
            item = r.blpop(QUEUE_KEY, timeout=5)
            if item is None:
                # 队列暂时为空,循环继续
                continue

            _, payload = item
            try:
                msg = json.loads(payload)
            except Exception:
                print("[ERROR] JSON decode failed. Put to dead-letter.")
                r.rpush(DEAD_KEY, payload)
                continue

            try:
                validate(msg)
            except Exception as e:
                print(f"[ERROR] Invalid message: {e}. Put to dead-letter.")
                r.rpush(DEAD_KEY, json.dumps({
                    "error": str(e),
                    "payload": msg
                }, ensure_ascii=False))
                continue

            # 执行任务
            execute_trade(msg)

        except KeyboardInterrupt:
            print("Worker stopping (Ctrl+C).")
            break
        except redis.exceptions.ConnectionError as e:
            print(f"[WARN] Redis connection issue: {e}. Retry in 3s...")
            time.sleep(3)
        except Exception:
            print("[ERROR] Unexpected error:\n", traceback.format_exc())
            # 不中断进程,继续监听
            time.sleep(1)

if __name__ == "__main__":
    main()

在命令行中:

set REDIS_PASSWORD=123456

然后再执行:

python worker.py

结果如图:

说明已经接收到对应信息!成功!

注意:在此之前,要保证redis是启动状态

五、结语

只需要将 execute_trade() 函数改成真实的QMT下单函数,就能够进行实盘交易了。

相关推荐
AC赳赳老秦10 小时前
网页公开附件自动采集:OpenClaw 批量下载页面内嵌 Word/Excel 附件,统一格式后结构化入库
java·python·word·php·excel·deepseek·openclaw
北斗落凡尘10 小时前
LangGraph 入门实战(3)
python·langchain
TAN-90°-10 小时前
Deep Learning for Computer Vision——Image Classification with Linear Classifiers
python·深度学习·算法·计算机视觉·线性回归
AINative软件工程10 小时前
LLM API 成本失控怎么办?工程师的实时异常检测指南
python
练习两年半的攻城狮10 小时前
LlamaIndex ResponseMode 深度解析
python·llamaindex
油丶酸萝卜别吃10 小时前
Redis 布隆过滤器快速实现
数据库·redis·缓存
阿pin10 小时前
Java随笔-红黑树
java·python·算法·红黑树
2603_9651481110 小时前
eBay商品数据API:寻找海外仓与价格洼地
大数据·人工智能·windows·python·microsoft
2601_9563198811 小时前
TqSdk Tick 数据适合做什么?获取方法与使用边界
人工智能·python