VProfile.tcl

Простой скрипт tcl для построения вертикального профиля рынка по результатам TickWriter. Генерирует CSV из пары полей «цена;объём». Файлы из которых надо строить профиль передаются через аргументы командной строки, полученный CSV выводится на стандартный вывод.

пример использования: tclsh VProfile.tcl EURUSD.tick.20170912.csv EURUSD.tick.20170913.csv EURUSD.tick.20170914.csv EURUSD.tick.20170915.csv EURUSD.tick.20170916.csv > profile.csv

VProfile.tcl
#/usr/bin/tclsh
#
# вычисление вертикального профиля по тиковым данным
#
 
set fileEncoding unicode
set fileTranslation auto
set fields { unixtime mcs asctime bid ask last volume realvol flags }
set n 0 
foreach field $fields {
	set index($field) $n
	incr n
}

# дискретность (точность) 
set precision 0.0001
set tcl_precision 14

# минимальная и максимальная цена
set minPrice 1000000
set maxPrice -1
 
set maxProfile -1
set maxBuy -1
set maxSell -1
set currAsk {}
set currBid {}
# чтение файлов
array set profile {}
foreach fileName [ lrange $argv 0 end ] {
	puts stderr "Reading $fileName"
	if { $fileName != "-" } {
		set f [ open $fileName "r" ]
	} else {
		set f stdin
	}
	fconfigure $f -encoding $fileEncoding -translation $fileTranslation
	while { ! [ eof $f ] } {
		set s [ gets $f ]
		if { $s == {} } {
			continue
		}
		set csv [ split $s ";" ]
		set ask [ lindex $csv $index(ask) ]
		set bid [ lindex $csv $index(bid) ]
		set last [ lindex $csv $index(last) ]
		set volume [ lindex $csv $index(volume) ]
		set flags [ lindex $csv $index(flags) ]
		if { $last != 0 } {
			set price [ expr round($last/$precision)*$precision ]
			if { $price < $minPrice } {
				set minPrice $price
			}
			if { $price > $maxPrice } {
				set maxPrice $price
			}
			if { ! [ info exists profile($price) ] } {
				set profile($price) $volume
				set buy($price) 0
				set sell($price) 0
			} else {
				set profile($price) [ expr $profile($price) + $volume ]
			}
			if { [ lsearch $flags "BUY" ] != -1 } {
				set buy($price) [ expr $buy($price) + $volume ]
			} else {
				set sell($price) [ expr $sell($price) + $volume ]
			}
			if { $profile($price) > $maxProfile } {
				set maxProfile $profile($price)
			}
			if { $buy($price) > $maxBuy } {
				set maxBuy $buy($price)
			}
			if { $sell($price) > $maxSell } {
				set maxSell $sell($price)
			}
		}
	}
	if { $fileName != "-" } {
		close $f
	}
}
 
foreach price [ lsort -real [ array names profile ] ] {
	if { $price < $bid} {
		set p $buy($price)
	} elseif { $price> $ask } {
		set p $sell($price)
	} else {
		set p [ expr ( $buy($price)+$sell($price) )/2 ]
	}
	set csv [ list $price $p ]
	puts [ join $csv ";" ]
}