首页 > 其他分享 >trade calculator tcalc.py

trade calculator tcalc.py

时间:2024-01-31 23:24:15浏览次数:16  
标签:volume code calculator py tcalc vp comm pair self

代码片

# -*- coding: utf-8 -*-

import sys
import getopt
# from qsutil import gspace as gs
from qsutil import pkl

fname='c:\\GTJA\\RichEZ\\newVer\\cnt.pkl'
# cn_dict = gs.pkl.pkl_load(fname)    
cn_dict = pkl.pkl_load(fname)    

class CBondTransaction(object):
    '''可转债日内轮回交易pnl计数器
    python 小程序的脚本可以直接在shell(命令行)解释器里运行:
        1. open anaconda powershell window
        2. PS > cd d:\algolab
        3. 在powershell命令行解释器里运行脚本:
            PS > python  tcalc.py
        3a. 或者在python解释器里运行脚本:
            PS > python 
            >>> import tcalc as cbc
            >>> cbc.CBondTransaction().trade()
        4. enter 4 'input' by the prompt: 
            可转债6位代码, 买入量(张数), 买入价, 卖出价
            code
            volume, buy_price
            sell_price
        5. Result will be displayed like below!!!

Result:
-------
market_id code__ name____ volume ave_b_price  sell_price    pnl   pnl%   comm
.sz       123177 测绘转债   120      149.900      150.920 118.79   0.66   3.61    
    '''
    
    # 定义类属性之: 券商佣金率, 最小佣金
    sz_comm  = 1.0/10000
    sh_comm  = 0.2/10000
    etf_comm = 0.5/10000
    stk_comm = 2.0/10000
    
    # sh_comm_min = 1.0
    cb_comm_min =  1.0
    stk_comm_min = 5.0
    
    stk_tax = 5/10000
    
    def __init__(self, code=None):
        '''类的实例化方法:
            self: 表示类的实例自身, python约定俗成地用self这个保留字
        '''
        self.code=code #设置证券代码属性, 并检查其合规性
        if self.code==None:
            self.code = str(input('please input 六位可转债代码: '))

        if  type(self.code)==int:
            self.code=str(self.code)
        
        assert len(self.code)==6, '证券代码不是6位数.' #提取断言可转债代码是否正确

    def _get_comm_rate(self):
        ''' 依据代码的字头确定品种, 设置相应的佣金率
        '5' 字头的为上海场内基金
        '15'字头的为深圳场内基金
        '12'字头的为深圳可转债
        '11'字头的为上海可转债
        '''
        # set stype, mkt_id, comm_rate, comm_min
        if self.code[0]=='5':
            self.stype, self.mkt_id = 'etf', '.sh'
            self.comm_rate, self.comm_min = self.etf_comm, 0.0
        elif self.code[:2]=='15':
            self.stype, self.mkt_id = 'etf', '.sz'
            self.comm_rate, self.comm_min = self.etf_comm, 0.0
            
        elif self.code[:2]=='12':
            self.stype, self.mkt_id = 'sz_cb', '.sz'
            self.comm_rate, self.comm_min = self.sz_comm, self.cb_comm_min
        elif self.code[:2] == '11':
            self.stype, self.mkt_id = 'sh_cb', '.sh'
            self.comm_rate, self.comm_min = self.sh_comm, self.cb_comm_min
        
        elif self.code[:2] == '60':
            self.stype, self.mkt_id = 'sh_stk', '.sh'
            self.comm_rate, self.comm_min = self.stk_comm, self.stk_comm_min
        elif self.code[:2] == '00':
            self.stype, self.mkt_id = 'sz_stk', '.sz'
            self.comm_rate, self.comm_min = self.stk_comm, self.stk_comm_min
        

    def _buy(self, vp_pair=None):
        '''  
        多次买入时, 需要用分号隔开. 比如有两次买入时可以这样输入:
             90,118.546;30,118.22  
             表示: 
                 开仓: 买入90张, 成交价118.546
                 补仓: 买入30张, 成交价118.220
        单次卖出时, 如果是多笔交割的, 也需要用分号隔开. 比如甩货卖出时分为两笔交割,可以这样输入:
             90,118.546;30,118.22  
             表示: 
                 第一笔交割: 卖出90张, 成交价118.546
                 第二笔交割: 卖出30张, 成交价118.220
        '''
        self._get_comm_rate()
        # self.market_id='.sz' if self.code[:2]=='12' else '.sh'

        if (vp_pair==None):
            # vp_pair = input('please input pair of (buy_volume(张), buy_price): ')
            vp_pair = input('请输入进场量价对(逗号为分界符, 多笔交割时用分号为分界符): ')
        vp_pair = [vp.split(',') for vp in vp_pair.split(';')]
        vp_pair = [(int(vp[0]), float(vp[1])) for vp in vp_pair]
        # print(vp_pair)
        
        self.volume, self.bamount, self.buy_cf, self.bcomm = 0, 0, 0, 0
        # 买入时, 当有多笔交割时, 汇总出: 总量 总金额 佣金 和均价
        for volume, bprice in vp_pair:
            amount = volume * bprice
            bcomm = amount * self.comm_rate
            self.volume += volume
            self.bamount += amount
            self.bcomm += bcomm
        if 'cb' in self.stype: # 可转债, 佣金最低为1元
            self.bcomm = max(self.cb_comm_min, self.bcomm)
        elif 'stk' in self.stype: # 股票, 佣金最低为5元
            self.bcomm = max(self.stk_comm_min, self.bcomm)
        self.buy_cf = -self.bamount - self.bcomm
        self.bprice = self.bamount / self.volume # 平均买入价(未考虑佣金)
        # self.bprice = -self.buy_cf / self.volume  # 持仓成本

    def _sell(self, vp_pair=None):
        '''
        输入卖出时的量价对vp, 可以采用下面的三种方式的任意一种方式:
            多笔交割: 40,115.447;20,115.448;10,115.45
            单笔交割: 115.888
            单笔交割: 70,115.888
        '''
        if vp_pair==None:
            # volume=int(input('please input buy volume:'))
            vp_pair = input('请输入出场量价对或者卖出价(逗号为分界符, 多笔交割时用分号作分界符):  ')
        vp_pair = [vp.split(',') for vp in vp_pair.split(';')]
        if len(vp_pair)>1:  # 一次委托单包括不同价格的多笔交割
            vp_pair = [(int(vp[0]), float(vp[1])) for vp in vp_pair]
            volume = sum([e[0] for e in vp_pair]) # 总量
            amount = sum([e[0] * e[1] for e in vp_pair]) # 总金额
            assert volume==self.volume, '卖出的数量不等于买入的数量!!!'
            self.sprice = amount/volume # 平均卖出价
        elif len(vp_pair)==1:  # 委托单是单笔交割的或者是对应同一价格的多笔交割
            vp_pair=vp_pair[0]
            if len(vp_pair)>1:  # 当输入是两个数字时, 被识别为: 量和价
                volume, self.sprice = int(vp_pair[0]), float(vp_pair[1])
                assert volume==self.volume, '卖出的数量不等于买入的数量!!!'
            else:
                self.sprice =  float(vp_pair[0]) # 当输入是单一数字时, 仅仅被识别为卖出价
                volume = self.volume             # 交割量被认为等于买入量
        
        # amount = self.volume * self.sprice
        amount = volume * self.sprice
        self.scomm = amount * self.comm_rate
        if 'cb' in self.stype: # 可转债, 佣金最低为1元
            self.scomm = max(self.cb_comm_min, self.scomm)
        elif 'stk' in self.stype: # 股票, 佣金最低为5元
            self.scomm = max(self.stk_comm_min, self.scomm)
            self.stax = amount * self.stk_tax # 卖出股票需要缴纳印花税
        self.sell_cf = (amount - self.scomm - self.stax) if 'stk' in self.stype else  (amount - self.scomm )
        
    def trade(self, buy_vp=None, sell_vp=None):
        self._buy(vp_pair=buy_vp)
        self._sell(vp_pair=sell_vp)
        self.pnl     = round(sum((self.buy_cf, self.sell_cf)), 2)
        self.pnl_pct = round((self.pnl / -self.buy_cf) * 100, 2)
        self.totcomm = round(sum((self.bcomm, self.scomm)), 2)
        self.tax = self.stax if 'stk' in self.stype else 0.0
        self.name = cn_dict[self.code+self.mkt_id]
        print('Result:')
        print('-------')
        print('market_id code__ name____ volume ave_b_price  sell_price    pnl   pnl%   comm    tax')
        print(' '.join([
            f'{self.mkt_id:9s}', 
            f'{self.code}', 
            f'{self.name}', 
            f'{self.volume:5d}',
            f'{self.bprice:12.3f}',
            f'{self.sprice:12.3f}', 
            f'{self.pnl:6.2f}',
            f'{self.pnl_pct:6.2f}',
            f'{self.totcomm:6.2f}',
            f'{self.tax:6.2f}',
            ]))
        
        return self


def print_help():
    print(
"""
功能简述: 可转债一轮交易的专用计算器. 运行时支持携带可选参数.
    在shell窗口里的运行方法:
        python [{0}] ... [-h] [-c code | -b buy_vp | -s sell_vp]  
    在IPython控制台窗口里的运行方法:
        %run   [{0}] ... [-h] [-c code | -b buy_vp | -s sell_vp]  

参数说明:
-c     : 六位证券代码
-b     : 买入时的量价对数据
-s     : 卖出时的量价对数据
-h     : 帮助信息

应用例子:
    获取帮助:
        # 在powershell的命令行窗口里
        PS> python cbond.py  -h
        
        # 在spyder的IPython控制台窗口里:
        In [12]:  %run cbond_calc.py  -h
    
    运行脚本:
        PS> python tcalc.py  -c  110052 -b  20,189.99 -s 191.23
        PS> python tcalc.py  -c  110052 -b  20,189.99;40,189.55 -s 191.23
         
        In [12]: %run tcalc.py  -c  110052 -b  20,189.99 -s 191.23
        In [12]: %run tcalc.py  -c  110052 -b  20,189.99;30,189.78 -s 191.23
        In [12]: %run tcalc.py  -c  110052 -b  20,189.99;30,189.78 -s 10,191.23;40,191.347

        %run tcalc.py -c 110077 -b "3600,5.01" -s 5.05
        %run tcalc.py -c 123177 -b "3600,5.01" -s 5.05
        %run tcalc.py -c 513330 -b "3600,5.01" -s 5.05
        %run tcalc.py -c 000539 -b "3600,5.01" -s 5.05
        
    备注:
        用到的代码表资源文件: 'c:\\GTJA\\RichEZ\\newVer\\cnt.pkl'.
        该文件应该经常更新(至少每月一次).
""".format(sys.argv[0]))


if __name__ == '__main__':
    opts, args = getopt.getopt(sys.argv[1:],"hc:b:s:")
    # print(opts) #附带的参数都被解析为字符串的类型, 元组的列表 
    # [('-c', '110052'), ('-b', '20,189.99'), ('-s', '191.23')]
    
    code, buy_vp, sell_vp = "", "", ""
    
    for op,value in opts:
        if op == '-c':
            code = value
        elif op == "-b":
            buy_vp = value
        elif op == "-s":
            sell_vp = value
        elif op == '-h':
            print_help()
            sys.exit()
    # print(code, buy_vp, sell_vp)
    
    t = CBondTransaction(code=code)
    t.trade(buy_vp, sell_vp)
    

标签:volume,code,calculator,py,tcalc,vp,comm,pair,self
From: https://www.cnblogs.com/duan-qs/p/18000337

相关文章

  • ztjdtj.py
    代码片#-*-coding:utf-8-*-"""计算涨停价和跌停价,给定品种和昨天收盘价.Parameters----------lc:前收盘价,浮点数stype:整型,optional证券品种(0=可转债,1=股票).Thedefaultis0.Returns-------None.使用举例:%runztjdtj.py100#......
  • plow.py
    代码#-*-coding:utf-8-*-importos,math;importopenpyxlimportdatetime,time;importpandasaspd,numpyasnpfromcollectionsimportnamedtuple_=(os,math,datetime,time,np)importcntfrompytdx2importreaderasrdimportcbondrjfw=......
  • python的十大数据结构之堆队列heapq(heap queue)
    heapqueque(堆队列),是一个完全二叉树,并且满足一个条件:每个节点(叶节点除外)的值都大于等于(或小于等于)它的子节点。提供了构建小顶堆的方法和一些小顶堆的基本操作方法(如入堆、出堆等),可以用于实现堆排序算法。创建堆的两种方法:importheapqlists=[3,10,20,52,2,83,52......
  • python中不同类型文件的读取方法
    在进行卷积神经网络的学习过程中,碰到了不同类型的数据集加载,下面总结一下:1、文本文件:CSV、TSV、Json、Txt1.1、简介CSV文件是逗号分隔值(Comma-SeparatedValues,CSV),其文件以纯文本形式存储表格数据(数字和文本);TSV是Tab-separatedvalues的缩写,即制表符分隔值,与csv和txt都同属......
  • CF1916E Happy Life in University
    关于我赛时线段树忘了开四倍空间导致白吃了一发罚时这档逝原题传送门约定\(x\)子树内的叶子称为\(x\)的叶子。与\(x\)颜色相同的点称为\(x\)的同色点或\(x\)色点。所有在\(x\)子树内的、到\(x\)的路径上(两端不含)没有\(x\)的同色点的\(x\)的同色点称为\(x\)......
  • 龙蜥8.6 源码安装python3.12
    ​ 闲来无事用虚拟机安装了一下龙蜥系统。[root@localhosthome]#cat/etc/*release*AnolisOSrelease8.6NAME="AnolisOS"VERSION="8.6"ID="anolis"ID_LIKE="rhelfedoracentos"VERSION_ID="8.6"PLATFORM_ID="platform:an......
  • python 语法
    >>>list=["a","b","c"]>>>printlist  #python2.x的print语句['a','b','c']>>>from__future__importprint_function #导入__future__包>>>printlist......
  • python学习
    函数python的特性之一:函数可以有多个返回值defdivide_exact(n,d):  returnn//d,n%d>>>a,b=divide_exact(2013,10)>>>a>>>201>>>b>>>3在定义函数时可以给参数默认值,也就是如果参数没有一个与其绑定的值,那么它就会跟默认值绑定。defdivide_exact(n,d=1......
  • Python 机器学习 K-近邻算法 常用距离度量方法
    ​K-近邻(K-NearestNeighbors,KNN)算法中,选择合适的距离度量是非常重要的,因为它决定了如何计算数据点之间的“相似性”。不同的距离度量可能会导致不同的KNN模型性能。选择哪种距离度量取决于数据的类型和问题的性质。可以通过交叉验证来比较不同距离度量对模型性能的影响,以选择最......
  • Python命令行参数的解析
    通常,我们运行Python项目或者脚本采用直接执行脚本的方式,但是Python作为一个脚本语言,在Linux中经常会结合Shell脚本使用,这个时候执行的Python脚本多半需要使用命令行参数传入一些变量,以更加灵活、动态地传递一些数据。例如,运行命令: pythonargv.py123其中12......