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 //代碼
#2330.TW-Name //商品
#2330.TW-Time //時間
#2330.TW-Bid //買進
#2330.TW-Ask //賣出
#2330.TW-Price //成交
#2330.TW-Volume //單量
#2330.TW-TotalVolume //總量
#2330.TW-High //最高
#2330.TW-Low //最低
#2330.TW-AvgPrice //均價
##########################################################
# 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: 轉碼後,中文註解部分是出現亂碼....
PS :
回覆刪除系統不穩, 有crack的跡象, 可用 *.sh 在外部做二次確保.
在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);