CZSC 官方文档（0.6.7）

> CZSC 是缠中说禅技术分析理论的 python 实现，该理论源自 缠中说禅 博客。

> 注意：文档写的比较匆忙，很多地方可能没有讲清楚。有什么疑问，可以到 常见问题（FAQ） 看看。看完还有疑问，可以直接在FAQ链接下面跟帖提问。

> 此文档仅适用于 `czsc == 0.6.7` ，地址: https://github.com/zengbin93/czsc

# 1. 缠中说禅技术分析理论基础

- 缠中说禅重新编排版《论语》（整理版）
- 缠中说禅交易指南
- 缠中说禅技术原理
- 缠中说禅图解分析示范

以上四篇文章，建议按顺序读一遍，如果读完后感觉缠中说禅技术分析理论还不错，推荐阅读原文。

# 2. 安装、更新与卸载

`czsc` 是一个python第三方库，安装、更新、卸载与任何 python 第三方库都是一样的。`czsc` 目前已经实现了缠中说禅技术分析理论中的一些核心概念，包括分型、笔等。基于此，设计并实现了N个缠中说禅技术分析信号，用于辅助策略设计和多因子建模。

> python 版本必须大于等于 3.7

直接从 `github` 安装与更新：

    pip install git+git://github.com/zengbin93/czsc.git -U

从 `pypi` 安装与更新：

    pip install czsc -U -i https://pypi.python.org/simple

快速卸载：

    pip uninstall czsc

# 3. 基础信息

## 3.1 符号说明

在信号和因子设计过程中，为了方便表达，引入以下符号，不区分大小写：

符号 | 说明
--- | ---
BI | 笔对象
FX | 分型对象
— | —
X5 | 五笔形态
X7 | 七笔形态
X9 | 九笔形态
L | 多头信号，Long 的首字母
S | 空头信号，Short 的首字母
— | —
C6 | 日线级别
C5 | 60分钟级别
C4 | 30分钟级别
C3 | 15分钟级别
C2 | 5分钟级别
C1 | 1分钟级别
— | —
L1 | 向下笔转折右侧
L2 | 向下笔转折左侧
L3 | 向上笔中继右侧
L4 | 向上笔中继左侧
S1 | 向上笔转折右侧
S2 | 向上笔转折左侧
S3 | 向下笔中继右侧
S4 | 向下笔中继左侧
— | —
R1 | 倒数第1笔
R2 | 倒数第2笔
R3 | 倒数第3笔
R4 | 倒数第4笔
R5 | 倒数第5笔

符合举例：
`X5LA0` 表示五笔形态为aAb式底背弛基础型，具体的说，X5 = 五笔形态，L = 多头，A0 = aAb式底背弛基础型

## 3.2 基础形态定义

在信号层面，定义了若干种常见形态，具体请参考：

- 缠中说禅形态挖掘之五笔形态
- 缠中说禅形态挖掘之七笔形态
- 缠中说禅形态挖掘之九笔形态

# 4. 简单用法

`czsc` 库目前内置了聚宽数据的获取方法，聚宽数据的用户可以很方便的使用一些基础功能。

## 4.1 查看分析结果

`CzscTrader` 是依赖聚宽数据实现的多级别分析类 ，聚宽数据用户可以直接使用。

    # 首次使用需要设置聚宽账户
    # from czsc.data.jq import set_token
    # set_token("phone number", 'password') # 第一个参数是JQData的手机号，第二个参数是登录密码

    from datetime import datetime
    import czsc
    from czsc.trader import CzscTrader

    assert czsc.__version__ == '0.6.7'

    # 在默认浏览器中打开最新分析结果，
    ct = CzscTrader(symbol="000001.XSHG", end_date=datetime.now())
    ct.open_in_browser(width="1400px", height="580px")
    # open_in_browser 方法可以在windows系统中使用，如果无法使用，可以直接保存结果到 html 文件
    # ct.take_snapshot(file_html="czsc_results.html", width="1400px", height="580px")

    # 在默认浏览器中打开指定结束日期的分析结果）
    ct = CzscTrader(symbol="000001.XSHG", end_date="2021-03-04")
    ct.open_in_browser(width="1400px", height="580px")

## 4.2 单级别形态选股

以三买为例，单级别形态选股的实现方法如下：

    # 首次使用需要设置聚宽账户
    # from czsc.data.jq import set_token
    # set_token("phone number", 'password') # 第一个参数是JQData的手机号，第二个参数是登录密码

    from datetime import datetime
    from typing import List
    from czsc.data.jq import get_kline, get_index_stocks
    import czsc
    from czsc.analyze import CZSC
    from czsc.enum import Signals

    assert czsc.__version__ == '0.6.7'

    def is_third_buy(symbol):
        """判断一个股票现在是否有日线三买"""
        bars = get_kline(symbol, freq="D", end_date=datetime.now(), count=1000)
        c = CZSC(bars, freq="日线")

        # 在这里判断是否有五笔三买形态，也可以换成自己感兴趣的形态
        if c.signals['倒1五笔'] in [Signals.X5LB0.value, Signals.X5LB1.value]:
            return True
        else:
            return False

    if __name__ == '__main__':
        # 获取上证50最新成分股列表，这里可以换成自己的股票池
        symbols: List = get_index_stocks("000016.XSHG")
        for symbol in symbols:
            try:
                if is_third_buy(symbol):
                    print("{} - 日线三买".format(symbol))
            except:
                print("{} - 执行失败".format(symbol))

## 4.3 实时监控并推送消息到企业微信

`CZSC` 内部实现了企业微信群聊机器人的实时消息推送方法，可以推送文本消息和文件，关于企业微信群聊机器人的使用方法，请参考腾讯文档：https://work.weixin.qq.com/api/doc/90000/90136/91770

下面是一个实时监控因子的案例，以日线笔因子为例：

    # 首次使用需要设置聚宽账户
    # from czsc.data.jq import set_token
    # set_token("phone number", 'password') # 第一个参数是JQData的手机号，第二个参数是登录密码
    import traceback
    import time
    import shutil
    import os
    import pickle
    from datetime import datetime
    from czsc.trader import CzscTrader, Factors
    from czsc.utils.qywx import push_text, push_file

    # =======================================================================================================
    # 基础参数配置
    ct_path = os.path.join(".", "czsc_traders")
    os.makedirs(ct_path, exist_ok=True)
    # 关于企业微信群聊机器人的使用文档，参考：https://work.weixin.qq.com/api/doc/90000/90136/91770
    # 企业微信群聊机器人的key
    qywx_key = "4ad2e226-2519-4893-8670-*****"

    # 定义需要监控的股票列表
    symbols = ["300033.XSHE", "300803.XSHE", "002739.XSHE"]
    # =======================================================================================================

    def save_pkl(data, file):
        with open(file, "wb") as f:
            pickle.dump(data, f)

    def read_pkl(file):
        with open(file, "rb") as f:
            data = pickle.load(f)
        return data

    def monitor(use_cache=True):
        push_text("自选股CZSC笔因子监控启动 @ {}".format(datetime.now().strftime("%Y-%m-%d %H:%M")), qywx_key)
        moni_path = os.path.join(ct_path, "monitor")
        # 首先清空历史快照
        if os.path.exists(moni_path):
            shutil.rmtree(moni_path)
        os.makedirs(moni_path, exist_ok=True)

        for s in symbols:
            print(s)
            try:
                file_ct = os.path.join(ct_path, "{}.ct".format(s))
                if os.path.exists(file_ct) and use_cache:
                    ct: CzscTrader = read_pkl(file_ct)
                    ct.update_factors()
                else:
                    ct = CzscTrader(s, max_count=1000)
                save_pkl(ct, file_ct)

                # 每次执行，会在moni_path下面保存一份快照
                file_html_ = os.path.join(moni_path, f"{ct.symbol}_{ct.kf.end_dt.strftime('%Y%m%d%H%M')}.html")
                ct.take_snapshot(file_html_, width="1400px", height="580px")

                if ct.s['日线笔因子'] != Factors.Other.value:
                    msg = "{} - {}\n".format(s, ct.s['日线笔因子'])
                    msg += "同花顺F10：http://basic.10jqka.com.cn/{}".format(s[:6])
                    push_text(msg, key=qywx_key)
                    file_html_new = os.path.join(moni_path, f"{ct.symbol}_{ct.kf.end_dt.strftime('%Y%m%d%H%M')}.html")
                    shutil.copyfile(file_html_, file_html_new)
                    push_file(file_html_new, key=qywx_key)

            except Exception as e:
                traceback.print_exc()
                print("{} 执行失败 - {}".format(s, e))

        push_text("自选股CZSC笔因子监控结束 @ {}".format(datetime.now().strftime("%Y-%m-%d %H:%M")), qywx_key)

    def run_monitor():
        mdt = ["09:30", "10:00", "10:30", "11:00", "11:20", "13:00", "13:30", "14:00", "14:30", "14:50"]
        monitor()
        while 1:
            print(datetime.now().strftime("%H:%M"))
            if datetime.now().strftime("%H:%M") in mdt:
                monitor()
            time.sleep(3)

    if __name__ == '__main__':
        run_monitor()

# 5. 高级用法

## 5.1 使用掘金量化终端进行缠论策略研究

使用掘金量化终端进行缠论策略研究的代码稍微有点复杂，主要是需要实现一些掘金量化平台的一些回调函数和下单方法，具体的内容，点击访问：https://github.com/zengbin93/czsc_gm

## 5.2 对接K线数据

缠中说禅技术分析理论只需要K线，因此，任何第三方数据源只要转换一下K线获取方法就可以使用。下面以 `Tushare` 数据为例，介绍下如何进行K线数据转换，重点是 `format_kline` 方法。

    import pandas as pd
    import tushare as ts
    from datetime import datetime, timedelta
    from typing import List
    import czsc
    from czsc.analyze import CZSC, RawBar
    from czsc.enum import Signals

    assert czsc.__version__ == '0.6.7'

    # 使用第三方数据，只需要定义一个K线转换函数
    def format_kline(kline: pd.DataFrame) -> List[RawBar]:
        """

        :param kline: Tushare 数据接口返回的K线数据
        :return: 转换好的K线数据
        """
        bars = []
        records = kline.to_dict('records')
        for record in records:
            # 将每一根K线转换成 RawBar 对象
            bar = RawBar(symbol=record['ts_code'], dt=pd.to_datetime(record['trade_date']), open=record['open'],
                         close=record['close'], high=record['high'], low=record['low'], vol=record['vol'])
            bars.append(bar)
        return bars

    def is_third_buy(ts_code):
        """判断一个股票现在是否有日线三买"""
        # 调用tushare的K线获取方法，Tushare数据的使用方法，请参考：https://tushare.pro/document/2
        end_date = datetime.now()
        start_date = end_date - timedelta(days=1000)
        df = ts.pro_bar(ts_code=ts_code, adj='qfq', asset="E",
                        start_date=start_date.strftime("%Y%m%d"),
                        end_date=end_date.strftime("%Y%m%d"))
        bars = format_kline(df)
        c = CZSC(bars, freq="日线")

        # 在这里判断是否有五笔三买形态，也可以换成自己感兴趣的形态
        if c.signals['倒1五笔'] in [Signals.X5LB0.value, Signals.X5LB1.value]:
            return True
        else:
            return False

    if __name__ == '__main__':
        # 这里可以换成自己的股票池
        ts_codes = ['603259.SH', '603288.SH', '603501.SH', '603986.SH']
        for ts_code in ts_codes:
            try:
                if is_third_buy(ts_code):
                    print("{} - 日线三买".format(ts_code))
            except:
                print("{} - 执行失败".format(ts_code))