2016年9月29日 星期四

股票經理:計算 EMA 及 MACD


數據已經儲存到資料庫,現在要做的是利用數據計算出一些常用的指標,如:SMA 移動平均線(Simple Moving Average)、EMA 移動平均線(Exponential Moving Average)及 MACD 振盪線(Moving Average Convergence/Divergence)。

SMA 很簡單,按自己的需要,把過往指定天數收市價的和,除以天數,便得到平均數。如:50 天的話,則把過去 50 天的收市價加總起來,再除以 50 便是。這個計算程式很簡單。

至於 EMA 則複雜一點。它其實是加權了的平均數。同樣按自己的需要,把指定天數放入以下公式得出加權值:


有了加權值,把當天的收市價及前一日的 EMA 值套用到以下 EMA 公式:


而 MACD 其實是兩條 EMA 相減,利用上面計算出來的結果就行了。

2016年9月28日 星期三

股票經理:導入數據・二

經過昨天的烏龍後,今天編寫了新的導入數據程式。我的目標是觀察 50 隻恒生指數成份股,如果利用昨天找到的 CSV 逐個導入,也很浪費時間。所以程式是直接從 Yahoo 下載 CSV 並進行導入工作。我只需要執行一句「php updateHistorical.php」指令就行。
<?php
//----------------------------------------------------------------------------------------
//  Stock Manager: Update Historical Data with Yahoo Finance API
//----------------------------------------------------------------------------------------
//  Platform: CentOS7 + PHP + Apache
//  Written by Pacess HO
//  Copyright 2016 Pacess Studio.  All rights reserved.
//----------------------------------------------------------------------------------------

header("Content-type: text/plain");
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Tue, 10 Mar 1987 00:00:00 GMT");

date_default_timezone_set("Asia/Hong_Kong");
mb_internal_encoding("UTF-8");
ini_set("memory_limit", "-1");
set_time_limit(0);

//----------------------------------------------------------------------------------------
//  * Order is important
require("libraries/constants.php");
require("libraries/databaseConnection.php");
require("libraries/stockData.php");

//----------------------------------------------------------------------------------------
//  Yahoo Finance API
//   http://chart.finance.yahoo.com/table.csv?s=0005.HK&a=0&b=1&c=2014&d=8&e=26&f=2016&g=d&ignore=.csv
//
//  Data Sample:
//    Date,Open,High,Low,Close,Volume,Adj Close
//    2016-08-05,53.30,53.85,53.25,53.50,34276500,52.742
//    2016-08-04,52.35,53.25,52.20,53.00,47823500,52.249
//    2016-08-03,50.00,51.80,49.75,51.60,56329500,50.869
//    2016-08-02,50.80,50.80,50.80,50.80,000,50.08
//    2016-08-01,50.80,51.10,50.75,50.80,20010100,50.08

$yahooHistoricalAPI = "http://chart.finance.yahoo.com/table.csv?s=0000.HK&a=mmmm&b=dddd&c=yyyy&d=MMMM&e=DDDD&f=YYYY&g=d&ignore=.csv";

$date = date("Ymd");
$year = intval(substr($date, 0, 4));
$month = intval(substr($date, 4, 2));
$day = intval(substr($date, 6, 2));

//  Prepare historical data URL up to today
$yahooHistoricalAPI = str_replace("YYYY", $year, $yahooHistoricalAPI);
$yahooHistoricalAPI = str_replace("MMMM", $month-1, $yahooHistoricalAPI);
$yahooHistoricalAPI = str_replace("DDDD", $day, $yahooHistoricalAPI);

//----------------------------------------------------------------------------------------
//  Get parameters
$year = 2010;
$month = 1;
$day = 1;

if (isset($_REQUEST["yyyy"]))  {$year = intval($_REQUEST["yyyy"]);}
if (isset($_REQUEST["mm"]))  {$month = intval($_REQUEST["mm"])-1;}
if (isset($_REQUEST["dd"]))  {$day = intval($_REQUEST["dd"]);}

$yahooHistoricalAPI = str_replace("yyyy", $year, $yahooHistoricalAPI);
$yahooHistoricalAPI = str_replace("mmmm", $month-1, $yahooHistoricalAPI);
$yahooHistoricalAPI = str_replace("dddd", $day, $yahooHistoricalAPI);

//----------------------------------------------------------------------------------------
//  Connect Yahoo Finance API and get current day value
$stockData = new stockData();
foreach ($_hengSengIndexesArray as $index)  {

   echo("Retrieving $index data from $url...");
   $url = str_replace("0000.HK", $index, $yahooHistoricalAPI);

   //  Download historical .csv
   //  * Not use fopen here because somehow it cannot read complete content
   $csvContent = file_get_contents($url);
   if ($csvContent)  {

      //  Extract CSV content
      $rowID = 0;
      $dataArray = explode("\n", $csvContent);
      $rowCount = count($dataArray);
      echo("$rowCount rows.\n");
      foreach ($dataArray as $row)  {
         $rowID++;

         $rowArray = str_getcsv($row);
         $count = count($rowArray);
         if ($count < 7)  {

            //  Not enough data, skip it
            echo("Skip #$rowID ($count)...\n");
            continue;
         }

         //  0 = Trade Date
         //  1 = Open Price
         //  2 = High Price
         //  3 = Low Price
         //  4 = Close Price
         //  5 = Volume
         //  6 = Adjusted Close Price
         $date = $rowArray[0];
         $dateSize = strlen($date);
         if ($dateSize < 10)  {

            //  First row is header, skip if row is now date
            continue;
         }

         //  It is data row, continue process
         $open = $rowArray[1];
         $high = $rowArray[2];
         $low = $rowArray[3];
         $close = $rowArray[4];
         $volume = $rowArray[5];
         $adjustedClose = $rowArray[6];

         $sma50 = 0;
         $sma200 = 0;
         $ema9 = 0;
         $ema12 = 0;
         $ema26 = 0;

         //  Save to database         
         $dictionary = array("date"=>$date, "status"=>1, "symbol"=>$index, "open"=>$open,
            "high"=>$high, "low"=>$low, "close"=>$close, "adjustedClose"=>$adjustedClose,
            "volume"=>$volume, "sma50"=>$sma50, "sma200"=>$sma200, "ema9"=>0, "ema12"=>0,
            "ema26"=>0);
         $dictionary = $stockData->addOrUpdateRecord($dictionary);
         if ($dictionary == null)  {
            echo("Parameter not found\n");
         }  else  {

            $affectedRow = $dictionary["affectedRows"];
            switch ($affectedRow)  {
               case 0:  echo("No change ($row)\n");  break;
               case 1:  echo("OK ($row)\n");  break;
               case 2:  echo("Updated ($row)\n");  break;
               default:  echo("Unable to save to database #$affectedRow\n");  break;
            }
         }
      }

   }  else  {

      //  Error
      echo("Unable to download historical data\n");
   }
}
unset($stockData);  $stockData = null;

?>

2016年9月27日 星期二

股票經理:導入數據


有了數據,第二步便是把數據導入到自己的數據庫,方便進行分析及運算,甚至是供給 Machine Learning 系統使用。於是編寫了以下程序:
<?php
//----------------------------------------------------------------------------------------
//  Stock Manager: Historical Price Parser
//----------------------------------------------------------------------------------------
//  Platform: CentOS7 + PHP + Apache
//  Written by Pacess HO
//  Copyright 2016 Pacess Studio.  All rights reserved.
//----------------------------------------------------------------------------------------

//  Reference:
//  https://greenido.wordpress.com/2009/12/22/work-like-a-pro-with-yahoo-finance-hidden-api/
//  http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.historicaldata%20where%20symbol=%222313.HK%22%20and%20startDate%20=%20%222012-09-11%22%20and%20endDate%20=%20%222014-02-11%22&format=json&diagnostics=true&env=store://datatables.org/alltableswithkeys&callback=
//  http://finance.yahoo.com/d/quotes.csv?s=2313.HK&f=snd1l1m3m4l1yr
//  http://finance.yahoo.com/quote/0005.HK/history?period1=1388505600&period2=1474819200&interval=1d&filter=history&frequency=1d

header("Content-type: application/json");
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Tue, 10 Mar 1987 00:00:00 GMT");

date_default_timezone_set("Asia/Hong_Kong");
mb_internal_encoding("UTF-8");
ini_set("memory_limit", "-1");
set_time_limit(0);

//----------------------------------------------------------------------------------------
//  * Order is important
require("libraries/constants.php");
require("libraries/databaseConnection.php");
require("libraries/stockData.php");

//----------------------------------------------------------------------------------------
//  Reading parameter
if (!isset($_REQUEST["data"]))  {echo(json_encode(array("status"=>-1, "message"=>"Parameter not found...")));  exit(-1);}
if (!isset($_REQUEST["symbol"]))  {echo(json_encode(array("status"=>-2, "message"=>"Parameter not found...")));  exit(-2);}

$data = $_REQUEST["data"];
$dataArray = explode("\n", $data);

$symbol = $_REQUEST["symbol"];

//----------------------------------------------------------------------------------------
//  Main parse routine
$skipCount = 0;
$errorCount = 0;
$parseCount = 0;
$stockData = new stockData();
foreach ($dataArray as $row)  {

   $rowArray = explode("\t", $row);
   $rowCount = count($rowArray);

   //  Skip it
   if ($rowCount < 7)  {$skipCount++;  continue;}

   //  Parse data
   //  0            1      2      3      4      5         6
   //    Date         Open   High   Low      Close   Adj Close*   Volume
   //    Sep 23, 2016   58.75   59.00   57.70   58.05   58.05      44,806,106
   $date = $rowArray[0];
   $open = $rowArray[1];
   $high = $rowArray[2];
   $low = $rowArray[3];
   $close = $rowArray[4];
   $adjustedClose = $rowArray[5];
   $volume = $rowArray[6];

   //  Convert 'Sep-26, 2016' to '2016-09-26'
   $dateObject = strtotime($date);
   $date = date("Y-m-d", $dateObject);

   //  Remove comma
   $volume = str_replace(",", "", $volume);

   $dictionary = array("date"=>$date, "status"=>1, "symbol"=>$symbol, "open"=>$open,
      "high"=>$high, "low"=>$low, "close"=>$close, "adjustedClose"=>$adjustedClose,
      "volume"=>$volume, "sma50"=>null, "sma200"=>null, "ema9"=>null, "ema12"=>null,
      "ema26"=>null);
   $dictionary = $stockData->addOrUpdateRecord($dictionary);
   if ($dictionary == null)  {
      $errorCount++;
   }  else  {
      $parseCount++;
   }
}
unset($stockData);  $stockData = null;
echo(json_encode(array(
   "status"=>1, "message"=>"Parse completed.", "errorCount"=>$errorCount,
   "parseCount"=>$parseCount, "skipCount"=>$skipCount, "symbol"=>$symbol)));

?>

使用上方的程式時,需要不停把網頁拖拉到底部,直至所有數據載入完成,才好拷貝並貼上程式。使用了一會兒之後,才發現頁面右上角有一個下載數據按鈕,可以簡單地下載 CSV 格式,不用慢慢拖拉。>_<

股票經理:索取過往市場數據


星期天,內子妹妹丈夫的伯父傳授我投資股票的秘技。他引用了五隻股票過去的數據說明,全部都能套用他的秘技而獲得利潤。雖然金額不至於生活無憂,但總能有點幫助。學伯父話齋:「這個方法不是用來發達,只是用來幫補。每個月有 2% 升幅不錯吧!更何況很多時候都不止這麼少呢」。不過,尋找合乎條件的股票是一件耗時的工作;對於熱愛自動化的我,當然又是把它交給機械人程式去做。我已經急不及待地想盡快完成程式,計算一下敝除心理因素,單憑秘技公式所得出來的利潤結果。

我把程式命名為「股票經理」。要編寫這樣的一個程式,首先是要有股票過往的收市股價數據。得到數據後才能計算出買入及賣出時間。究竟如何取得數據?一是付費購買,二是從網頁抓取。前者不用煩惱,後者需要處理,而且數值最少延遲十五分鐘。對於窮困的我,必然選擇後者。伯父的秘技不是高頻交易,時間不是一個重要的因素,選擇後者不會易響結果。找到 Yahoo 這個頁面:http://finance.yahoo.com/quote/0005.HK/history

2016年9月23日 星期五

Google Allo


看到 Google Allo 推出消息的那天,應用程式還沒有上架,無法下載。其後已經忘記得一乾二淨。到今日再次看到報導,才醒起這個程式。

二十年前,不記得是看「電腦時代」還是「電腦教育」;當時已經有跟機械人聊天的程式。在沒有上網的年代,那個程式已經算是做得不錯,心想有朝一日能開發出這樣的程式也不錯。到今天,還是做不出來。背後需要非常多的知識及運算能力。在嘗試過跟 Google Allo 交談後,感覺比 Siri 優勝一點,畢竟 Google 是搜尋器的大哥,儲存了大量的數據,無論 Apple 怎樣努力,還是有一段差距。至於聊天這個目標,還有很長的路要走。

2016年9月21日 星期三

好書推介:碼書


之前看過一篇關於圖靈的報導,知道他的故事記錄在碼書內。我很想了解更多,決定要找到這本書。

一如以往,在香港要找年份大於兩年的書是機乎沒可能,尤其是不出名的書籍更甚。如果單看書名及封面設計,相信我不會購買此書。幸好,台灣那邊書便宜、層面廣、貨源多。這本 2000 年出版的書,在博客來還有數本,立即購買。剛好朋友出差到台灣,順道託他帶回來。原本都不想麻煩朋友當速遞,但我是愛書之人,博客來寄來的書因為沒有包裝好,在運送的過程中,一定會導致書本殘殘舊舊;所以才辛苦朋友帶回來。星期日見面時,拿到此書,一看十分吸引。它就像小說跟技術書籍的混合體,不僅能欣賞當中的歷史故事,更讓我對加密解密的方法有更多的認識。值得推介。

2016年9月17日 星期六

iPhone SE 到着


女兒的生日快到了,她想要一台 iPhone SE。

自從九月的蘋果大會推出 iPhone 7 後,其他 iPhone 型號都有作出減價,最吸引我的是 iPhone SE。無他,它是一台 4 寸版本的 iPhone 6s,減去了一點點小功能,如: 3D Touch。但 64GB 價錢只需要 HK$3888。非常划算。加上我認識蘋果員工,大幅度的節扣更無比吸引。還有,我收集的 iPhone 型號,沒有 iPhone SE,遲早也要買一台。在種種籍口的驅使下,支持我的購買行動。原本星期一才送來的手機,晚上收到電話,直接到順豐倉提貨。

2016年9月15日 星期四

Apple Store apm


香港新的 Apple Store,將位於官塘的 apm。今日部門中秋午餐在附近,吃完順道過來看一看。不知道開幕當日派發的 T 恤是否跟這塊板的配色一樣呢?9 月 22 日便會知道。

2016年9月14日 星期三

AWS: NoSQL and Lambda Workshop


今天出席了由 Amazon Web Services 舉辦的「AWS: NoSQL and Lambda Workshop」,以下是一點筆記:
  • DynamoDB 的內容是會自動儲存三份
  • DynamoDB 會依照 Hash Key 的值來決定儲存在哪個區間
  • 如果有 Range Key 時,還是會以 Hash Key 做區間的依據,不同的 Range Key 會放在同一區間的不同位置
  • Query 指令中的 Where 只接受 Hash Key 及 Range Key
  • Scan 指令則自由很多,但慢
  • Local Secondary Index 最大為 10GB,但 GSI 可以大過 10GB
  • DynamoDB 一件物件支援最大 400KB
  • 2016年9月13日 星期二

    IBM Watson API


    上星期,上司介紹我瀏覽 IBM Watson 的網頁。IBM Watson?一直有留意機械人業界的消息,也有閱讀相關書籍的我早已知道是甚麼東西來。但上司叫到,還是需要看看網頁。上司?沒錯,我已經離開了 BeyondZ 兩個多月了。她目前繼續由拍檔營運,而我也把所有股份平分給所有股東。

    說回正題。原來 IBM 把 Watson 以 Amazon Web Services 般的方式運作。意味著我可以利用 Watson 的 API 去建立自己的人工智能程序。突然很有發揮的感覺。網頁有數個示範例子,拿我最希望開發的聊天機械人程式試試。可惜,不知是 Watson 的數據不足,還是程式過於簡單;她不能明白我所說的話,比起 Siri 感覺差得遠。明明是很利害的人工智能,何以有這樣的結果?!已經沒有興趣嘗試。隔幾個星期後,再看看有沒有衝勁利用她的 API 編寫程序吧。

    2016年9月12日 星期一

    iPhone 7 開賣通知程式

    過去數年,我能成功購買到第一水 iPhone 及 iPad,是因為編寫了簡單的開賣通知程式,在開賣的一刻以電郵通知我。不過,程式寫得不好,容易出現誤鳴。所以今年重新設計,同時以新學到的 Bash 技術實現。代碼如下:
    #!/bin/bash
    
    ##----------------------------------------------------------------------------------------
    ##  iPhone 7 Availability Monitor
    ##----------------------------------------------------------------------------------------
    ##  Platform: CentOS7 + bash
    ##  Written by Pacess
    ##  Copyright 2016 Pacess Studio.  All rights reserved.
    ##----------------------------------------------------------------------------------------
    
    ##  Variables
    userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36" 
    directory="snapshot"
    log="guard.log"
    
    timeOut=5
    noOfRetry=3
    
    ##----------------------------------------------------------------------------------------
    function PHLog  {
       echo "$1"
       echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$log"
    }
    
    ##----------------------------------------------------------------------------------------
    ##  Program start
    echo "$(date '+%Y-%m-%d %H:%M:%S')"
    echo "-----------------------------------------------------------"
    echo "--  iPhone 7 Availability Monitor Version 1.00           --"
    echo "--  Written by Pacess                                    --"
    echo "--  Copyright 2016 Pacess Studio.  All rights reserved.  --"
    echo "-----------------------------------------------------------"
    echo ""
    
    ##  Move to home directory first
    cd /root/iphone-7-availability-monitor
    
    ##----------------------------------------------------------------------------------------
    ##  Retrieving website content
    echo "Retrieving website content..."
    curl -s --retry $noOfRetry -m $timeOut -A "$userAgent" http://www.apple.com/hk/shop/buy-iphone/iphone-7/5.5-inch-display-128gb-jet-black#01,10,20 > "$directory/store.apple.com.html"
    errorCode=$?;  test "$errorCode" -ne "0" && { PHLog "curl exit error code: $errorCode";  exit; }
    
    ##----------------------------------------------------------------------------------------
    ##  Load website content
    content=$(cat "$directory/store.apple.com.html")
    checkSum=$(echo "$content" | md5sum)
    echo "Check sum: $checkSum"
    
    ##  Check if keyword "Relate" found
    wording=$(grep -o ">Add to Bag<" "$directory/store.apple.com.html")
    wordingSize=${#wording}
    echo "Wording size: $wordingSize"
    if (($wordingSize < 12)); then
       echo "Content ok!"
    else
       PHLog "Apple website content have been changed..."
    
       ##  Save file
       mv "$directory/store.apple.com.html" "$directory/$(date '+%Y%m%d%H%M%S')_store.apple.com.html"
    
       ##  Update checksum, prevent sending email every 15 mins, use > will replace existing contents
       echo "$checkSum" > store.apple.com.md5
    
       ##----------------------------------------------------------------------------------------
       ##  Send email alert
       echo -e "Dear Pacess,\n\niPhone 7 is now available at http://www.apple.com/hk/shop/buy-iphone/iphone-7/5.5-inch-display-128gb-jet-black#01,10,20.\n\nThanks!\n\nSita-bot" | mail -r "robot@pacess.com (Sita-bot)" -s "[Monitor] iPhone 7 is available now..." pacess@pacess.com
    fi

    2016年9月9日 星期五

    iPhone 7 搶機神器・二


    昨天寫的《iPhone 7 搶機神器》在開賣的一刻失敗了,一直無法把 iPhone 7 加到購物籃。不過,今次的失敗並不是程式寫得不好;而是我想買的亮黑色 128GB 在網頁開賣的一刻沒有貨...。

    一如以往,自 iPhone 4s 起,最先開賣的是 Apple Store 應用程式。當天情況依舊。不過卻是 CSL 客戶能優先選購。在開賣的一刻,使用 CSL 1010 的同事順利進入 Apple Store。那時,我在使用公司的 WiFi;不論網頁還是應用程式都處於閉店狀態,就算重新啟動應用程式,還是閉店。我甚至利用了兩個 VPN 來連接,同樣是閉店。直到同事輕輕鬆鬆買了兩台 iPhone 7 Plus 亮黑色 128GB,我的電腦及手機才緩慢地開店。但亮黑色已經售罄...。


    在努力連線,我仍然是閉店的時候,朋友傳來開店畫面。他也是用 CSL 1010。在 Facebook 看到朋友成功購買的貼圖,又是 CSL。似乎 CSL 真的做得好一點。

    2016年9月8日 星期四

    iPhone 7 搶機神器


    明天是第一批 iPhone 7 在網上發售的日子,下午三時候開賣。過去數年到設定了開賣程式,在開賣時以電郵通知我進行手動購買。今次也不例外,編寫了一個全新的通知程式,準確度更高。

    雖然有開賣提示幫忙,但是明天當刻有兩個較長的會議,可能無法親自落單。既然如此,唯有編寫機械人程式代勞。程式員就像有分身這個能力一樣。利用早前學到的 CasperJS 技巧,花了三個多小時,不斷反覆測試,終於完成了「iPhone 7 搶機神器」。只要輸入一行指令,拍一下 Enter 鍵,程式便能自動進入 iPhone 7 頁面購買。如果利用 Cronjob 把它執行,便能在開賣時不停地買。到時,最怕是卡數爬升得太快...;還有就是大量人湧入 Apple 網頁時造成的網絡延遲及突發情況,未知程式能否處理得來。

    2016年9月2日 星期五

    AWS: Relational Database and Migration Workshop


    今日出席了 Amazon Web Services 舉辦的「AWS: Relational Database and Migration Workshop」,以下是一點筆記:
  • 使用 Master-Slave 方式時,可以用不同的 Availability Zone
  • AWS 的 DB 沒有 SSH/RDP 服務
  • PostgreSQL 支援 SSL
  • EBS 加密數據庫時在數據庫層面; Hardware Security Module 則是在檔案層面
  • 一個 AWS 帳號不以生產不同的用戶帳號及權限
  • 當 Primary 數據庫出問題後,AWS 需要花 5-30 秒去轉換 Availability Zone
  • 建議最多用 5 個 Replica
  • CloudWatch 可以查看 VPC 的情況
  • 2016年9月1日 星期四

    Windows + Apache + MSSQL + PHP 測試

    平時較常用 Linux + Apache + MySQL + PHP。今日嘗試把當中兩項改為 Microsoft 的產品,變成 Windows + Apache + MSSQL + PHP,看看需要有多大的改動。

    安裝好 Windows Server 後,裝上 Apache 及 PHP 後,編寫了一個簡單的程式,分別以 PDO 及 sqlsrv 方式對 MSSQL 內的表格進行存取。
    <?php
    //----------------------------------------------------------------------------------------
    //  MSSQL Connection and Query Test for Microsoft Windows 2012
    //----------------------------------------------------------------------------------------
    //  Platform: Windows Server 2012 + PHP7 + Apache24 + MSSQL
    //  Written by Pacess HO
    //  Copyright 2016 Pacess Studio.  All rights reserved.
    //----------------------------------------------------------------------------------------
    
    //  Variables
    $hostname = "127.0.0.1";
    $username = "pacess";
    $password = "Sita0310";
    $database = "SitaChan";
    
    $date = date("YmdHis");
    
    //----------------------------------------------------------------------------------------
    //  Connect to database
    $connectionInfo = array("Database"=>$database, "UID"=>$username, "PWD"=>$password);
    $sqlConnection = sqlsrv_connect($hostname, $connectionInfo);
    
    //----------------------------------------------------------------------------------------
    //  SELECT statement
    $statement = "SELECT * FROM dbo.employees";
    $query = sqlsrv_query($sqlConnection, $statement);
    echo("<br>statement=$statement");
    
    while ($row = sqlsrv_fetch_array($query, SQLSRV_FETCH_NUMERIC))  {
        echo("<br>".$row[1]." / ".$row[2]);
    }
    echo("<hr>");
    
    //----------------------------------------------------------------------------------------
    //  PDO: Connect to database
    //----------------------------------------------------------------------------------------
    $dsn = "sqlsrv:Server=".$hostname.";Database=".$database;
    $pdo = new PDO($dsn, $username, $password);
    $pdo->exec("SET NAMES 'utf8'");
    $pdo->exec("SET CHARACTER SET UTF8");
    $pdo->exec("SET CHARACTER_SET_RESULTS=UTF8");
    
    $pdo->exec("USE TestingDB;");
    
    //----------------------------------------------------------------------------------------
    //  SELECT statement
    $statement = "SELECT * FROM dbo.employees";
    $resultArray = $pdo->query($statement);
    echo("<br>statement=$statement");
    
    $nextID = 1;
    foreach ($resultArray as $row)  {
        $nextID++;
        echo("<br>".$row["employee_name"]." / ".$row["employee_password"]);
    }
    echo("<hr>");
    
    //----------------------------------------------------------------------------------------
    //  INSERT statement
    $newPassword = md5("Pass_".$date);
    
    $statement = "INSERT INTO dbo.employees (employee_id, employee_name, employee_password) VALUES (".$nextID.", 'User_".$date."', '".$newPassword."');";
    $affectedRows = $pdo->exec($statement);
    echo("<br>statement=$statement");
    echo("<br>affectedRows=$affectedRows");
    echo("<hr>");
    
    //----------------------------------------------------------------------------------------
    //  UPDATE statement
    $userPassword = md5($date);
    
    $statement = "UPDATE dbo.employees SET employee_password='".$userPassword."' WHERE employee_name='Pacess'";
    $affectedRows = $pdo->exec($statement);
    echo("<br>statement=$statement");
    echo("<br>affectedRows=$affectedRows");
    echo("<hr>");
    
    ?>