2010年5月17日 星期一

RealDDE 4 Fubon Server...

Target: 利用Real Time 的 DDE 做即時的進場/出場判斷機制. DDE 4 FuBon(富邦) 一些基本的定義,可參考底下的連結. http://funningboy.blogspot.com/2010/02/dde-server-for-stock.html Design Flow: Advantages: 1.利用 Thread 的方式增加系統的效能. 2.Entry Rule 可針對特定的StockID 有不同的進出場方式. 3.利用Queue來增加系統的穩定性,避免Latency 4 Proc, 拖垮系統的效能. CostFunc: Memory(記憶體), CPU Time處理速度...

Sample : 底下用最簡單的 Sample 當例子. Entry Rule : 當連續10筆資料中, 出現 "成交價 大於 買進價 且 成交量 大於等於 100 的次數" 大於 10*2/3=6 次, 就告知可以做買進的動作. 當然你也可以自己定義你的進出場訊號.最後在接回Display, 或者是 Internet 傳送.... Code
use Class::Struct; #use strict; use Win32::DDE::Client; use Win32::DDE; use Data::Dumper; use threads qw(yield); use Thread; use Thread::Queue; use threads::shared; #no warnings 'threads'; # example 4 2330.TW ########################################################## #2330.TW-ID //&#20195;&#30908; #2330.TW-Name //&#21830;&#21697; #2330.TW-Time //&#26178;&#38291; #2330.TW-Bid //&#36023;&#36914; #2330.TW-Ask //&#36067;&#20986; #2330.TW-Price //&#25104;&#20132; #2330.TW-Volume //&#21934;&#37327; #2330.TW-TotalVolume //&#32317;&#37327; #2330.TW-High //&#26368;&#39640; #2330.TW-Low //&#26368;&#20302; #2330.TW-AvgPrice //&#22343;&#20729; ########################################################## # DDE Info definition struct( DDEInfo => { DDE_SER => '$', DDE_HOST => '$', }); my $DDE = DDEInfo->new(); $DDE->DDE_SER('XQFAP'); $DDE->DDE_HOST('Quote'); # Stock info 4 FuBon definition struct( STInfo => { ST_ID => '$', ST_NM => '$', ST_TM => '$', ST_BID=> '$', ST_ASK=> '$', ST_PRC=> '$', ST_VOL=> '$', ST_HIG=> '$', ST_LOW=> '$', }); # Queue Definition 4 DDE 2 Entry struct ( QUInfo => { QU_SIZ => '$', QU_PT_OK_LAT=> '$', QU_PT_NO_LAT=> '$', QU_GT_OK_LAT=> '$', QU_GT_NO_LAT=> '$', }); my $QU = QUInfo->new(); $QU->QU_SIZ(5); $QU->QU_PT_OK_LAT(1); $QU->QU_PT_NO_LAT(2); $QU->QU_GT_OK_LAT(1); $QU->QU_GT_NO_LAT(2); # Buffer Definition 4 Entry struct ( BUFInfo => { BUF_SIZ => '$', }); my $BUF = BUFInfo->new(); $BUF->BUF_SIZ(10); #==============================================# # Create Each Thread 4 StockID #==============================================# open (iStockIDPtr, "../../StockList.csv") die "Open StockList Error\n"; while(<iStockIDPtr>){ chomp; my $StockID = $_; my $q = Thread::Queue->new(); my $thr1 = threads->create(\&GetQueue,$StockID,$q); my $thr2 = threads->create(\&PutQueue,$StockID,$q); } #=============================================# # Run And Display #=============================================# for(;;){ my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year += 1900; $mon += 1; my $MyEndTime = $year."/".$mon."/".$mday."/".$hour."::".$min."::".$sec; print "OK...".$MyEndTime."\n"; sleep 60; } sub PutQueue :locked { my $StockID = $_[0]; my $q = $_[1]; for(;;){ if($q->pending()<=$QU->QU_SIZ()){ my $t= &GetStockInfo($StockID); $q->enqueue($t); yield; sleep $QU->QU_PT_OK_LAT(); } else { yield; sleep $QU->QU_PT_NO_LAT(); } } } sub GetQueue :locked { my $StockID = $_[0]; my $q = $_[1]; for(;;){ if($q->pending()!=0 ){ $t = $q->dequeue; GetEntryInfo($StockID,$t); yield; sleep $QU->QU_GT_OK_LAT(); } else{ yield; sleep $QU->QU_GT_OK_LAT(); } } return $t; } sub GetStockInfo { my $StockID = $_[0]; my $Client = new Win32::DDE::Client ( $DDE->DDE_SER(), $DDE->DDE_HOST() ); die "Unable to initiate conversation" if $Client->Error; my ($ID,$NM,$TM,$BID,$ASK,$PRC,$VOL,$HIG,$LOW) = (-1,-1,-1,-1,-1,-1,-1,-1,-1); defined ( $ID = $Client->Request ($StockID.'-ID')) print "Error ID request\n"; defined ( $NM = $Client->Request ($StockID.'-Name')) print "Error NM request\n"; defined ( $TM = $Client->Request ($StockID.'-Time')) print "Error TM request\n"; defined ( $BID = $Client->Request ($StockID.'-Bid')) print "Error BID request\n"; defined ( $ASK = $Client->Request ($StockID.'-Ask')) print "Error ASK request\n"; defined ( $PRC = $Client->Request ($StockID.'-Price')) print "Error PRC request\n"; defined ( $VOL = $Client->Request ($StockID.'-Volume')) print "Error VOL request\n"; defined ( $HIG = $Client->Request ($StockID.'-High')) print "Error HIG request\n"; defined ( $LOW = $Client->Request ($StockID.'-Low')) print "Error LOW request\n"; my $t = STInfo->new(); $t->ST_ID($ID); $t->ST_NM($NM); $t->ST_TM($TM); $t->ST_BID($BID); $t->ST_ASK($ASK); $t->ST_PRC($PRC); $t->ST_VOL($VOL); $t->ST_HIG($HIG); $t->ST_LOW($LOW); return $t; } sub GetEntryInfo { my $StockID = $_[0]; my $t = $_[1]; my @ArrPtr = @{$BufHsPtr{$StockID}}; if( $#ArrPtr == $BUF->BUF_SIZ() ){ #print Dumper(\@ArrPtr); my $cot =0; for(my $i=0; $i<=$#ArrPtr; $i++){ if( $ArrPtr[$i]->ST_PRC() > $ArrPtr[$i]->ST_BID() && $ArrPtr[$i]->ST_VOL >= 100 ){ $cot++;} } if( $cot >= $#ArrPtr*2/3 ){ print "Found ::".$StockID." count( PRC>BID &&VOL >=100 )\n"; } shift( @{$BufHsPtr{$StockID}} ); } else { push ( @{$BufHsPtr{$StockID}}, $t); } }
code download http://sites.google.com/site/funningboy/perl_code/realtime3.pl?attredirects=0&d=1 PS: 轉碼後,中文註解部分是出現亂碼....

2 則留言:

  1. PS :
    系統不穩, 有crack的跡象, 可用 *.sh 在外部做二次確保.

    回覆刪除
  2. 在FuBon 的e01 下, 大概20秒刷新一次Data, 所以我們要把Latency 加大,不然會access到相同的Data, 且 Crack 機會大增.

    Before
    my $QU = QUInfo->new();
    $QU->QU_SIZ(5);
    $QU->QU_PT_OK_LAT(1);
    $QU->QU_PT_NO_LAT(2);
    $QU->QU_GT_OK_LAT(1);
    $QU->QU_GT_NO_LAT(2);

    After
    my $QU = QUInfo->new();
    $QU->QU_SIZ(5);
    $QU->QU_PT_OK_LAT(20);
    $QU->QU_PT_NO_LAT(30);
    $QU->QU_GT_OK_LAT(20);
    $QU->QU_GT_NO_LAT(30);

    回覆刪除