android

数据挖掘:eBay上的Galaxy Note

Rplot01

从有Samsung  Galaxy Note 的消息开始,就很期待这款 5.3 寸屏的手机(5.3 寸啊!5.3 寸啊!5.3 寸啊!),但是不出所料,这款手机要很迟才能在北美上市(甚至连会不会上市都还是一个未知数),所以当 Galaxy Note 在欧洲和亚洲发布之后,就只能关注 eBay,等待它从亚欧流入北美。

当欧洲刚刚发布这款手机的时候,eBay 也同步有人开始售卖,一开始的价格大约在 $1000 左右,并且数量很少。等了一段时间,香港的发布会过后,随着大量香港卖家的加入,价钱开始迅速下跌,很快跌倒了$800左右。作为以数字为生的人,当然会“萌”任何时间序列的漂移、扩散和跳跃(不负责的翻译 drift,  diffusion, & jump),但是不断的刷新去查看eBay页面是在令人厌恶,于是就写了一个简单的 C# 程序,定时去“挖掘”eBay 页面上的价格。

但凡提及买卖/价格,就不能不考虑风险(风险也是钱啊),特别是在 eBay 这样高风险的地方。eBay 正好在推出一个新的 beta 产品页面,在 这个页面上 eBay 已经利用自己的算法选出了风险和价格最优的产品,这样一来,挖数据就简单多了,就像附在后面的 C# codes 里显示的那样,只要 request 页面数据,把数据转化成 string,然后利用 C# 自己的 string search/index method,找到相关数据 CSS class, 读入数据即可(数据量很小,所以任何优化都不用做)。然后把数据不断存入 txt 文本。

开始测试时是每两个小时 quote 一次,后来改成一个小时 quote 一次。屏幕上跳出的数字,很像交易所的证券,所以就干脆把它用 chartSeries (R 的 quantmod package)画出来,然后就从数据里发现了很有趣的规律:

  1. 首先总的价格趋势是下跌的,因为开始的高价格完全是因为 supply 的不足,再加上消费类电子产品本身的贬值以及与之相竞争的 HTC,Samsung Android 手机的推出(譬如在北美正式销售的 Galaxy SII skyRocket)

  2. 其次从 Nov 11 到 Nov 14 之间,在微观结构上是两个卖家相互竞争导致价格下跌。为了拿到 eBay 页面上的产品推荐,风险相同的卖家不得不通过降价来相互竞争,但是降价的幅度一般都比较小,特别是从 Nov 13 开始,基本上就是几毛几毛的降;

  3. Nov 15 左右出现了一段价格的稳定期,大约是一家放弃了价格的竞争;

  4. Nov 16 其中一家的货卖完了,剩下的一家觉得自己暂时处在低风险卖家的垄断地位,所以遽然的开始升价,我们看到了一个大大的 jump;

  5. 但是 jump 过后显然市场的反应冷淡,并且我们在上面说过价格的总体趋势是下跌的,如果不能及时卖出,卖家始终有一个 negative carry (也就说价格对于时间的一阶导数是负的),还有最重要的是差不多这个时候,Apple 开始 ship unlock 的 iPhone 4S ,价格大约在 $649 ,对于 Galaxy Note 的价格也是一个打击;

  6. 所以过了 Nov 17 同一卖家又开始降回比原来更低的价格水平

  7. 然后 Nov 18, 价格又开始大幅度的下调,因为有一个新的竞争者出现,而现在手里还攒有大量货的早期卖家基于自己的进货成本,不得不加大降价的力度, theta bleeds :)

当然数据有限,很多只是我的猜测,不过数据本身挺有趣的,不仅本身是一个很 behavior economics的测试,如果数据点足够的多,还能 fit 出一个 term structure 模型来。。。

。。。 所以到后来忘了,我只是来买手机的。。。

image

附 C# codes:

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
 
 
/// <summary>
/// Fetch eBay Price 
/// </summary>
class WebFetch
{
    static void Main(string[] args)
    {
        while (true)
        {
        // used to build entire input
        StringBuilder sb = new StringBuilder();
 
        // used on each read operation
        byte[] buf = new byte[8192];
 
        // prepare the web page we will be asking for
        HttpWebRequest request = (HttpWebRequest)
            WebRequest.Create("http://www.ebay.com/ctg/Samsung-Galaxy-Note-32GB-Black-Unlocked-Smartphone-/110509414");
 
        // execute the request
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        
            // we will read data via the response stream
            Stream resStream = response.GetResponseStream();
 
            string tempString = null;
            int count = 0;
 
            do
            {
                // fill the buffer with data
                count = resStream.Read(buf, 0, buf.Length);
 
                // make sure we read some data
                if (count != 0)
                {
                    // translate from bytes to ASCII text
                    tempString = Encoding.ASCII.GetString(buf, 0, count);
 
                    // continue building the string
                    sb.Append(tempString);
                }
            }
            while (count > 0);
 
            string page = sb.ToString();
 
            //page = Regex.Replace(page, @"<(.|\n)*?>", "");
 
            // print out page source
            string targetString = "bbx2-pv";
            int first = page.IndexOf(targetString);
            string price = page.Substring(first + targetString.Length + 2, 7);
 
            targetString = "ship tfsp bbx2-s";
            first = page.IndexOf(targetString);
            string temp = page.Substring(first + targetString.Length + 2, 20);
            targetString = "</s";
            first = temp.IndexOf(targetString);
            string shipping = temp.Substring(0, first);
 
            if (shipping == "Free shipping") shipping = "$0";
 
            DateTime time = DateTime.Now;
 
            string path = @"C:\Users\Kai\Dropbox\Mis\Android App\GalaxyNote.txt";
 
            using (StreamWriter sw = File.AppendText(path))
            {
                sw.WriteLine("{0}\t{1}\t{2}", time.ToString(), price, shipping);
            }
 
            Console.WriteLine("{0}\t{1}\t{2}", time.ToString(), price, shipping);
 
           Thread.Sleep(1000 * 60 * 60);
        }
        
    }
}
Blog分类: