javaanddonet 发表于 2018-5-9 18:21:46

一个MR的面试题


         ORDERIDTRADERSTKCODEQUANTITYPRICETRADETYPEFEETIMESTAMP
1AAA22222210010Buy0.25/9/2016 13:38
2BBB33333310008.8Sell10.565/9/2016 10:37
3AAA22222210011Sell1.325/10/2016 13:38
4BBB3333338009Buy1.65/11/2016 14:58
5BBB3333334009.2Buy0.85/16/2016 10:28
6AAA55555560015.5Buy25/16/2016 10:31


数据如上所示,逗号作为字段之间的分隔符。
Note: Either long a stock (buy first, and sell later) or short a stock (sell first, and buy later) first is allowedFor a trader, total Buy Quantity and Sell Quantity might not be equal, in that case, just calculate the realized profit or lossTransaction fee should be considered as cost, and all fees are realized

要求得到如下结果:
AAA 96.48
BBB -252.96

每个账号每个股票的盈亏情况,
使用MR或你擅长的任何语言都可以。






补充内容 (2018-5-10 14:02):
DESCRIPTION
Here we have a list of stock orders for some users in the same period. We want to sort these users according to their realized profit, i.e. how much they have already earned.

Please note that:
Either long a stock (buy first, and sell later) or short a stock (sell first, and buy later) first is allowed
For a trader, total Buy Quantity and Sell Quantity might not be equal, in that case, just calculate the realized profit or loss
Transaction fee should be considered as cost, and all fees are realized

INPUT
Input is in TSV format, i.e. columns are separated by tab, like:

OrderId        Trader        StkCode        Quantity        Price        TradeType        Fee        Timestamp
1        AAA        222222        100        10        Buy        0.2        2016-05-09 13:38:24
2        BBB        333333        1000        8.8        Sell        10.56        2016-05-09 10:37:16
3        AAA        222222        100        11        Sell        1.32        2016-05-10 13:38:24
4        BBB        333333        800        9.0        Buy        1.6        2016-05-11 14:58:30
5        BBB        333333        400        9.2        Buy        0.8        2016-05-16 10:28:24
6        AAA        555555        600        15.5        Buy        2.0        2016-05-16 10:31:33
7        ...

OUTPUT
Output should be TSV format too, including 2 columns: Trader, profit/loss. Header is not needed.

For example, given the input above, the correct output is:
AAA        96.48
BBB        -252.96       

REQUIREMENT
Please write code that takes orders as input, and outputs users’ profits, sorted in descending order.
You may use any language you like. Your solution will be graded on the following criteria:
Codereadability, quality, and design. In terms of quality, please write your code as if it would eventually be pushed into production.
Correctness / performance (speed/memory footprint

javaanddonet 发表于 2018-5-11 17:00:49

nextuser 发表于 2018-5-11 13:55
对股票业务不了解。楼主知道这个结果是怎么来的吗




            OrderIdTraderStkCodeQuantityPriceTradeTypeFeeTimestamp
1AAA22222210010Buy0.25/9/2016 13:38-11000.00-1000.000.20-1000.2
3AAA22222210011Sell1.325/10/2016 13:3811100.001100.001.321098.68
6AAA55555560015.5Buy25/16/2016 10:3119300.009300.002.00
上面的600废弃 98.48
2BBB33333310008.8Sell10.565/9/2016 10:3718800.008800.0010.568789.44
4BBB3333338009Buy1.65/11/2016 14:58-17200.00-7200.001.60-7201.6
5BBB3333334009.2Buy0.85/16/2016 10:28-13680.00-3680.000.80-3680.8
上面的400,得拆出来一个200,才能是1000=800+20
BBB3333332009.2Buy0.85/16/2016 10:28-11840.00-1840.000.80-1840.8
-252.96



我分析了一下,每个人的股票的买入和卖出的数目相同的情况下才能进行统计。如果不相同,需要进行舍弃忽略或者拆分的操作。
1.比如上面的ID为6的记录,A用户买入了600股555555,这600股,没有卖出,不能计算这个股票的盈亏。舍弃这样的记录,因为这张股票还在A手中,我们不知道以后股票卖出的时候,是涨还是跌。所以不能计算。
2.ID为5的记录,表示B买入了400股333333。综合交易时间来看,B先卖出了1000股333333,后来又买入了800股,过来几天,又对333333买入了400股。此时就B对股票333333而已,卖出1000,买入1200,计算盈亏的时候,不能将多买入的200计算在内,应该将买入的1000和买入的800+200进行计算盈亏。多买入的200股,还在B手中持有,不能计算这200股的盈亏,原因和上面的A持有的600股不能计算盈亏原因一样。

这是我目前的理解。

hello2018 发表于 2018-5-10 07:36:09

这个问题还需要详细说说。有时间亲自试验下

javaanddonet 发表于 2018-5-10 09:38:11

hello2018 发表于 2018-5-10 07:36
这个问题还需要详细说说。有时间亲自试验下

我目前所理解的是:A买入的“555555”股票的600股,不能计算在内,因为这个股票A还在持有当中,不能计算他的盈亏情况。
B最后买入的“333333”股票400股,不能全部计算在内,只能计算200股,让其加上上面的800股,等于B卖出的1000股,这样对于B的“333333”的1000股的买入和卖出进行计算盈亏。


感觉不是很好写。有点难度。

fly2015 发表于 2018-5-10 11:40:55

需求严重不清晰,先把需求弄清楚再发上来,否则别人帮不到你。

nextuser 发表于 2018-5-11 13:55:05

javaanddonet 发表于 2018-5-10 09:38
我目前所理解的是:A买入的“555555”股票的600股,不能计算在内,因为这个股票A还在持有当中,不能计算 ...

对股票业务不了解。楼主知道这个结果是怎么来的吗

javaanddonet 发表于 2018-5-14 13:42:58

研究了一下,有一个这样的思路:

Mapper中根据用户名+股票代码作为key,将整行记录作为一个自定义的bean对象作为输出的value,在自定义bean中,实现compareTo方法,根据交易日期倒序排列。这里的排序是为了后面在Reducer段获取需要平账的记录。

在Reducer端,遍历每一个用户+股票代码对应的beans。

在判断的过程中,记录每一个key出现的beans的个数。如果某一个用户名+股票代码只有一个bean结果,那么则舍弃这样的记录。

判断所有的bean中的股票数相加是否为0(这里有一个前提是:在自定义的bean中,将Buy的股票数乘以-1,Sell的股票数目乘以1)。

如果为0的记录,可以直接进行求知:收益=股票数*股票单价-手续费。

如果不为0的记录,可以得到一个差值,这里标记为m,然后取出集合中的第一个bean对象,将它的股票数目-m就可以平衡用户+股票代码下面的股票数目。然后在按照收益公式进行计算。

sstutu 发表于 2018-5-14 17:42:38

本帖最后由 sstutu 于 2018-5-14 17:54 编辑

javaanddonet 发表于 2018-5-14 13:42
研究了一下,有一个这样的思路:

Mapper中根据用户名+股票代码作为key,将整行记录作为一个自定义的bean ...
收益这里是关键,这样才能正确的计算。
首先有长期买入或则做空,
对应先买后卖,或则先卖后买。
下面公式:
收益=卖出股票-手续费-买入股票。
接下来一个个计算
Sell 卖出股票=股票数量*股票价格-手续费
Buy 买股票=股票数量*股票价格+手续费
股票收费费不等为0.2%,10.56 %等。这样收益就的出来了。
首先手工计算花的钱

AAA总共买了两家股票
222222:数量100 价格10    手续费0.2%      
555555:数量600 价格15.5 手续费2%

然后计算收入

222222 数量100 价格11    手续费1.32%

首先计算222222 购买花的钱
100*10+100*0.2%=1000+0.2=1000.2

赚的钱
100*11-100*1.32%=1100-1.32=1098.68

222222 收益=赚的钱-花钱=1098.68-1000.2=98.48




sstutu 发表于 2018-5-14 18:07:56

如果使用mapreduce来实现。
当然首先是按照股票代码为基准,当然需要带上用户,为一个key,然后如果既有sell,有用buy,这样就可以计算,否则如果只有一个则放弃计算。然后按照上面的收益公式来计算。
思路其实跟楼主的也是吻合。

spftoto 发表于 2018-6-26 09:38:13

有点复杂,知道了计算公式,不知道怎么用mapreduce实现
页: [1]
查看完整版本: 一个MR的面试题