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)))
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
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
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]
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
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
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