# 东方财富交易代理 (emta)
[](https://pypi.org/project/emta/)
[](https://pypi.org/project/emta/)
[](https://github.com/your-username/emta/blob/main/LICENSE)
东方财富非官方Python交易库
## 概述
东方财富交易代理(`emta`)是一个非官方的Python库,提供对东方财富交易平台的编程访问。它支持自动化的交易操作,包括下单、查询账户余额和获取市场数据等功能。
## 主要特性
* **身份验证**:支持验证码识别和密码加密的安全登录
* **订单管理**:支持下单、查询和撤单操作
* **账户信息**:获取账户余额和持仓信息
* **市场数据**:访问股票实时市场数据
* **模块化设计**:代码结构清晰,关注点分离明确
* **类型安全**:完整的类型提示,提高代码可靠性
* **错误处理**:全面的异常处理机制,确保应用稳定性
## 安装
请确保使用Python 3.11或更高版本(但低于4.0)。
```bash
pip install emta
```
## 快速开始
```python
from emta import TradingAgent, OrderType
# 创建交易代理
agent = TradingAgent("your_username", "your_password")
# 登录东方财富
if agent.login():
# 获取账户信息
account_info = agent.get_account_info()
print(f"账户余额: {account_info.get('account_balance', 0)}")
# 下买单
order_id = agent.place_order("600000", OrderType.BUY, 100, 12.5)
if order_id:
print(f"订单提交成功,订单号: {order_id}")
# 获取市场数据
market_data = agent.get_market_data("600000")
print(f"当前价格: {market_data}")
# 登出
agent.logout()
```
完整示例请参见 [examples/trading_example.py](examples/trading_example.py)。
## API 参考
### TradingAgent
与东方财富交易服务交互的主要接口。
#### 构造函数
```python
TradingAgent(username: str | None = None, password: str | None = None)
```
#### 方法
| 方法 | 描述 |
|------|------|
| `login(username=None, password=None, duration=30)` | 东方财富身份验证 |
| `logout()` | 结束当前会话 |
| `get_account_info()` | 获取账户余额和持仓信息 |
| `place_order(stock_code, trade_type, amount, price)` | 下达买入或卖出订单 |
| `query_orders()` | 获取最近的订单列表 |
| `cancel_order(order_id)` | 撤销现有订单 |
| `get_market_data(stock_code)` | 获取股票的当前市场数据 |
## 技术栈
* **Python**: 3.11+
* **依赖管理**: [UV](https://github.com/astral-sh/uv) 用于快速依赖解析
* **HTTP客户端**: [HTTPX](https://www.python-httpx.org/) 用于异步/同步HTTP请求
* **测试**: [Pytest](https://docs.pytest.org/) 用于全面的测试覆盖
* **类型检查**: [Mypy](http://mypy-lang.org/) 用于静态类型分析
* **代码质量**: [Ruff](https://docs.astral.sh/ruff/) 用于代码检查和格式化
* **验证码识别**: [ddddocr](https://github.com/sml2h3/ddddocr) 用于自动验证码识别
## 开发环境搭建
1. 克隆仓库:
```bash
git clone https://github.com/your-username/emta.git
cd emta
```
2. 使用UV安装依赖:
```bash
uv sync
```
3. 运行测试:
```bash
uv run pytest
```
4. 类型检查:
```bash
uv run mypy src/
```
5. 代码检查:
```bash
uv run ruff check src/
```
## 项目结构
```
src/emta/
├── __init__.py # 包初始化文件
├── py.typed # 类型提示标记
├── core/ # 核心交易代理实现
│ └── agent.py # 主要交易代理类
├── models/ # 数据模型和异常
│ ├── trading.py # 交易数据模型
│ └── exceptions.py # 异常类
├── auth/ # 认证模块
│ └── client.py # 认证客户端
├── api/ # API客户端交易操作
│ └── client.py # API客户端实现
└── utils/ # 工具函数
├── encryption.py # 密码加密工具
├── captcha.py # 验证码识别工具
└── stocks.py # 股票市场代码工具
```
## 贡献
欢迎贡献!如果您有改进建议、错误修复或新增功能:
1. Fork 仓库
2. 创建功能分支
3. 进行修改
4. 如适用,请添加测试
5. 确保所有测试通过
6. 提交 pull request
请遵循现有的代码风格,并为新功能添加适当的文档。
## 测试
测试使用 pytest 编写。运行测试:
```bash
uv run pytest
```
运行带覆盖率的测试:
```bash
uv run coverage run -m pytest
uv run coverage report
```
## 许可证
本项目是根据 [MIT 许可证](./LICENSE) 发布的开源软件。
Raw data
{
"_id": null,
"home_page": null,
"name": "emta",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "trade, trade api, \u4e1c\u65b9\u8d22\u5bcc, \u4e1c\u8d22, \u4ea4\u6613, \u4ea4\u6613API, \u4ea4\u6613\u4ee3\u7406, \u4ea4\u6613\u673a\u5668\u4eba, \u81ea\u52a8\u4ea4\u6613, \u81ea\u52a8\u5316\u4ea4\u6613",
"author": null,
"author_email": "zhou bo <wokspc@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/f8/ce/f4f9debed283df7da99637a33c12d8bd7eec4a04334caa79cda925d47817/emta-0.5.0.tar.gz",
"platform": null,
"description": "# \u4e1c\u65b9\u8d22\u5bcc\u4ea4\u6613\u4ee3\u7406 (emta)\n\n[](https://pypi.org/project/emta/)\n[](https://pypi.org/project/emta/)\n[](https://github.com/your-username/emta/blob/main/LICENSE)\n\n\u4e1c\u65b9\u8d22\u5bcc\u975e\u5b98\u65b9Python\u4ea4\u6613\u5e93\n\n## \u6982\u8ff0\n\n\u4e1c\u65b9\u8d22\u5bcc\u4ea4\u6613\u4ee3\u7406\uff08`emta`\uff09\u662f\u4e00\u4e2a\u975e\u5b98\u65b9\u7684Python\u5e93\uff0c\u63d0\u4f9b\u5bf9\u4e1c\u65b9\u8d22\u5bcc\u4ea4\u6613\u5e73\u53f0\u7684\u7f16\u7a0b\u8bbf\u95ee\u3002\u5b83\u652f\u6301\u81ea\u52a8\u5316\u7684\u4ea4\u6613\u64cd\u4f5c\uff0c\u5305\u62ec\u4e0b\u5355\u3001\u67e5\u8be2\u8d26\u6237\u4f59\u989d\u548c\u83b7\u53d6\u5e02\u573a\u6570\u636e\u7b49\u529f\u80fd\u3002\n\n## \u4e3b\u8981\u7279\u6027\n\n* **\u8eab\u4efd\u9a8c\u8bc1**\uff1a\u652f\u6301\u9a8c\u8bc1\u7801\u8bc6\u522b\u548c\u5bc6\u7801\u52a0\u5bc6\u7684\u5b89\u5168\u767b\u5f55\n* **\u8ba2\u5355\u7ba1\u7406**\uff1a\u652f\u6301\u4e0b\u5355\u3001\u67e5\u8be2\u548c\u64a4\u5355\u64cd\u4f5c\n* **\u8d26\u6237\u4fe1\u606f**\uff1a\u83b7\u53d6\u8d26\u6237\u4f59\u989d\u548c\u6301\u4ed3\u4fe1\u606f\n* **\u5e02\u573a\u6570\u636e**\uff1a\u8bbf\u95ee\u80a1\u7968\u5b9e\u65f6\u5e02\u573a\u6570\u636e\n* **\u6a21\u5757\u5316\u8bbe\u8ba1**\uff1a\u4ee3\u7801\u7ed3\u6784\u6e05\u6670\uff0c\u5173\u6ce8\u70b9\u5206\u79bb\u660e\u786e\n* **\u7c7b\u578b\u5b89\u5168**\uff1a\u5b8c\u6574\u7684\u7c7b\u578b\u63d0\u793a\uff0c\u63d0\u9ad8\u4ee3\u7801\u53ef\u9760\u6027\n* **\u9519\u8bef\u5904\u7406**\uff1a\u5168\u9762\u7684\u5f02\u5e38\u5904\u7406\u673a\u5236\uff0c\u786e\u4fdd\u5e94\u7528\u7a33\u5b9a\u6027\n\n## \u5b89\u88c5\n\n\u8bf7\u786e\u4fdd\u4f7f\u7528Python 3.11\u6216\u66f4\u9ad8\u7248\u672c\uff08\u4f46\u4f4e\u4e8e4.0\uff09\u3002\n\n```bash\npip install emta\n```\n\n## \u5feb\u901f\u5f00\u59cb\n\n```python\nfrom emta import TradingAgent, OrderType\n\n# \u521b\u5efa\u4ea4\u6613\u4ee3\u7406\nagent = TradingAgent(\"your_username\", \"your_password\")\n\n# \u767b\u5f55\u4e1c\u65b9\u8d22\u5bcc\nif agent.login():\n # \u83b7\u53d6\u8d26\u6237\u4fe1\u606f\n account_info = agent.get_account_info()\n print(f\"\u8d26\u6237\u4f59\u989d: {account_info.get('account_balance', 0)}\")\n\n # \u4e0b\u4e70\u5355\n order_id = agent.place_order(\"600000\", OrderType.BUY, 100, 12.5)\n if order_id:\n print(f\"\u8ba2\u5355\u63d0\u4ea4\u6210\u529f\uff0c\u8ba2\u5355\u53f7: {order_id}\")\n\n # \u83b7\u53d6\u5e02\u573a\u6570\u636e\n market_data = agent.get_market_data(\"600000\")\n print(f\"\u5f53\u524d\u4ef7\u683c: {market_data}\")\n\n # \u767b\u51fa\n agent.logout()\n```\n\n\u5b8c\u6574\u793a\u4f8b\u8bf7\u53c2\u89c1 [examples/trading_example.py](examples/trading_example.py)\u3002\n\n## API \u53c2\u8003\n\n### TradingAgent\n\n\u4e0e\u4e1c\u65b9\u8d22\u5bcc\u4ea4\u6613\u670d\u52a1\u4ea4\u4e92\u7684\u4e3b\u8981\u63a5\u53e3\u3002\n\n#### \u6784\u9020\u51fd\u6570\n```python\nTradingAgent(username: str | None = None, password: str | None = None)\n```\n\n#### \u65b9\u6cd5\n\n| \u65b9\u6cd5 | \u63cf\u8ff0 |\n|------|------|\n| `login(username=None, password=None, duration=30)` | \u4e1c\u65b9\u8d22\u5bcc\u8eab\u4efd\u9a8c\u8bc1 |\n| `logout()` | \u7ed3\u675f\u5f53\u524d\u4f1a\u8bdd |\n| `get_account_info()` | \u83b7\u53d6\u8d26\u6237\u4f59\u989d\u548c\u6301\u4ed3\u4fe1\u606f |\n| `place_order(stock_code, trade_type, amount, price)` | \u4e0b\u8fbe\u4e70\u5165\u6216\u5356\u51fa\u8ba2\u5355 |\n| `query_orders()` | \u83b7\u53d6\u6700\u8fd1\u7684\u8ba2\u5355\u5217\u8868 |\n| `cancel_order(order_id)` | \u64a4\u9500\u73b0\u6709\u8ba2\u5355 |\n| `get_market_data(stock_code)` | \u83b7\u53d6\u80a1\u7968\u7684\u5f53\u524d\u5e02\u573a\u6570\u636e |\n\n## \u6280\u672f\u6808\n\n* **Python**: 3.11+\n* **\u4f9d\u8d56\u7ba1\u7406**: [UV](https://github.com/astral-sh/uv) \u7528\u4e8e\u5feb\u901f\u4f9d\u8d56\u89e3\u6790\n* **HTTP\u5ba2\u6237\u7aef**: [HTTPX](https://www.python-httpx.org/) \u7528\u4e8e\u5f02\u6b65/\u540c\u6b65HTTP\u8bf7\u6c42\n* **\u6d4b\u8bd5**: [Pytest](https://docs.pytest.org/) \u7528\u4e8e\u5168\u9762\u7684\u6d4b\u8bd5\u8986\u76d6\n* **\u7c7b\u578b\u68c0\u67e5**: [Mypy](http://mypy-lang.org/) \u7528\u4e8e\u9759\u6001\u7c7b\u578b\u5206\u6790\n* **\u4ee3\u7801\u8d28\u91cf**: [Ruff](https://docs.astral.sh/ruff/) \u7528\u4e8e\u4ee3\u7801\u68c0\u67e5\u548c\u683c\u5f0f\u5316\n* **\u9a8c\u8bc1\u7801\u8bc6\u522b**: [ddddocr](https://github.com/sml2h3/ddddocr) \u7528\u4e8e\u81ea\u52a8\u9a8c\u8bc1\u7801\u8bc6\u522b\n\n## \u5f00\u53d1\u73af\u5883\u642d\u5efa\n\n1. \u514b\u9686\u4ed3\u5e93\uff1a\n ```bash\n git clone https://github.com/your-username/emta.git\n cd emta\n ```\n\n2. \u4f7f\u7528UV\u5b89\u88c5\u4f9d\u8d56\uff1a\n ```bash\n uv sync\n ```\n\n3. \u8fd0\u884c\u6d4b\u8bd5\uff1a\n ```bash\n uv run pytest\n ```\n\n4. \u7c7b\u578b\u68c0\u67e5\uff1a\n ```bash\n uv run mypy src/\n ```\n\n5. \u4ee3\u7801\u68c0\u67e5\uff1a\n ```bash\n uv run ruff check src/\n ```\n\n## \u9879\u76ee\u7ed3\u6784\n\n```\nsrc/emta/\n\u251c\u2500\u2500 __init__.py # \u5305\u521d\u59cb\u5316\u6587\u4ef6\n\u251c\u2500\u2500 py.typed # \u7c7b\u578b\u63d0\u793a\u6807\u8bb0\n\u251c\u2500\u2500 core/ # \u6838\u5fc3\u4ea4\u6613\u4ee3\u7406\u5b9e\u73b0\n\u2502 \u2514\u2500\u2500 agent.py # \u4e3b\u8981\u4ea4\u6613\u4ee3\u7406\u7c7b\n\u251c\u2500\u2500 models/ # \u6570\u636e\u6a21\u578b\u548c\u5f02\u5e38\n\u2502 \u251c\u2500\u2500 trading.py # \u4ea4\u6613\u6570\u636e\u6a21\u578b\n\u2502 \u2514\u2500\u2500 exceptions.py # \u5f02\u5e38\u7c7b\n\u251c\u2500\u2500 auth/ # \u8ba4\u8bc1\u6a21\u5757\n\u2502 \u2514\u2500\u2500 client.py # \u8ba4\u8bc1\u5ba2\u6237\u7aef\n\u251c\u2500\u2500 api/ # API\u5ba2\u6237\u7aef\u4ea4\u6613\u64cd\u4f5c\n\u2502 \u2514\u2500\u2500 client.py # API\u5ba2\u6237\u7aef\u5b9e\u73b0\n\u2514\u2500\u2500 utils/ # \u5de5\u5177\u51fd\u6570\n \u251c\u2500\u2500 encryption.py # \u5bc6\u7801\u52a0\u5bc6\u5de5\u5177\n \u251c\u2500\u2500 captcha.py # \u9a8c\u8bc1\u7801\u8bc6\u522b\u5de5\u5177\n \u2514\u2500\u2500 stocks.py # \u80a1\u7968\u5e02\u573a\u4ee3\u7801\u5de5\u5177\n```\n\n## \u8d21\u732e\n\n\u6b22\u8fce\u8d21\u732e\uff01\u5982\u679c\u60a8\u6709\u6539\u8fdb\u5efa\u8bae\u3001\u9519\u8bef\u4fee\u590d\u6216\u65b0\u589e\u529f\u80fd\uff1a\n\n1. Fork \u4ed3\u5e93\n2. \u521b\u5efa\u529f\u80fd\u5206\u652f\n3. \u8fdb\u884c\u4fee\u6539\n4. \u5982\u9002\u7528\uff0c\u8bf7\u6dfb\u52a0\u6d4b\u8bd5\n5. \u786e\u4fdd\u6240\u6709\u6d4b\u8bd5\u901a\u8fc7\n6. \u63d0\u4ea4 pull request\n\n\u8bf7\u9075\u5faa\u73b0\u6709\u7684\u4ee3\u7801\u98ce\u683c\uff0c\u5e76\u4e3a\u65b0\u529f\u80fd\u6dfb\u52a0\u9002\u5f53\u7684\u6587\u6863\u3002\n\n## \u6d4b\u8bd5\n\n\u6d4b\u8bd5\u4f7f\u7528 pytest \u7f16\u5199\u3002\u8fd0\u884c\u6d4b\u8bd5\uff1a\n\n```bash\nuv run pytest\n```\n\n\u8fd0\u884c\u5e26\u8986\u76d6\u7387\u7684\u6d4b\u8bd5\uff1a\n\n```bash\nuv run coverage run -m pytest\nuv run coverage report\n```\n\n## \u8bb8\u53ef\u8bc1\n\n\u672c\u9879\u76ee\u662f\u6839\u636e [MIT \u8bb8\u53ef\u8bc1](./LICENSE) \u53d1\u5e03\u7684\u5f00\u6e90\u8f6f\u4ef6\u3002\n",
"bugtrack_url": null,
"license": null,
"summary": "Easy Money Trading Agent",
"version": "0.5.0",
"project_urls": null,
"split_keywords": [
"trade",
" trade api",
" \u4e1c\u65b9\u8d22\u5bcc",
" \u4e1c\u8d22",
" \u4ea4\u6613",
" \u4ea4\u6613api",
" \u4ea4\u6613\u4ee3\u7406",
" \u4ea4\u6613\u673a\u5668\u4eba",
" \u81ea\u52a8\u4ea4\u6613",
" \u81ea\u52a8\u5316\u4ea4\u6613"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "c619a9f2b727f59067ba13e28223450c11190613562154a6db6c6058bf50a412",
"md5": "b1aae5c6745ca2129aa885a1e097085d",
"sha256": "3b783d85d657745f5046950294fd243af7b082187491996d75e530c24aa32d97"
},
"downloads": -1,
"filename": "emta-0.5.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b1aae5c6745ca2129aa885a1e097085d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 17888,
"upload_time": "2025-09-09T02:41:41",
"upload_time_iso_8601": "2025-09-09T02:41:41.662683Z",
"url": "https://files.pythonhosted.org/packages/c6/19/a9f2b727f59067ba13e28223450c11190613562154a6db6c6058bf50a412/emta-0.5.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f8cef4f9debed283df7da99637a33c12d8bd7eec4a04334caa79cda925d47817",
"md5": "6ef04dfb0b0acf153d62b3c9d3a72904",
"sha256": "ee7736ce2512746d0753db642f36471af98af4ddf8194fcbd121da853681f56e"
},
"downloads": -1,
"filename": "emta-0.5.0.tar.gz",
"has_sig": false,
"md5_digest": "6ef04dfb0b0acf153d62b3c9d3a72904",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 69328,
"upload_time": "2025-09-09T02:41:42",
"upload_time_iso_8601": "2025-09-09T02:41:42.436144Z",
"url": "https://files.pythonhosted.org/packages/f8/ce/f4f9debed283df7da99637a33c12d8bd7eec4a04334caa79cda925d47817/emta-0.5.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-09 02:41:42",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "emta"
}