예제 #1
0
 def test_get_workdays_holidays(self):
     cases = [
         ((2018, 2, 1), (2018, 1, 1), 0, 0, 0),
         ((2018, 1, 1), (2018, 1, 1), 1, 1, 0),
         ((2018, 1, 1), (2018, 1, 7), 3, 1, 4),
         ((2018, 1, 1), (2018, 2, 1), 9, 1, 23),
     ]
     for start, end, include_weekends, exclude_weekends, workdays in cases:
         start, end = datetime.date(*start), datetime.date(*end)
         self.assertEqual(include_weekends,
                          len(chinese_calendar.get_holidays(start, end)))
         self.assertEqual(
             exclude_weekends,
             len(
                 chinese_calendar.get_holidays(start,
                                               end,
                                               include_weekends=False)))
         self.assertEqual(workdays,
                          len(chinese_calendar.get_workdays(start, end)))
예제 #2
0
 def generate_holidays(self, start_date, end_date):
     """
     利用 chinese-calendar 的第三方库生成起止时间段内的法定节假日列表 并将其转换为 date_int 的格式
     :param start_date:
     :param end_date:
     :return:
     """
     holidays = get_holidays(start_date, end_date, include_weekends=False)
     int_holidays = [self.yyyymmdd_date(h) for h in holidays]
     return int_holidays
예제 #3
0
def get_holidays(year=None, include_weekends=True):
    """
    获取某一年的所有节假日,默认当年
    :param year: which year
    :param include_weekends: False for excluding Saturdays and Sundays
    :return: list
    """
    if not year:
        year = datetime.datetime.now().year
    else:
        year = year
    start = datetime.date(year, 1, 1)
    end = datetime.date(year, 12, 31)
    holidays = chinese_calendar.get_holidays(start, end, include_weekends)
    return holidays
예제 #4
0
 def find_holidays(self):
     self.holidays = get_holidays(self.year_start, self.year_end)
     self.holidays = [[holiday.month, holiday.day]
                      for holiday in self.holidays]
예제 #5
0
def update_asset_graph(asset_code, date_range, customized_date_range):
    start_date, end_date = None, None
    if date_range == '1m':
        start_date = (datetime.now() - timedelta(days=30)).date()
    elif date_range == '3m':
        start_date = (datetime.now() - timedelta(days=60)).date()
    elif date_range == '6m':
        start_date = (datetime.now() - timedelta(days=180)).date()
    elif date_range == '12m':
        start_date = (datetime.now() - timedelta(days=365)).date()
    elif date_range == 'thisyear':
        start_date = datetime.now().replace(month=1, day=1).date()
    elif date_range == 'thismonth':
        start_date = datetime.now().replace(day=1).date()
    elif date_range == 'thisweek':
        today = datetime.now().date()
        start_date = today - timedelta(days=today.weekday())
    elif date_range == 'customized' and customized_date_range:
        start_year, end_year = customized_date_range
        start_date = date(start_year, 1, 1)
        end_date = date(end_year, 1, 1)

    asset = Asset.get(zs_code=asset_code)
    deals = []
    for item in asset.deals:
        if item.action not in ('buy', 'sell'):
            continue

        if start_date and item.time.date() < start_date:
            continue

        if end_date and item.time.date() >= end_date:
            continue

        deals.append({
            'account': item.account,
            'date': item.time.date(),
            'action': item.action,
            'amount': item.amount,
            'price': item.price,
        })

    df = pd.DataFrame(deals)
    if len(deals):
        df.date = pd.to_datetime(df.date)

    fig = go.Figure()
    data = []
    min_date = df.date.min() if start_date is None else start_date
    prices = asset.history.where(AssetMarketHistory.date >= min_date)
    if end_date:
        prices = prices.where(AssetMarketHistory.date < end_date)

    for item in prices.order_by(AssetMarketHistory.date.desc()):
        if item.close_price is not None:
            data.append({
                'date': item.date,
                'open': item.open_price,
                'close': item.close_price,
                'high': item.high_price,
                'low': item.low_price,
            })
        else:
            data.append({
                'date': item.date,
                'price': item.nav,
            })

    data.sort(key=itemgetter('date'))
    price_df = pd.DataFrame(data)
    price_df.date = pd.to_datetime(price_df.date)
    if len(price_df.columns) == 2:
        fig.add_trace(
            go.Scatter(
                x=price_df.date,
                y=price_df.price,
                line={'color': 'orange', 'width': 2},
                name='价格',
                mode='lines'
            )
        )
        if deals and len(df[df.action == 'buy']) > 0:
            fig.add_trace(
                go.Scatter(
                    x=df[df.action == 'buy'].date,
                    y=df[df.action == 'buy'].price,
                    text=[f'{price:0.4f}' for price in df[df.action == 'buy'].price.tolist()],
                    name='买入',
                    mode='markers',
                    marker={'color': 'green'},
                )
            )
        if deals and len(df[df.action == 'sell']) > 0:
            fig.add_trace(
                go.Scatter(
                    x=df[df.action == 'sell'].date,
                    y=df[df.action == 'sell'].price,
                    text=[f'{price:0.4f}' for price in df[df.action == 'sell'].price.tolist()],
                    name='卖出',
                    mode='markers',
                    marker={'color': 'red'},
                )
            )
    else:
        fig.add_trace(
            go.Candlestick(
                x=price_df.date,
                open=price_df.open,
                close=price_df.close,
                high=price_df.high,
                low=price_df.low,
                name='价格',
                opacity=0.3,
                increasing_fillcolor='red',
                increasing_line_color='red',
                decreasing_line_color='green',
                decreasing_fillcolor='green',
            )
        )
        if deals and len(df[df.action == 'buy']) > 0:
            fig.add_trace(
                go.Scatter(
                    x=df[df.action == 'buy'].date,
                    y=df[df.action == 'buy'].price,
                    text=[f'{price:0.4f}' for price in df[df.action == 'buy'].price.tolist()],
                    name='买入',
                    mode='markers',
                    marker={'color': '#1E90FF'},
                )
            )
        if deals and len(df[df.action == 'sell']) > 0:
            fig.add_trace(
                go.Scatter(
                    x=df[df.action == 'sell'].date,
                    y=df[df.action == 'sell'].price,
                    text=[f'{price:0.4f}' for price in df[df.action == 'sell'].price.tolist()],
                    name='卖出',
                    mode='markers',
                    marker={'color': 'purple'},
                )
            )

    fig.update_layout(
        xaxis_rangeslider_visible=False,
        height=500,
        margin={'l': 4, 'r': 4, 'b': 20, 't': 10, 'pad': 4},
        legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01, font_size=14),
        xaxis={'fixedrange': True},
        yaxis={'fixedrange': True},
    )
    fig.update_xaxes(
        tickformat="%m/%d\n%Y",
        rangebreaks=[
            {'bounds': ["sat", "mon"]},
            {
                'values': get_holidays(price_df.date.min(), price_df.date.max(), False)
            }
        ]
    )
    return fig
예제 #6
0
def make_asset_card(asset_info, show_money=True):

    def get_color(value):
        if not isinstance(value, (float, int)):
            return None

        if value > 0:
            return 'text-danger'
        if value < 0:
            return 'text-success'

        return None

    header = dbc.CardHeader([
        html.H5(
            html.A(
                f'{asset_info["name"]}({asset_info["code"]})',
                href=f'/asset/{asset_info["code"].replace(".", "").lower()}',
                target='_blank'
            ),
            className='mb-0'
        ),
        html.P(f'更新日期 {asset_info["price_date"]}', className='mb-0'),
    ])

    body_content = []
    body_content.append(
        make_card_component(
            [
                {'item_cls': html.P, 'type': 'text', 'content': '持有金额/份额'},
                {'item_cls': html.H4, 'type': 'money', 'content': asset_info['money']},
                {'item_cls': html.P, 'type': 'amount', 'content': asset_info['amount']}
            ],
            show_money=show_money,
        )
    )
    body_content.append(
        make_card_component(
            [
                {'item_cls': html.P, 'type': 'text', 'content': '日收益'},
                {
                    'item_cls': html.H4,
                    'type': 'money',
                    'content': asset_info['day_return'],
                    'color': get_color(asset_info['day_return']),
                },
                {
                    'item_cls': html.P,
                    'type': 'percent',
                    'content': asset_info['day_return_rate'],
                    'color': get_color(asset_info['day_return']),
                }
            ],
            show_money=show_money,
        )
    )
    body_content.append(
        make_card_component(
            [
                {'item_cls': html.P, 'type': 'text', 'content': '现价/成本'},
                {'item_cls': html.H4, 'type': 'price', 'content': asset_info['price']},
                {'item_cls': html.P, 'type': 'price', 'content': asset_info['avg_cost'] or 'N/A'}
            ],
            show_money=show_money,
        )
    )

    asset = Asset.get(zs_code=asset_info['code'])
    prices = []
    for item in asset.history.order_by(AssetMarketHistory.date.desc()).limit(10):
        if item.close_price is not None:
            prices.append({
                'date': item.date,
                'price': item.close_price,
            })
        else:
            prices.append({
                'date': item.date,
                'price': item.nav,
            })

        if len(prices) >= 10:
            break

    prices.sort(key=itemgetter('date'))
    df = pd.DataFrame(prices)
    df['date'] = pd.to_datetime(df['date'])
    fig = go.Figure()
    fig.add_trace(
        go.Scatter(
            x=df['date'],
            y=df['price'],
            showlegend=False,
            marker={'color': 'orange'},
            mode='lines+markers',
        )
    )
    fig.update_layout(
        width=150,
        height=100,
        margin={'l': 4, 'r': 4, 'b': 20, 't': 10, 'pad': 4},
        xaxis={'showticklabels': False, 'showgrid': False, 'fixedrange': True},
        yaxis={'showticklabels': False, 'showgrid': False, 'fixedrange': True},
    )
    fig.update_xaxes(
        rangebreaks=[
            {'bounds': ["sat", "mon"]},
            {
                'values': get_holidays(df.date.min(), df.date.max(), False)
            }
        ]
    )
    body_content.append(
        make_card_component(
            [
                {'item_cls': html.P, 'type': 'text', 'content': '十日走势'},
                {
                    'item_cls': None,
                    'type': 'figure',
                    'content': fig
                }
            ],
            show_money=show_money
        )
    )
    body_content.append(
        make_card_component(
            [
                {'item_cls': html.P, 'type': 'text', 'content': '累计收益'},
                {
                    'item_cls': html.H4,
                    'type': 'money',
                    'content': asset_info['return'],
                    'color': get_color(asset_info['return']),
                },
                {
                    'item_cls': html.P,
                    'type': 'percent',
                    'content': asset_info['return_rate'],
                    'color': get_color(asset_info['return']),
                }
            ],
            show_money=show_money,
        )
    )
    body_content.append(
        make_card_component(
            [
                {'item_cls': html.P, 'type': 'text', 'content': '占比'},
                {'item_cls': html.H4, 'type': 'percent', 'content': asset_info['position']},
            ],
            show_money=show_money,
        )
    )

    card = dbc.Card(
        [
            header,
            dbc.CardBody(
                dbc.Row(
                    [dbc.Col([card_component]) for card_component in body_content],
                ),
                className='py-2',
            )
        ],
        className='my-auto'
    )

    return card
예제 #7
0
def draw_day_return_chart(accounts_history, start_date, end_date, show_money):
    df = pd.DataFrame(accounts_history)
    df['date'] = pd.to_datetime(df['date'])
    if start_date is not None:
        df = df[df['date'] >= pd.to_datetime(start_date)]
    if end_date is not None:
        df = df[df['date'] < pd.to_datetime(end_date)]

    df = df[df['account'] == '总计']
    df['day_return'] = (df['return'] - df['return'].shift()).replace({np.nan: 0})

    max_return = df['day_return'].abs().max()
    if not show_money:
        df.loc[:, 'day_return'] = df['day_return'] / max_return

    fig = go.Figure()
    fig.add_trace(
        go.Bar(
            x=df[df['day_return'] >= 0]['date'],
            y=df[df['day_return'] >= 0]['day_return'],
            marker={'color': '#f2757a'},
            showlegend=False,
            name='盈利',
        )
    )
    fig.add_trace(
        go.Bar(
            x=df[df['day_return'] < 0]['date'],
            y=df[df['day_return'] < 0]['day_return'],
            marker={'color': 'green'},
            showlegend=False,
            name='亏损',
        )
    )
    fig.add_hline(
        y=df.day_return.mean(),
        annotation_text="平均值",
        annotation_position="top left",
        line_width=1,
        opacity=0.5,
        line_dash='dot',
    )
    fig.add_hline(
        y=df.day_return.std(),
        annotation_text="标准差",
        annotation_position="top left",
        line_width=1,
        line_dash='dot',
        opacity=0.5,
    )
    fig.update_layout(
        legend_title_text='',
        legend=dict(
            font_size=24,
        ),
        xaxis_tickformat='%m/%d\n%Y',
        margin={'l': 4, 'r': 4, 'b': 20, 't': 10, 'pad': 4},
        xaxis={'fixedrange': True},
        yaxis={'fixedrange': True},
        hovermode='x unified',
    )
    fig.update_xaxes(
        tickformat="%m/%d\n%Y",
        rangebreaks=[
            {'bounds': ["sat", "mon"]},
            {
                'values': get_holidays(df.date.min(), df.date.max(), False)
            }
        ]
    )
    return fig