CCF-BDCI基于买方意向的货物撮合交易-方案分享

2023-10-30 04:20

本文主要是介绍CCF-BDCI基于买方意向的货物撮合交易-方案分享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

感谢starry老哥的投稿,下面就来介绍本次比赛的背景任务和他优秀的解决思路吧(文末附有136分的完整代码链接哦)!!!

赛题链接

链接

赛题背景

期货市场上的货物卖方和货物的买方期望通过期货市场进行货物买卖,达到买卖双方钱货交换的目的(买方从卖方获取货物并向卖方支付对应货款)。

赛题任务

卖方客户已公布需要卖出的货物具体信息,如表格1所示。
表格 1 卖方已公布货物信息

图片

买方客户群体确定,买方客户根据自身需求,并根据卖方客户已公布的货物信息,申报所需购买货物的意向(如表格2所示),当然客户也可不申报意向(购买货物种类、数量确定,只是不指定希望购买货物的属性),由系统进行分配。

 

表格 2 买方客户购买货物意向

图片

任务:通过系统按照买方意向将卖方客户所公布的货物分配给买方客户,要求买方客户的满意率最高,其中买方客户在获取按其意向要求货物的同时,拿到的货物尽量在一个仓库中,则其满意率最高。总体满意率按客户购买货物数量加权计算。

约束条件:具体分配时,优先考虑客户的第一意向,当存在客户的第一意向未满足或者部分未满足时,再考虑客户的第二意向,依次类推。
第一意向在同意向维度、同意向值的情况下,优先为“平均持仓时间”(在买方客户购买意向数据中给出)长的买方客户分配货物。
在按照前述条件下分配货物时,优先分配入库时间长的货物。

评测标准

一、评分原则

在正确反应题目要求和规则的前提下,区分不同参赛队伍算法的相对优劣。


二、计算方法


算法评分包含客户评分和算法整体评分,总分根据以上两项评分进行计算,具体如下

1.在单个品种上,每个客户满意率评分的维度分为意向分和记录分2项,所占权重分别为0.6和0.4,计算规则如下
1)意向分(Hope_score)
根据每个意向上分配的货物数量计算加权得分,具体计算公式如下

图片

j是货物编号,货物编号j的属性满足第k意向(k可以是多个值),POSij指货物编号j的分配货物数量,POSi为客户i 在某品种上购买货物的总量,SCOREk指货物编号j在第k意向上的得分(各品种在每个意向上的得分见下表)。

2)记录分(Diary_score)
客户分到仓库的记录数越少越好,该值设置的目标为梯度得分,直至扣分。具体计算如下:

图片

3.总分计算
单个品种下score公式为:
图片
其中意向分和记录分按客户购买货物数量计算加权得分(大客户分数所占权重更大),此公式中i指客户。
参赛者的总分为各品种下得分加和:
图片
此公式中i指品种。

解决方案

给每一个buyer分配资源,分配的规则是意向优先,尽可能让该buyer满足更多的意向

 1   def search_for_one_buyer(self,var,yixiangs,buyer_id,buyer_index):2        """3        :param var:  SR CF5        :param yixiangs:     该buyer的意向6        :param buyer_id:     该buyer的id7        :param buyer_index: 该buyer在self.buyer的index8        :return:             不返回值,更新剩余资源和Buyer信息9        """
10        buyer_tem=self.tem_buyer.copy()
11        tem_seller=self.tem_seller.copy()
12        number = buyer_tem.loc[buyer_index,'购买货物数量']#.values[0]
13        satisfy_yixiang = [str(self.tem_yixiang_index+1)]
14        for i, (yixiang, yixiang_value) in enumerate(yixiangs):
15            if pd.isna(yixiang):
16                continue
17            if yixiang == '仓库' or yixiang == '年度':
18                yixiang_value = int(yixiang_value)
19            if sum(tem_seller[tem_seller[yixiang] == yixiang_value]['货物数量(张)']) > 0: ##尽可能的取出可以满足多个意向的
20                tem_seller = tem_seller[tem_seller[yixiang] == yixiang_value]
21                satisfy_yixiang.append(str(i + self.tem_yixiang_index+2))
22        tem_seller = tem_seller.sort_values(by=['货物数量(张)'], ascending=True)
23        for i in tem_seller.index:
24            good_num = tem_seller.loc[i]['货物数量(张)']
25            if good_num<=0:
26                continue
27            seller_id=tem_seller.loc[i]['卖方客户']
28            good_id=tem_seller.loc[i]['货物编号']
29            ware_id=tem_seller.loc[i]['仓库']
30
31            # print(good_num)
32            if good_num >= number:
33                tem_seller.loc[i,'货物数量(张)'] = good_num - number
34                self.tem_seller.loc[i,'货物数量(张)'] = good_num - number  ##真实的记录下来
35                self.seller.loc[i,'货物数量(张)']=good_num - number
36                self.result.append([buyer_id, seller_id, var, good_id, ware_id, number, '-'.join(satisfy_yixiang)])
37                number = 0
38                break
39            else:
40                self.result.append([buyer_id, seller_id, var, good_id, ware_id, good_num, '-'.join(satisfy_yixiang)])
41                number = number - good_num
42                tem_seller.loc[i,'货物数量(张)'] = 0  #tem_seller.loc[i]['货物数量(张)'] -good_num
43                self.tem_seller.loc[i,'货物数量(张)'] =0  # self.tem_seller.loc[i]['货物数量(张)']-good_num
44                self.seller.loc[i, '货物数量(张)']=0
45                if number==0:
46                    break
47        self.tem_buyer.loc[buyer_index,'购买货物数量']=number
48        self.buyer.loc[buyer_index,'购买货物数量']=number
49        if number > 0 and sum(self.tem_seller['货物数量(张)']) > 0: ##如果满足最基础意向的还有剩下的,那么就继续  这两个哪怕有一个等一0,那么都不需要继续了。
50            self.search_for_one_buyer(var,yixiangs,buyer_id,buyer_index)

 

根据意向和购买数量对Buyer设定权重

 1    def getorder(self,buyer_tm,var,col1):2       3        if var == "SR":4            weight = [40, 30, 20, 10]5            for i in range(self.tem_yixiang_index, 4):6                buyer_tm.loc[buyer_tm.index, '权值系数'] = buyer_tm.loc[buyer_tm.index, '权值系数'] + pd.notna(buyer_tm.loc[buyer_tm.index, col1[i]]).astype(int) * weight[i]7        else:8            weight = [33, 27, 20, 13, 7]9            for i in range(self.tem_yixiang_index, 5):
10                buyer_tm.loc[buyer_tm.index, '权值系数'] = buyer_tm.loc[buyer_tm.index, '权值系数'] + pd.notna(
11                    buyer_tm.loc[buyer_tm.index, col1[i]]).astype(int) * weight[i]
12        buyer_tm.loc[buyer_tm.index, '权重'] = buyer_tm.loc[buyer_tm.index, '权值系数'] * buyer_tm.loc[buyer_tm.index, '购买货物数量']
13        buyer_tm=buyer_tm.sort_values(by=['权重'],ascending=True)
14        return buyer_tm

 

选择相同意向的buyer进行优先级分类

 1    def search_sameyixiang(self,emotions_and_good):2        """3        :param emotions_and_good:5        :return:6        """7        for dis, var, sum1, _ in emotions_and_good:8            print(dis,var,sum1)9            if sum1<=0:
10                continue
11            thefirst = self.buyer[self.buyer[self.yixiang2value[self.tem_yixiang]] == dis][self.tem_yixiang].iloc[0]
12            self.tem_buyer = self.buyer[(self.buyer[self.yixiang2value[self.tem_yixiang]] == dis) & (self.buyer['品种'] == var)]
13            if thefirst=='年度' or thefirst=='仓库':
14                dis=int(dis)
15            self.tem_seller=self.seller[(self.seller[thefirst]==dis) & (self.seller['品种']==var)]  ##取出这个品种下这个意向的所有seller
16            print('第几意向:', str(self.tem_yixiang_index + 1), '该意向下Buyer数量:', len(self.tem_buyer), "seller数量:",
17                  len(self.tem_seller), '买方的总数量:', sum(self.tem_buyer['购买货物数量']), '卖方总数量:',
18                  sum(self.tem_seller['货物数量(张)']))
19
20            if sum(self.tem_seller['货物数量(张)'])==0:  #如果满足这个意向的货物没有了,那么就不需要了
21                continue
22            self.tem_buyer.loc[self.tem_buyer.index, '权值系数'] = 0
23
24            if self.tem_yixiang_index==0 and sum(self.tem_seller['货物数量(张)'])<sum(self.tem_buyer['购买货物数量']): ##只要在是第一意向并且卖的货物少于买的货物的时候才会这
25                self.tem_buyer=self.tem_buyer.sort_values(by=['平均持仓时间','购买货物数量'],ascending=False) ##根据平均持仓时间倒序,持仓时间越长的越优先挑选货物
26                ##我只要把持有时间长的都弄为第一意向就可以了,别的人就不管他了。
27                sum_seller= sum(self.tem_seller['货物数量(张)']) ##总共有这么多
28                for ii,ij in enumerate(self.tem_buyer.index):
29                    if sum_seller>0:
30                        sum_seller=sum_seller-self.tem_buyer.loc[ij,'购买货物数量']
31                    else:
32                        ##把前面哪些人供应好了就可以了,后面的可以不管
33                        tem_buyer1=self.tem_buyer[:ii]
34                        if sum(tem_buyer1['购买货物数量'])>sum(self.tem_seller['货物数量(张)']): ##这么多的已经足够消化了
35                            print('1111')
36                        tem_buyer2=self.tem_buyer[ii:ii+1]
37                        tem_buyer3=self.tem_buyer[ii+1:]
38                        break
39                tem_buyer1=self.getorder(tem_buyer1,var,list(self.yixiang2value.keys()).copy())
40                tem_buyer3 = self.getorder(tem_buyer3, var, list(self.yixiang2value.keys()).copy())
41                self.tem_buyer=pd.concat([tem_buyer1,tem_buyer2,tem_buyer3])
42            else:##否则按照购买数量进行排序,购买数量越多的就越优先
43                self.tem_buyer=self.getorder(self.tem_buyer,var,list(self.yixiang2value.keys()).copy())
44
45            buyer_tem_len = len(self.tem_buyer)
46
47            for i,buyer_index in enumerate(self.tem_buyer.index):
48                buyer_id=self.tem_buyer.loc[buyer_index,'买方客户']
49                if i==buyer_tem_len-1:
50                    print("第几个买家:",i+1,"多少买家:",buyer_tem_len ,"买家id:",buyer_id,"时间:",datetime.datetime.now(),sum(self.buyer['购买货物数量'])==sum(self.seller['货物数量(张)'])) #
51                if sum(self.tem_seller['货物数量(张)']) == 0:                        ##如果满足意向的货物没有了,那么后面的都不需要再满足了。
52                    break
53                yixiangs=[]
54                for i in range(self.tem_yixiang_index+1,len(self.yixiang2value)):
55                    yixiang=list(self.yixiang2value.keys())[i]
56                    yixiang_value=self.yixiang2value[yixiang]
57                    yixiangs.append(yixiang)
58                    yixiangs.append(yixiang_value)
59                tt = self.tem_buyer[self.tem_buyer.index== buyer_index][yixiangs]
60                tt = tt.values[:1].tolist()[0]
61                yixiangs=[(tt[i],tt[i+1]) for i in range(0,len(tt),2)]
62                self.search_for_one_buyer(var,yixiangs,buyer_id,buyer_index)
63                self.tem_seller = self.tem_seller [self.tem_seller ['货物数量(张)'] > 0]
64                if i==buyer_tem_len-1:
65                    print("该意向下还剩下多少卖家:",len(self.tem_seller))
66            self.seller=self.seller[self.seller['货物数量(张)']>0]
67            self.buyer=self.buyer[self.buyer['购买货物数量']>0]
68            print("目前剩下多少买家:",len(self.buyer))
69            print("目前剩下多少卖家:",len(self.seller))

与search_for_one_buyer相似,只是不需要在乎意向。

 1    def search_by_noyixiang_onebuy(self,buyer_id,var,buyer_index):2        """3        :param buyer_id:5        :param var:6        :param buyer_index:7        :return:8        """9        buyer_tem = self.tem_buyer.copy()
10        tem_seller = self.tem_seller.copy()
11        satisfy_yixiang="0"
12        number = buyer_tem.loc[buyer_index, '购买货物数量']
13        tem_seller = tem_seller.sort_values(by=['货物数量(张)'], ascending=True)
14        for i in tem_seller.index:
15            seller_id=tem_seller.loc[i]['卖方客户']
16            good_id=tem_seller.loc[i]['货物编号']
17            ware_id=tem_seller.loc[i]['仓库']
18            good_num=tem_seller.loc[i]['货物数量(张)']
19            if good_num==0:
20                break
21            index = i
22            if good_num >= number:
23                tem_seller.loc[i,'货物数量(张)'] = good_num - number
24                self.tem_seller.loc[i,'货物数量(张)'] = good_num - number  ##真实的记录下来
25                self.seller.loc[i,'货物数量(张)']=good_num - number
26                self.result.append([buyer_id, seller_id, var, good_id, ware_id, number, satisfy_yixiang])
27                number = 0
28                break
29            else:
30                self.result.append([buyer_id, seller_id, var, good_id, ware_id, good_num, satisfy_yixiang])
31                number = number - good_num
32                tem_seller.loc[i,'货物数量(张)'] = 0  #tem_seller.loc[i]['货物数量(张)'] -good_num
33                self.tem_seller.loc[i,'货物数量(张)'] =0  # self.tem_seller.loc[i]['货物数量(张)']-good_num
34                self.seller.loc[i, '货物数量(张)']=0
35                if number==0:
36                    break
37        self.tem_buyer.loc[buyer_index, '购买货物数量'] = number
38        self.buyer.loc[buyer_index, '购买货物数量'] = number

 

与search_sameyixiang相似,只是不需要在乎意向

 1    def search_by_noyixiang(self):2        """3        :return:5        """6        for var in ["SR","CF"]:7            self.tem_seller=self.seller[self.seller['品种']==var]8            self.tem_buyer=self.buyer[self.buyer['品种']==var]9            self.tem_buyer=self.tem_buyer.sort_values(by=['购买货物数量'], ascending=True)
10            buyer_tem_len = len(self.tem_buyer)
11            print("该情况下买方用户的数量", buyer_tem_len)
12            for i, buyer_index in enumerate(self.tem_buyer.index):
13                buy_id=self.tem_buyer.loc[buyer_index,'买方客户']
14                if i==buyer_tem_len-1:
15                    print("第几个买家:", i + 1, "多少买家:", buyer_tem_len, "买家id:", buy_id, "时间:", datetime.datetime.now(),sum(self.buyer['购买货物数量'])==sum(self.seller['货物数量(张)']))
16                self.search_by_noyixiang_onebuy(buy_id,var,buyer_index)
17                self.tem_seller = self.tem_seller[self.tem_seller['货物数量(张)'] > 0]
18                if i==buyer_tem_len-1:
19                    print("该意向下还剩下多少卖家:", len(self.tem_seller))
20            self.seller=self.seller[self.seller['货物数量(张)']>0]
21            self.buyer=self.buyer[self.buyer['购买货物数量']>0]
22            print("目前剩下多少买家:",len(self.buyer))
23            print("目前剩下多少卖家:",len(self.seller))

 

从第一意向到第五意向搜索。

 1    def sort_by_xiyang(self):2        """3        :return:5        """6        if self.tem_yixiang_index<5:7            self.tem_yixiang = list(self.yixiang2value.keys())[self.tem_yixiang_index]8            tem_buyer=self.buyer[~pd.isna(self.buyer[self.tem_yixiang])]9            tem_yixiang_value=self.yixiang2value[self.tem_yixiang]
10            emotions = list(set(tem_buyer[tem_yixiang_value]))
11            emotions_and_good = []
12            for i in emotions:
13                tem1 = tem_buyer[(tem_buyer[tem_yixiang_value] == i) & (tem_buyer['品种'] == 'SR')]["购买货物数量"].sum()
14                tem2 = tem_buyer[(tem_buyer[tem_yixiang_value] == i) & (tem_buyer['品种'] == 'CF')]["购买货物数量"].sum()
15                emotions_and_good.append((i, "SR", tem1, tem1 * self.SR_value[self.tem_yixiang_index]))
16                emotions_and_good.append((i, "CF", tem2, tem2 * self.CF_value[self.tem_yixiang_index]))
17
18            emotions_and_good=[i for i in emotions_and_good if i[2]>0]
19            emotions_and_good = sorted(emotions_and_good, key=lambda x: x[3])#[::-1]
20            self.search_sameyixiang(emotions_and_good)

关注公众号ChallengeHub回复“ccf购买”获取136分的完整代码链接。加入ChallengeHub粉丝群,共同探讨,共同学习,共同进步!!!
在这里插入图片描述
在这里插入图片描述

这篇关于CCF-BDCI基于买方意向的货物撮合交易-方案分享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/305564

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.

如何选择SDR无线图传方案

在开源软件定义无线电(SDR)领域,有几个项目提供了无线图传的解决方案。以下是一些开源SDR无线图传方案: 1. **OpenHD**:这是一个远程高清数字图像传输的开源解决方案,它使用SDR技术来实现高清视频的无线传输。OpenHD项目提供了一个完整的工具链,包括发射器和接收器的硬件设计以及相应的软件。 2. **USRP(Universal Software Radio Periphera

java常用面试题-基础知识分享

什么是Java? Java是一种高级编程语言,旨在提供跨平台的解决方案。它是一种面向对象的语言,具有简单、结构化、可移植、可靠、安全等特点。 Java的主要特点是什么? Java的主要特点包括: 简单性:Java的语法相对简单,易于学习和使用。面向对象:Java是一种完全面向对象的语言,支持封装、继承和多态。跨平台性:Java的程序可以在不同的操作系统上运行,称为"Write once,

MyBatis 切换不同的类型数据库方案

下属案例例当前结合SpringBoot 配置进行讲解。 背景: 实现一个工程里面在部署阶段支持切换不同类型数据库支持。 方案一 数据源配置 关键代码(是什么数据库,该怎么配就怎么配) spring:datasource:name: test# 使用druid数据源type: com.alibaba.druid.pool.DruidDataSource# @需要修改 数据库连接及驱动u

一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究

转自: 一种改进的red5集群方案的应用: http://wenku.baidu.com/link?url=jYQ1wNwHVBqJ-5XCYq0PRligp6Y5q6BYXyISUsF56My8DP8dc9CZ4pZvpPz1abxJn8fojMrL0IyfmMHStpvkotqC1RWlRMGnzVL1X4IPOa_  基于Red5服务器集群负载均衡调度算法研究 http://ww