[float] 卖方向当日持仓盈亏
764058
def sell_holding_pnl(self):
        
        return (self.sell_avg_holding_price - self.last_price) * self.sell_quantity * self.contract_multiplier
939156
def caldata(self, time):
        ''' 
        '''
        if time.date() in self.__ocdate['close']:  # 判對是否為法定休市
            return False
        elif time.date() in self.__ocdate['open']:  # 判對是否為法定開市
            return True
        else:
            if time.weekday() <= 4:  # 判斷是否為平常日開市
                return True
            else:
                return False
162950
def fetch_data(self, stock_no, nowdatetime, firsttime = 1):
    
    url = 'http://www.twse.com.tw/ch/trading/exchange/STOCK_DAY/STOCK_DAY_print.php?genpage=genpage/Report%(year)d%(mon)02d/%(year)d%(mon)02d_F3_1_8_%(stock)s.php&type=csv&r=%(rand)s' % {'year': nowdatetime.year, 'mon': nowdatetime.month, 'stock': stock_no, 'rand': random.randrange(1,1000000)}
    self.debug_print(url)
    logging.info(url)
    #print cc.info().headers

    # set memcache expire
    now = TWTime().now
    if now >= datetime(now.year, now.month, now.day, 14, 45):
      addday = 1
    else:
      addday = 0
    endtime = datetime(now.year, now.month, now.day, 14, 00) + timedelta(days = addday) ## change from 13:35 to 14:00
    logging.info('endtime: %s' % str(endtime))

    if firsttime == 0:
      if endtime <= now:
        expire = 'ALUP' ## always update.
      else:
        expire = (endtime - now).seconds
    else:
      expire = 0 ## never expire.
    logging.info('expire: %s' % expire)

    ## get memcache
    memname = '%(stock)s%(year)d%(mon)02d' % {'year': nowdatetime.year, 'mon': nowdatetime.month,'stock': stock_no}
    stkm = memcache.get(memname)
    if stkm:
      csv_read = csv.reader(stkm)
      logging.info('#MemcacheGet: %s' % memname)
    else:
      cc = urllib2.urlopen(url)
      cc_read = cc.readlines()
      csv_read = csv.reader(cc_read)
      if expire != 'ALUP':
        memcache.add(memname, cc_read, expire)
      else:
        memcache.delete(memname)
      memcache.add('time%s' % memname, '%s %s' % (now, expire))
      logging.info('#MemcacheAdd: %s' % memname)

    return csv_read
616300
def QA_SU_save_stock_min(client=DATABASE, ui_log=None, ui_progress=None):
    
    # 导入掘金模块且进行登录
    try:
        from gm.api import set_token
        from gm.api import history
        # 请自行将掘金量化的 TOKEN 替换掉 GMTOKEN
        set_token("9c5601171e97994686b47b5cbfe7b2fc8bb25b09")
    except:
        raise ModuleNotFoundError

    # 股票代码格式化
    code_list = list(
        map(
            lambda x: "SHSE." + x if x[0] == "6" else "SZSE." + x,
            QA_fetch_get_stock_list().code.unique().tolist(),
        ))
    coll = client.stock_min
    coll.create_index([
        ("code", pymongo.ASCENDING),
        ("time_stamp", pymongo.ASCENDING),
        ("date_stamp", pymongo.ASCENDING),
    ])
    err = []

    def __transform_gm_to_qa(df, type_):
        """
        将掘金数据转换为 qa 格式
        """

        if df is None or len(df) == 0:
            raise ValueError("没有掘金数据")

        df = df.rename(columns={
            "eob": "datetime",
            "volume": "vol",
            "symbol": "code"
        }).drop(["bob", "frequency", "position", "pre_close"], axis=1)
        df["code"] = df["code"].map(str).str.slice(5, )
        df["datetime"] = pd.to_datetime(df["datetime"].map(str).str.slice(
            0, 19))
        df["date"] = df.datetime.map(str).str.slice(0, 10)
        df = df.set_index("datetime", drop=False)
        df["date_stamp"] = df["date"].apply(lambda x: QA_util_date_stamp(x))
        df["time_stamp"] = (
            df["datetime"].map(str).apply(lambda x: QA_util_time_stamp(x)))
        df["type"] = type_

        return df[[
            "open",
            "close",
            "high",
            "low",
            "vol",
            "amount",
            "datetime",
            "code",
            "date",
            "date_stamp",
            "time_stamp",
            "type",
        ]]

    def __saving_work(code, coll):
        QA_util_log_info(
            "##JOB03 Now Saving STOCK_MIN ==== {}".format(code), ui_log=ui_log)
        try:
            for type_ in ["1min", "5min", "15min", "30min", "60min"]:
                col_filter = {"code": str(code)[5:], "type": type_}
                ref_ = coll.find(col_filter)
                end_time = str(now_time())[0:19]
                if coll.count_documents(col_filter) > 0:
                    start_time = ref_[coll.count_documents(
                        col_filter) - 1]["datetime"]
                    print(start_time)
                    QA_util_log_info(
                        "##JOB03.{} Now Saving {} from {} to {} == {}".format(
                            ["1min",
                             "5min",
                             "15min",
                             "30min",
                             "60min"
                             ].index(type_),
                            str(code)[5:],
                            start_time,
                            end_time,
                            type_,
                        ),
                        ui_log=ui_log,
                    )
                    if start_time != end_time:
                        df = history(
                            symbol=code,
                            start_time=start_time,
                            end_time=end_time,
                            frequency=MIN_SEC[type_],
                            df=True
                        )
                        __data = __transform_gm_to_qa(df, type_)
                        if len(__data) > 1:
                            # print(QA_util_to_json_from_pandas(__data)[1::])
                            # print(__data)
                            coll.insert_many(
                                QA_util_to_json_from_pandas(__data)[1::])
                else:
                    start_time = "2015-01-01 09:30:00"
                    QA_util_log_info(
                        "##JOB03.{} Now Saving {} from {} to {} == {}".format(
                            ["1min",
                             "5min",
                             "15min",
                             "30min",
                             "60min"
                             ].index(type_),
                            str(code)[5:],
                            start_time,
                            end_time,
                            type_,
                        ),
                        ui_log=ui_log,
                    )
                    if start_time != end_time:
                        df = history(
                            symbol=code,
                            start_time=start_time,
                            end_time=end_time,
                            frequency=MIN_SEC[type_],
                            df=True
                        )
                        __data = __transform_gm_to_qa(df, type_)
                        if len(__data) > 1:
                            # print(__data)
                            coll.insert_many(
                                QA_util_to_json_from_pandas(__data)[1::])
                            # print(QA_util_to_json_from_pandas(__data)[1::])
        except Exception as e:
            QA_util_log_info(e, ui_log=ui_log)
            err.append(code)
            QA_util_log_info(err, ui_log=ui_log)

    executor = ThreadPoolExecutor(max_workers=2)
    res = {
        executor.submit(__saving_work, code_list[i_], coll)
        for i_ in range(len(code_list))
    }
    count = 0
    for i_ in concurrent.futures.as_completed(res):
        QA_util_log_info(
            'The {} of Total {}'.format(count,
                                        len(code_list)),
            ui_log=ui_log
        )

        strProgress = "DOWNLOAD PROGRESS {} ".format(
            str(float(count / len(code_list) * 100))[0:4] + "%")
        intProgress = int(count / len(code_list) * 10000.0)
        QA_util_log_info(
            strProgress,
            ui_log,
            ui_progress=ui_progress,
            ui_progress_int_value=intProgress
        )
        count = count + 1
    if len(err) < 1:
        QA_util_log_info("SUCCESS", ui_log=ui_log)
    else:
        QA_util_log_info(" ERROR CODE \n ", ui_log=ui_log)
        QA_util_log_info(err, ui_log=ui_log)
193359
def st_atime(self):
        """"""
        atime = self._st_atime_ns / 1e9
        return atime if self.use_float else int(atime)
1358064
def roll_forward(self, dt):
        
        dt = pd.Timestamp(dt, tz='UTC')

        trading_days = self.all_sessions()
        try:
            return trading_days[trading_days.searchsorted(dt)]
        except IndexError:
            raise ValueError(
                "Date {} was past the last session for domain {}. "
                "The last session for this domain is {}.".format(
                    dt.date(),
                    self,
                    trading_days[-1].date()
                )
            )
29224
def QA_SU_save_stock_min(client=DATABASE, ui_log=None, ui_progress=None):
    
    # 导入聚宽模块且进行登录
    try:
        import jqdatasdk
        # 请自行将 JQUSERNAME 和 JQUSERPASSWD 修改为自己的账号密码
        jqdatasdk.auth("JQUSERNAME", "JQUSERPASSWD")
    except:
        raise ModuleNotFoundError

    # 股票代码格式化
    code_list = list(
        map(
            lambda x: x + ".XSHG" if x[0] == "6" else x + ".XSHE",
            QA_fetch_get_stock_list().code.unique().tolist(),
        ))
    coll = client.stock_min
    coll.create_index([
        ("code", pymongo.ASCENDING),
        ("time_stamp", pymongo.ASCENDING),
        ("date_stamp", pymongo.ASCENDING),
    ])
    err = []

    def __transform_jq_to_qa(df, code, type_):
        """
        处理 jqdata 分钟数据为 qa 格式，并存入数据库
        1. jdatasdk 数据格式:
                          open  close   high    low     volume       money
        2018-12-03 09:31:00  10.59  10.61  10.61  10.59  8339100.0  88377836.0
        2. 与 QUANTAXIS.QAFetch.QATdx.QA_fetch_get_stock_min 获取数据进行匹配，具体处理详见相应源码

                          open  close   high    low           vol        amount    ...
        datetime
        2018-12-03 09:31:00  10.99  10.90  10.99  10.90  2.211700e+06  2.425626e+07 ...
        """

        if df is None or len(df) == 0:
            raise ValueError("没有聚宽数据")

        df = df.reset_index().rename(columns={
            "index": "datetime",
            "volume": "vol",
            "money": "amount"
        })

        df["code"] = code
        df["date"] = df.datetime.map(str).str.slice(0, 10)
        df = df.set_index("datetime", drop=False)
        df["date_stamp"] = df["date"].apply(lambda x: QA_util_date_stamp(x))
        df["time_stamp"] = (
            df["datetime"].map(str).apply(lambda x: QA_util_time_stamp(x)))
        df["type"] = type_

        return df[[
            "open",
            "close",
            "high",
            "low",
            "vol",
            "amount",
            "datetime",
            "code",
            "date",
            "date_stamp",
            "time_stamp",
            "type",
        ]]

    def __saving_work(code, coll):
        QA_util_log_info(
            "##JOB03 Now Saving STOCK_MIN ==== {}".format(code), ui_log=ui_log)
        try:
            for type_ in ["1min", "5min", "15min", "30min", "60min"]:
                col_filter = {"code": str(code)[0:6], "type": type_}
                ref_ = coll.find(col_filter)
                end_time = str(now_time())[0:19]
                if coll.count_documents(col_filter) > 0:
                    start_time = ref_[coll.count_documents(
                        col_filter) - 1]["datetime"]
                    QA_util_log_info(
                        "##JOB03.{} Now Saving {} from {} to {} == {}".format(
                            ["1min",
                             "5min",
                             "15min",
                             "30min",
                             "60min"].index(type_),
                            str(code)[0:6],
                            start_time,
                            end_time,
                            type_,
                        ),
                        ui_log=ui_log,
                    )
                    if start_time != end_time:
                        df = jqdatasdk.get_price(
                            security=code,
                            start_date=start_time,
                            end_date=end_time,
                            frequency=type_.split("min")[0]+"m",
                        )
                        __data = __transform_jq_to_qa(
                            df, code=code[:6], type_=type_)
                        if len(__data) > 1:
                            coll.insert_many(
                                QA_util_to_json_from_pandas(__data)[1::])
                else:
                    start_time = "2015-01-01 09:30:00"
                    QA_util_log_info(
                        "##JOB03.{} Now Saving {} from {} to {} == {}".format(
                            ["1min",
                             "5min",
                             "15min",
                             "30min",
                             "60min"].index(type_),
                            str(code)[0:6],
                            start_time,
                            end_time,
                            type_,
                        ),
                        ui_log=ui_log,
                    )
                    if start_time != end_time:
                        __data == __transform_jq_to_qa(
                            jqdatasdk.get_price(
                                security=code,
                                start_date=start_time,
                                end_date=end_time,
                                frequency=type_.split("min")[0]+"m",
                            ),
                            code=code[:6],
                            type_=type_
                        )
                        if len(__data) > 1:
                            coll.insert_many(
                                QA_util_to_json_from_pandas(__data)[1::])
        except Exception as e:
            QA_util_log_info(e, ui_log=ui_log)
            err.append(code)
            QA_util_log_info(err, ui_log=ui_log)

    # 聚宽之多允许三个线程连接
    executor = ThreadPoolExecutor(max_workers=2)
    res = {
        executor.submit(__saving_work, code_list[i_], coll)
        for i_ in range(len(code_list))
    }
    count = 0
    for i_ in concurrent.futures.as_completed(res):
        QA_util_log_info(
            'The {} of Total {}'.format(count,
                                        len(code_list)),
            ui_log=ui_log
        )

        strProgress = "DOWNLOAD PROGRESS {} ".format(
            str(float(count / len(code_list) * 100))[0:4] + "%")
        intProgress = int(count / len(code_list) * 10000.0)

        QA_util_log_info(
            strProgress,
            ui_log,
            ui_progress=ui_progress,
            ui_progress_int_value=intProgress
        )
        count = count + 1
    if len(err) < 1:
        QA_util_log_info("SUCCESS", ui_log=ui_log)
    else:
        QA_util_log_info(" ERROR CODE \n ", ui_log=ui_log)
        QA_util_log_info(err, ui_log=ui_log)
596412
function stringToRegularHolidays (value) {
  var regular = {};
  value = value.split(',').map(x => x.trim());

  // 曜日
  regular.week = makeMap(getWeekIndex(value) || []);

  // 日
  var day = value.map(x => REG_NUM.test(x) ? x * 1 : 0)
                 .filter(x => 1 <= x && x <= 31);
  regular.day = makeMap(day);

  // 第nw曜日
  var xweek = value.map(x => {
    var m = x.match(REG_NUMYOBI);
    if (m) {
      var n = +m[1];
      n = 5 < n ? 5 : n;
      var w = getWeekIndex(m[2]);
      if (1 <= n && w !== null) {
        return n + '-' + w;
      }
    }
    return null;
  }).filter(x => x);
  regular.xweek = makeMap(xweek);
  return regular;
}
517779
def toFloat(val):
    """"""
    hex = "0123456789abcdef"
    return float(hex.find(val[0]) * 16 + hex.find(val[1]))
757830
def _trade(self, security, price=0, amount=0, volume=0, entrust_bs="buy"):
        
        stock = self._search_stock_info(security)
        balance = self.get_balance()[0]
        if stock is None:
            raise exceptions.TradeError(u"没有查询要操作的股票信息")
        if not volume:
            volume = int(float(price) * amount)  # 可能要取整数
        if balance["current_balance"] < volume and entrust_bs == "buy":
            raise exceptions.TradeError(u"没有足够的现金进行操作")
        if stock["flag"] != 1:
            raise exceptions.TradeError(u"未上市、停牌、涨跌停、退市的股票无法操作。")
        if volume == 0:
            raise exceptions.TradeError(u"操作金额不能为零")

        # 计算调仓调仓份额
        weight = volume / balance["asset_balance"] * 100
        weight = round(weight, 2)

        # 获取原有仓位信息
        position_list = self._get_position()

        # 调整后的持仓
        is_have = False
        for position in position_list:
            if position["stock_id"] == stock["stock_id"]:
                is_have = True
                position["proactive"] = True
                old_weight = position["weight"]
                if entrust_bs == "buy":
                    position["weight"] = weight + old_weight
                else:
                    if weight > old_weight:
                        raise exceptions.TradeError(u"操作数量大于实际可卖出数量")
                    else:
                        position["weight"] = old_weight - weight
                position["weight"] = round(position["weight"], 2)
        if not is_have:
            if entrust_bs == "buy":
                position_list.append(
                    {
                        "code": stock["code"],
                        "name": stock["name"],
                        "enName": stock["enName"],
                        "hasexist": stock["hasexist"],
                        "flag": stock["flag"],
                        "type": stock["type"],
                        "current": stock["current"],
                        "chg": stock["chg"],
                        "percent": str(stock["percent"]),
                        "stock_id": stock["stock_id"],
                        "ind_id": stock["ind_id"],
                        "ind_name": stock["ind_name"],
                        "ind_color": stock["ind_color"],
                        "textname": stock["name"],
                        "segment_name": stock["ind_name"],
                        "weight": round(weight, 2),
                        "url": "/S/" + stock["code"],
                        "proactive": True,
                        "price": str(stock["current"]),
                    }
                )
            else:
                raise exceptions.TradeError(u"没有持有要卖出的股票")

        if entrust_bs == "buy":
            cash = (
                (balance["current_balance"] - volume)
                / balance["asset_balance"]
                * 100
            )
        else:
            cash = (
                (balance["current_balance"] + volume)
                / balance["asset_balance"]
                * 100
            )
        cash = round(cash, 2)
        log.debug("weight:%f, cash:%f", weight, cash)

        data = {
            "cash": cash,
            "holdings": str(json.dumps(position_list)),
            "cube_symbol": str(self.account_config["portfolio_code"]),
            "segment": 1,
            "comment": "",
        }

        try:
            resp = self.s.post(self.config["rebalance_url"], data=data)
        # pylint: disable=broad-except
        except Exception as e:
            log.warning("调仓失败: %s ", e)
            return None
        else:
            log.debug(
                "调仓 %s%s: %d", entrust_bs, stock["name"], resp.status_code
            )
            resp_json = json.loads(resp.text)
            if "error_description" in resp_json and resp.status_code != 200:
                log.error("调仓错误: %s", resp_json["error_description"])
                return [
                    {
                        "error_no": resp_json["error_code"],
                        "error_info": resp_json["error_description"],
                    }
                ]
            return [
                {
                    "entrust_no": resp_json["id"],
                    "init_date": self._time_strftime(resp_json["created_at"]),
                    "batch_no": "委托批号",
                    "report_no": "申报号",
                    "seat_no": "席位编号",
                    "entrust_time": self._time_strftime(
                        resp_json["updated_at"]
                    ),
                    "entrust_price": price,
                    "entrust_amount": amount,
                    "stock_code": security,
                    "entrust_bs": "买入",
                    "entrust_type": "雪球虚拟委托",
                    "entrust_status": "-",
                }
            ]
474848
def AmericanDateToEpoch(self, date_str):
    """"""
    try:
      epoch = time.strptime(date_str, "%m/%d/%Y")
      return int(calendar.timegm(epoch)) * 1000000
    except ValueError:
      return 0
863042
def portfolio_value(portfolio, date, price='close'):
    
    value = 0.0
    for (sym, sym_shares) in portfolio.iteritems():
        sym_price = None
        if sym_shares:
            sym_price = get_price(symbol=sym, date=date, price=price)
        # print sym, sym_shares, sym_price
        # print last_date, k, price
        if sym_price != None:
            if np.isnan(sym_price):
                print 'Invalid price, shares, value, total: ', sym_price, sym_shares, (float(sym_shares) * float(sym_price)) if sym_shares and sym_price else 'Invalid', value
                if sym_shares:
                    return float('nan')
            else:
                # print ('{0} shares of {1} = {2} * {3} = {4}'.format(sym_shares, sym, sym_shares, sym_price, sym_shares * sym_price))
                value += sym_shares * sym_price
                # print 'new price, value = {0}, {1}'.format(sym_price, value)
    return value
270197
def get_today_ipo_data():
    

    agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/20100101 Firefox/43.0"
    send_headers = {
        "Host": "xueqiu.com",
        "User-Agent": agent,
        "Accept": "application/json, text/javascript, */*; q=0.01",
        "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
        "Accept-Encoding": "deflate",
        "Cache-Control": "no-cache",
        "X-Requested-With": "XMLHttpRequest",
        "Referer": "https://xueqiu.com/hq",
        "Connection": "keep-alive",
    }

    timestamp = random.randint(1000000000000, 9999999999999)
    home_page_url = "https://xueqiu.com"
    ipo_data_url = (
        "https://xueqiu.com/proipo/query.json?column=symbol,name,onl_subcode,onl_subbegdate,actissqty,onl"
        "_actissqty,onl_submaxqty,iss_price,onl_lotwiner_stpub_date,onl_lotwinrt,onl_lotwin_amount,stock_"
        "income&orderBy=onl_subbegdate&order=desc&stockType=&page=1&size=30&_=%s"
        % (str(timestamp))
    )

    session = requests.session()
    session.get(home_page_url, headers=send_headers)  # 产生cookies
    ipo_response = session.post(ipo_data_url, headers=send_headers)

    json_data = json.loads(ipo_response.text)
    today_ipo = []

    for line in json_data["data"]:
        if datetime.datetime.now().strftime("%a %b %d") == line[3][:10]:
            today_ipo.append(
                {
                    "stock_code": line[0],
                    "stock_name": line[1],
                    "apply_code": line[2],
                    "price": line[7],
                }
            )

    return today_ipo
772196
def settlement_date(self, value):
        
        if value:
            self._settlement_date = parse(value).date() if isinstance(value, type_check) else value
605391
function getDayData(input){
    var data = csvTable(input,"\t");
    var today = new Date().getTime(); //getDateDDMMYYYY();
    var header = data[0];
    var column = 2;
    var minDiff = Number.MAX_SAFE_INTEGER;
    while(column<header.length){
        var columnDate =  new Date(header[column]+' 12:00:00 GMT-0500').getTime();
        if(Math.abs(today-columnDate)<minDiff){
            column++;
            minDiff = Math.abs(today-columnDate);
        }
        else{
            column--;
            break;
        }

    }
    if(column>=header.length){
        return null;
    }
    var result = new Array(data.length-1);
    for(var i=1;i<data.length;i++){
        result[i-1]={id:data[i][0],value:Number(data[i][column]),date:header[column]};

    }

    var table = new Array();
    table.push(result);
    for(var k=2;k<=column-1;k++){
        var row = new Array(data.length-1);
        for(var i=1;i<data.length;i++){
            row[i-1]={id:data[i][0],value:Number(data[i][k]),date:header[k]};
        }
        table.push(row);
    }

    return table;
}
61812
def to_ts(date: datetime.date) -> float:
    
    return datetime.datetime(
        date.year, date.month, date.day,
        tzinfo=datetime.timezone.utc).timestamp()
88626
def propagate(self, date):
        

        i0, Ω0, e0, ω0, M0, n0 = self.tle
        n0 *= 60  # conversion to min⁻¹
        if isinstance(date, Date):
            t0 = self.tle.date.datetime
            tdiff = (date.datetime - t0).total_seconds() / 60.
        elif isinstance(date, timedelta):
            tdiff = date.total_seconds() / 60.
            date = self.tle.date + date
        else:
            raise TypeError("Unhandled type for 'date': %s" % type(date))

        bstar = self.tle.complements['bstar']
        µ = self.gravity.µ_e
        r_e = self.gravity.r_e
        k_e = self.gravity.k_e

        # retrieve initialized variables
        _i = self._init
        n0 = _i.n0

        Mdf = M0 + _i.Mdot * n0 * tdiff
        ωdf = ω0 + _i.ωdot * n0 * tdiff
        Ωdf = Ω0 + _i.Ωdot * n0 * tdiff

        delta_ω = bstar * _i.C3 * cos(ω0) * tdiff
        delta_M = 0.
        if e0 > 1e-4:
            delta_M = - 2 / 3 * (_i.q0 - _i.s) ** 4 * bstar * _i.ξ ** 4 / (e0 * _i.η) * ((1 + _i.η * cos(Mdf)) ** 3 - (1 + _i.η * cos(M0)) ** 3)

        Mp = (Mdf + delta_ω + delta_M) % (2 * np.pi)
        ω = ωdf - delta_ω - delta_M
        Ω = Ωdf - 21 * n0 * _i.k2 * _i.θ / (2 * _i.a0 ** 2 * _i.β_0 ** 2) * _i.C1 * tdiff ** 2
        e = e0 - bstar * _i.C4 * tdiff - bstar * _i.C5 * (sin(Mp) - sin(M0))

        if e < 1e-6:
            e = 1e-6

        a = _i.a0 * (1 - _i.C1 * tdiff - _i.D2 * tdiff ** 2 - _i.D3 * tdiff ** 3 - _i.D4 * tdiff ** 4) ** 2

        L = Mp + ω + Ω + n0 * (3 / 2 * _i.C1 * tdiff ** 2 + (_i.D2 + 2 * _i.C1 ** 2) * tdiff ** 3 + 1 / 4 * (3 * _i.D3 + 12 * _i.C1 * _i.D2 + 10 * _i.C1 ** 3) * tdiff ** 4 + 1 / 5 * (3 * _i.D4 + 12 * _i.C1 * _i.D3 + 6 * _i.D2 ** 2 + 30 * _i.C1 ** 2 * _i.D2 + 15 * _i.C1 ** 4) * tdiff ** 5)

        β = sqrt(1 - e ** 2)
        n = µ / (a ** (3 / 2))

        # Long-period terms
        axN = e * cos(ω)
        ayNL = _i.A30 * sin(i0) / (4 * _i.k2 * a * β ** 2)
        tmp = (1 + _i.θ) if (1 + _i.θ) > 1.5e-12 else 1.5e-12
        L_L = ayNL / 2 * axN * ((3 + 5 * _i.θ) / tmp)

        L_T = L + L_L
        ayN = e * sin(ω) + ayNL

        # Resolving of kepler equation
        U = (L_T - Ω) % (2 * np.pi)
        Epω = U
        for xxx in range(10):
            delta_Epω = (U - ayN * cos(Epω) + axN * sin(Epω) - Epω) / (1 - ayN * sin(Epω) - axN * cos(Epω))
            if abs(delta_Epω) < 1e-12:
                break
            Epω = Epω + delta_Epω

        # Short-period terms
        ecosE = axN * cos(Epω) + ayN * sin(Epω)
        esinE = axN * sin(Epω) - ayN * cos(Epω)
        e_L = sqrt(axN ** 2 + ayN ** 2)
        p_L = a * (1 - e_L ** 2)
        r = a * (1 - ecosE)
        rdot = sqrt(a) / r * esinE
        rfdot = sqrt(p_L) / r

        cosu = a / r * (cos(Epω) - axN + ayN * esinE / (1 + sqrt(1 - e_L ** 2)))
        sinu = a / r * (sin(Epω) - ayN - axN * esinE / (1 + sqrt(1 - e_L ** 2)))
        u = arctan2(sinu, cosu)

        Delta_r = _i.k2 / (2 * p_L) * (1 - _i.θ ** 2) * cos(2 * u)
        Delta_u = - _i.k2 / (4 * p_L ** 2) * (7 * _i.θ ** 2 - 1) * sin(2 * u)
        Delta_Ω = 3 * _i.k2 * _i.θ / (2 * p_L ** 2) * sin(2 * u)
        Delta_i = 3 * _i.k2 * _i.θ / (2 * p_L ** 2) * sin(i0) * cos(2 * u)
        Delta_rdot = - n * _i.k2 * (1 - _i.θ ** 2) * sin(2 * u) / (p_L * µ)
        Delta_rfdot = _i.k2 * n * ((1 - _i.θ ** 2) * cos(2 * u) - 3 / 2 * (1 - 3 * _i.θ ** 2)) / (p_L * µ)

        rk = r * (1 - 3 / 2 * _i.k2 * sqrt(1 - e_L ** 2) / (p_L ** 2) * (3 * _i.θ ** 2 - 1)) + Delta_r
        uk = u + Delta_u
        Ωk = Ω + Delta_Ω
        ik = i0 + Delta_i
        rdotk = rdot + Delta_rdot
        rfdotk = rfdot + Delta_rfdot

        # Vectors
        vM = np.array([- sin(Ωk) * cos(ik), cos(Ωk) * cos(ik), sin(ik)])
        vN = np.array([cos(Ωk), sin(Ωk), 0])

        vU = vM * sin(uk) + vN * cos(uk)
        vV = vM * cos(uk) - vN * sin(uk)

        vR = rk * vU * r_e
        vRdot = (rdotk * vU + rfdotk * vV) * (r_e * k_e / 60.)

        vector = np.concatenate((vR, vRdot)) * 1000  # conversion to meters

        return self.tle.__class__(date, vector, 'cartesian', 'TEME', self.__class__(), **self.tle.complements)