├── CMakeLists.txt ├── compile.sh ├── configs ├── Direct.Bats.ini ├── Direct.Bats.ini~ ├── admin_config.xml ├── admin_config.xml~ ├── admin_config_server.xml ├── symbol_config_new.xml ├── symbol_config_new.xml~ ├── symbol_config_onlyC.xml ├── trading_config_new.xml └── trading_config_new.xml~ ├── connect.sh ├── copylog.sh ├── deploy.sh ├── run_stem.sh ├── scripts ├── file.csv ├── kill_stem.sh ├── line-0 ├── line-1 ├── liverun.txt ├── liverun.txt~ ├── livestats.sh ├── livestatsold.sh ├── livestatssorted.sh ├── log_processing.sh ├── log_processing.sh~ ├── order_processing.awk ├── positiontoredis.sh ├── readarray ├── redisfile.csv ├── redistofile.sh ├── run_stem.sh ├── run_stem.sh~ └── run_stem_for_server.sh └── src ├── CMakeLists.txt ├── CMakeLists.txt~ ├── STEMConsole.cpp ├── akela ├── CMakeLists.txt ├── OrderAccount.cpp ├── OrderAccount.h ├── STEMDirectConnection.cpp ├── STEMDirectConnection.h ├── STEMMaddogConnection.cpp └── STEMMaddogConnection.h ├── avicenna ├── AvicennaInterface.cpp ├── AvicennaInterface.h └── CMakeLists.txt ├── cli ├── CLI.cpp ├── CLI.h └── CMakeLists.txt ├── config ├── AdminConfig.h ├── CMakeLists.txt ├── ConfigReader.h ├── SymbolConfig.h └── TradingConfig.h ├── libs ├── avicenna │ ├── AvicennaSuperPlus.h │ ├── Definition.h │ ├── Output.txt │ ├── Sample.txt │ ├── SuperPlusdata.txt │ └── libAvicennaSuperPlus.so └── redis │ ├── anet.c │ ├── anet.h │ ├── fmacros.h │ ├── libredisclient.a │ └── redisclient.h ├── manager ├── CMakeLists.txt ├── SymbolManager.cpp ├── SymbolManager.h ├── TradeAccountManager.cpp └── TradeAccountManager.h ├── redis ├── CMakeLists.txt ├── RedisWriter.cpp └── RedisWriter.h ├── stem1.cpp ├── tests ├── CMakeLists.txt ├── order_sending.cpp └── position_table.cpp ├── trade ├── AbstractTradeAccount.cpp ├── AbstractTradeAccount.h ├── AvicennaInterface.cpp~ ├── AvicennaInterface.h~ ├── CMakeLists.txt ├── CMakeLists.txt~ ├── LongTradeAccount.cpp ├── LongTradeAccount.h ├── PositionRecordTable.h ├── STEMMaddogConnection.cpp~ ├── ShortTradeAccount.cpp ├── ShortTradeAccount.h ├── TradeCase.cpp ├── TradeCase.h ├── TradeInstance.cpp └── TradeInstance.h └── utils ├── AsynchronousQueue.cpp ├── AsynchronousQueue.h ├── AsynchronousUnorderedMap.h ├── AsynchronousVector.h ├── CMakeLists.txt ├── ThreadPool.h ├── console.h ├── log.cpp ├── log.h └── utils.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | 4 | project(stem3) 5 | 6 | #set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install) 7 | message("-- installation directory ${CMAKE_INSTALL_PREFIX}") 8 | 9 | 10 | add_definitions(-std=c++11) 11 | add_definitions(-DBOOST_LOG_DYN_LINK=1) 12 | add_definitions(-DBOOST_TEST_DYN_LINK) 13 | 14 | set(CMAKE_VERBOSE_MAKEFILE 1) 15 | 16 | include_directories(${PROJECT_SOURCE_DIR}/src/libs/avicenna/) 17 | include_directories(${PROJECT_SOURCE_DIR}/src/libs/redis/) 18 | include_directories($ENV{AKELA_SDK_ROOT}/include/) 19 | include_directories(/home/jamil/workspace/boost_1_57_0/) 20 | 21 | message("-- linking akela library from ... $ENV{AKELA_SDK_ROOT}/lib") 22 | link_directories($ENV{AKELA_SDK_ROOT}/lib) 23 | message("-- linking avicenna library from ... ${PROJECT_SOURCE_DIR}/src/libs/avicenna") 24 | link_directories(${PROJECT_SOURCE_DIR}/src/libs/avicenna) 25 | message("-- linking redis library from ... ${PROJECT_SOURCE_DIR}/src/libs/redis") 26 | link_directories(${PROJECT_SOURCE_DIR}/src/libs/redis) 27 | 28 | 29 | add_subdirectory(src) 30 | 31 | install(DIRECTORY scripts/ 32 | DESTINATION scripts 33 | FILES_MATCHING PATTERN "*.sh" 34 | PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE 35 | GROUP_WRITE GROUP_READ GROUP_EXECUTE 36 | WORLD_WRITE WORLD_READ WORLD_EXECUTE) 37 | install(DIRECTORY configs/ 38 | DESTINATION configs/) 39 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | syntax_msg () { 4 | echo "syntax: compile.sh build-directory target-directory"; 5 | } 6 | 7 | if [ "$#" -ne 2 ]; then 8 | syntax_msg; 9 | exit 1; 10 | else 11 | echo "build directory "$1" specified"; 12 | echo "target directory "$2" specified "; 13 | 14 | if [ -d $2 ]; then 15 | echo "Deleting target directory"; 16 | rm -rf $2 && echo "target directory successfully deleted"; 17 | fi 18 | fi 19 | 20 | if [ -d $1 ]; then 21 | echo "build directory already exist -- do you want to remove it? "; 22 | read user; 23 | 24 | case "$user" in 25 | yes|y|Y|YES) 26 | rm -rf "$1" && echo "$1 -- deleted successfully"; 27 | mkdir "$1" && echo "creating new directory $1"; 28 | ;; 29 | 30 | no|n|N|NO) 31 | ;; 32 | 33 | *) 34 | echo "exiting --> incorrect selection -- select yes|no|y|n|YES|NO"; 35 | exit 1 36 | ;; 37 | esac 38 | else 39 | mkdir $1 40 | fi 41 | 42 | 43 | 44 | cd $1 && echo "changing directory to $1"; 45 | cmake -DCMAKE_CXX_FLAGS=-pg -DCMAKE_INSTALL_PREFIX="../$2" -DCMAKE_BUILD_TYPE=Debug .. && make && make install && cd .. && tar cvzf "$2.tar.gz" $2; 46 | 47 | if [ "$?" -ne 0 ]; then 48 | echo "STEM compilation has failed -- exiting"; 49 | exit 1; 50 | fi 51 | 52 | -------------------------------------------------------------------------------- /configs/Direct.Bats.ini: -------------------------------------------------------------------------------- 1 | [Direct.Bats] 2 | Subject List = #FEED_BATS 3 | Service List = MulticastPitchfh 4 | Router Address = 127.0.0.1 5 | Debug Log = On 6 | -------------------------------------------------------------------------------- /configs/Direct.Bats.ini~: -------------------------------------------------------------------------------- 1 | [Direct.Bats] 2 | Subject List = #FEED_BATS 3 | Service List = MulticastPitchfh 4 | Router Address = 127.0.0.1 5 | -------------------------------------------------------------------------------- /configs/admin_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20:30:00 4 | 20:30:00 5 | 20:30:00 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /configs/admin_config.xml~: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13:45:00 4 | 14:45:00 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /configs/admin_config_server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20:30:00 4 | 20:30:00 5 | 20:30:00 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /configs/symbol_config_new.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /configs/symbol_config_new.xml~: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /configs/symbol_config_onlyC.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /configs/trading_config_new.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | user1 5 | user2 6 | 1 7 | 1 8 | 1 9 | 10 | 11 | 10 12 | 2 13 | 10.1.20.74 14 | false 15 | AAA 16 | ABB 17 | II 18 | EE 19 | BB 20 | 21 | 22 | 23 | 10 24 | 2 25 | 10.1.20.74 26 | false 27 | AAA 28 | ABB 29 | II 30 | EE 31 | BB 32 | 33 | 34 | 40 35 | 80 36 | 37 | 38 | XBowSIM 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /configs/trading_config_new.xml~: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | user1 6 | user_high_risk 7 | 1 8 | 1 9 | 1 10 | 10 11 | 2 12 | 10.1.20.74 13 | false 14 | AAA 15 | ABB 16 | II 17 | EE 18 | BB 19 | 20 | 21 | XBowSIM 22 | BAT 23 | ARCA 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /connect.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ssh acm@172.25.172.52 4 | -------------------------------------------------------------------------------- /copylog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ ! -d serverlogs ]; then 3 | echo "serverlogs directory doesn't exist -- creating one"; 4 | mkdir serverlogs; 5 | fi 6 | 7 | #if [ $# -ne 1 ]; then 8 | # echo "must provide destination file name for serverlogs/{file-name}"; 9 | # exit 1; 10 | #fi 11 | 12 | 13 | FN=`date +%Y%m%d-%H`.log 14 | 15 | scp acm@172.25.172.52:~/deploy/scripts/stem.log serverlogs/$FN 16 | if [ $? -eq 0 ]; then 17 | echo "file copied from server successfully"; 18 | else 19 | echo "log copy from vpn has failed"; 20 | exit 1; 21 | fi 22 | 23 | tar cvzf serverlogs/$1.tar.gz serverlogs/$FN; 24 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | scp deploy.tar.gz acm@172.25.172.52:~ 4 | -------------------------------------------------------------------------------- /run_stem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | scripts/positiontoredis.sh -c -a 3 | rm core 4 | ulimit -c unlimited 5 | local/bin/stem 127.0.0.1 0 -s:configs/symbol_config_new.xml -t:configs/trading_config_new.xml -a:configs/admin_config.xml -v:TRACE 6 | -------------------------------------------------------------------------------- /scripts/file.csv: -------------------------------------------------------------------------------- 1 | EQUITY,,user_high_risk,AA.BA,AA.BA,,,-400,,10.197000 2 | EQUITY,,user1,AA.BA,AA.BA,,,0,,10.174444 3 | kfsfksfj;skfj;askjfd 4 | -------------------------------------------------------------------------------- /scripts/kill_stem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | kill `ps -e|grep "stem"|cut -f1 -d' '` 3 | -------------------------------------------------------------------------------- /scripts/line-0: -------------------------------------------------------------------------------- 1 | drwxrwxr-x 2 jamil jamil 4.0K دسمبر 28 17:14 . 2 | -rw-rw-r-- 1 jamil jamil 115 ستمبر 19 23:08 file.csv 3 | -rw-rw-r-- 1 jamil jamil 197 دسمبر 28 17:14 line-1 4 | -rwxrwxr-x 1 jamil jamil 3.6K نومبر 30 23:55 livestatssorted.sh 5 | -rwxrw-r-- 1 jamil jamil 1.2K دسمبر 28 16:47 log_processing.sh~ 6 | -rw-rw-r-- 1 jamil jamil 0 دسمبر 28 15:20 readarray 7 | -rwxrwxr-x 1 jamil jamil 2.3K اكتوب 26 20:34 redistofile.sh 8 | -rwxr-xr-x 1 jamil jamil 222 نومبر 25 09:08 run_stem.sh 9 | -------------------------------------------------------------------------------- /scripts/line-1: -------------------------------------------------------------------------------- 1 | total 60K 2 | drwxrwxr-x 15 jamil jamil 4.0K دسمبر 27 21:25 .. 3 | -rw-rw-r-- 1 jamil jamil 49 نومبر 25 08:15 kill_stem.sh 4 | -rwxrwxr-x 1 jamil jamil 2.7K دسمبر 11 19:38 livestats.sh 5 | -rwxrw-r-- 1 jamil jamil 1.2K دسمبر 28 16:48 log_processing.sh 6 | -rwxrwxr-x 1 jamil jamil 2.0K ستمبر 30 19:00 positiontoredis.sh 7 | -rw-rw-r-- 1 jamil jamil 388 ستمبر 20 00:00 redisfile.csv 8 | -rw-r--r-- 1 jamil jamil 187 ستمبر 28 18:52 run_stem_for_server.sh 9 | -rw-r--r-- 1 jamil jamil 176 ستمبر 20 04:03 run_stem.sh~ 10 | -------------------------------------------------------------------------------- /scripts/livestats.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | trap ctrl_c INT 3 | idtoexit=0 4 | tput civis -- invisible 5 | function ctrl_c() { 6 | # echo "** Trapped CTRL-C" 7 | echo "Exiting ..." 8 | tput cnorm -- normal 9 | kill $idtoexit 10 | exit 11 | } 12 | 13 | positionRecords (){ 14 | #echo $1 15 | #echo $2 16 | #clear 17 | tput reset 18 | #positionRecordsNum="$(echo 'LRANGE '$1';'$2' 0 -1' | redis-cli -h $ip -p $port)" 19 | #echo $positionRecordsNum 20 | echo 'average_at_open,open_order_id,open_price,open_size,average_at_close,close_order_id,close_price,close_size,pnl,sign,is_complete' 21 | echo $1 22 | echo 'LRANGE '$1';'$2' 0 -1' | redis-cli -h $ip -p $port 23 | echo "" 24 | echo $3 25 | echo 'LRANGE '$3';'$2' 0 -1' | redis-cli -h $ip -p $port 26 | sleep 4 27 | #for i in {1..71} 28 | #do 29 | #printf "\033[A" 30 | #done 31 | #tput cup 0 0 32 | } 33 | 34 | statsOrders () 35 | { 36 | rediskeys="$(echo keys ''$user1',*' | redis-cli -h $ip -p $port)" #| wc -l 37 | 38 | # first user 39 | #echo ' ' 40 | #echo ' ' 41 | echo ' '$user1': ' 42 | IFS=' ' read -r -a array <<< "$rediskeys" 43 | #echo 'keys '$user',*' | redis-cli -h $ip -p $port| sed 's/^/get /' | redis-cli -h $ip -p $port 44 | #for i in "${rediskeys[@]}"; do 45 | #echo ''$i' \n' 46 | #done 47 | stringarray=($rediskeys) 48 | for i in "${stringarray[@]}" 49 | do 50 | #echo ''$i' \n' 51 | redisVal="$(echo get ''$i'' | redis-cli -h $ip -p $port)" 52 | #echo ''$i' '$redisVal'' 53 | IFS=',' read -r -a splitarray <<< "$redisVal" 54 | if [ -z "${splitarray[4]}" ] && [ -z "${splitarray[7]}" ] && [ "${splitarray[0]}" == "$redissymbol" ] 55 | then 56 | #echo ${splitarray[4]} 57 | echo ' '$redisVal'' 58 | #read input 59 | fi 60 | #echo ' ' 61 | done 62 | # ...................................... 63 | 64 | 65 | #second user 66 | rediskeys2="$(echo keys ''$user2',*' | redis-cli -h $ip -p $port)" 67 | #echo ' ' 68 | #echo ' ' 69 | echo ' '$user2': ' 70 | IFS=' ' read -r -a array2 <<< "$rediskeys2" 71 | stringarray2=($rediskeys2) 72 | for i in "${stringarray2[@]}" 73 | do 74 | redisVal2="$(echo get ''$i'' | redis-cli -h $ip -p $port)" 75 | IFS=',' read -r -a splitarray2 <<< "$redisVal2" 76 | if [ -z "${splitarray2[4]}" ] && [ -z "${splitarray2[7]}" ] && [ "${splitarray2[0]}" == "$redissymbol" ] 77 | then 78 | echo ' '$redisVal2'' 79 | fi 80 | done 81 | echo ' ' 82 | # ...................................... 83 | } 84 | 85 | stats () 86 | { 87 | #symbols list detection 88 | if [ "$enable_auto_symbol_list" = true ] ; then 89 | #for auto symbol list 90 | keys1="$(echo keys ''$user1':*' | redis-cli -h $ip -p $port)" 91 | keys2="$(echo keys ''$user2':*' | redis-cli -h $ip -p $port)" 92 | #echo 'account 1 keys :: '$keys1'' 93 | #echo 'account 2 keys :: '$keys2'' 94 | temp1="$(echo $keys1 | sed 's/'$user1'://g')" 95 | temp2="$(echo $keys2 | sed 's/'$user2'://g')" 96 | temp3=''$temp1' '$temp2'' 97 | #echo $temp1 98 | #echo $temp2 99 | #echo 'joining list' 100 | #echo $temp3 101 | 102 | #echo 'sorting list' 103 | IFS=' ' read -ra KEYLIST <<< "$temp3" 104 | sorted_unique_ids=$(echo "${KEYLIST[@]}" | tr ' ' '\n' | sort -u | tr '\n' ',') 105 | #echo $sorted_unique_ids 106 | last="$(echo "${sorted_unique_ids: -1}")" 107 | #echo $last 108 | if [ "$last" == "," ]; then 109 | #sorted_unique_ids=${sorted_unique_ids::-1} 110 | size=${#sorted_unique_ids} 111 | size=$((size-1)) 112 | #echo ${sorted_unique_ids:0:$size} 113 | symbollist="$(echo ${sorted_unique_ids:0:$size})" 114 | fi 115 | #echo 'symbol list '$symbollist'' 116 | #read input_variable 117 | #for auto symbol list 118 | fi 119 | #symbols list detection 120 | 121 | IFS=',' read -ra ADDR <<< "$symbollist" 122 | for i in "${ADDR[@]}"; do 123 | val1="$(echo get ''$user1':'${i}'' | redis-cli -h $ip -p $port)" 124 | #val1=get ''$user1':'${i}'' | redis-cli -h $ip -p $port 125 | val2="$(echo get ''$user2':'${i}'' | redis-cli -h $ip -p $port)" 126 | val3="$(echo LRANGE ''$pair'#'${i}'' -1 -1 | redis-cli -h $ip -p $port)" 127 | IFS=',' read -r -a array <<< "$val1" 128 | IFS=',' read -r -a array2 <<< "$val2" 129 | IFS=',' read -r -a array3 <<< "$val3" 130 | if [ -z "${array[12]}" ] 131 | then 132 | array[12]=0 133 | fi 134 | if [ -z "${array[13]}" ] 135 | then 136 | array[13]=0 137 | fi 138 | if [ -z "${array2[12]}" ] 139 | then 140 | array2[12]=0 141 | fi 142 | if [ -z "${array2[13]}" ] 143 | then 144 | array2[13]=0 145 | fi 146 | if [ -z "${array[14]}" ] 147 | then 148 | array[14]=0 149 | fi 150 | if [ -z "${array2[14]}" ] 151 | then 152 | array2[14]=0 153 | fi 154 | if [ -z "${array[7]}" ] 155 | then 156 | array[7]=0 157 | fi 158 | if [ -z "${array[9]}" ] 159 | then 160 | array[9]=0.0000 161 | fi 162 | if [ -z "${array2[7]}" ] 163 | then 164 | array2[7]=0 165 | fi 166 | if [ -z "${array2[9]}" ] 167 | then 168 | array2[9]=0.0000 169 | fi 170 | if [ "${array3[1]}" == "TRIGGER_STATE_POSITIVE" ] 171 | then 172 | sign="+ve" 173 | elif [ "${array3[1]}" == "TRIGGER_STATE_NEGATIVE" ] 174 | then 175 | sign="-ve" 176 | else 177 | sign=" " 178 | fi 179 | #totallive1=0 180 | #else 181 | totallive1=`expr ${array[12]} + ${array[13]}` 182 | #fi 183 | totallive2=`expr ${array2[12]} + ${array2[13]}` 184 | symbollength=${#i} 185 | if [ $symbollength -eq 2 ] 186 | then 187 | i=$i' ' 188 | fi 189 | echo ''$pair'('$user1'-'$user2')::'${i}':'${sign}','${array3[2]}'('${array3[3]}','${array3[4]}','${array3[5]}','${array3[6]}','${array3[7]}') '${array[7]}','${array[9]}','${array[12]}','${array[13]}','$totallive1','${array[14]}' : '${array2[7]}','${array2[9]}','${array2[12]}','${array2[13]}','$totallive2','${array2[14]}' ' 190 | if [ "${i}" == "${redissymbol}" ] && [ $1 = true ] 191 | then 192 | statsOrders 193 | fi 194 | done 195 | #date 196 | #echo 2*$i 197 | #i=$((i+1)) 198 | IFS=',' read -ra APPR <<< "$symbollist" 199 | for i in "${APPR[@]}"; do 200 | printf "\033[A" 201 | 202 | done 203 | sleep 0.5 204 | #printf "\033[A" 205 | #printf "\033[A" 206 | tput cup 3 0 207 | #read input_variable 208 | } # Function declaration must precede call. 209 | 210 | clear 211 | ip="127.0.0.1" 212 | port=6379 213 | pair=$1 214 | user1=$2 215 | user2=$3 216 | symbollist=$4 217 | enable_auto_symbol_list=true 218 | echo "Pair '$pair'" 219 | echo "Account 1 '$user1'" 220 | echo "Account 2 '$user2'" 221 | symbolcount=0 222 | redissymbol="" 223 | 224 | status="normal" 225 | if [ $# -lt 3 ]; then 226 | echo 'Help' 227 | echo "Usage: $0 PairName Account1 Account2" 228 | echo "To switch to detailed live order mode press S" 229 | echo "Enter the name of the symbol and press enter" 230 | echo "To switch back to normal mode press B" 231 | echo "To switch symbol in detailed live order mode press V" 232 | exit 233 | fi 234 | 235 | while true; 236 | do 237 | 238 | 239 | case $status in 240 | normal) 241 | #echo "in false" 242 | 243 | clear 244 | echo "Pair '$pair'" 245 | echo "Account 1 '$user1'" 246 | echo "Account 2 '$user2'" 247 | 248 | while [ 1 ] 249 | do 250 | stats false 251 | done & 252 | 253 | main=$! 254 | #echo "# main is $main" >&2 255 | idtoexit=$main 256 | 257 | # livinfree's neat dd trick from that other thread vino pointed out 258 | #tput smso 259 | #echo "Press any key to return \c" 260 | #tput rmso 261 | result="" 262 | while [ "$result" != "s" ] && [ "$result" != "p" ]; 263 | do 264 | oldstty=`stty -g` 265 | stty -icanon -echo min 1 time 0 266 | result=`dd bs=1 count=1 2>/dev/null` 267 | stty "$oldstty" 268 | #echo $result 269 | done 270 | #/home/akela/Desktop/new.sh $main 271 | kill $main 272 | wait $main 2>/dev/null 273 | 274 | 275 | 276 | if [ "$result" == "s" ] 277 | then 278 | status="symbol" 279 | fi 280 | 281 | if [ "$result" == "p" ] 282 | then 283 | status="positionRecord" 284 | fi 285 | ;; 286 | 287 | 288 | 289 | 290 | 291 | symbol) 292 | #echo "in true" 293 | clear 294 | echo "Enter the symbol:" 295 | read str 296 | redissymbol="$(echo "${str^^}")" 297 | echo 'Symbol read is:'$redissymbol'' 298 | clear 299 | echo "Pair '$pair'" 300 | echo "Account 1 '$user1'" 301 | echo "Account 2 '$user2'" 302 | 303 | 304 | while : ; do 305 | stats true 306 | done & 307 | 308 | main2=$! 309 | #echo "# main is $main2" >&2 310 | idtoexit=$main2 311 | 312 | # livinfree's neat dd trick from that other thread vino pointed out 313 | #tput smso 314 | #echo "Press any key to return \c" 315 | #tput rmso 316 | result2="" 317 | while [ "$result2" != "b" ] && [ "$result2" != "r" ]; 318 | do 319 | oldstty=`stty -g` 320 | stty -icanon -echo min 1 time 0 321 | result2=`dd bs=1 count=1 2>/dev/null` 322 | stty "$oldstty" 323 | #echo $result2 324 | done 325 | 326 | kill $main2 327 | wait $main2 2>/dev/null 328 | 329 | 330 | if [ "$result2" == "b" ] 331 | then 332 | status="normal" 333 | fi 334 | if [ "$result2" == "r" ] 335 | then 336 | status="symbol" 337 | fi 338 | ;; 339 | orange|tangerine) 340 | echo $'Eeeks! I don\'t like those!\nGo away!' 341 | exit 1 342 | ;; 343 | positionRecord) 344 | clear 345 | #echo "Enter the user:" 346 | #read pos_acc 347 | echo "Enter the symbol:" 348 | read pos_sym 349 | Capitalized_pos_sym="$(echo "${pos_sym^^}")" 350 | while : ; do 351 | positionRecords $user1 $Capitalized_pos_sym $user2 352 | done & 353 | 354 | main3=$! 355 | #echo "# main is $main3" >&2 356 | idtoexit=$main3 357 | 358 | result3="" 359 | while [ "$result3" != "b" ] && [ "$result3" != "r" ]; 360 | do 361 | oldstty=`stty -g` 362 | stty -icanon -echo min 1 time 0 363 | result3=`dd bs=1 count=1 2>/dev/null` 364 | stty "$oldstty" 365 | #echo $result 366 | done 367 | #/home/akela/Desktop/new.sh $main3 368 | kill $main3 369 | wait $main3 2>/dev/null 370 | if [ "$result3" == "b" ] 371 | then 372 | status="normal" 373 | fi 374 | if [ "$result3" == "r" ] 375 | then 376 | status="positionRecord" 377 | fi 378 | ;; 379 | *) 380 | echo "Unknown Command?" 381 | esac 382 | 383 | done 384 | -------------------------------------------------------------------------------- /scripts/livestatsold.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | clear 3 | tput civis -- invisible 4 | 5 | # trap ctrl-c and call ctrl_c() 6 | trap ctrl_c INT 7 | 8 | function ctrl_c() { 9 | # echo "** Trapped CTRL-C" 10 | echo "Exiting ..." 11 | tput cnorm -- normal 12 | exit 13 | } 14 | ip="127.0.0.1" 15 | port=6379 16 | pair=$1 17 | user1=$2 18 | user2=$3 19 | symbollist=$4 20 | enable_auto_symbol_list=true 21 | echo "Account 1 '$user1'" 22 | echo "Account 2 '$user2'" 23 | symbolcount=0 24 | IFS=',' read -ra ADDR <<< "$symbollist" 25 | for i in "${ADDR[@]}"; do 26 | echo 'symbol '${i}'' 27 | symbolcount=$((symbolcount+1)) 28 | done 29 | echo 'symbol count '${symbolcount}'' 30 | 31 | 32 | while [ 1 ] 33 | do 34 | #symbols list detection 35 | if [ "$enable_auto_symbol_list" = true ] ; then 36 | #for auto symbol list 37 | keys1="$(echo keys ''$user1':*' | redis-cli -h $ip -p $port)" 38 | keys2="$(echo keys ''$user2':*' | redis-cli -h $ip -p $port)" 39 | #echo 'account 1 keys :: '$keys1'' 40 | #echo 'account 2 keys :: '$keys2'' 41 | temp1="$(echo $keys1 | sed 's/'$user1'://g')" 42 | temp2="$(echo $keys2 | sed 's/'$user2'://g')" 43 | temp3=''$temp1' '$temp2'' 44 | #echo $temp1 45 | #echo $temp2 46 | #echo 'joining list' 47 | #echo $temp3 48 | 49 | #echo 'sorting list' 50 | IFS=' ' read -ra KEYLIST <<< "$temp3" 51 | sorted_unique_ids=$(echo "${KEYLIST[@]}" | tr ' ' '\n' | sort -u | tr '\n' ',') 52 | #echo $sorted_unique_ids 53 | last="$(echo "${sorted_unique_ids: -1}")" 54 | #echo $last 55 | if [ "$last" == "," ]; then 56 | #sorted_unique_ids=${sorted_unique_ids::-1} 57 | size=${#sorted_unique_ids} 58 | size=$((size-1)) 59 | #echo ${sorted_unique_ids:0:$size} 60 | symbollist="$(echo ${sorted_unique_ids:0:$size})" 61 | fi 62 | #echo 'symbol list '$symbollist'' 63 | #read input_variable 64 | #for auto symbol list 65 | fi 66 | #symbols list detection 67 | 68 | IFS=',' read -ra ADDR <<< "$symbollist" 69 | for i in "${ADDR[@]}"; do 70 | val1="$(echo get ''$user1':'${i}'' | redis-cli -h $ip -p $port)" 71 | #val1=get ''$user1':'${i}'' | redis-cli -h $ip -p $port 72 | val2="$(echo get ''$user2':'${i}'' | redis-cli -h $ip -p $port)" 73 | val3="$(echo LRANGE ''$pair'#'${i}'' -1 -1 | redis-cli -h $ip -p $port)" 74 | IFS=',' read -r -a array <<< "$val1" 75 | IFS=',' read -r -a array2 <<< "$val2" 76 | IFS=',' read -r -a array3 <<< "$val3" 77 | if [ -z "${array[12]}" ] 78 | then 79 | array[12]=0 80 | fi 81 | if [ -z "${array[13]}" ] 82 | then 83 | array[13]=0 84 | fi 85 | if [ -z "${array2[12]}" ] 86 | then 87 | array2[12]=0 88 | fi 89 | if [ -z "${array2[13]}" ] 90 | then 91 | array2[13]=0 92 | fi 93 | if [ -z "${array[14]}" ] 94 | then 95 | array[14]=0 96 | fi 97 | if [ -z "${array2[14]}" ] 98 | then 99 | array2[14]=0 100 | fi 101 | if [ -z "${array[7]}" ] 102 | then 103 | array[7]=0 104 | fi 105 | if [ -z "${array[9]}" ] 106 | then 107 | array[9]=0.0000 108 | fi 109 | if [ -z "${array2[7]}" ] 110 | then 111 | array2[7]=0 112 | fi 113 | if [ -z "${array2[9]}" ] 114 | then 115 | array2[9]=0.0000 116 | fi 117 | if [ "${array3[1]}" == "TRIGGER_STATE_POSITIVE" ] 118 | then 119 | sign="+ve" 120 | elif [ "${array3[1]}" == "TRIGGER_STATE_NEGATIVE" ] 121 | then 122 | sign="-ve" 123 | else 124 | sign=" " 125 | fi 126 | #totallive1=0 127 | #else 128 | totallive1=`expr ${array[12]} + ${array[13]}` 129 | #fi 130 | totallive2=`expr ${array2[12]} + ${array2[13]}` 131 | symbollength=${#i} 132 | if [ $symbollength -eq 2 ] 133 | then 134 | i=$i' ' 135 | fi 136 | echo ''$pair'('$user1'-'$user2')::'${i}':'${sign}','${array3[2]}' '${array[7]}','${array[9]}','${array[12]}','${array[13]}','$totallive1','${array[14]}' : '${array2[7]}','${array2[9]}','${array2[12]}','${array2[13]}','$totallive2','${array2[14]}' ' 137 | done 138 | #date 139 | #echo 2*$i 140 | #i=$((i+1)) 141 | IFS=',' read -ra APPR <<< "$symbollist" 142 | for i in "${APPR[@]}"; do 143 | printf "\033[A" 144 | 145 | done 146 | sleep 0.5 147 | #printf "\033[A" 148 | #printf "\033[A" 149 | tput cup 3 0 150 | #read input_variable 151 | done 152 | 153 | tput cnorm -- normal 154 | -------------------------------------------------------------------------------- /scripts/livestatssorted.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | tput civis -- invisible 4 | 5 | # trap ctrl-c and call ctrl_c() 6 | trap ctrl_c INT 7 | trap stp QUIT 8 | enable_output=true 9 | function ctrl_c() { 10 | # echo "** Trapped CTRL-C" 11 | echo "" 12 | tput cnorm -- normal 13 | exit 14 | } 15 | 16 | function stp() { 17 | echo "** Trapped CTRL-" 18 | echo "" 19 | clear 20 | tput cnorm -- normal 21 | #exit 22 | } 23 | indexselect=1 24 | 25 | ip="127.0.0.1" 26 | port=6379 27 | user1=$1 28 | user2=$2 29 | #symbollist=$3 30 | userselect=$3 31 | indexselect=$4 32 | 33 | if [ $indexselect -eq 1 ]; then 34 | indexselect=12 35 | fi 36 | 37 | if [ $indexselect -eq 2 ]; then 38 | indexselect=13 39 | fi 40 | 41 | if [ $indexselect -eq 4 ]; then 42 | indexselect=14 43 | fi 44 | 45 | enable_auto_symbol_list=true 46 | echo "Account 1 '$user1'" 47 | echo "Account 2 '$user2'" 48 | symbolcount=0 49 | IFS=',' read -ra ADDR <<< "$symbollist" 50 | for i in "${ADDR[@]}"; do 51 | echo 'symbol '${i}'' 52 | symbolcount=$((symbolcount+1)) 53 | done 54 | echo 'symbol count '${symbolcount}'' 55 | 56 | while [ 1 ] 57 | do 58 | #symbols list detection 59 | 60 | if [ "$enable_auto_symbol_list" = true ] ; then 61 | #for auto symbol list 62 | keys1="$(echo keys ''$user1':*' | redis-cli -h $ip -p $port)" 63 | keys2="$(echo keys ''$user2':*' | redis-cli -h $ip -p $port)" 64 | #echo 'account 1 keys :: '$keys1'' 65 | #echo 'account 2 keys :: '$keys2'' 66 | temp1="$(echo $keys1 | sed 's/'$user1'://g')" 67 | temp2="$(echo $keys2 | sed 's/'$user2'://g')" 68 | temp3=''$temp1' '$temp2'' 69 | #echo $temp1 70 | #echo $temp2 71 | #echo 'joining list' 72 | #echo $temp3 73 | 74 | #echo 'sorting list' 75 | IFS=' ' read -ra KEYLIST <<< "$temp3" 76 | sorted_unique_ids=$(echo "${KEYLIST[@]}" | tr ' ' '\n' | sort -u | tr '\n' ',') 77 | #echo $sorted_unique_ids 78 | last="$(echo "${sorted_unique_ids: -1}")" 79 | #echo $last 80 | if [ "$last" == "," ]; then 81 | #sorted_unique_ids=${sorted_unique_ids::-1} 82 | size=${#sorted_unique_ids} 83 | size=$((size-1)) 84 | #echo ${sorted_unique_ids:0:$size} 85 | symbollist="$(echo ${sorted_unique_ids:0:$size})" 86 | fi 87 | #echo 'symbol list '$symbollist'' 88 | #read input_variable 89 | #for auto symbol list 90 | fi 91 | #symbol list detection 92 | 93 | 94 | #added for sorting 95 | IFS=',' read -ra SYM <<< "$symbollist" 96 | declare -A hashmap 97 | for j in "${SYM[@]}"; do 98 | readvalue="$(echo get ''$userselect':'${j}'' | redis-cli -h $ip -p $port)" 99 | IFS=',' read -ra READSTR <<< "$readvalue" 100 | hashmap[${j}]=${READSTR[$indexselect]} 101 | 102 | if [ $indexselect -eq 3 ]; then 103 | hashmap[${j}]=$((${READSTR[12]}+${READSTR[13]})) 104 | fi 105 | 106 | done 107 | 108 | 109 | val="$(for k in "${!hashmap[@]}" 110 | do 111 | echo $k '#' ${hashmap["$k"]}';' 112 | done | 113 | sort -rn -k3)" 114 | #echo $val 115 | some_variable="$( echo "$val" | sed 's/.#.*;//g' )" 116 | #echo $some_variable 117 | symbollist="$( echo "$some_variable" | tr '\n' ',' )" 118 | #echo 'final:'${symbollist} 119 | #read input_variable 120 | #added for sorting 121 | IFS=',' read -ra ADDR <<< "$symbollist" 122 | for i in "${ADDR[@]}"; do 123 | val1="$(echo get ''$user1':'${i}'' | redis-cli -h $ip -p $port)" 124 | #val1=get ''$user1':'${i}'' | redis-cli -h $ip -p $port 125 | val2="$(echo get ''$user2':'${i}'' | redis-cli -h $ip -p $port)" 126 | IFS=',' read -r -a array <<< "$val1" 127 | IFS=',' read -r -a array2 <<< "$val2" 128 | if [ -z "${array[12]}" ] 129 | then 130 | array[12]=0 131 | fi 132 | if [ -z "${array[13]}" ] 133 | then 134 | array[13]=0 135 | fi 136 | if [ -z "${array2[12]}" ] 137 | then 138 | array2[12]=0 139 | fi 140 | if [ -z "${array2[13]}" ] 141 | then 142 | array2[13]=0 143 | fi 144 | if [ -z "${array[14]}" ] 145 | then 146 | array[14]=0 147 | fi 148 | if [ -z "${array2[14]}" ] 149 | then 150 | array2[14]=0 151 | fi 152 | #totallive1=0 153 | #else 154 | totallive1=`expr ${array[12]} + ${array[13]}` 155 | #fi 156 | totallive2=`expr ${array2[12]} + ${array2[13]}` 157 | echo ''$user1'-'$user2' :: '${i}' :'${array[12]}','${array[13]}','$totallive1','${array[14]}' : '${array2[12]}','${array2[13]}','$totallive2','${array2[14]}' ' 158 | done 159 | #date 160 | #echo 2*$i 161 | #i=$((i+1)) 162 | IFS=',' read -ra APPR <<< "$symbollist" 163 | for i in "${APPR[@]}"; do 164 | printf "\033[A" 165 | 166 | done 167 | sleep 0.5 168 | #printf "\033[A" 169 | #printf "\033[A" 170 | #read input_variable 171 | done 172 | 173 | tput cnorm -- normal 174 | -------------------------------------------------------------------------------- /scripts/log_processing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | 5 | echo "Starting log $1 processing -- please wait" 6 | 7 | oddstat(){ 8 | 9 | file=$3 10 | grep -E "$1.*OnOrder" $2 > $file 11 | lines=`cut -d" " -f9 $file` 12 | 13 | total=0 14 | canceled=0 15 | changed=0 16 | error=0 17 | executed=0 18 | 19 | for i in $lines; do 20 | case $i in 21 | 0) 22 | total=$(($total+1)); 23 | ;; 24 | 3) 25 | executed=$(($executed+1)); 26 | ;; 27 | 4) 28 | canceled=$(($canceled+1)); 29 | ;; 30 | 16) 31 | changed=$(($changed+1)); 32 | ;; 33 | 233|255|245) 34 | error=$(($error+1)); 35 | ;; 36 | esac 37 | done 38 | 39 | echo "Order Info($1): Sent: $total Executed: $executed Canceled: $canceled Changed: $changed Error: $error" 40 | 41 | } 42 | 43 | oddexec(){ 44 | exec_file=`echo $1|sed 's/file/exec/g'` 45 | cat $1|sed "s/\]\[/ /g" |cut -d" " -f2,9-|sort -k 2 > $exec_file 46 | 47 | orders=( `cat $exec_file|cut -d" " -f2|uniq -c` ) 48 | 49 | i="1"; 50 | size=${#orders[@]} 51 | #echo $size $exec_file 52 | while [ $i -lt $size ]; do 53 | nrecords=${orders[$i-1]}; 54 | id="${orders[$i]}" 55 | order_info=( `grep "$id" $exec_file` ) 56 | j="0"; 57 | 58 | declare -a order_status 59 | price="${order_info[3]}" 60 | quantity="${order_info[4]}" 61 | acc_type=$2 62 | case "${order_info[5]}" in 63 | 0) 64 | type="BUY" 65 | ;; 66 | 1) 67 | type="SEL" 68 | ;; 69 | 4) 70 | type="SSL" 71 | ;; 72 | *) 73 | type="ERR" 74 | ;; 75 | esac 76 | 77 | 78 | ack="00:00:00.000000" 79 | rec="00:00:00.000000"; 80 | exe="00:00:00.000000"; 81 | canc="00:00:00.000000"; 82 | chan="00:00:00.000000"; 83 | err="00:00:00.000000"; 84 | othr="00:00:00.000000"; 85 | while [ $j -lt $nrecords ]; do 86 | time="${order_info[$(($j*6+0))]}" 87 | status="${order_info[$(($j*6+2))]}" 88 | 89 | case $status in 90 | 10) 91 | ack=$time 92 | ;; 93 | 0) 94 | rec=$time 95 | ;; 96 | 3) 97 | exe=$time 98 | ;; 99 | 4) 100 | canc=$time 101 | ;; 102 | 16) 103 | chan=$time 104 | ;; 105 | 255|245|233) 106 | err=$time 107 | ack=$time 108 | ;; 109 | *) 110 | othr=$time 111 | ;; 112 | esac 113 | j=$(($j+1)) 114 | done 115 | echo -e $ack $id $acc_type $price $quantity $type $rec $exe $canc $chan $err 116 | i=$(($i+2)) 117 | done 118 | 119 | } 120 | 121 | triginfo(){ 122 | #grep "TRIGGER CHANGED" $1|sed "s/\]\[/ /g"|awk '/\,\+\,/ {print $2 " POS"} /,-,/ {print $2 " NEG"}' 123 | #grep "selecting case" $1|sed "s/\]\[/ /g"|cut -d" " -f2 124 | grep "selecting case" $1|sed "s/\]\[/ /g"|awk '/\,\+\,/ {print $2 " POS " $NF} /\,\-\,/ {print $2 " NEG " $NF}' 125 | } 126 | 127 | sfile="/tmp/short-file.log" #temporary file to store short order records 128 | lfile="/tmp/long-file.log" #temporary file to store short order records 129 | 130 | oddstat short $1 $sfile 131 | oddstat long $1 $lfile 132 | 133 | oddexec $sfile short 134 | oddexec $lfile long 135 | 136 | triginfo $1 137 | -------------------------------------------------------------------------------- /scripts/log_processing.sh~: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | 5 | echo "Starting log $1 processing -- please wait" 6 | 7 | oddstat(){ 8 | 9 | file=$3 10 | grep -E "$1.*OnOrder" $2 > $file 11 | lines=`cut -d" " -f9 $file` 12 | 13 | total=0 14 | canceled=0 15 | changed=0 16 | error=0 17 | executed=0 18 | 19 | for i in $lines; do 20 | case $i in 21 | 0) 22 | total=$(($total+1)); 23 | ;; 24 | 3) 25 | executed=$(($executed+1)); 26 | ;; 27 | 4) 28 | canceled=$(($canceled+1)); 29 | ;; 30 | 16) 31 | changed=$(($changed+1)); 32 | ;; 33 | 233|255|245) 34 | error=$(($error+1)); 35 | ;; 36 | esac 37 | done 38 | 39 | echo "Order Info($1): Sent: $total Executed: $executed Canceled: $canceled Changed: $changed Error: $error" 40 | 41 | } 42 | 43 | oddexec(){ 44 | exec_file=`echo $1|sed 's/file/exec/g'` 45 | cat $1|sed "s/\]\[/ /g" |cut -d" " -f2,9-|sort -k 2 > $exec_file 46 | 47 | orders=( `cat $exec_file|cut -d" " -f2|uniq -c` ) 48 | 49 | i="1"; 50 | size=${#orders[@]} 51 | #echo $size $exec_file 52 | while [ $i -lt $size ]; do 53 | nrecords=${orders[$i-1]}; 54 | id="${orders[$i]}" 55 | order_info=( `grep "$id" $exec_file` ) 56 | j="0"; 57 | 58 | declare -a order_status 59 | price="${order_info[3]}" 60 | quantity="${order_info[4]}" 61 | acc_type=$2 62 | case "${order_info[5]}" in 63 | 0) 64 | type="BUY" 65 | ;; 66 | 1) 67 | type="SEL" 68 | ;; 69 | 4) 70 | type="SSL" 71 | ;; 72 | *) 73 | type="ERR" 74 | ;; 75 | esac 76 | 77 | 78 | ack="00:00:00.000000" 79 | rec="00:00:00.000000"; 80 | exe="00:00:00.000000"; 81 | canc="00:00:00.000000"; 82 | chan="00:00:00.000000"; 83 | err="00:00:00.000000"; 84 | othr="00:00:00.000000"; 85 | while [ $j -lt $nrecords ]; do 86 | time="${order_info[$(($j*6+0))]}" 87 | status="${order_info[$(($j*6+2))]}" 88 | 89 | case $status in 90 | 10) 91 | ack=$time 92 | ;; 93 | 0) 94 | rec=$time 95 | ;; 96 | 3) 97 | exe=$time 98 | ;; 99 | 4) 100 | canc=$time 101 | ;; 102 | 16) 103 | chan=$time 104 | ;; 105 | 255|245|233) 106 | err=$time 107 | ;; 108 | *) 109 | othr=$time 110 | ;; 111 | esac 112 | j=$(($j+1)) 113 | done 114 | echo -e $ack $id $acc_type $price $quantity $type $rec $exe $canc $chan $err 115 | i=$(($i+2)) 116 | done 117 | 118 | } 119 | 120 | triginfo(){ 121 | #grep "TRIGGER CHANGED" $1|sed "s/\]\[/ /g"|awk '/\,\+\,/ {print $2 " POS"} /,-,/ {print $2 " NEG"}' 122 | #grep "selecting case" $1|sed "s/\]\[/ /g"|cut -d" " -f2 123 | grep "selecting case" $1|sed "s/\]\[/ /g"|awk '/\,\+\,/ {print $2 " POS " $NF} /\,\-\,/ {print $2 " NEG " $NF}' 124 | } 125 | 126 | sfile="/tmp/short-file.log" #temporary file to store short order records 127 | lfile="/tmp/long-file.log" #temporary file to store short order records 128 | 129 | oddstat short $1 $sfile 130 | oddstat long $1 $lfile 131 | 132 | oddexec $sfile short 133 | oddexec $lfile long 134 | 135 | triginfo $1 136 | -------------------------------------------------------------------------------- /scripts/order_processing.awk: -------------------------------------------------------------------------------- 1 | BEGIN {print $1 "\t" $3} 2 | -------------------------------------------------------------------------------- /scripts/positiontoredis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -eq 0 ]; then 4 | echo "Usage: $0 " 5 | echo "-c [comma seperated list of symbols to clear entries from redis]" 6 | echo "-f [filepath to read values from file to redis]" 7 | exit 8 | fi 9 | 10 | # A POSIX variable 11 | OPTIND=1 # Reset in case getopts has been used previously in the shell. 12 | 13 | # Initialize our own variables: 14 | input_file="" 15 | isclear=0 16 | isall=0 17 | clear_vr="" 18 | ip="127.0.0.1" 19 | port=6379 20 | while getopts "h?c:i:p:f:" opt; do 21 | case "$opt" in 22 | help|\?) 23 | echo "Usage: $0 -c -f -i -p" 24 | echo "-f filepath containing positions" 25 | echo "-c to clear positions of certain symbols from redis eg AAPL,AAB" 26 | echo "-c -a to clear positions of all symbols from redis " 27 | echo "-i ip [optional default 6379]" 28 | echo "-p port [optional default 127.0.0.1]" 29 | exit 0 30 | ;; 31 | c) clear_vr=$OPTARG 32 | isclear=1 33 | ;; 34 | f) input_file=$OPTARG 35 | ;; 36 | a) isall=1 37 | ;; 38 | i) ip=$OPTARG 39 | ;; 40 | p) port=$OPTARG 41 | ;; 42 | esac 43 | done 44 | 45 | shift $((OPTIND-1)) 46 | 47 | [ "$1" = "--" ] && shift 48 | 49 | echo "clear=$isclear,clear_vr=$clear_vr, all=$isall, input_file='$input_file' ,ip='$ip',port='$port'" 50 | 51 | if [ "$isclear" = 1 ]; then 52 | 53 | if [ "$clear_vr" = "-a" ]; then 54 | echo "Deleting all positions in redis " 55 | echo 'keys *:*' | redis-cli -h $ip -p $port| sed 's/^/del /' | redis-cli -h $ip -p $port #clears positions 56 | echo 'keys *,*' | redis-cli -h $ip -p $port| sed 's/^/del /' | redis-cli -h $ip -p $port #clears order info 57 | echo 'keys *#*' | redis-cli -h $ip -p $port| sed 's/^/del /' | redis-cli -h $ip -p $port #clears trade case info 58 | else 59 | echo "Deleting symbol list $clear_vr" 60 | IFS=',' read -ra ADDR <<< "$clear_vr" 61 | for i in "${ADDR[@]}"; do 62 | echo 'keys *:'$i'' | redis-cli -h $ip -p $port| sed 's/^/del /' | redis-cli -h $ip -p $port 63 | #echo "$i" 64 | done 65 | 66 | fi 67 | exit 68 | fi 69 | 70 | if [ -z "$input_file" ] 71 | then 72 | echo "input file path is null." 73 | else 74 | #echo "'$input_file' is NOT null." 75 | while IFS= read -r line; do 76 | echo "Reading line : $line" 77 | IFS=', ' read -r -a array <<< "$line" 78 | echo "User : ${array[2]}" 79 | echo "Symbol: ${array[3]}" 80 | c=${array[2]}':'${array[3]} 81 | #echo $c 82 | echo 'set '${c}' '${line}'' | redis-cli -h $ip -p $port 83 | done < "$input_file" 84 | fi 85 | -------------------------------------------------------------------------------- /scripts/readarray: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjamilfarooq/tradingapp/2baa792f4ece6dd918a0ef7c74967c36f59ae487/scripts/readarray -------------------------------------------------------------------------------- /scripts/redisfile.csv: -------------------------------------------------------------------------------- 1 | RecordType,AccountName,SymbolorUnderlier,Root,ExpirationDate,Strike,Quantity,PutorCall,Price 2 | EQUITY,,user1,AA.BA,AA.BA,,,0,,10.181087 3 | EQUITY,,user1,AAPL.BA,AAPL.BA,,,400,,104.857500 4 | EQUITY,,user1,ABX.BA,ABX.BA,,,0,,16.169634 5 | EQUITY,,user_high_risk,AA.BA,AA.BA,,,-400,,10.196000 6 | EQUITY,,user_high_risk,ABX.BA,ABX.BA,,,-400,,16.176250 7 | EQUITY,,user_high_risk,AAPL.BA,AAPL.BA,,,0,,104.848750 8 | -------------------------------------------------------------------------------- /scripts/redistofile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | #if [ $# -eq 0 ]; then 5 | #echo 'keys *:*' | redis-cli | sed 's/^/get /' | redis-cli >file.csv 6 | #exit 7 | #fi 8 | 9 | user_list="" 10 | output_file="file.csv" 11 | ip="127.0.0.1" 12 | port=6379 13 | 14 | while getopts "h?f:u:i:p:" opt; do 15 | case "$opt" in 16 | help|\?) 17 | echo "Usage: $0 -f -u -i -p" 18 | echo "-f filepath" 19 | echo "-u userlist e.g ROOT1,ROOT2,ROOT3" 20 | echo "-i ip [optional default 6379]" 21 | echo "-p port [optional default 127.0.0.1]" 22 | exit 0 23 | ;; 24 | u) user_list=$OPTARG 25 | ;; 26 | f) output_file=$OPTARG 27 | ;; 28 | i) ip=$OPTARG 29 | ;; 30 | p) port=$OPTARG 31 | ;; 32 | esac 33 | done 34 | 35 | shift $((OPTIND-1)) 36 | 37 | [ "$1" = "--" ] && shift 38 | 39 | echo "output_file=$output_file,user_list=$user_list,ip='$ip',port='$port'" 40 | 41 | echo "Copying following user's positions from redis to file : $user_list" 42 | if [ -z "$user_list" ] 43 | then 44 | echo "user list is null." 45 | echo 'keys *:*' | redis-cli -h $ip -p $port| sed 's/^/get /' | redis-cli -h $ip -p $port 46 | echo 'RecordType,AccountName,SymbolorUnderlier,Root,ExpirationDate,Strike,Quantity,PutorCall,Price'>${output_file} 47 | echo 'keys *:*' | redis-cli -h $ip -p $port| sed 's/^/get /' | redis-cli -h $ip -p $port>>${output_file} 48 | #to discard 11 and 12 collumn of the positions file 49 | cut --complement -f 11-12 -d, ${output_file} > temp.csv 50 | mv temp.csv ${output_file} 51 | else 52 | echo 'RecordType,Reserved,AccountName,SymbolorUnderlier,Root,ExpirationDate,Strike,Quantity,PutorCall,Price'>${output_file} 53 | IFS=',' read -ra ADDR <<< "$user_list" 54 | for i in "${ADDR[@]}"; do 55 | echo 'keys '${i}':*' | redis-cli -h $ip -p $port| sed 's/^/get /' | redis-cli -h $ip -p $port>>${output_file} 56 | echo "Redis data written to file for user '$i'" 57 | done 58 | #to discard 11 and 12 collumn of the positions file 59 | cut --complement -f 11-12 -d, ${output_file} > temp.csv 60 | mv temp.csv ${output_file} 61 | fi 62 | 63 | 64 | #if [ $# -gt 0 ]; then 65 | #filename=$1 66 | #for arg in "$@" ; do 67 | # if [[ "$arg" = "$0" ]] ; then 68 | # echo 'skiping oth\n' 69 | # fi 70 | # if [[ "$arg" = "$1" ]] ; then 71 | # echo 'RecordType,AccountName,SymbolorUnderlier,Root,ExpirationDate,Strike,Quantity,PutorCall,Price'>${filename} 72 | # else 73 | # echo 'keys '${arg}':*' | redis-cli | sed 's/^/get /' | redis-cli >>${filename} 74 | #fi 75 | #done 76 | 77 | #else 78 | #echo 'keys *:*' | redis-cli | sed 's/^/get /' | redis-cli >file.csv 79 | #fi 80 | -------------------------------------------------------------------------------- /scripts/run_stem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./positiontoredis.sh -c -a 3 | rm core 4 | ulimit -c unlimited 5 | nohup ../bin/stem 127.0.0.1 0 -s:../configs/symbol_config_new.xml -t:../configs/trading_config_new.xml -a:../configs/admin_config.xml -v:TRACE >/dev/null & 6 | 7 | -------------------------------------------------------------------------------- /scripts/run_stem.sh~: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm core 4 | ulimit -c unlimited 5 | ../bin/stem 127.0.0.1 0 -s:../configs/symbol_config_new.xml -t:../config/trading_config_new.xml -a:../config/admin_config.xml -v:TRACE 6 | 7 | -------------------------------------------------------------------------------- /scripts/run_stem_for_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm core 4 | ulimit -c unlimited 5 | ../bin/stem 127.0.0.1 0 -s:../configs/symbol_config_onlyC.xml -t:../configs/trading_config_new.xml -a:../configs/admin_config_server.xml -v:TRACE 6 | 7 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(akela) 3 | add_subdirectory(cli) 4 | add_subdirectory(avicenna) 5 | add_subdirectory(config) 6 | add_subdirectory(manager) 7 | add_subdirectory(trade) 8 | add_subdirectory(utils) 9 | add_subdirectory(redis) 10 | add_subdirectory(tests) 11 | 12 | 13 | add_executable(stem stem1.cpp ${SOURCE} ${AKELA_SOURCES} ${UTILS_SOURCES}) 14 | add_executable(stem-cli STEMConsole.cpp) 15 | 16 | 17 | target_link_libraries(stem AvicennaSuperPlus MaddogUtils EdgeLinkx EdgeUtils EdgeDB MaddogConnection ConnectorLinkxTCP boost_atomic boost_log_setup boost_log boost_system pthread rt boost_thread boost_unit_test_framework readline XBowConnection DirectConnection EdgeDB MaddogProcessor ExchangeProcessor libredisclient.a) 18 | 19 | 20 | target_link_libraries(stem-cli boost_atomic boost_log_setup boost_log boost_system pthread rt boost_thread readline ) 21 | 22 | 23 | install(TARGETS stem stem-cli 24 | RUNTIME DESTINATION bin) 25 | -------------------------------------------------------------------------------- /src/CMakeLists.txt~: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(akela) 3 | add_subdirectory(cli) 4 | add_subdirectory(avicenna) 5 | add_subdirectory(config) 6 | add_subdirectory(manager) 7 | add_subdirectory(trade) 8 | add_subdirectory(utils) 9 | add_subdirectory(redis) 10 | 11 | 12 | add_executable(stem stem1.cpp ${SOURCE}) 13 | add_executable(stem-cli STEMConsole.cpp) 14 | 15 | target_link_libraries(stem AvicennaSuperPlus MaddogUtils EdgeLinkx EdgeUtils MaddogConnection ConnectorLinkxTCP boost_atomic boost_log_setup boost_log boost_system pthread rt boost_thread readline XBowConnection DirectConnection libredisclient.a) 16 | 17 | 18 | target_link_libraries(stem-cli boost_atomic boost_log_setup boost_log boost_system pthread rt boost_thread readline ) 19 | 20 | 21 | install(TARGETS stem stem-cli 22 | RUNTIME DESTINATION bin) 23 | -------------------------------------------------------------------------------- /src/STEMConsole.cpp: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | // Name : STEMConsole.cpp 3 | // Author : Muhammad Jamil Farooq 4 | // Version : 5 | // Copyright : riskapplication.com 6 | // Description : STEM Console Application to talk to STEM 7 | 8 | //============================================================================ 9 | 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | using namespace std; 22 | using namespace boost::interprocess; 23 | 24 | #define CLI_COMMAND_PROMPT_STRING "stem console>" 25 | #define CLI_MESSAGE_QUEUE_IDENTIFIER "stem-message-queue" 26 | 27 | int main () 28 | { 29 | try{ 30 | //Open a message queue. 31 | message_queue mq (open_only, CLI_MESSAGE_QUEUE_IDENTIFIER); 32 | unsigned int priority; 33 | message_queue::size_type recvd_size; 34 | 35 | //Receive 100 numbers 36 | while(true){ 37 | 38 | string buffer = readline(CLI_COMMAND_PROMPT_STRING); 39 | 40 | boost::algorithm::trim(buffer); 41 | 42 | 43 | if ( !buffer.empty() ) { 44 | //place commad in history to be used later 45 | add_history(buffer.c_str()); 46 | } 47 | 48 | if ( buffer == "exit" ) return 0; 49 | 50 | mq.send(buffer.c_str(), buffer.size(), 0); 51 | cout<<"sending ... "<(this)->Subscribe(ticker); 16 | if ( ECERR_SUCCESS != status ) { 17 | //log this event 18 | ERROR<<"can't subscribe to symbol ("<tickerList.push_back(ticker); 22 | } 23 | } 24 | } 25 | 26 | void STEMMaddogConnection::Subscribe(std::vector &symList) { 27 | std::for_each(symList.begin(), symList.end(), [this](std::string str){ 28 | MarketData::Ticker ticker; 29 | if ( ticker.Parse(str, MarketData::Ticker::TYPE_EQUITY) ) { 30 | int status = static_cast(this)->Subscribe(ticker); 31 | if ( ECERR_SUCCESS != status ) { 32 | //log this event 33 | ERROR<<"can't subscribe to symbol ("<tickerList.push_back(ticker); 37 | } 38 | } 39 | }); 40 | } 41 | 42 | void STEMMaddogConnection::Unsubscribe(std::string symbol) { 43 | std::for_each(tickerList.begin(), tickerList.end(),[](MarketData::Ticker ticker){ 44 | 45 | }); 46 | } 47 | 48 | void STEMMaddogConnection::Unsubscribe() { 49 | std::for_each(tickerList.begin(), tickerList.end(), [this](MarketData::Ticker &ticker){ 50 | static_cast(this)->Unsubscribe(ticker); 51 | }); 52 | } 53 | 54 | STEMMaddogConnection::STEMMaddogConnection(Linkx::IClient &client): 55 | Maddog::Connection(client), 56 | //member variables 57 | m_bDump(false), 58 | m_bTrades(true), 59 | m_bQuotes(true), 60 | m_bDepth(true), 61 | m_bOrderBook(true) { 62 | 63 | int status = this->Connect("Maddog"); 64 | if (ECERR_SUCCESS != status) { 65 | FATAL<<"Maddog::Connect failed rc="< "<(message.priceType)<<" = "<(message.data[0].price), message.data[0].priceType).AsDouble(); 102 | trade_signal(message.ticker.ToString(), 103 | price_double); 104 | } 105 | } 106 | 107 | /*=========================================================================================*/ 108 | 109 | void STEMMaddogConnection::OnQuote(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 110 | const MarketData::Quote &message) 111 | { 112 | if (m_bQuotes) { 113 | //copying quote data in symbol manager 114 | TRACE<<"bid and ask sizes "< = "<<((double)message.bidSize - (double)message.askSize) / ((double)message.bidSize + (double)message.askSize); 116 | quote_signal(message.ticker.ToString(), 117 | message.bidSize, 118 | Utils::Price(static_cast(message.bid), message.priceType).AsDouble(), 119 | message.askSize, 120 | Utils::Price(static_cast(message.ask), message.priceType).AsDouble()); 121 | } 122 | } 123 | 124 | /*=========================================================================================*/ 125 | 126 | void STEMMaddogConnection::OnQuoteDepth(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 127 | const size_t subjectLength, const MarketData::Depth &message) 128 | { 129 | // if (m_bDepth) { 130 | // ::fprintf(stdout, "Depth,%d,%lf,%s,%08X,%d,%d\n", message.header.sequence, message.header.timeStamp, 131 | // message.ticker.ToString().c_str(), message.flags, message.priceType, message.levelCount); 132 | // Process(&message, message.header.length); 133 | // } 134 | } 135 | 136 | /*=========================================================================================*/ 137 | 138 | void STEMMaddogConnection::OnQuoteDepthList(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 139 | const size_t subjectLength, const MarketData::DepthList &message) 140 | { 141 | // if (m_bDepth) { 142 | // ::fprintf(stdout, "DepthList,%d,%lf,%s,%08X,%d\n", message.header.sequence, message.header.timeStamp, 143 | // message.ticker.ToString().c_str(), message.flags, message.priceType); 144 | // Process(&message, message.header.length); 145 | // } 146 | } 147 | 148 | /*=========================================================================================*/ 149 | 150 | void STEMMaddogConnection::OnRefresh(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 151 | const size_t subjectLength, const MarketData::Refresh &message) 152 | { 153 | // ::fprintf(stdout, "Refresh,%d,%lf,%s,%08X,%d,%d\n", message.header.sequence, message.header.timeStamp, 154 | // message.ticker.ToString().c_str(), message.flags, message.priceType, message.fieldCount); 155 | // Process(&message, message.header.length); 156 | } 157 | 158 | /*=========================================================================================*/ 159 | 160 | void STEMMaddogConnection::OnAlert(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 161 | const size_t subjectLength, const MarketData::Alert &message) 162 | { 163 | ::fprintf(stdout, "Alert,%d,%lf,%s,%08X,%d\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str(), 164 | message.flags, message.state); 165 | // Process(&message, message.header.length); 166 | } 167 | 168 | /*=========================================================================================*/ 169 | 170 | void STEMMaddogConnection::OnOrder(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 171 | const size_t subjectLength, const MarketData::Order &message) 172 | { 173 | // if (m_bOrderBook) { 174 | // ::fprintf(stdout, "Order,%d,%lf,%s,%d\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str(), 175 | // message.priceType); 176 | // Process(&message, message.header.length); 177 | // } 178 | } 179 | 180 | /*=========================================================================================*/ 181 | 182 | void STEMMaddogConnection::OnOrderList(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 183 | const size_t subjectLength, const MarketData::OrderList &message) 184 | { 185 | // if (m_bOrderBook) { 186 | // ::fprintf(stdout, "OrderList,%d,%lf,%s\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str()); 187 | // Process(&message, message.header.length); 188 | // } 189 | } 190 | 191 | /*=========================================================================================*/ 192 | 193 | void STEMMaddogConnection::OnCancel(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 194 | const size_t subjectLength, const MarketData::Cancel &message) 195 | { 196 | // if (m_bOrderBook) { 197 | // ::fprintf(stdout, "Cancel,%d,%lf,%s\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str()); 198 | // Process(&message, message.header.length); 199 | // } 200 | } 201 | 202 | /*=========================================================================================*/ 203 | 204 | void STEMMaddogConnection::OnExecution(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 205 | const size_t subjectLength, const MarketData::Execution &message) 206 | { 207 | // if (m_bTrades || m_bOrderBook) { 208 | // ::fprintf(stdout, "Execution,%d,%lf,%s,%d,%d,%d,%d\n", message.header.sequence, message.header.timeStamp, 209 | // message.ticker.ToString().c_str(), message.priceType, message.price, message.size, message.volume); 210 | // Process(&message, message.header.length); 211 | // } 212 | } 213 | 214 | /*=========================================================================================*/ 215 | 216 | void STEMMaddogConnection::OnSettlement(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 217 | const size_t subjectLength, const MarketData::Settlement &message) 218 | { 219 | // ::fprintf(stdout, "Settlement,%d,%lf,%s,%d\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str(), 220 | // message.priceType); 221 | // Process(&message, message.header.length); 222 | } 223 | 224 | -------------------------------------------------------------------------------- /src/akela/STEMMaddogConnection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * STEMMaddogConnection.h 3 | * 4 | * Created on: Apr 26, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef STEMMADDOGCONNECTION_H_ 9 | #define STEMMADDOGCONNECTION_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "../utils/log.h" 19 | 20 | class SymbolManager; 21 | 22 | class STEMMaddogConnection: public Maddog::Connection { 23 | public: 24 | using TradeSlotType = void (const std::string &, double); 25 | using QuoteSlotType = void (const std::string &, uint32_t, double, uint32_t, double); 26 | 27 | boost::signals2::signal trade_signal; 28 | boost::signals2::signal quote_signal; 29 | 30 | STEMMaddogConnection(Linkx::IClient &); 31 | virtual ~STEMMaddogConnection(); 32 | 33 | 34 | 35 | void connect(TradeSlotType, 36 | QuoteSlotType); 37 | void Subscribe(std::string sym); 38 | void Subscribe(std::vector &symList); 39 | void Unsubscribe(); 40 | void Unsubscribe(std::string); 41 | 42 | protected: 43 | void Process(const void *pUpdate, const size_t updateLength); 44 | virtual void OnTrade(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 45 | const MarketData::Trade &trade); 46 | virtual void OnTradeList(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 47 | const MarketData::TradeList &tradeList); 48 | virtual void OnQuote(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 49 | const MarketData::Quote "e); 50 | virtual void OnQuoteDepth(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 51 | const MarketData::Depth &depth); 52 | virtual void OnQuoteDepthList(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 53 | const MarketData::DepthList &depthList); 54 | virtual void OnRefresh(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 55 | const MarketData::Refresh &refresh); 56 | virtual void OnAlert(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 57 | const MarketData::Alert &alert); 58 | virtual void OnOrder(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 59 | const MarketData::Order &order); 60 | virtual void OnOrderList(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 61 | const MarketData::OrderList &orderList); 62 | virtual void OnCancel(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 63 | const MarketData::Cancel &cancel); 64 | virtual void OnExecution(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 65 | const MarketData::Execution &execution); 66 | virtual void OnSettlement(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 67 | const MarketData::Settlement &settlement); 68 | 69 | private: 70 | STEMMaddogConnection(const STEMMaddogConnection&); 71 | STEMMaddogConnection &operator=(const STEMMaddogConnection&); 72 | 73 | bool m_bDump, m_bTrades, m_bQuotes, m_bDepth, m_bOrderBook; 74 | 75 | std::list tickerList; 76 | 77 | std::unique_ptr sm; 78 | }; 79 | 80 | #endif /* STEMMADDOGCONNECTION_H_ */ 81 | -------------------------------------------------------------------------------- /src/avicenna/AvicennaInterface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AvicennaInterface.cpp 3 | * 4 | * Created on: May 12, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #include "../avicenna/AvicennaInterface.h" 9 | 10 | #include "../config/TradingConfig.h" 11 | 12 | 13 | AvicennaConnection::AvicennaConnection(const std::string account_id, 14 | const std::string symbol, 15 | const AvicennaConfiguration &config): 16 | account_id(account_id), 17 | symbol(symbol), 18 | price_estimate(-1.00), 19 | price_estimate_3(-1.00), 20 | startup(true), 21 | ms(0) { 22 | 23 | SetIP(const_cast(config.dll_ip.c_str())); 24 | SetVariableConfig( 25 | const_cast(config.dll_str1.c_str()), 26 | const_cast(config.dll_str3.c_str()), 27 | const_cast(config.dll_str4.c_str()), 28 | const_cast(config.dll_str5.c_str()) 29 | ); 30 | 31 | } 32 | 33 | AvicennaConnection::AvicennaConnection( 34 | const std::string account_id, 35 | const std::string symbol, 36 | const std::string ip, 37 | const std::string str1, 38 | const std::string str2, 39 | const std::string str3, 40 | const std::string str4, 41 | const std::string str5): 42 | account_id(account_id), 43 | symbol(symbol), 44 | price_estimate(-1.00), 45 | price_estimate_3(-1.00), 46 | startup(true), 47 | ms(0) { 48 | 49 | SetIP(const_cast(ip.c_str())); 50 | SetVariableConfig( 51 | const_cast(str1.c_str()), 52 | const_cast(str3.c_str()), 53 | const_cast(str4.c_str()), 54 | const_cast(str5.c_str()) 55 | ); 56 | 57 | } 58 | 59 | void AvicennaConnection::calculate(double price, double min, double max ) { 60 | // DEBUG< price_estimate_3 ) { 78 | // TRACE<id; 104 | 105 | if ( SymbolConfig::user_symbols_map->find(account_id) == SymbolConfig::user_symbols_map->end() ) { 106 | FATAL<<"exiting AvicennaInterface::timeoutThread for "<find(account_id)->second.get(); 111 | 112 | auto timer1 = trade_account->avicenna_configuration[0].dll_timer1; 113 | auto timer2 = trade_account->avicenna_configuration[1].dll_timer1; 114 | 115 | 116 | for (auto itr = symbols_map->begin(); itr != symbols_map->end(); itr++) { 117 | //initialize AvicennaConnection for each symbol 118 | auto symbol = itr->first; 119 | 120 | AvicennaConnectionPair *pair = nullptr; 121 | 122 | pair = new AvicennaConnectionPair{ 123 | new AvicennaConnection( 124 | trade_account->id, 125 | symbol, 126 | trade_account->avicenna_configuration[0] 127 | ), 128 | new AvicennaConnection( 129 | trade_account->id, 130 | symbol, 131 | trade_account->avicenna_configuration[1] 132 | ) 133 | }; 134 | 135 | avicenna_list.emplace(symbol, pair); 136 | 137 | } 138 | 139 | 140 | timeout_thread1 = new std::thread(&AvicennaInterface::timeoutThread, this, timer1, 0); 141 | timeout_thread2 = new std::thread(&AvicennaInterface::timeoutThread, this, timer2, 1); 142 | 143 | } 144 | 145 | void AvicennaInterface::timeoutThread(int timeout, int index) { 146 | 147 | auto symbols_map = SymbolConfig::user_symbols_map->find(account_id)->second.get(); 148 | while ( !stop_timeout_thread ) { 149 | 150 | for (auto itr = symbols_map->begin(); itr != symbols_map->end(); itr++) { 151 | auto& symbol = *itr->second.get(); 152 | 153 | auto& avicenna_connection = ( 0 == index ) ? 154 | *avicenna_list[symbol.name]->avicenna1: 155 | *avicenna_list[symbol.name]->avicenna2; 156 | 157 | Symbol::reset_interval_callback_type newEstimate = [&avicenna_connection, this, &symbol, index] ( 158 | double lat, double min, double max, double ear)->double { 159 | if ( lat > 0 ) { 160 | auto invert = true; 161 | auto val = lat; 162 | while ( avicenna_connection.price_estimate <= 0.0 && avicenna_connection.startup ) { 163 | if ( invert ) { 164 | invert = false; 165 | val += 0.01; 166 | } else { 167 | invert = true; 168 | val -= 0.01; 169 | } 170 | avicenna_connection.calculate(val, min, max); 171 | } 172 | 173 | avicenna_connection.calculate(lat, min, max); 174 | avicenna_connection.startup = false; 175 | auto symbol = avicenna_connection.symbol; 176 | // TRACE< 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | //#include "../config/TradingConfig.h" 21 | #include "../config/SymbolConfig.h" 22 | #include "../libs/avicenna/AvicennaSuperPlus.h" 23 | 24 | 25 | class AvicennaConfiguration; 26 | class TradeAccount; 27 | 28 | #define LOG_AVICENNA_INTERFACE " <"<account_id<<"> " 29 | #define LOG_AVICENNA_CONNECTION " <"<account_id<<","< " 30 | 31 | struct AvicennaConnection:public CAvicenna_SuperPlus { 32 | double price_estimate; 33 | double price_estimate_3; 34 | 35 | double ms; 36 | 37 | const std::string account_id; 38 | const std::string symbol; 39 | 40 | bool startup; 41 | 42 | AvicennaConnection(const std::string, 43 | const std::string, 44 | const AvicennaConfiguration &); 45 | AvicennaConnection( 46 | const std::string, 47 | const std::string, 48 | const std::string, 49 | const std::string, 50 | const std::string, 51 | const std::string, 52 | const std::string, 53 | const std::string); 54 | 55 | void calculate(double, double, double); 56 | 57 | }; 58 | 59 | 60 | class AvicennaInterface { 61 | 62 | std::string account_id; 63 | std::string symbol; 64 | const TradeAccount *trade_account; 65 | 66 | std::thread *timeout_thread1, *timeout_thread2; 67 | bool stop_timeout_thread; 68 | void timeoutThread(int, int); 69 | void newEstimate(double latest, double min = 0.0, double max = 0.0, double earliest = 0.0); 70 | double output[4]; 71 | double price_estimate; 72 | 73 | struct AvicennaConnectionPair { 74 | AvicennaConnection *avicenna1; 75 | AvicennaConnection *avicenna2; 76 | }; 77 | 78 | 79 | std::map avicenna_list; 80 | 81 | public: 82 | 83 | AvicennaInterface(const TradeAccount *trade_account); 84 | ~AvicennaInterface(); 85 | }; 86 | 87 | #endif /* AVICENNAINTERFACE_H_ */ 88 | -------------------------------------------------------------------------------- /src/avicenna/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE 2 | ${SOURCE} 3 | ${CMAKE_CURRENT_SOURCE_DIR}/AvicennaInterface.cpp 4 | PARENT_SCOPE 5 | ) 6 | set(HEADERS 7 | ${HEADERS} 8 | ${CMAKE_CURRENT_SOURCE_DIR}/AvicennaInterface.h 9 | PARENT_SCOPE 10 | ) 11 | -------------------------------------------------------------------------------- /src/cli/CLI.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * CLI.cpp 3 | * 4 | * Created on: Apr 19, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #include "CLI.h" 9 | 10 | CLI *CLI::single = nullptr; 11 | map CLI::callbackLookup; 12 | 13 | CommandCallback::~CommandCallback() { 14 | 15 | } 16 | 17 | CLI::CLI() { 18 | 19 | buffer = new char[CLI_READLINE_BUFFER_SIZE]; 20 | 21 | //initiate message queue for IPC 22 | try { 23 | boost::interprocess::message_queue::remove(CLI_MESSAGE_QUEUE_IDENTIFIER); 24 | mq = new boost::interprocess::message_queue ( 25 | boost::interprocess::create_only, 26 | CLI_MESSAGE_QUEUE_IDENTIFIER, 27 | CLI_MESSAGE_QUEUE_SIZE, 28 | CLI_READLINE_BUFFER_SIZE 29 | ); 30 | } catch ( boost::interprocess::interprocess_exception &e ) { 31 | ERROR<receive(message_buffer, CLI_READLINE_BUFFER_SIZE, message_size, priority); 86 | char *temp = strndup(message_buffer, message_size); 87 | TRACE< 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "../utils/log.h" 22 | 23 | using namespace std; 24 | 25 | #define CLI_READLINE_BUFFER_SIZE 500 26 | #define CLI_MESSAGE_QUEUE_SIZE 100 27 | #define CLI_COMMAND_PROMPT_STRING "stem>" 28 | #define CLI_MESSAGE_QUEUE_IDENTIFIER "stem-message-queue" 29 | 30 | typedef vector stringlist; 31 | 32 | class CommandCallback { 33 | public: 34 | virtual ~CommandCallback(); 35 | virtual void operator()(stringlist args) = 0; //implement this functor to register callback function 36 | }; 37 | 38 | class CLI { 39 | boost::interprocess::message_queue *mq; 40 | char *buffer; 41 | boost::thread *cli; 42 | boost::thread *cli_client; 43 | CLI(); 44 | virtual ~CLI(); 45 | string readCommand(); 46 | static map callbackLookup; 47 | static CLI *single; //singleton for cli 48 | void readCommandAndDispatch(); 49 | void readCommandAndDispatchFromCLIClient(); 50 | 51 | public: 52 | static void init(); 53 | static bool registerCommand(string, CommandCallback *); 54 | }; 55 | 56 | 57 | 58 | 59 | #endif /* CLI_H_ */ 60 | -------------------------------------------------------------------------------- /src/cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE 2 | ${SOURCE} 3 | ${CMAKE_CURRENT_SOURCE_DIR}/CLI.cpp 4 | PARENT_SCOPE 5 | ) 6 | set(HEADERS 7 | ${HEADERS} 8 | ${CMAKE_CURRENT_SOURCE_DIR}/CLI.h 9 | PARENT_SCOPE 10 | ) 11 | -------------------------------------------------------------------------------- /src/config/AdminConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AdminConfig.h 3 | * 4 | * Created on: Apr 19, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef ADMINCONFIG_H_ 9 | #define ADMINCONFIG_H_ 10 | 11 | #include "ConfigReader.h" 12 | 13 | class AdminSettings { 14 | std::string panic_close_time; 15 | std::string soft_close_time; 16 | std::string log_severity; 17 | std::string verbose_severity; 18 | std::string positionfile_time; 19 | int redis_port; 20 | std::string redis_ip; 21 | bool redis_enable; 22 | public: 23 | AdminSettings(boost::property_tree::ptree &pt) { 24 | panic_close_time = pt.get_child("panic_close_time").get_value(); 25 | soft_close_time = pt.get_child("soft_close_time").get_value(); 26 | log_severity = pt.get_child("log").get_child("").get_child("severity").get_value(); 27 | verbose_severity = pt.get_child("verbose").get_child("").get_child("severity").get_value(); 28 | positionfile_time=pt.get_child("generate_positionfile_time").get_value(); 29 | redis_ip=pt.get_child("redis").get_child("").get_child("ip").get_value(); 30 | redis_port=pt.get_child("redis").get_child("").get_child("port").get_value(); 31 | redis_enable=pt.get_child("redis").get_child("").get_child("enable").get_value(); 32 | cout<<"AdminSettings: panic close time (UTC) "< tag")); 92 | else if ( 1 < count ) BOOST_THROW_EXCEPTION(ConfigException()<")); 93 | 94 | ptree &admin = pt.get_child("admin"); 95 | settings = new AdminSettings(admin); 96 | if ( nullptr == settings ) BOOST_THROW_EXCEPTION(ConfigException()< 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #include "../cli/CLI.h" 36 | #include "../utils/log.h" 37 | #include "../utils/utils.h" 38 | 39 | 40 | using namespace std; 41 | using boost::property_tree::ptree; 42 | 43 | 44 | typedef boost::error_info config_info; 45 | struct ConfigException:public boost::exception, public std::exception { 46 | const char *what() const noexcept { 47 | return "configuration error:"; 48 | } 49 | }; 50 | 51 | 52 | //class ConfigReader { 53 | //public: 54 | // 55 | // ConfigReader(string filename): 56 | // filename(filename) { 57 | // } 58 | // 59 | // virtual ~ConfigReader(){ 60 | // } 61 | // 62 | //protected: 63 | // string filename; 64 | // virtual void parse(); 65 | // bool parse_error; 66 | // ptree pt; 67 | //}; 68 | 69 | #endif /* CONFIGREADER_H_ */ 70 | -------------------------------------------------------------------------------- /src/config/TradingConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TradingConfig.h 3 | * 4 | * Created on: Apr 19, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef TRADINGCONFIG_H_ 9 | #define TRADINGCONFIG_H_ 10 | 11 | #include "ConfigReader.h" 12 | #include "../avicenna/AvicennaInterface.h" 13 | #include "../trade/TradeInstance.h" 14 | 15 | 16 | enum TRADE_ACCOUNT_TYPE { 17 | TA_SINGLE, 18 | TA_PAIR, 19 | 20 | }; 21 | 22 | struct AvicennaConfiguration { 23 | int dll_timer1; 24 | string dll_ip; 25 | bool dll_input; 26 | string dll_str1; 27 | string dll_str2; 28 | string dll_str3; 29 | string dll_str4; 30 | string dll_str5; 31 | 32 | }; 33 | 34 | 35 | struct TradeAccount { 36 | string id; 37 | 38 | TRADE_ACCOUNT_TYPE type; 39 | // in case if account type is TA_SINGLE 40 | string username; //only username should be there 41 | 42 | 43 | //in case if account type is TA_PAIR 44 | string long_acc; //long account id 45 | string short_acc; //short account id 46 | 47 | //Timer data 48 | int legacy_timer; 49 | int legacy_trader_timer; 50 | int legacy_pit_timer; 51 | 52 | uint32_t maximum_order; //< any order generated by the account shouldn't get exceed this value 53 | uint32_t maximum_live; // avicenna_interface; 59 | std::unique_ptr short_account; 60 | std::unique_ptr long_account; 61 | 62 | using TradeInstances = std::map> ; 63 | TradeInstances trade_instances; //symbol name and corresponding trade instances 64 | 65 | 66 | std::vector venues; 67 | uint8_t attempts; 68 | 69 | static bool all_enable; 70 | bool enable_this; 71 | 72 | TradeAccount(ptree &pt): avicenna_interface(nullptr), short_account(nullptr), long_account(nullptr), enable_this(true) { 73 | 74 | ptree attr = pt.get_child(""); 75 | id = attr.get_child("id").data(); 76 | 77 | string temp = attr.get_child("type").data(); 78 | 79 | if ( "single" == temp ) { 80 | type = TA_SINGLE; 81 | username = pt.get_child("username").data(); 82 | if ( "" == username ) { 83 | BOOST_THROW_EXCEPTION(ConfigException()<(); 98 | maximum_live = pt.get_child("maximum_live").get_value(); 99 | 100 | //Avicenna paramters 101 | legacy_timer = pt.get_child("legacy_timer").get_value(); 102 | if ( 0 == legacy_timer ) BOOST_THROW_EXCEPTION(ConfigException()<(); 104 | if ( 0 == legacy_trader_timer ) BOOST_THROW_EXCEPTION(ConfigException()<(); 106 | if ( 0 == legacy_pit_timer ) BOOST_THROW_EXCEPTION(ConfigException()<(); 113 | avicenna_configuration[0].dll_ip = avicenna1.get_child("ip").get_value(); 114 | avicenna_configuration[0].dll_input = avicenna1.get_child("dll_input").get_value() == "true"?true:false; 115 | avicenna_configuration[0].dll_str1 = avicenna1.get_child("dll_str1").get_value(); 116 | avicenna_configuration[0].dll_str2 = avicenna1.get_child("dll_str2").get_value(); 117 | avicenna_configuration[0].dll_str3 = avicenna1.get_child("dll_str3").get_value(); 118 | avicenna_configuration[0].dll_str4 = avicenna1.get_child("dll_str4").get_value(); 119 | avicenna_configuration[0].dll_str5 = avicenna1.get_child("dll_str5").get_value(); 120 | 121 | 122 | auto& avicenna2 = pt.get_child("avicenna2"); 123 | 124 | avicenna_configuration[1].dll_timer1 = avicenna2.get_child("dll_timer1").get_value(); 125 | avicenna_configuration[1].dll_ip = avicenna2.get_child("ip").get_value(); 126 | avicenna_configuration[1].dll_input = avicenna2.get_child("dll_input").get_value() == "true"?true:false; 127 | avicenna_configuration[1].dll_str1 = avicenna2.get_child("dll_str1").get_value(); 128 | avicenna_configuration[1].dll_str2 = avicenna2.get_child("dll_str2").get_value(); 129 | avicenna_configuration[1].dll_str3 = avicenna2.get_child("dll_str3").get_value(); 130 | avicenna_configuration[1].dll_str4 = avicenna2.get_child("dll_str4").get_value(); 131 | avicenna_configuration[1].dll_str5 = avicenna2.get_child("dll_str5").get_value(); 132 | 133 | 134 | // dll_timer1 = pt.get_child("dll_timer1").get_value(); 135 | // if ( 0 == dll_timer1 ) BOOST_THROW_EXCEPTION(ConfigException()<(); 137 | // if ( 0 == dll_timer2 ) BOOST_THROW_EXCEPTION(ConfigException()<(); 139 | // if ( "" == dll_ip ) BOOST_THROW_EXCEPTION(ConfigException()<() == "true"?true:false; 141 | // 142 | // dll_str1 = pt.get_child("dll_str1").get_value(); 143 | // if ( "" == dll_str1 ) BOOST_THROW_EXCEPTION(ConfigException()<(); 145 | // if ( "" == dll_str2 ) BOOST_THROW_EXCEPTION(ConfigException()<(); 147 | // if ( "" == dll_str3 ) BOOST_THROW_EXCEPTION(ConfigException()<(); 149 | // if ( "" == dll_str4 ) BOOST_THROW_EXCEPTION(ConfigException()<(); 151 | // if ( "" == dll_str5 ) BOOST_THROW_EXCEPTION(ConfigException()<").get_child("attempts").get_value(); 157 | INFO<<"no of attempts to be made for venues: "<<(int)attempts; 158 | 159 | for (auto itr = venues.begin(); itr != venues.end(); itr++ ) { 160 | if ( itr->first != "venue" ) { 161 | // WARN<<"reading venues: contains unrecongnised element .."<first; 162 | continue; 163 | } 164 | 165 | this->venues.push_back(itr->second.get_value()); 166 | } 167 | 168 | } 169 | 170 | friend std::ostream& operator<<(std::ostream &os, const TradeAccount &tad) { 171 | // os<second->stopAction(); 179 | } 180 | 181 | short_account->CancelAllOrders(); 182 | long_account->CancelAllOrders(); 183 | } 184 | 185 | uint32_t getMaximumLiveLimit() const { 186 | return maximum_live; 187 | } 188 | 189 | void start() { 190 | for (auto itr = trade_instances.begin(); itr != trade_instances.end(); itr++ ) { 191 | itr->second->startAction(); 192 | } 193 | } 194 | 195 | void stop(std::string &symbol) { 196 | if ( trade_instances.find(symbol) != trade_instances.end() ) { 197 | trade_instances[symbol]->stopAction(); 198 | } else { 199 | WARN<<"no symbol under account found "<startAction(); 206 | } else { 207 | WARN<<"no symbol under account found "<first ) 215 | itr->second->enablePanicClose(); 216 | } 217 | } 218 | 219 | void disablePanicClose(const std::string &symbol = "" ) { 220 | for (auto itr = trade_instances.begin(); itr != trade_instances.end(); itr++ ) { 221 | if ( symbol == "" || symbol == itr->first ) 222 | itr->second->disablePanicClose(); 223 | } 224 | } 225 | 226 | void enableSoftClose(const std::string &symbol = "" ) { 227 | for (auto itr = trade_instances.begin(); itr != trade_instances.end(); itr++ ) { 228 | if ( symbol == "" || symbol == itr->first ) 229 | itr->second->enableSoftClose(); 230 | } 231 | } 232 | 233 | void disableSoftClose(const std::string &symbol = "" ) { 234 | for (auto itr = trade_instances.begin(); itr != trade_instances.end(); itr++ ) { 235 | if ( symbol == "" || symbol == itr->first ) 236 | itr->second->disableSoftClose(); 237 | } 238 | } 239 | 240 | void avicennaToggle() { 241 | std::for_each(trade_instances.begin(), trade_instances.end(), [](TradeInstances::value_type &value){ 242 | auto& symbol = value.first; 243 | auto& trade_instance = *value.second; 244 | trade_instance.avicennaToggle(); 245 | }); 246 | } 247 | 248 | }; 249 | 250 | 251 | class TradeAccountMap: public unordered_map> { 252 | public: 253 | TradeAccountMap(ptree &pt) { 254 | for (auto itr = pt.begin(); itr != pt.end(); itr++ ) { 255 | if ( "account" == itr->first ) { 256 | std::unique_ptr trade_account(new TradeAccount(itr->second)); 257 | string id = trade_account->id; 258 | emplace(id, std::move(trade_account)); 259 | } else { 260 | WARN<<"trade configuration files expect configurations"; 261 | } 262 | } 263 | } 264 | }; 265 | 266 | class TradingConfig { 267 | public: 268 | 269 | static TradeAccountMap* trade_accounts_map; 270 | 271 | virtual ~TradingConfig(){ 272 | } 273 | 274 | static void parse(string filename) { 275 | static std::once_flag only_once; 276 | std::call_once(only_once, [filename](){ 277 | ptree pt; 278 | boost::property_tree::xml_parser::read_xml(filename, pt); 279 | int count = pt.count("trading"); 280 | if ( 0 == count ) BOOST_THROW_EXCEPTION(ConfigException()< tag")); 281 | else if ( 1 < count ) BOOST_THROW_EXCEPTION(ConfigException()<")); 282 | 283 | ptree &trading = pt.get_child("trading"); 284 | trade_accounts_map = new TradeAccountMap(trading); 285 | if ( nullptr == trade_accounts_map ) BOOST_THROW_EXCEPTION(ConfigException()< 9 | #include "../AvicennaSuperPlus/AvicennaSuperPlus.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | #define MAX_PATH 260 19 | /* 20 | * 21 | */ 22 | int main(int argc, char** argv) 23 | { 24 | 25 | 26 | try 27 | { 28 | char buffer[MAX_PATH]; 29 | ifstream read_file("SuperPlusdata.txt", ios::in); // reading input data 30 | if (!read_file) 31 | { 32 | cout << "File not found\n"; 33 | return 0; 34 | } 35 | CAvicenna_SuperPlus objSuperPlus;// Create Object of AVicennaSuperPlus 36 | char szSign[25], szSignNext[25]; 37 | char szStr[512]; 38 | double open = 0, close = 0, avi1 = 0, diff1 = 0, avi2 = 0, diff2 = 0; 39 | FILE *fp = NULL; 40 | fp = fopen("Output.txt","w+"); 41 | strcpy(buffer,""); 42 | objSuperPlus.SetIP("10.1.20.73"); // IP call here 43 | objSuperPlus.SetVariableConfig("AAA", "ABB", "II","EE","BB"); 44 | // "AAA" = Avicenna1, 45 | // "ABB" = Avicenna2, 46 | // "II" = Variable3, 47 | // "EE" = Advance 48 | // "BB" = Deimal code for Precision 49 | int loop = 0; 50 | while(!read_file.eof()) 51 | { 52 | loop++; 53 | read_file.getline(buffer,MAX_PATH); // getting the whole input data 54 | 55 | objSuperPlus.CalculateAvicennaSuperPlus(atof(buffer));// Call "CalculateAvicennaSuperPlus" function to get export Value and pass input values 56 | if(atof(buffer) > 0 ) 57 | { 58 | //objSuperPlus.GetExportValue1() = to get Avicenna1 export value 59 | //objSuperPlus.GetExportValue2() = to get Avicenna2 export value 60 | //objSuperPlus.GetExportValue3() = to get Variable3 export value 61 | //objSuperPlus.GetExportValue4() = to get Advance export value 62 | sprintf(szStr,"Input = %.2f, Value1 = %.2f, Value2 = %.2f, Value3 = %.2f, Value4 = %.2f\n",atof(buffer),objSuperPlus.GetExportValue1(), objSuperPlus.GetExportValue2(), objSuperPlus.GetExportValue3(), objSuperPlus.GetExportValue4()); 63 | cout< 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "fmacros.h" 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "anet.h" 47 | 48 | static void anetSetError(char *err, const char *fmt, ...) 49 | { 50 | va_list ap; 51 | 52 | if (!err) return; 53 | va_start(ap, fmt); 54 | vsnprintf(err, ANET_ERR_LEN, fmt, ap); 55 | va_end(ap); 56 | } 57 | 58 | int anetNonBlock(char *err, int fd) 59 | { 60 | int flags; 61 | 62 | /* Set the socket nonblocking. 63 | * Note that fcntl(2) for F_GETFL and F_SETFL can't be 64 | * interrupted by a signal. */ 65 | if ((flags = fcntl(fd, F_GETFL)) == -1) { 66 | anetSetError(err, "fcntl(F_GETFL): %s\n", strerror(errno)); 67 | return ANET_ERR; 68 | } 69 | if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { 70 | anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s\n", strerror(errno)); 71 | return ANET_ERR; 72 | } 73 | return ANET_OK; 74 | } 75 | 76 | int anetTcpNoDelay(char *err, int fd) 77 | { 78 | int yes = 1; 79 | if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) 80 | { 81 | anetSetError(err, "setsockopt TCP_NODELAY: %s\n", strerror(errno)); 82 | return ANET_ERR; 83 | } 84 | return ANET_OK; 85 | } 86 | 87 | int anetSetSendBuffer(char *err, int fd, int buffsize) 88 | { 89 | if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1) 90 | { 91 | anetSetError(err, "setsockopt SO_SNDBUF: %s\n", strerror(errno)); 92 | return ANET_ERR; 93 | } 94 | return ANET_OK; 95 | } 96 | 97 | int anetTcpKeepAlive(char *err, int fd) 98 | { 99 | int yes = 1; 100 | if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) { 101 | anetSetError(err, "setsockopt SO_KEEPALIVE: %s\n", strerror(errno)); 102 | return ANET_ERR; 103 | } 104 | return ANET_OK; 105 | } 106 | 107 | int anetResolve(char *err, char *host, char *ipbuf) 108 | { 109 | struct sockaddr_in sa; 110 | 111 | sa.sin_family = AF_INET; 112 | if (inet_aton(host, &sa.sin_addr) == 0) { 113 | struct hostent *he; 114 | 115 | he = gethostbyname(host); 116 | if (he == NULL) { 117 | anetSetError(err, "can't resolve: %s\n", host); 118 | return ANET_ERR; 119 | } 120 | memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); 121 | } 122 | strcpy(ipbuf,inet_ntoa(sa.sin_addr)); 123 | return ANET_OK; 124 | } 125 | 126 | #define ANET_CONNECT_NONE 0 127 | #define ANET_CONNECT_NONBLOCK 1 128 | static int anetTcpGenericConnect(char *err, char *addr, int port, int flags) 129 | { 130 | int s, on = 1; 131 | struct sockaddr_in sa; 132 | 133 | if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 134 | anetSetError(err, "creating socket: %s\n", strerror(errno)); 135 | return ANET_ERR; 136 | } 137 | /* Make sure connection-intensive things like the redis benckmark 138 | * will be able to close/open sockets a zillion of times */ 139 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 140 | 141 | sa.sin_family = AF_INET; 142 | sa.sin_port = htons(port); 143 | if (inet_aton(addr, &sa.sin_addr) == 0) { 144 | struct hostent *he; 145 | 146 | he = gethostbyname(addr); 147 | if (he == NULL) { 148 | anetSetError(err, "can't resolve: %s\n", addr); 149 | close(s); 150 | return ANET_ERR; 151 | } 152 | memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); 153 | } 154 | if (flags & ANET_CONNECT_NONBLOCK) { 155 | if (anetNonBlock(err,s) != ANET_OK) 156 | return ANET_ERR; 157 | } 158 | if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { 159 | if (errno == EINPROGRESS && 160 | flags & ANET_CONNECT_NONBLOCK) 161 | return s; 162 | 163 | anetSetError(err, "connect: %s\n", strerror(errno)); 164 | close(s); 165 | return ANET_ERR; 166 | } 167 | return s; 168 | } 169 | 170 | int anetTcpConnect(char *err, char *addr, int port) 171 | { 172 | return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONE); 173 | } 174 | 175 | int anetTcpNonBlockConnect(char *err, char *addr, int port) 176 | { 177 | return anetTcpGenericConnect(err,addr,port,ANET_CONNECT_NONBLOCK); 178 | } 179 | 180 | /* Like read(2) but make sure 'count' is read before to return 181 | * (unless error or EOF condition is encountered) */ 182 | int anetRead(int fd, char *buf, int count) 183 | { 184 | int nread, totlen = 0; 185 | while(totlen != count) { 186 | nread = read(fd,buf,count-totlen); 187 | if (nread == 0) return totlen; 188 | if (nread == -1) return -1; 189 | totlen += nread; 190 | buf += nread; 191 | } 192 | return totlen; 193 | } 194 | 195 | /* Like write(2) but make sure 'count' is read before to return 196 | * (unless error is encountered) */ 197 | int anetWrite(int fd, char *buf, int count) 198 | { 199 | int nwritten, totlen = 0; 200 | while(totlen != count) { 201 | nwritten = write(fd,buf,count-totlen); 202 | if (nwritten == 0) return totlen; 203 | if (nwritten == -1) return -1; 204 | totlen += nwritten; 205 | buf += nwritten; 206 | } 207 | return totlen; 208 | } 209 | 210 | int anetTcpServer(char *err, int port, char *bindaddr) 211 | { 212 | int s, on = 1; 213 | struct sockaddr_in sa; 214 | 215 | if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 216 | anetSetError(err, "socket: %s\n", strerror(errno)); 217 | return ANET_ERR; 218 | } 219 | if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { 220 | anetSetError(err, "setsockopt SO_REUSEADDR: %s\n", strerror(errno)); 221 | close(s); 222 | return ANET_ERR; 223 | } 224 | memset(&sa,0,sizeof(sa)); 225 | sa.sin_family = AF_INET; 226 | sa.sin_port = htons(port); 227 | sa.sin_addr.s_addr = htonl(INADDR_ANY); 228 | if (bindaddr) { 229 | if (inet_aton(bindaddr, &sa.sin_addr) == 0) { 230 | anetSetError(err, "Invalid bind address\n"); 231 | close(s); 232 | return ANET_ERR; 233 | } 234 | } 235 | if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { 236 | anetSetError(err, "bind: %s\n", strerror(errno)); 237 | close(s); 238 | return ANET_ERR; 239 | } 240 | if (listen(s, 511) == -1) { /* the magic 511 constant is from nginx */ 241 | anetSetError(err, "listen: %s\n", strerror(errno)); 242 | close(s); 243 | return ANET_ERR; 244 | } 245 | return s; 246 | } 247 | 248 | int anetAccept(char *err, int serversock, char *ip, int *port) 249 | { 250 | int fd; 251 | struct sockaddr_in sa; 252 | unsigned int saLen; 253 | 254 | while(1) { 255 | saLen = sizeof(sa); 256 | fd = accept(serversock, (struct sockaddr*)&sa, &saLen); 257 | if (fd == -1) { 258 | if (errno == EINTR) 259 | continue; 260 | else { 261 | anetSetError(err, "accept: %s\n", strerror(errno)); 262 | return ANET_ERR; 263 | } 264 | } 265 | break; 266 | } 267 | if (ip) strcpy(ip,inet_ntoa(sa.sin_addr)); 268 | if (port) *port = ntohs(sa.sin_port); 269 | return fd; 270 | } 271 | -------------------------------------------------------------------------------- /src/libs/redis/anet.h: -------------------------------------------------------------------------------- 1 | /* anet.c -- Basic TCP socket stuff made a bit less boring 2 | * 3 | * Copyright (c) 2006-2010, Salvatore Sanfilippo 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Redis nor the names of its contributors may be used 15 | * to endorse or promote products derived from this software without 16 | * specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | * POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef ANET_H 32 | #define ANET_H 33 | 34 | #define ANET_OK 0 35 | #define ANET_ERR -1 36 | #define ANET_ERR_LEN 256 37 | 38 | int anetTcpConnect(char *err, char *addr, int port); 39 | int anetTcpNonBlockConnect(char *err, char *addr, int port); 40 | int anetRead(int fd, char *buf, int count); 41 | int anetResolve(char *err, char *host, char *ipbuf); 42 | int anetTcpServer(char *err, int port, char *bindaddr); 43 | int anetAccept(char *err, int serversock, char *ip, int *port); 44 | int anetWrite(int fd, char *buf, int count); 45 | int anetNonBlock(char *err, int fd); 46 | int anetTcpNoDelay(char *err, int fd); 47 | int anetTcpKeepAlive(char *err, int fd); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/libs/redis/fmacros.h: -------------------------------------------------------------------------------- 1 | #ifndef _REDIS_FMACRO_H 2 | #define _REDIS_FMACRO_H 3 | 4 | #define _BSD_SOURCE 5 | #define _XOPEN_SOURCE 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /src/libs/redis/libredisclient.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjamilfarooq/tradingapp/2baa792f4ece6dd918a0ef7c74967c36f59ae487/src/libs/redis/libredisclient.a -------------------------------------------------------------------------------- /src/manager/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(SOURCE 4 | ${SOURCE} 5 | ${CMAKE_CURRENT_SOURCE_DIR}/SymbolManager.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/TradeAccountManager.cpp 7 | PARENT_SCOPE 8 | ) 9 | set(HEADERS 10 | ${HEADERS} 11 | ${CMAKE_CURRENT_SOURCE_DIR}/SymbolManager.h 12 | ${CMAKE_CURRENT_SOURCE_DIR}/TradeAccountManager.h 13 | PARENT_SCOPE 14 | ) 15 | -------------------------------------------------------------------------------- /src/manager/SymbolManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SymbolManager.cpp 3 | * 4 | * Created on: May 9, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #include "../manager/SymbolManager.h" 9 | 10 | #include "../akela/STEMMaddogConnection.h" 11 | 12 | bool SymbolInfo::all_enable = true; 13 | 14 | SymbolManager::SymbolManager(Linkx::Client &client)/*: 15 | market(client)*/ { 16 | 17 | 18 | //register signal handler for tradelist and quote event 19 | market.trade_signal.connect(boost::bind(&SymbolManager::updatePrice, this, _1, _2)); 20 | market.quote_signal.connect(boost::bind(&SymbolManager::updateQuote, this, _1, _2, _3, _4, _5)); 21 | 22 | 23 | 24 | auto &user_symbol_map = *SymbolConfig::user_symbols_map; 25 | 26 | for (auto usrptr = user_symbol_map.begin(); 27 | usrptr != user_symbol_map.end(); 28 | usrptr++) { 29 | auto id = usrptr->first; 30 | auto &symbol_map = *usrptr->second.get(); 31 | DEBUG<<"Loading symbols from: "<first; 37 | auto sym = symptr->second.get(); 38 | 39 | 40 | if ( symbol_hash.find(name) == symbol_hash.end() ) { //if symbol doesn't already exist 41 | auto symbol_data = SymbolHash::mapped_type(new SymbolInfo(name)); 42 | symbol_hash.emplace(name, std::move(symbol_data)); 43 | market.Subscribe(name+"."+sym->exchange); //subscribing symbol 44 | 45 | } 46 | 47 | symbol_hash.find(name)->second->registerSymbol(sym); 48 | 49 | } 50 | } 51 | 52 | CLI::registerCommand("ss", this); 53 | CLI::registerCommand("rs", this); 54 | } 55 | 56 | 57 | void SymbolManager::subscribeSymbols() { 58 | // for (auto itr = symbol_hash.begin(); itr != symbol_hash.end(); itr++ ) { 59 | // auto symbol = itr->first; 60 | // auto sym = itr->second.get(); 61 | // DEBUG<second).this_enable = false; 104 | } 105 | } 106 | } else if ( args[0] == "rs" ) { 107 | if ( args[1] == "-a" ) { //restart all 108 | SymbolInfo::all_enable = true; 109 | } else { //second argument must be name of the symbol 110 | auto itr = symbol_hash.find(args[1]); 111 | if ( itr != symbol_hash.end() ) { //if symbol exist 112 | (*itr->second).this_enable = true; 113 | } 114 | } 115 | } 116 | 117 | } 118 | 119 | SymbolManager::~SymbolManager() { 120 | // TODO Auto-generated destructor stub 121 | } 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/manager/SymbolManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SymbolManager.h 3 | * 4 | * Created on: May 9, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef SYMBOLMANAGER_H_ 9 | #define SYMBOLMANAGER_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../akela/STEMMaddogConnection.h" 16 | #include "../akela/STEMDirectConnection.h" 17 | //#include 18 | 19 | #include "../config/SymbolConfig.h" 20 | 21 | #include "../akela/STEMMaddogConnection.h" 22 | #include "../akela/STEMDirectConnection.h" 23 | 24 | #define LOG_SYMBOL_MANAGER " <"< " 25 | #define LOG_SYMBOL_DATA " <"<name<<">: " 26 | 27 | 28 | struct SymbolInfo { 29 | 30 | std::string name; 31 | std::chrono::time_point last_updated; //start time for each symbol default value epoch 32 | std::vector symbols; //all the Symbol in UserSymbolsMap correspond to this symbol "name" 33 | static bool all_enable; 34 | bool this_enable; 35 | 36 | SymbolInfo(std::string symbol): 37 | name(symbol), this_enable(true) { 38 | } 39 | 40 | //this shall register corresponding symbol in user domain 41 | void registerSymbol(Symbol *sym) { 42 | symbols.push_back(sym); 43 | } 44 | 45 | }; 46 | 47 | 48 | using SymbolHash = std::unordered_map>; 49 | class STEMMaddogConnection; 50 | 51 | 52 | class SymbolManager: public CommandCallback { 53 | // STEMMaddogConnection market; 54 | STEMDirectConnection market; 55 | SymbolHash symbol_hash; 56 | 57 | void updatePrice(const std::string &, double); 58 | void updateQuote(const std::string &, uint32_t, double, uint32_t, double); 59 | 60 | public: 61 | SymbolManager(Linkx::Client &); 62 | ~SymbolManager(); 63 | void subscribeSymbols(); 64 | void operator()(stringlist); 65 | 66 | 67 | }; 68 | 69 | #endif /* SYMBOLMANAGER_H_ */ 70 | -------------------------------------------------------------------------------- /src/manager/TradeAccountManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TradeAccountManager.cpp 3 | * 4 | * Created on: Jul 3, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #include "../manager/TradeAccountManager.h" 9 | 10 | #include "../config/TradingConfig.h" 11 | 12 | //Linkx::Client* TradeInstance::client = nullptr; 13 | 14 | bool TradeAccount::all_enable = true; 15 | 16 | TradeAccountManager::TradeAccountManager(Linkx::Client &client) { 17 | // TradeInstance::client = &client; 18 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 19 | 20 | 21 | for (auto usrptr = trade_accounts_map.begin(); 22 | usrptr != trade_accounts_map.end(); 23 | usrptr++ ) { 24 | auto id = usrptr->first; 25 | auto& account = *usrptr->second; 26 | 27 | account.avicenna_interface = std::unique_ptr(new AvicennaInterface(&account)); 28 | account.short_account = std::unique_ptr(new OrderAccount(client, account.short_acc, ORDER_ACCOUNT_SHORT, account.venues)); 29 | account.long_account = std::unique_ptr(new OrderAccount(client, account.long_acc, ORDER_ACCOUNT_LONG, account.venues)); 30 | 31 | auto& symbol_map = (*SymbolConfig::user_symbols_map)[account.id]; 32 | for (auto symbol_itr = symbol_map.begin(); symbol_itr != symbol_map.end(); symbol_itr++) { 33 | // symbol_itr->second->trade_trigger.connect(boost::bind(&TradeInstance::triggerProcessing, this, _1)); 34 | // symbol_itr->second->processing_thread = new std::thread(&TradeInstance::triggerProcessing, this, symbol_itr->second.get()); 35 | auto trade_instance = std::unique_ptr(new TradeInstance(account, *symbol_itr->second)); 36 | account.trade_instances.emplace(symbol_itr->first, std::move(trade_instance)); 37 | } 38 | 39 | 40 | 41 | 42 | } 43 | 44 | CLI::registerCommand("st", this); //stop trading 45 | CLI::registerCommand("rt", this); //restart trading 46 | CLI::registerCommand("pc", this); //panic close 47 | CLI::registerCommand("dpc", this); //disable panic close 48 | CLI::registerCommand("sc", this); //soft close 49 | CLI::registerCommand("dsc", this); //disable soft close 50 | CLI::registerCommand("av", this); 51 | 52 | } 53 | 54 | void TradeAccountManager::operator ()(stringlist args) { 55 | 56 | auto size = args.size(); 57 | 58 | if ( size < 2 ) { 59 | DEBUG<<"command arguments missing"; 60 | return; 61 | } 62 | 63 | if ( args[0] == "st" ) { 64 | if ( args[1] == "" ) { 65 | TRACE<<"unrecognized command arguments"; 66 | } else if ( args[1] == "-a" ) { //all symbol must stop 67 | TradeAccount::all_enable = false; 68 | stop(); 69 | } else { //second argument must be name of the symbol 70 | if ( size == 3 ) 71 | stop(args[1], args[2]); 72 | else stop(args[1]); 73 | } 74 | } else if ( args[0] == "rt" ) { 75 | 76 | if ( args[1] == "" ) { 77 | TRACE<<"unrecognized command arguments"; 78 | } else if ( args[1] == "-a" ) { //all symbol must stop 79 | TradeAccount::all_enable = true; 80 | start(); 81 | } else { //second argument must be name of the symbol 82 | if ( size == 3 ) 83 | start(args[1], args[2]); 84 | else start(args[1]); 85 | } 86 | } else if ( args[0] == "pc" ) { //panic close 87 | if ( args[1] == "" ) { 88 | TRACE<<"unrecognized command arguments"; 89 | } else if ( args[1] == "-d" ) { //disable soft close 90 | if ( args[2] == "-a" ) { //disable soft close for all symbols 91 | panicClose("", "", false); 92 | } else { //second argument must be name of the symbol 93 | if ( size == 4 ) 94 | panicClose(args[2], args[3], false); 95 | else panicClose(args[2],"", false); 96 | } 97 | 98 | } else if ( args[1] == "-a" ) { //all symbol must stop 99 | 100 | panicClose(); 101 | } else { //second argument must be name of the symbol 102 | if ( size == 3 ) 103 | panicClose(args[1], args[2]); 104 | else panicClose(args[1]); 105 | } 106 | } else if ( args[0] == "sc" ) {//soft close 107 | if ( args[1] == "" ) { 108 | TRACE<<"unrecognized command arguments"; 109 | } else if ( args[1] == "-d" ) { //disable soft close 110 | if ( args[2] == "-a" ) { //disable soft close for all symbols 111 | softClose("", "", false); 112 | } else { //second argument must be name of the symbol 113 | if ( size == 4 ) 114 | softClose(args[2], args[3], false); 115 | else softClose(args[2],"", false); 116 | } 117 | 118 | } else if ( args[1] == "-a" ) { //all symbol must stop 119 | softClose(); 120 | } else { //second argument must be name of the symbol 121 | if ( size == 3 ) 122 | softClose(args[1], args[2]); 123 | else softClose(args[1]); 124 | } 125 | } else if ( args[0] == "av") { //avicenna toggle command 126 | if ( args[1] =="-a" ) { //all accounts avicenna estimate should be toggle 127 | avicennaToggle(); 128 | } else { 129 | avicennaToggle(args[1]); 130 | } 131 | 132 | } 133 | 134 | 135 | } 136 | 137 | void TradeAccountManager::avicennaToggle(const std::string &account_id) { 138 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 139 | 140 | if ( account_id == "" ) { 141 | TRACE<<"avicennaToggle: toggle all accounts"; 142 | std::for_each(trade_accounts_map.begin(), trade_accounts_map.end(), [&account_id, this] (TradeAccountMap::value_type &value) { 143 | auto& id = value.first; 144 | auto& account = *value.second; 145 | account.avicennaToggle(); 146 | }); 147 | } 148 | else { 149 | auto account = trade_accounts_map.find(account_id); 150 | if ( account != trade_accounts_map.end() ) { 151 | auto& id = account->first; 152 | TRACE<<"avicennaToggle: toggling "<second; 154 | acc.avicennaToggle(); 155 | } else { 156 | TRACE<<"avicennaToggle: account not found"; 157 | return; 158 | } 159 | } 160 | } 161 | 162 | void TradeAccountManager::panicClose(const std::string &account_id, const std::string &symbol, const bool enable) { 163 | 164 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 165 | 166 | for (auto usrptr = trade_accounts_map.begin(); 167 | usrptr != trade_accounts_map.end(); 168 | usrptr++ ) { 169 | auto& id = usrptr->first; 170 | auto& account = *usrptr->second; 171 | if ( account_id == "" || account_id == id ) { //if there is no account_id all should be panicClose 172 | if ( enable ) 173 | account.enablePanicClose(symbol); 174 | else account.disablePanicClose(symbol); 175 | } 176 | } 177 | 178 | } 179 | 180 | void TradeAccountManager::softClose(const std::string &account_id, const std::string &symbol, const bool enable) { 181 | 182 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 183 | 184 | for (auto usrptr = trade_accounts_map.begin(); 185 | usrptr != trade_accounts_map.end(); 186 | usrptr++ ) { 187 | auto& id = usrptr->first; 188 | auto& account = *usrptr->second; 189 | if ( account_id == "" || account_id == id ) { //if there is no account_id all should be panicClose 190 | if ( enable ) 191 | account.enableSoftClose(symbol); 192 | else account.disableSoftClose(symbol); 193 | } 194 | } 195 | 196 | } 197 | 198 | 199 | 200 | void TradeAccountManager::stop() { 201 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 202 | 203 | for (auto usrptr = trade_accounts_map.begin(); 204 | usrptr != trade_accounts_map.end(); 205 | usrptr++ ) { 206 | auto id = usrptr->first; 207 | auto& account = *usrptr->second; 208 | 209 | account.stop(); 210 | } 211 | } 212 | 213 | void TradeAccountManager::start() { 214 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 215 | 216 | for (auto usrptr = trade_accounts_map.begin(); 217 | usrptr != trade_accounts_map.end(); 218 | usrptr++ ) { 219 | auto id = usrptr->first; 220 | auto& account = *usrptr->second; 221 | 222 | account.start(); 223 | } 224 | } 225 | 226 | void TradeAccountManager::start(std::string &account_id) { 227 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 228 | if ( trade_accounts_map.find(account_id) != trade_accounts_map.end() ){ 229 | trade_accounts_map[account_id]->start(); 230 | } else { 231 | TRACE<<"unrecognized account id"; 232 | } 233 | } 234 | 235 | void TradeAccountManager::stop(std::string &account_id) { 236 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 237 | if ( trade_accounts_map.find(account_id) != trade_accounts_map.end() ){ 238 | trade_accounts_map[account_id]->stop(); 239 | } else { 240 | TRACE<<"unrecognized account id"; 241 | } 242 | } 243 | 244 | void TradeAccountManager::start(std::string &account_id, std::string &symbol) { 245 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 246 | if ( trade_accounts_map.find(account_id) != trade_accounts_map.end() ){ 247 | trade_accounts_map[account_id]->start(symbol); 248 | } else { 249 | TRACE<<"unrecognized account id"; 250 | } 251 | } 252 | 253 | void TradeAccountManager::stop(std::string &account_id, std::string &symbol) { 254 | auto& trade_accounts_map = *TradingConfig::trade_accounts_map; 255 | if ( trade_accounts_map.find(account_id) != trade_accounts_map.end() ){ 256 | trade_accounts_map[account_id]->stop(symbol); 257 | } else { 258 | TRACE<<"unrecognized account id"; 259 | } 260 | } 261 | 262 | void TradeAccountManager::dayEnd() { 263 | INFO<<"******************************End Handler Called****************************************"; 264 | INFO<<"******************************End Handler Called****************************************"; 265 | INFO<<"******************************End Handler Called****************************************"; 266 | } 267 | 268 | void TradeAccountManager::generatePositionFile() { 269 | system("../scripts/redistofile.sh"); 270 | 271 | } 272 | 273 | TradeAccountManager::~TradeAccountManager() { 274 | // TODO Auto-generated destructor stub 275 | } 276 | 277 | 278 | 279 | 280 | 281 | -------------------------------------------------------------------------------- /src/manager/TradeAccountManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TradeAccountManager.h 3 | * 4 | * Created on: Jul 3, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef TRADE_TRADEACCOUNTMANAGER_H_ 9 | #define TRADE_TRADEACCOUNTMANAGER_H_ 10 | 11 | //#include "../config/TradingConfig.h" 12 | #include "../akela/OrderAccount.h" 13 | #include "../avicenna/AvicennaInterface.h" 14 | #include "../utils/log.h" 15 | #include 16 | 17 | 18 | class TradeAccountManager: public CommandCallback { 19 | public: 20 | TradeAccountManager(Linkx::Client &); 21 | virtual ~TradeAccountManager(); 22 | void operator()(stringlist); 23 | 24 | void stop(); 25 | void start(); 26 | void stop(std::string& ); 27 | void start(std::string& ); 28 | void start(std::string &, std::string&); 29 | void stop(std::string &, std::string&); 30 | 31 | void panicClose(const std::string &account_id = "", const std::string &symbol="", const bool enable = true); 32 | void softClose(const std::string &account_id = "", const std::string &symbol="", const bool enable = true); 33 | void avicennaToggle(const std::string &account_id = ""); 34 | 35 | 36 | void dayEnd(); 37 | void generatePositionFile(); 38 | }; 39 | 40 | #endif /* TRADE_TRADEACCOUNTMANAGER_H_ */ 41 | -------------------------------------------------------------------------------- /src/redis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(SOURCE 4 | ${SOURCE} 5 | ${CMAKE_CURRENT_SOURCE_DIR}/RedisWriter.cpp 6 | PARENT_SCOPE 7 | ) 8 | set(HEADERS 9 | ${HEADERS} 10 | ${CMAKE_CURRENT_SOURCE_DIR}/RedisWriter.h 11 | PARENT_SCOPE 12 | ) 13 | -------------------------------------------------------------------------------- /src/redis/RedisWriter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RedisWriter.h 3 | * 4 | * Created on: Sep 9, 2016 5 | * Author: akela 6 | */ 7 | 8 | #ifndef SRC_REDIS_REDISWRITER_H_ 9 | #define SRC_REDIS_REDISWRITER_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "../utils/log.h" 20 | #include "../trade/PositionRecordTable.h" 21 | struct Position { 22 | 23 | std::string Type; 24 | std::string Reserved; 25 | std::string Account; 26 | std::string Underlier; 27 | std::string Root; 28 | std::string Expiration ; 29 | std::string Strike; 30 | std::string Quantity; 31 | std::string PutorCall; 32 | std::string Price; 33 | 34 | std::string rif; 35 | std::string pif; 36 | 37 | 38 | std::string liveSharesBuy; 39 | std::string liveSharesSell; 40 | std::string TotalExecutedShares; 41 | 42 | }; 43 | 44 | struct RedisOrderInfo{ 45 | std::string Symbol; 46 | std::string Size; 47 | std::string Price; 48 | std::string Type; 49 | std::string ExecutionTime; 50 | std::string AckTime ; 51 | std::string ChangeTime; 52 | std::string CancelTime; 53 | 54 | 55 | }; 56 | 57 | class RedisWriter { 58 | public: 59 | 60 | 61 | RedisWriter(std::string ip, uint16_t port): client(ip, port,0) { 62 | DEBUG<<"Inside RedisWriter constructor "< readStem1KeyFromRedis(); 74 | Position parseStem1Value(std::string value); 75 | // static void initRedisWriter(std::string ip, uint16_t port,bool enable); 76 | static bool isRedisEnabled; 77 | /* static RedisWriter* getRedisPointer() { 78 | return singleton; 79 | }*/ 80 | //static redis::client *c; 81 | std::mutex redis_mutex; 82 | 83 | RedisOrderInfo parseRedisOrderInfo(std::string value); 84 | bool writeOrderInfoToRedis(std::string user,std::string requestid,std::string symbol,std::string size,std::string price,std::string type,std::string execution_time,std::string ack_time,std::string change_time,std::string cancel_time); 85 | bool updateOrderCancleTime(std::string user,std::string requestId,std::string cancleTime); 86 | bool updateOrderExecTime(std::string user,std::string requestId,std::string execTime); 87 | bool updateOrderChangeTime(std::string user,std::string requestId,std::string changeTime); 88 | std::string getCurrentTime(); 89 | bool writeTradeCaseToRedis(std::string user,std::string symbol,std::string time,std::string state,std::string tradeCaseNumber,std::string bid_size,std::string bid_price,std::string ask_size,std::string ask_price,std::string price_estimate); 90 | bool writePositionRecordToRedis(std::string user,std::string symbol,PositionRecord record); 91 | bool writePositionRecordCommonDataToRedis(std::string user,std::string symbol,uint32_t open_size,double pnl,double average); 92 | bool writePositionRecordTableToRedis(std::string user,std::string symbol,PositionRecordTable &table); 93 | 94 | private: 95 | redis::client client; 96 | //static RedisWriter *singleton; 97 | 98 | }; 99 | 100 | #endif /* SRC_REDIS_REDISWRITER_H_ */ 101 | -------------------------------------------------------------------------------- /src/stem1.cpp: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | // Name : STEM1.cpp 3 | // Author : Muhammad Jamil Farooq 4 | // Version : 5 | // Copyright : riskapplication.com 6 | // Description : STEM Application First Version 7 | // Features: 8 | // 1- Reading Symbol Configuration File 9 | // 2- Reading Trading Configuration File 10 | // 3- Reading Admin Configuration File 11 | //============================================================================ 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | //#include 20 | //#include 21 | //#include 22 | //#include 23 | 24 | #include "config/SymbolConfig.h" 25 | #include "config/TradingConfig.h" 26 | #include "config/AdminConfig.h" 27 | 28 | #include "redisclient.h" 29 | #include "redis/RedisWriter.h" 30 | #include "utils/log.h" 31 | #include "cli/CLI.h" 32 | #include "manager/SymbolManager.h" 33 | #include "manager/TradeAccountManager.h" 34 | 35 | using namespace std; 36 | 37 | const char *g_VersionString = "1.0"; 38 | 39 | #define PROGRAM_ARGUMENT_LIST(declare) \ 40 | declare(ARG_ROUTER_ADDRESS, "LinkAddress", "", false) \ 41 | declare(ARG_ROUTER_PORT, "LinkPort", "", false) \ 42 | 43 | 44 | enum ProgramArgumentId 45 | { 46 | PROGRAM_ARGUMENT_LIST(EXTRACT_PROGRAM_ARGUMENT_ID) 47 | }; 48 | 49 | const Config::CommandLineParser::ProgramArgument g_ArgumentList[] = 50 | { 51 | PROGRAM_ARGUMENT_LIST(MAKE_PROGRAM_ARGUMENT) 52 | }; 53 | 54 | 55 | /*=========================================================================================*/ 56 | 57 | #define PROGRAM_OPTION_LIST(declare) \ 58 | declare(ARG_VERBOSE, \ 59 | "Verbose", \ 60 | "v", \ 61 | "Verbose Output Level", \ 62 | "TRACE", \ 63 | OPTION_NORMAL, \ 64 | 0) \ 65 | declare(ARG_LOGGING, \ 66 | "Logging", \ 67 | "l", \ 68 | "Loggin Output Level", \ 69 | "TRACE", \ 70 | OPTION_NORMAL, \ 71 | 0) \ 72 | declare(ARG_SYMBOL_CONFIG, \ 73 | "SymbolConfig", \ 74 | "s", \ 75 | "Symbol Configuration ", \ 76 | "symbol_config.xml", \ 77 | OPTION_NORMAL, \ 78 | 0) \ 79 | declare(ARG_TRADING_CONFIG, \ 80 | "TradingConfig", \ 81 | "t", \ 82 | "Tradig Configuration", \ 83 | "trading_config.xml", \ 84 | OPTION_NORMAL, \ 85 | 0) \ 86 | declare(ARG_ADMIN_CONFIG, \ 87 | "AdminConfig", \ 88 | "a", \ 89 | "Admin Configuration", \ 90 | "admin_config.xml", \ 91 | OPTION_NORMAL, \ 92 | 0) \ 93 | declare(ARG_APPLICATION_NAME, \ 94 | "ApplicationName", \ 95 | "m", \ 96 | "STEM Application for NYSE", \ 97 | "STEM", \ 98 | OPTION_NORMAL, \ 99 | 0) \ 100 | declare(ARG_HELP, \ 101 | "help", \ 102 | "?", \ 103 | "Command Line Help", \ 104 | "", \ 105 | OPTION_HELP, \ 106 | 0) \ 107 | 108 | enum ProgramOptionId 109 | { 110 | PROGRAM_OPTION_LIST(EXTRACT_PROGRAM_OPTION_ID) 111 | }; 112 | 113 | const Config::CommandLineParser::ProgramOption g_OptionList[] = 114 | { 115 | PROGRAM_OPTION_LIST(MAKE_PROGRAM_OPTION) 116 | }; 117 | 118 | /*=========================================================================================*/ 119 | 120 | //static configuration variable initializations 121 | UserSymbolsMap* SymbolConfig::user_symbols_map = nullptr; 122 | TradeAccountMap* TradingConfig::trade_accounts_map = nullptr; 123 | AdminSettings* AdminConfig::settings = nullptr; 124 | 125 | SymbolManager* symbol_manager = nullptr; 126 | TradeAccountManager* account_manager = nullptr; 127 | 128 | bool exit_signal = false; 129 | 130 | int main(int argc, char *argv[]) { 131 | 132 | 133 | Config::CommandLineParser programParams("STEM1", g_VersionString, "STEM 1.0 Application", g_ArgumentList, 134 | ARRAY_SIZE(g_ArgumentList), g_OptionList, ARRAY_SIZE(g_OptionList)); 135 | unsigned status; 136 | 137 | status = programParams.Parse(argc, argv); 138 | if (ECERR_SUCCESS != status) { 139 | fprintf(stderr, "CommandLineParser::Parser() failed, rc=%d\n", status); 140 | return 1; 141 | } 142 | 143 | std::string routerAddress; 144 | std::string data; 145 | std::string verbose; 146 | std::string logging; 147 | 148 | std::string symbol_config; 149 | std::string trading_config; 150 | std::string admin_config; 151 | 152 | 153 | boost::log::trivial::severity_level severity_option = boost::log::trivial::trace; 154 | 155 | auto routerPort = LINKX_DEFAULT_PORT; 156 | try { 157 | 158 | //extracting RouterAddress 159 | if (!programParams.GetValue("LinkAddress", routerAddress) || 0 == routerAddress.size()) { 160 | fprintf(stderr, "No router address specified.\n"); 161 | return 1; 162 | } 163 | 164 | //extracting RouterPort 165 | if (!programParams.GetValue("LinkPort", data) || 0 == data.size()) { 166 | fprintf(stderr, "No router port specified. setting to default (%d)\n", routerPort); 167 | return 1; 168 | } else { 169 | routerPort = atoi(data.c_str()); 170 | if ( 0 == routerPort ) { 171 | routerPort = LINKX_DEFAULT_PORT; 172 | fprintf(stderr, "Zero is not a valid port. setting to default (%d)\n", routerPort); 173 | } 174 | } 175 | 176 | //setting verbosity level for the application from trace to error 177 | if ( programParams.GetValue("Verbose", verbose) ) { 178 | if ( 0 == strcasecmp(verbose.c_str(), "trace") ) severity_option = boost::log::trivial::trace; 179 | else if ( 0 == strcasecmp(verbose.c_str(), "debug") ) severity_option = boost::log::trivial::debug; 180 | else if ( 0 == strcasecmp(verbose.c_str(), "info") ) severity_option = boost::log::trivial::info; 181 | else if ( 0 == strcasecmp(verbose.c_str(), "warning") ) severity_option = boost::log::trivial::warning; 182 | else if ( 0 == strcasecmp(verbose.c_str(), "error") ) severity_option = boost::log::trivial::error; 183 | else if ( 0 == strcasecmp(verbose.c_str(), "fatal") ) severity_option = boost::log::trivial::fatal; 184 | else { 185 | fprintf(stderr, "Unrecognized verbosity option setting to default option (trace)"); 186 | } 187 | } 188 | 189 | 190 | if ( !programParams.GetValue("SymbolConfig", symbol_config) ) { 191 | fprintf(stderr, "must specify symbol configuration"); 192 | } 193 | 194 | if ( !programParams.GetValue("TradingConfig", trading_config) ) { 195 | fprintf(stderr, "must specify symbol configuration"); 196 | } 197 | 198 | if ( !programParams.GetValue("AdminConfig", admin_config) ) { 199 | fprintf(stderr, "must specify symbol configuration"); 200 | } 201 | 202 | fprintf(stdout, "configurations files include\n%s\n%s\n%s\n", 203 | symbol_config.c_str(), trading_config.c_str(), admin_config.c_str()); 204 | 205 | 206 | } catch (std::exception &ex) { 207 | fprintf(stderr, "Command line parse error, %s\n", ex.what()); 208 | programParams.Usage(); 209 | 210 | return 1; 211 | } 212 | 213 | TRACE<<"STARTING STEM"; 214 | 215 | // boost::log::core::get()->set_filter 216 | // ( 217 | // boost::log::trivial::severity >= severity_option 218 | // ); 219 | 220 | try { 221 | SymbolConfig::parse(symbol_config); 222 | TradingConfig::parse(trading_config); 223 | // AdminConfig::parse(admin_config); 224 | } catch (ConfigException &e) { 225 | cerr<getRedisIp(),AdminConfig::settings->getRedisPort(),0); 239 | //RedisWriter::initRedisWriter(AdminConfig::settings->getRedisIp(),AdminConfig::settings->getRedisPort(), AdminConfig::settings->getRedisEnable()); 240 | RedisWriter::isRedisEnabled=AdminConfig::settings->getRedisEnable(); 241 | 242 | 243 | CLI::init(); //initiate command line interface 244 | // 245 | 246 | //initiating maddog connection 247 | // STEMMaddogConnection connection(client); 248 | 249 | //Symbol Manager is passed with Maddog Connection to subscribe symbols 250 | symbol_manager = new SymbolManager(client); 251 | account_manager = new TradeAccountManager(client); 252 | 253 | boost::asio::io_service io; 254 | boost::asio::deadline_timer panic_close_timer(io); 255 | boost::asio::deadline_timer soft_close_timer(io); 256 | boost::asio::deadline_timer position_file_timer(io); 257 | 258 | boost::gregorian::date today = boost::gregorian::day_clock::local_day(); //current date 259 | 260 | boost::posix_time::time_duration panic_duration = boost::posix_time::duration_from_string(AdminConfig::settings->getPanicCloseTime()); 261 | boost::posix_time::ptime panic_time (today, panic_duration); 262 | 263 | panic_close_timer.expires_at(panic_time); 264 | panic_close_timer.async_wait(boost::bind(&TradeAccountManager::dayEnd, account_manager)); 265 | 266 | 267 | boost::posix_time::time_duration soft_duration = boost::posix_time::duration_from_string(AdminConfig::settings->getSoftCloseTime()); 268 | boost::posix_time::ptime soft_time (today, soft_duration); 269 | 270 | soft_close_timer.expires_at(soft_time); 271 | soft_close_timer.async_wait(boost::bind(&TradeAccountManager::dayEnd, account_manager)); 272 | 273 | boost::posix_time::time_duration position_duration = boost::posix_time::duration_from_string(AdminConfig::settings->getPositionFileTime()); 274 | boost::posix_time::ptime position_time (today, position_duration); 275 | 276 | position_file_timer.expires_at(position_time); 277 | position_file_timer.async_wait(boost::bind(&TradeAccountManager::generatePositionFile, account_manager)); 278 | 279 | 280 | auto signal_handler = [&io](const boost::system::error_code& err_no, int signum){ 281 | INFO<<"=======+++++++========= Killing STEM =================+++++++++++=="; 282 | INFO<<"==========++====== Canceling all pending orders ==================="; 283 | 284 | cout<<"exiting from stem using signal handler"; 285 | account_manager->stop(); 286 | io.stop(); 287 | }; 288 | 289 | boost::asio::signal_set signals(io, SIGINT, SIGTERM); 290 | signals.async_wait(signal_handler); 291 | 292 | io.run(); 293 | 294 | // signal(SIGINT, signal_handler); 295 | // signal(SIGTERM, signal_handler); 296 | // signal(SIGHUP, signal_handler); 297 | 298 | // while ( !exit_signal ) { 299 | // this_thread::sleep_for(std::chrono::milliseconds(1000)); 300 | // }; 301 | 302 | cout<<" exiting from STEM!!!!!"; 303 | 304 | return 0; 305 | } 306 | -------------------------------------------------------------------------------- /src/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(order_sending order_sending.cpp ${AKELA_SOURCES} ${UTILS_SOURCES}) 3 | add_definitions(-DUNIT_TEST ) 4 | add_executable(position_table position_table.cpp) 5 | 6 | target_link_libraries(order_sending MaddogUtils EdgeLinkx EdgeUtils EdgeDB MaddogConnection ConnectorLinkxTCP boost_atomic boost_log_setup boost_log boost_system pthread rt boost_thread boost_unit_test_framework readline XBowConnection DirectConnection EdgeDB MaddogProcessor ExchangeProcessor) 7 | target_link_libraries(position_table boost_atomic boost_system pthread rt boost_log_setup boost_log boost_thread boost_unit_test_framework) 8 | 9 | install(TARGETS order_sending 10 | RUNTIME DESTINATION ../bin) 11 | install(TARGETS position_table 12 | RUNTIME DESTINATION ../bin) 13 | -------------------------------------------------------------------------------- /src/tests/order_sending.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * order_sending.cpp 3 | * 4 | * Created on: Nov 9, 2016 5 | * Author: jamil 6 | */ 7 | 8 | 9 | 10 | #define BOOST_TEST_MODULE first test 11 | #include 12 | 13 | #include "../akela/OrderAccount.h" 14 | #include "../config/AdminConfig.h" 15 | 16 | 17 | using namespace std; 18 | 19 | AdminSettings* AdminConfig::settings = nullptr; 20 | 21 | BOOST_AUTO_TEST_SUITE(stringtester) 22 | 23 | BOOST_AUTO_TEST_CASE(zerosize) { 24 | Linkx::Client client; 25 | auto status = client.Connect("127.0.0.1", 48000); 26 | if ( ECERR_SUCCESS != status ) { 27 | FATAL<<"Linkx::Client::Connect failed for 127.0.0.1:48000 rc = "<{"XBowSIM"}); 32 | 33 | BOOST_CHECK(true); 34 | } 35 | 36 | 37 | 38 | 39 | BOOST_AUTO_TEST_SUITE_END() 40 | -------------------------------------------------------------------------------- /src/tests/position_table.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * position_table.cpp 3 | * 4 | * Created on: Mar 1, 2017 5 | * Author: jamil 6 | */ 7 | 8 | 9 | 10 | 11 | #define BOOST_TEST_MODULE position table tests 12 | #include 13 | 14 | #define UNIT_TEST 1 15 | 16 | #include "../trade/PositionRecordTable.h" 17 | #include 18 | 19 | using namespace std; 20 | 21 | BOOST_AUTO_TEST_SUITE(position_table_tests) 22 | 23 | PositionRecordTable ltable(true); //long account 24 | PositionRecordTable stable(false); //short account 25 | 26 | std::vector test_positions; 27 | std::vector correct_order; 28 | 29 | void populate_test_vector1() { 30 | test_positions.clear();correct_order.clear(); 31 | //push test positions 32 | test_positions.push_back(PositionRecord(1, 100, 39.5, 39.50, 1)); 33 | test_positions.push_back(PositionRecord(2, 200, 39.6, 39.56, 1)); 34 | test_positions.push_back(PositionRecord(3, 300, 38.2, 38.88, 1)); 35 | test_positions.push_back(PositionRecord(4, 400, 37.1, 38.17, 1)); 36 | test_positions.push_back(PositionRecord(5, 500, 38.3, 38.21, 1)); 37 | 38 | //correct order for test position 39 | correct_order.push_back(4); 40 | correct_order.push_back(3); 41 | correct_order.push_back(5); 42 | correct_order.push_back(1); 43 | correct_order.push_back(2); 44 | } 45 | 46 | void populate_test_vector2() { 47 | test_positions.clear();correct_order.clear(); 48 | //push test positionsk for short table 49 | test_positions.push_back(PositionRecord(1, 100, 39.5, 39.50, -1)); 50 | test_positions.push_back(PositionRecord(2, 200, 39.6, 39.56, -1)); 51 | test_positions.push_back(PositionRecord(3, 300, 38.2, 38.88, -1)); 52 | test_positions.push_back(PositionRecord(4, 400, 37.1, 38.17, -1)); 53 | test_positions.push_back(PositionRecord(5, 500, 38.3, 38.21, -1)); 54 | 55 | //correct order for test position 56 | correct_order.push_back(2); 57 | correct_order.push_back(1); 58 | correct_order.push_back(5); 59 | correct_order.push_back(3); 60 | correct_order.push_back(4); 61 | 62 | } 63 | 64 | void populate_table(decltype(ltable) &table) { 65 | table.clear(); 66 | std::for_each(test_positions.begin(), test_positions.end(), [&] (decltype(test_positions)::const_reference position) { 67 | table.recordOpenPosition(position.open_order_id, 68 | position.open_size, 69 | position.open_price); 70 | }); 71 | } 72 | 73 | void test_order(decltype(ltable) &table) { 74 | auto i = 0; 75 | for (auto itr = table.begin(); itr != table.end(); itr++, i++) { 76 | BOOST_CHECK_MESSAGE( itr->open_order_id == correct_order[i], "table order failure for "< AvicennaInterface::avicenna_pool = std::vector(); 12 | std::thread * AvicennaInterface::api_call = nullptr; 13 | bool AvicennaInterface::stop = true; 14 | std::mutex AvicennaInterface::start_mutex; 15 | std::condition_variable AvicennaInterface::start_condition; 16 | 17 | AvicennaInterface::AvicennaInterface(std::string sym, std::string account_id): 18 | account_id(account_id), 19 | symbol(sym), 20 | latest_price(-1.00), 21 | earliest_price(-1.00), 22 | max_price(-1.00), 23 | min_price(-1.00), 24 | start_interval(true) { 25 | init(); 26 | //register for all avicenna connection 27 | avicenna_pool.push_back(this); 28 | 29 | //initialize thread to call api to inquire 30 | //this should be called only once to initiate update price thread for all Avicenna Connections 31 | static std::once_flag only_once; 32 | std::call_once(only_once, [](){ 33 | api_call = new std::thread(AvicennaInterface::updateAllPrices); 34 | }); 35 | } 36 | 37 | 38 | void AvicennaInterface::init() { 39 | 40 | TradingConfig &tradingConfig = *TradingConfig::getInstance(); 41 | 42 | TradeAccountData *tradeAccountData = tradingConfig.getTradeAccountData(account_id); 43 | if ( nullptr == tradeAccountData ) { 44 | WARN < lock(rw_mutex); 69 | std::chrono::duration elapsed_time = std::chrono::steady_clock::now() - last_executed; 70 | if ( elapsed_time.count() > trade_account_data.dll_timer1 ) { //if timer for the call has expired 71 | price = earliest_price; 72 | if ( price > 0 ) { 73 | TRACE< 0 ) { 84 | TRACE< 0 ) { 95 | TRACE< 0 ) { 106 | TRACE< lock(start_mutex); 124 | start_condition.wait(lock, [](){ return !stop;}); 125 | 126 | while ( !stop ) { 127 | for (auto itr = avicenna_pool.begin(); itr != avicenna_pool.end(); itr++) { 128 | AvicennaInterface *avicenna = *itr; 129 | avicenna->updatePrice(); 130 | } 131 | //sleep for one second 132 | std::this_thread::sleep_for(std::chrono::seconds(1)); 133 | } 134 | } 135 | 136 | AvicennaInterface::~AvicennaInterface() { 137 | 138 | } 139 | 140 | -------------------------------------------------------------------------------- /src/trade/AvicennaInterface.h~: -------------------------------------------------------------------------------- 1 | /* 2 | * AvicennaInterface.h 3 | * 4 | * Created on: May 12, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef AVICENNAINTERFACE_H_ 9 | #define AVICENNAINTERFACE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "../config/TradingConfig.h" 20 | #include "../libs/avicenna/AvicennaSuperPlus.h" 21 | 22 | 23 | #define LOG_AVICENNA_INTERFACE " <"<symbol<<","<account_id<<"> " 24 | 25 | 26 | class AvicennaInterface:public CAvicenna_SuperPlus { 27 | 28 | std::string account_id; 29 | std::string symbol; 30 | TradeAccountData trade_account_data; 31 | std::chrono::steady_clock::time_point last_executed; 32 | double output[4]; 33 | atomic price; 34 | bool is_price_changed; 35 | bool is_initialized; 36 | 37 | 38 | //this should maintain all avicenna connections pool 39 | static std::vector avicenna_pool; 40 | static std::thread *api_call; 41 | static void updateAllPrices(); 42 | static bool stop; 43 | 44 | void init(); //called by construtor to connect initialize Avicenna 45 | void updatePrice(); 46 | public: 47 | AvicennaInterface(std::string, std::string ); //configuration that contain input paramters and ip 48 | ~AvicennaInterface(); 49 | 50 | void update_price (uint8_t priceType, uint32_t price) { 51 | DEBUG<(price)/pow(10.0, priceType); 53 | this->price.exchange(price_double); 54 | is_price_changed = true; 55 | } 56 | 57 | 58 | }; 59 | 60 | #endif /* AVICENNAINTERFACE_H_ */ 61 | -------------------------------------------------------------------------------- /src/trade/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(SOURCE 4 | ${SOURCE} 5 | ${CMAKE_CURRENT_SOURCE_DIR}/TradeInstance.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/TradeCase.cpp 7 | ${CMAKE_CURRENT_SOURCE_DIR}/AbstractTradeAccount.cpp 8 | ${CMAKE_CURRENT_SOURCE_DIR}/LongTradeAccount.cpp 9 | ${CMAKE_CURRENT_SOURCE_DIR}/ShortTradeAccount.cpp 10 | PARENT_SCOPE 11 | ) 12 | set(HEADERS 13 | ${HEADERS} 14 | ${CMAKE_CURRENT_SOURCE_DIR}/TradeInstance.h 15 | ${CMAKE_CURRENT_SOURCE_DIR}/TradeCase.h 16 | ${CMAKE_CURRENT_SOURCE_DIR}/AbstractTradeAccount.h 17 | ${CMAKE_CURRENT_SOURCE_DIR}/LongTradeAccount.h 18 | ${CMAKE_CURRENT_SOURCE_DIR}/ShortTradeAccount.h 19 | PARENT_SCOPE 20 | ) 21 | -------------------------------------------------------------------------------- /src/trade/CMakeLists.txt~: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(SOURCE 4 | ${SOURCE} 5 | ${CMAKE_CURRENT_SOURCE_DIR}/TradeInstance.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/AbstractTradeAccount.cpp 7 | ${CMAKE_CURRENT_SOURCE_DIR}/LongTradeAccount.cpp 8 | ${CMAKE_CURRENT_SOURCE_DIR}/ShortTradeAccount.cpp 9 | PARENT_SCOPE 10 | ) 11 | set(HEADERS 12 | ${HEADERS} 13 | ${CMAKE_CURRENT_SOURCE_DIR}/TradeInstance.h 14 | ${CMAKE_CURRENT_SOURCE_DIR}/AbstractTradeAccount.h 15 | ${CMAKE_CURRENT_SOURCE_DIR}/LongTradeAccount.h 16 | ${CMAKE_CURRENT_SOURCE_DIR}/ShortTradeAccount.h 17 | PARENT_SCOPE 18 | ) 19 | -------------------------------------------------------------------------------- /src/trade/LongTradeAccount.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * LongTradeAccount.cpp 3 | * 4 | * Created on: Aug 15, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #include "LongTradeAccount.h" 9 | 10 | LongTradeAccount::LongTradeAccount(const std::string &symbol, OrderAccount &account, uint32_t divisor): 11 | AbstractTradeAccount(symbol, account, divisor) { 12 | 13 | onOpenFillReceived = new OrderInfo::onFillFunctionType(std::bind(&LongTradeAccount::onOpenFill, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); 14 | onCloseFillReceived = new OrderInfo::onFillFunctionType(std::bind(&LongTradeAccount::onCloseFill, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); 15 | 16 | } 17 | 18 | 19 | LongTradeAccount::~LongTradeAccount() { 20 | 21 | } 22 | 23 | void LongTradeAccount::onCloseFill(std::shared_ptr& order_info, const double price, const uint32_t size) { 24 | std::lock_guard lock(mt); 25 | 26 | order_info->fill_size += size; 27 | 28 | // calculateSpread(price, size, false); 29 | 30 | auto before_close = total/max_pos; 31 | total -= size; 32 | auto after_close = total/max_pos; 33 | 34 | if ( before_close > after_close ) dec_tranch(); 35 | 36 | 37 | //totalExecuted+=size; 38 | //livesell-=size; 39 | TRACE<rif<pif; 53 | std::ostringstream os; 54 | os << this->pif; 55 | string redisPIF= os.str(); 56 | std::ostringstream oss; 57 | oss << this->rif; 58 | string redisRIF= oss.str(); 59 | //redisWriter->writeToRedis(account.getAccountName(),symbol,std::to_string(total),std::to_string(average),redisRIF,redisPIF,std::to_string(livebuy),std::to_string(livesell),std::to_string(totalExecuted)); 60 | 61 | AbstractTradeAccount::onCloseFill(order_info, price, size); 62 | } 63 | 64 | void LongTradeAccount::onOpenFill(std::shared_ptr& order_info, const double price, const uint32_t size) { 65 | std::lock_guard lock(mt); 66 | 67 | order_info->fill_size += size; 68 | 69 | calculateSpread(price, size, true); 70 | 71 | total += size; 72 | last_open_price = price; 73 | //totalExecuted+=size; 74 | //livebuy-=size; 75 | 76 | TRACE<rif<pif; 89 | std::ostringstream os; 90 | os << this->pif; 91 | string redisPIF= os.str(); 92 | std::ostringstream oss; 93 | oss << this->rif; 94 | string redisRIF= oss.str(); 95 | //redisWriter->writeToRedis(account.getAccountName(),symbol,std::to_string(total),std::to_string(average),redisRIF,redisPIF,std::to_string(livebuy),std::to_string(livesell),std::to_string(totalExecuted)); 96 | 97 | AbstractTradeAccount::onOpenFill(order_info, price, size); 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/trade/LongTradeAccount.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LongTradeAccount.h 3 | * 4 | * Created on: Aug 15, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef SRC_TRADE_LONGTRADEACCOUNT_H_ 9 | #define SRC_TRADE_LONGTRADEACCOUNT_H_ 10 | 11 | #include "AbstractTradeAccount.h" 12 | 13 | 14 | #define LOG_LONG_TRADE_ACCOUNT "<"<" 15 | 16 | class LongTradeAccount: public AbstractTradeAccount { 17 | public: 18 | LongTradeAccount(const std::string &, OrderAccount &, uint32_t); 19 | virtual ~LongTradeAccount(); 20 | 21 | void onCloseFill(std::shared_ptr&, const double, const uint32_t); 22 | void onOpenFill(std::shared_ptr&, const double, const uint32_t); 23 | }; 24 | 25 | #endif /* SRC_TRADE_LONGTRADEACCOUNT_H_ */ 26 | -------------------------------------------------------------------------------- /src/trade/STEMMaddogConnection.cpp~: -------------------------------------------------------------------------------- 1 | /* 2 | * STEMMaddogConnection.cpp 3 | * 4 | * Created on: Apr 26, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #include "STEMMaddogConnection.h" 9 | #include "SymbolManager.h" 10 | 11 | void STEMMaddogConnection::Subscribe(std::string sym){ 12 | MarketData::Ticker ticker; 13 | if ( ticker.Parse(sym, MarketData::Ticker::TYPE_EQUITY) ) { 14 | int status = static_cast(this)->Subscribe(ticker); 15 | if ( ECERR_SUCCESS != status ) { 16 | //log this event 17 | ERROR<<"can't subscribe to symbol ("<tickerList.push_back(ticker); 21 | } 22 | } 23 | } 24 | 25 | void STEMMaddogConnection::Subscribe(std::vector &symList) { 26 | std::for_each(symList.begin(), symList.end(), [this](std::string str){ 27 | MarketData::Ticker ticker; 28 | if ( ticker.Parse(str, MarketData::Ticker::TYPE_EQUITY) ) { 29 | int status = static_cast(this)->Subscribe(ticker); 30 | if ( ECERR_SUCCESS != status ) { 31 | //log this event 32 | ERROR<<"can't subscribe to symbol ("<tickerList.push_back(ticker); 36 | } 37 | } 38 | }); 39 | } 40 | 41 | void STEMMaddogConnection::Unsubscribe(std::string symbol) { 42 | std::for_each(tickerList.begin(), tickerList.end(),[](MarketData::Ticker ticker){ 43 | 44 | }); 45 | } 46 | 47 | void STEMMaddogConnection::Unsubscribe() { 48 | std::for_each(tickerList.begin(), tickerList.end(), [this](MarketData::Ticker &ticker){ 49 | static_cast(this)->Unsubscribe(ticker); 50 | }); 51 | } 52 | 53 | STEMMaddogConnection::STEMMaddogConnection(Linkx::IClient &client): 54 | Maddog::Connection(client), 55 | //member variables 56 | m_bDump(false), 57 | m_bTrades(true), 58 | m_bQuotes(true), 59 | m_bDepth(true), 60 | m_bOrderBook(true) { 61 | 62 | int status = this->Connect("Maddog"); 63 | if (ECERR_SUCCESS != status) { 64 | fprintf(stderr, "Linkx::Client::Connect(%s, %d, ...) failed, rc=%d\n", status); 65 | } else fprintf(stderr, "Linkx::Client::Connect(%s, %d, ...) successfull, rc=%d\n", status); 66 | 67 | 68 | sm = new SymbolManager(this); 69 | } 70 | 71 | STEMMaddogConnection::~STEMMaddogConnection() { 72 | 73 | } 74 | 75 | /*=========================================================================================*/ 76 | 77 | void STEMMaddogConnection::Process(const void *pUpdate, const size_t updateLength) 78 | { 79 | if (m_bDump) 80 | ::HexDump(pUpdate, updateLength); 81 | } 82 | 83 | /*=========================================================================================*/ 84 | 85 | void STEMMaddogConnection::OnTrade(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, const size_t subjectLength, 86 | const MarketData::Trade &message) 87 | { 88 | if (m_bTrades) { 89 | ::fprintf(stdout, "Trade,%d,%lf,%s,%08X,%d,%d,%d,%d\n", message.header.sequence, message.header.timeStamp, 90 | message.ticker.ToString().c_str(), message.flags, message.priceType, message.price, message.size, message.volume); 91 | Process(&message, message.header.length); 92 | } 93 | } 94 | 95 | /*=========================================================================================*/ 96 | 97 | void STEMMaddogConnection::OnTradeList(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 98 | const size_t subjectLength, const MarketData::TradeList &message) 99 | { 100 | if (m_bTrades) { 101 | // ::fprintf(stdout, "TradeList,%d,%lf,%s,%08X,%d,%d,%d\n", message.header.sequence, message.header.timeStamp, 102 | // message.ticker.ToString().c_str(), message.flags, message.priceType, message.totalSize, message.volume); 103 | TRACE<<" <"< "<(message.priceType)<<" = "< = "<<((double)message.bidSize - (double)message.askSize) / ((double)message.bidSize + (double)message.askSize); 130 | 131 | 132 | // Process(&message, message.header.length); 133 | } 134 | } 135 | 136 | /*=========================================================================================*/ 137 | 138 | void STEMMaddogConnection::OnQuoteDepth(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 139 | const size_t subjectLength, const MarketData::Depth &message) 140 | { 141 | // if (m_bDepth) { 142 | // ::fprintf(stdout, "Depth,%d,%lf,%s,%08X,%d,%d\n", message.header.sequence, message.header.timeStamp, 143 | // message.ticker.ToString().c_str(), message.flags, message.priceType, message.levelCount); 144 | // Process(&message, message.header.length); 145 | // } 146 | } 147 | 148 | /*=========================================================================================*/ 149 | 150 | void STEMMaddogConnection::OnQuoteDepthList(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 151 | const size_t subjectLength, const MarketData::DepthList &message) 152 | { 153 | // if (m_bDepth) { 154 | // ::fprintf(stdout, "DepthList,%d,%lf,%s,%08X,%d\n", message.header.sequence, message.header.timeStamp, 155 | // message.ticker.ToString().c_str(), message.flags, message.priceType); 156 | // Process(&message, message.header.length); 157 | // } 158 | } 159 | 160 | /*=========================================================================================*/ 161 | 162 | void STEMMaddogConnection::OnRefresh(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 163 | const size_t subjectLength, const MarketData::Refresh &message) 164 | { 165 | // ::fprintf(stdout, "Refresh,%d,%lf,%s,%08X,%d,%d\n", message.header.sequence, message.header.timeStamp, 166 | // message.ticker.ToString().c_str(), message.flags, message.priceType, message.fieldCount); 167 | // Process(&message, message.header.length); 168 | } 169 | 170 | /*=========================================================================================*/ 171 | 172 | void STEMMaddogConnection::OnAlert(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 173 | const size_t subjectLength, const MarketData::Alert &message) 174 | { 175 | // ::fprintf(stdout, "Alert,%d,%lf,%s,%08X,%d\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str(), 176 | // message.flags, message.state); 177 | // Process(&message, message.header.length); 178 | } 179 | 180 | /*=========================================================================================*/ 181 | 182 | void STEMMaddogConnection::OnOrder(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 183 | const size_t subjectLength, const MarketData::Order &message) 184 | { 185 | // if (m_bOrderBook) { 186 | // ::fprintf(stdout, "Order,%d,%lf,%s,%d\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str(), 187 | // message.priceType); 188 | // Process(&message, message.header.length); 189 | // } 190 | } 191 | 192 | /*=========================================================================================*/ 193 | 194 | void STEMMaddogConnection::OnOrderList(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 195 | const size_t subjectLength, const MarketData::OrderList &message) 196 | { 197 | // if (m_bOrderBook) { 198 | // ::fprintf(stdout, "OrderList,%d,%lf,%s\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str()); 199 | // Process(&message, message.header.length); 200 | // } 201 | } 202 | 203 | /*=========================================================================================*/ 204 | 205 | void STEMMaddogConnection::OnCancel(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 206 | const size_t subjectLength, const MarketData::Cancel &message) 207 | { 208 | // if (m_bOrderBook) { 209 | // ::fprintf(stdout, "Cancel,%d,%lf,%s\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str()); 210 | // Process(&message, message.header.length); 211 | // } 212 | } 213 | 214 | /*=========================================================================================*/ 215 | 216 | void STEMMaddogConnection::OnExecution(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 217 | const size_t subjectLength, const MarketData::Execution &message) 218 | { 219 | // if (m_bTrades || m_bOrderBook) { 220 | // ::fprintf(stdout, "Execution,%d,%lf,%s,%d,%d,%d,%d\n", message.header.sequence, message.header.timeStamp, 221 | // message.ticker.ToString().c_str(), message.priceType, message.price, message.size, message.volume); 222 | // Process(&message, message.header.length); 223 | // } 224 | } 225 | 226 | /*=========================================================================================*/ 227 | 228 | void STEMMaddogConnection::OnSettlement(const Linkx::Address &source, const unsigned serviceId, const void *pSubject, 229 | const size_t subjectLength, const MarketData::Settlement &message) 230 | { 231 | // ::fprintf(stdout, "Settlement,%d,%lf,%s,%d\n", message.header.sequence, message.header.timeStamp, message.ticker.ToString().c_str(), 232 | // message.priceType); 233 | // Process(&message, message.header.length); 234 | } 235 | 236 | -------------------------------------------------------------------------------- /src/trade/ShortTradeAccount.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ShortTradeAccount.cpp 3 | * 4 | * Created on: Aug 15, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #include "ShortTradeAccount.h" 9 | 10 | ShortTradeAccount::ShortTradeAccount(const std::string &symbol, OrderAccount &account, uint32_t divisor): 11 | AbstractTradeAccount(symbol, account, divisor) { 12 | 13 | //register event 14 | onOpenFillReceived = new OrderInfo::onFillFunctionType(std::bind(&ShortTradeAccount::onOpenFill, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); 15 | onCloseFillReceived = new OrderInfo::onFillFunctionType(std::bind(&ShortTradeAccount::onCloseFill, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); 16 | } 17 | 18 | 19 | ShortTradeAccount::~ShortTradeAccount() { 20 | 21 | } 22 | 23 | 24 | void ShortTradeAccount::onCloseFill(std::shared_ptr& order_info, const double price, const uint32_t size) { 25 | std::lock_guard lock(mt); 26 | 27 | order_info->fill_size += size; 28 | 29 | // calculateSpread(price, size, false); 30 | 31 | auto before_close = total/max_pos; 32 | total -= size; 33 | auto after_close = total/max_pos; 34 | 35 | if ( before_close > after_close ) dec_tranch(); 36 | 37 | //totalExecuted+=size; 38 | //livebuy-=size; 39 | TRACE<rif<pif; 52 | std::ostringstream os; 53 | os << this->pif; 54 | string redisPIF= os.str(); 55 | std::ostringstream oss; 56 | oss << this->rif; 57 | string redisRIF= oss.str(); 58 | //redisWriter->writeToRedis(account.getAccountName(),symbol,std::to_string(-1*total),std::to_string(average),redisRIF,redisPIF,std::to_string(livebuy),std::to_string(livesell),std::to_string(totalExecuted)); 59 | 60 | AbstractTradeAccount::onCloseFill(order_info, price, size); 61 | } 62 | 63 | void ShortTradeAccount::onOpenFill(std::shared_ptr& order_info, const double price, const uint32_t size) { 64 | std::lock_guard lock(mt); 65 | 66 | calculateSpread(price, size, true); 67 | 68 | total += size; 69 | last_open_price = price; 70 | //totalExecuted+=size; 71 | //livesell-=size; 72 | order_info->fill_size += size; 73 | 74 | 75 | if ( getPosition() >= other->getPosition()) { 76 | DEBUG< opposite position noting pif "<rif<pif; 94 | std::ostringstream os; 95 | os << this->pif; 96 | string redisPIF= os.str(); 97 | std::ostringstream oss; 98 | oss << this->rif; 99 | string redisRIF= oss.str(); 100 | //redisWriter->writeToRedis(account.getAccountName(),symbol,std::to_string(-1*total),std::to_string(average),redisRIF,redisPIF,std::to_string(livebuy),std::to_string(livesell),std::to_string(totalExecuted)); 101 | 102 | 103 | AbstractTradeAccount::onOpenFill(order_info, price, size); 104 | } 105 | -------------------------------------------------------------------------------- /src/trade/ShortTradeAccount.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ShortTradeAccount.h 3 | * 4 | * Created on: Aug 15, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef SRC_TRADE_SHORTTRADEACCOUNT_H_ 9 | #define SRC_TRADE_SHORTTRADEACCOUNT_H_ 10 | 11 | #include "AbstractTradeAccount.h" 12 | 13 | 14 | #define LOG_SHORT_TRADE_ACCOUNT "<"<" 15 | 16 | class ShortTradeAccount: public AbstractTradeAccount { 17 | public: 18 | ShortTradeAccount(const std::string &, OrderAccount &, uint32_t); 19 | virtual ~ShortTradeAccount(); 20 | 21 | void onCloseFill(std::shared_ptr&, const double, const uint32_t); 22 | void onOpenFill(std::shared_ptr&, const double, const uint32_t); 23 | }; 24 | 25 | #endif /* SRC_TRADE_SHORTTRADEACCOUNT_H_ */ 26 | -------------------------------------------------------------------------------- /src/trade/TradeCase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TradeCase.h 3 | * 4 | * Created on: Nov 10, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef SRC_TRADE_TRADECASE_H_ 9 | #define SRC_TRADE_TRADECASE_H_ 10 | 11 | 12 | 13 | 14 | #define LOG_TRADE_CASE "<"<name<<"|"<stage<<">: " 15 | 16 | struct OrderRep { 17 | uint32_t id; 18 | uint32_t size; 19 | double open; 20 | double close; 21 | bool is_exectued; 22 | }; 23 | 24 | 25 | using RequoteOrders = std::vector; 26 | 27 | class TradeInstance; 28 | 29 | enum TriggerState { 30 | TRIGGER_STATE_INIT = 0, 31 | TRIGGER_STATE_POSITIVE = 1, 32 | TRIGGER_STATE_NEGATIVE = 2, 33 | }; 34 | 35 | class TradeCase { 36 | public: 37 | 38 | enum State { 39 | INIT = 1, 40 | PRICE_CHANGE, 41 | OPEN_MMF, 42 | CHANGE_MMF, 43 | WAIT, 44 | FAILED, 45 | DONE, 46 | NOT_SELECTED, 47 | }; 48 | 49 | protected: 50 | TradeInstance &trade_instance; 51 | AbstractTradeAccount *current_acc; 52 | AbstractTradeAccount *opposite_acc; 53 | 54 | double send_price; 55 | double requote_price; 56 | uint32_t round_target; 57 | uint32_t main_order_id; 58 | 59 | 60 | const std::string name; 61 | std::string stage; 62 | State state; 63 | 64 | 65 | const int sign; 66 | 67 | std::function on_requote_order_done; 68 | 69 | std::function on_trade_send_close; 70 | 71 | bool requote_order_flag; 72 | 73 | 74 | RequoteOrders requote_orders; 75 | 76 | public: 77 | 78 | 79 | 80 | const enum Type { 81 | NONE = 0, 82 | CASE_1 = 1, 83 | CASE_2, 84 | CASE_3, 85 | CASE_4, 86 | CASE_5, 87 | CASE_CLOSEOPPOSITE, 88 | CASE_HEDGECURRENT, 89 | CASE_6C, 90 | CASE_7, 91 | CASE_9, 92 | CASE_10, 93 | CASE_MAXTLV, 94 | CASE_CLOSEOPPOSITEWITH_ANTICIPATED_PNL, 95 | CASE_HEDGEDMODE, 96 | CASE_ONEQUALITY, 97 | CASE_CLOSE_TRIGGER, 98 | PANIC_CLOSE, 99 | SOFT_CLOSE, 100 | } type; 101 | 102 | TradeCase(TradeInstance &, std::string, const Type); 103 | virtual State run(); 104 | const Type getType(); 105 | const State getState(); 106 | const std::string getName(); 107 | virtual ~TradeCase(); 108 | 109 | bool isDone(); 110 | 111 | protected: 112 | 113 | virtual void init() = 0; 114 | virtual void reprice() = 0; 115 | virtual void wait(); 116 | virtual void failed(); 117 | virtual void cancel() = 0; 118 | virtual void done() = 0; 119 | 120 | double openPrice(uint32_t, double = 0.0); //depending upon trigger 121 | double closePrice(uint32_t, double = 0.0); //depending upon trigger 122 | double sellPrice(uint32_t); //depend upon decision of selling 123 | double buyPrice(uint32_t); //depend upon decision of buying 124 | 125 | void sendRequoteOrders(); 126 | void updateRequoteOrders(); 127 | 128 | }; 129 | 130 | class TradeCaseFactory { 131 | 132 | public: 133 | static std::unique_ptr create(TradeInstance&, TradeCase::Type); 134 | }; 135 | 136 | class PanicClose: public TradeCase { 137 | AbstractTradeAccount& short_acc; 138 | AbstractTradeAccount& long_acc; 139 | uint32_t close_size; 140 | 141 | 142 | public: 143 | PanicClose(TradeInstance&); 144 | virtual void init(); 145 | virtual void reprice(); 146 | virtual void cancel(); 147 | virtual void wait(); 148 | virtual void done(); 149 | virtual ~PanicClose(); 150 | }; 151 | 152 | 153 | 154 | class SoftClose: public TradeCase { 155 | AbstractTradeAccount& short_acc; 156 | AbstractTradeAccount& long_acc; 157 | uint32_t close_size; 158 | 159 | 160 | public: 161 | SoftClose(TradeInstance&); 162 | virtual void init(); 163 | virtual void reprice(); 164 | virtual void cancel(); 165 | virtual void wait(); 166 | virtual void done(); 167 | virtual ~SoftClose(); 168 | }; 169 | 170 | class TradeCase1: public TradeCase { 171 | uint32_t close_size; 172 | double prev_send_price; 173 | 174 | bool checkFails(); 175 | public: 176 | TradeCase1(TradeInstance&); 177 | virtual void init(); 178 | virtual void reprice(); 179 | virtual void cancel(); 180 | virtual void done(); 181 | virtual ~TradeCase1(); 182 | }; 183 | 184 | 185 | class TradeCase3: public TradeCase { 186 | uint32_t close_size; 187 | double prev_send_price; 188 | 189 | bool checkFails(); 190 | public: 191 | TradeCase3(TradeInstance&); 192 | virtual void init(); 193 | virtual void reprice(); 194 | virtual void cancel(); 195 | virtual void done(); 196 | virtual ~TradeCase3(); 197 | }; 198 | 199 | class TradeCase4: public TradeCase { 200 | const uint32_t init_pos; 201 | double threshold; 202 | double threshold_limit; 203 | 204 | uint32_t first_order; 205 | uint32_t first_order_size; 206 | double first_order_price; 207 | 208 | public: 209 | TradeCase4(TradeInstance&); 210 | virtual void init(); 211 | virtual void reprice(); 212 | virtual void cancel(); 213 | virtual void done(); 214 | virtual void wait(); 215 | virtual ~TradeCase4(); 216 | }; 217 | 218 | class OnEquality: public TradeCase { 219 | const uint32_t init_pos; 220 | uint32_t target_pos; 221 | std::vector order_ids; 222 | 223 | public: 224 | OnEquality(TradeInstance&); 225 | virtual void init(); 226 | virtual void reprice(); 227 | virtual void cancel(); 228 | virtual void done(); 229 | virtual void wait(); 230 | virtual ~OnEquality(); 231 | }; 232 | 233 | class TradeCase5: public TradeCase { 234 | 235 | uint32_t curr_close_size; 236 | uint32_t oppo_close_size; 237 | 238 | double curr_send_price; 239 | double oppo_send_price; 240 | 241 | uint32_t curr_order, oppo_order; 242 | 243 | public: 244 | TradeCase5(TradeInstance&); 245 | virtual void init(); 246 | virtual void reprice(); 247 | virtual void cancel(); 248 | virtual void done(); 249 | virtual ~TradeCase5(); 250 | private: 251 | double currentPrice(); 252 | double oppositePrice(); 253 | }; 254 | 255 | 256 | class CloseOppositeWithPNL: public TradeCase { 257 | 258 | double close_price; 259 | const uint32_t init_size; 260 | uint32_t close_size; 261 | uint32_t close_id; 262 | public: 263 | CloseOppositeWithPNL(TradeInstance&); 264 | virtual void init(); 265 | virtual void reprice(); 266 | virtual void wait(); 267 | virtual void cancel(); 268 | virtual void failed(); 269 | virtual void done(); 270 | virtual ~CloseOppositeWithPNL(); 271 | 272 | }; 273 | 274 | class HedgeCurrent: public TradeCase { 275 | uint32_t ho_size; 276 | public: 277 | HedgeCurrent(TradeInstance&); 278 | virtual void init(); 279 | virtual void reprice(); 280 | virtual void wait(); 281 | virtual void cancel(); 282 | virtual void done(); 283 | virtual ~HedgeCurrent(); 284 | 285 | }; 286 | 287 | class TradeCase6C: public TradeCase { 288 | const uint32_t init_pos; 289 | const uint32_t tranch_at_init; 290 | 291 | public: 292 | TradeCase6C(TradeInstance&); 293 | virtual void init(); 294 | virtual void reprice(); 295 | virtual void cancel(); 296 | virtual void done(); 297 | virtual void wait(); 298 | virtual ~TradeCase6C(); 299 | }; 300 | 301 | class TradeCase7: public TradeCase { 302 | 303 | 304 | public: 305 | TradeCase7(TradeInstance&); 306 | virtual void init(); 307 | virtual void reprice(); 308 | virtual void cancel(); 309 | virtual void wait(); 310 | virtual void done(); 311 | virtual ~TradeCase7(); 312 | 313 | }; 314 | 315 | class TradeCase9: public TradeCase { 316 | 317 | uint32_t close_size; 318 | public: 319 | TradeCase9(TradeInstance&); 320 | virtual void init(); 321 | virtual void reprice(); 322 | virtual void cancel(); 323 | virtual void wait(); 324 | virtual void done(); 325 | virtual ~TradeCase9(); 326 | 327 | }; 328 | 329 | 330 | class MaxTLV: public TradeCase { 331 | double curr_price; 332 | double oppo_price; 333 | uint32_t curr_id; 334 | uint32_t oppo_id; 335 | const uint32_t curr_size_init; 336 | const uint32_t oppo_size_init; 337 | public: 338 | MaxTLV(TradeInstance&); 339 | virtual void init(); 340 | virtual void reprice(); 341 | virtual void cancel(); 342 | virtual void wait(); 343 | virtual void done(); 344 | virtual ~MaxTLV(); 345 | }; 346 | 347 | class CloseOppositeWithAnticipatedPNL: public TradeCase { 348 | uint32_t close_size; 349 | double close_price; 350 | uint32_t order_id; 351 | public: 352 | CloseOppositeWithAnticipatedPNL(TradeInstance&); 353 | virtual void init(); 354 | virtual void reprice(); 355 | virtual void cancel(); 356 | virtual void wait(); 357 | virtual void done(); 358 | virtual ~CloseOppositeWithAnticipatedPNL(); 359 | 360 | private: 361 | bool isOppositeCloseProfitable(const double); 362 | }; 363 | 364 | class HedgedMode: public TradeCase { 365 | 366 | uint32_t ho_size; 367 | double price; 368 | AbstractTradeAccount& short_acc; 369 | AbstractTradeAccount& long_acc; 370 | uint32_t order_id; 371 | AbstractTradeAccount *selected_account; 372 | AbstractTradeAccount *other_account; 373 | public: 374 | HedgedMode(TradeInstance&); 375 | virtual void init(); 376 | virtual void reprice(); 377 | virtual void cancel(); 378 | virtual void wait(); 379 | virtual void done(); 380 | virtual ~HedgedMode(); 381 | }; 382 | 383 | class CloseTrigger: public TradeCase { 384 | 385 | 386 | 387 | uint32_t close_size; 388 | double error; 389 | std::vector orders; 390 | 391 | public: 392 | CloseTrigger(TradeInstance&); 393 | virtual void init(); 394 | virtual void reprice(); 395 | virtual void cancel(); 396 | virtual void wait(); 397 | virtual void done(); 398 | virtual ~CloseTrigger(); 399 | }; 400 | 401 | 402 | class TradeCase10: public TradeCase { 403 | TriggerState trigger_state; 404 | uint32_t close_size; 405 | uint32_t original_size; 406 | double error; 407 | std::vector orders; 408 | AbstractTradeAccount *account_to_close; 409 | 410 | public: 411 | TradeCase10(TradeInstance&); 412 | 413 | virtual void init(); 414 | virtual void reprice(); 415 | virtual void cancel(); 416 | virtual void wait(); 417 | virtual void done(); 418 | ~TradeCase10(); 419 | }; 420 | 421 | #endif /* SRC_TRADE_TRADECASE_H_ */ 422 | -------------------------------------------------------------------------------- /src/trade/TradeInstance.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TradeAccountManager.h 3 | * 4 | * Created on: Jul 3, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef TRADE_INSTANCE_H_ 9 | #define TRADE_INSTANCE_H_ 10 | 11 | #include 12 | #include 13 | 14 | //#include "../config/TradingConfig.h" 15 | #include "../akela/OrderAccount.h" 16 | #include "../avicenna/AvicennaInterface.h" 17 | #include "../utils/log.h" 18 | #include "../utils/utils.h" 19 | #include "../utils/ThreadPool.h" 20 | #include "../redis/RedisWriter.h" 21 | #include "ShortTradeAccount.h" 22 | #include "LongTradeAccount.h" 23 | #include "TradeCase.h" 24 | 25 | #define LOG_PREVIOUS_BAR bar0.open<<","<trade_account.id<<","<symbol.name<<","<<(( trade_case )?trade_case->getName():"")<<","<trigger_state]<<","<<(current_acc?current_acc->getPositionString():"")<<","<<(opposite_acc?opposite_acc->getPositionString():"")<<","<: " 27 | #define TRADE_INSTANCE_OPEN_RETRY 3 28 | 29 | 30 | 31 | 32 | 33 | 34 | enum TradeInstanceState { 35 | TRADE_INSTANCE_NONE = 0, 36 | TRADE_INSTANCE_INIT, 37 | TRADE_INSTANCE_CHECK_CANCEL, 38 | TRADE_INSTANCE_SELECT_CASES, 39 | TRADE_INSTANCE_LIMIT_EXCEED, 40 | TRADE_INSTANCE_MAIN_COND_TRUE, 41 | TRADE_INSTANCE_MAIN_COND_FALSE, 42 | TRADE_INSTANCE_CASE_1_INIT, 43 | TRADE_INSTANCE_CASE_1, 44 | TRADE_INSTANCE_CASE_2_INIT, 45 | TRADE_INSTANCE_CASE_2, 46 | TRADE_INSTANCE_CASE_3_INIT, 47 | TRADE_INSTANCE_CASE_3, 48 | TRADE_INSTANCE_CASE_4_INIT, 49 | TRADE_INSTANCE_CASE_4, 50 | TRADE_INSTANCE_CASE_5_INIT, 51 | TRADE_INSTANCE_CASE_5, 52 | TRADE_INSTANCE_CASE_6_INIT, 53 | TRADE_INSTANCE_CASE_6, 54 | TRADE_INSTANCE_CASE_7_INIT, 55 | TRADE_INSTANCE_CASE_7, 56 | TRADE_INSTANCE_SOFT_CLOSE_INIT, 57 | TRADE_INSTANCE_SOFT_CLOSE, 58 | TRADE_INSTANCE_PANIC_CLOSE_INIT, 59 | TRADE_INSTANCE_PANIC_CLOSE, 60 | 61 | }; 62 | 63 | 64 | enum PanicCloseState { 65 | PANIC_CLOSE_INIT = 0, 66 | PANIC_CLOSE_WAIT_CANCEL, 67 | PANIC_CLOSE_EXECUTE_CLOSE, 68 | PANIC_CLOSE_CHECK_CLOSE, 69 | PANIC_CLOSE_NONE, 70 | }; 71 | 72 | enum PositionCloseState { 73 | POSITION_CLOSE_INIT, 74 | POSITION_CLOSE_CHECK, 75 | POSITION_CLOSE_WAIT_CANCEL, 76 | 77 | }; 78 | 79 | 80 | 81 | 82 | class TradeInstance { 83 | 84 | friend class TradeCase; 85 | friend class PanicClose; 86 | friend class SoftClose; 87 | friend class TradeCase1; 88 | friend class TradeCase3; 89 | friend class TradeCase4; 90 | friend class TradeCase5; 91 | friend class CloseOppositeWithPNL; 92 | friend class HedgeCurrent; 93 | friend class TradeCase6C; 94 | friend class TradeCase7; 95 | friend class TradeCase9; 96 | friend class TradeCase10; 97 | 98 | friend class MaxTLV; 99 | friend class CloseOppositeWithAnticipatedPNL; 100 | friend class HedgedMode; 101 | friend class OnEquality; 102 | friend class CloseTrigger; 103 | 104 | std::unique_ptr trade_case; 105 | TradeCase::Type previous_case; 106 | TradeCase::State last_state; 107 | 108 | double wait_for_next_time_window_avicenna; 109 | bool wait_for_next_time_window; 110 | 111 | static ThreadPool trade_instances; 112 | 113 | const TradeAccount &trade_account; 114 | Symbol &symbol; 115 | 116 | RoundVector& share_rounds; //set of all rounds 117 | uint32_t tranch_value; 118 | 119 | 120 | const size_t max_round; //maximum value of round 121 | const size_t min_round; //minimum value of round 122 | size_t max_pos, min_pos; 123 | RoundVector::const_iterator current_round; 124 | RoundVector::const_iterator previous_round; 125 | 126 | 127 | const double mpv_value; 128 | const double mpv_limit; 129 | const uint32_t mpv_multiplier; 130 | 131 | const bool mmf; 132 | const int base_qty; 133 | const bool cancel_on_trigger; 134 | 135 | const double multiplier; 136 | const uint32_t divisor; 137 | 138 | TriggerState trigger_state; 139 | TriggerState avicenna_trigger_state; 140 | TriggerState prev_trigger_state; 141 | static const char trigger_rep[]; 142 | static const std::string state_rep[]; 143 | 144 | 145 | double min_price; 146 | double open_price; 147 | double max_price; 148 | double close_price; 149 | 150 | 151 | uint32_t ask_size; 152 | double ask_price; 153 | uint32_t bid_size; 154 | double bid_price; 155 | double price_estimate; //avicenna price 156 | double price_estimate_prev; 157 | bool avicenna_toggle; 158 | double instrument_skew; 159 | 160 | double trade_price; //ask_price in case of +ive trigger and bid_price in case of -ive trigger for market order 161 | double price_estimate_on_trigger; //price estimate on trigger 162 | double reference_price; //price of bid or ask in when trigger changes 163 | 164 | 165 | 166 | TradeInstanceState state; 167 | PositionCloseState position_close_state; 168 | 169 | RedisWriter redisWriter; 170 | ShortTradeAccount short_acc; 171 | LongTradeAccount long_acc; 172 | 173 | AbstractTradeAccount *current_acc; 174 | AbstractTradeAccount *opposite_acc; 175 | 176 | bool data_wait; 177 | 178 | bool is_enable; 179 | 180 | bool is_panic_close; 181 | bool panic_close_init; 182 | bool is_soft_close; 183 | bool soft_close_init; 184 | 185 | std::chrono::time_point start, end; 186 | 187 | struct Bar { 188 | double open; 189 | double close; 190 | double minimum; 191 | double maximum; 192 | } bar0, bar1; 193 | 194 | public: 195 | 196 | // static Linkx::Client *client; 197 | 198 | TradeInstance(const TradeAccount &account, Symbol &symbol); 199 | double sendPrice(uint32_t qto); 200 | private: 201 | 202 | void readSymbolData(); 203 | void triggerSelection(); 204 | void caseSelection(); 205 | bool specialCases(); 206 | void selfDestruct(); 207 | void triggerProcessing(); 208 | std::string stateString(); 209 | 210 | // void testSelfDestruct(); 211 | 212 | void reprice(); 213 | 214 | /* 215 | * @brief Get next round of shares to be sell/purchase 216 | * 217 | * @param current position for long account 218 | * 219 | * @param current position for short account 220 | * 221 | * @param position to open is +ive or -ive 222 | * 223 | * @return size of next round to be purchase/sell 224 | */ 225 | uint32_t quantityToOpen(); 226 | size_t roundInForce(); 227 | uint32_t roundForCurrentAccount(); 228 | 229 | public: 230 | 231 | void stopAction(); 232 | void startAction(); 233 | void enablePanicClose(); 234 | void disablePanicClose(); 235 | void enableSoftClose(); 236 | void disableSoftClose(); 237 | 238 | void firstReprice(); 239 | void resume(); 240 | void pause(); 241 | void avicennaToggle(); 242 | 243 | }; 244 | 245 | 246 | inline void TradeInstance::firstReprice() { 247 | auto spread = fabs(current_acc->getAverage() - opposite_acc->getAverage()); 248 | current_acc->setAverage( price_estimate ); 249 | if ( dynamic_cast ( current_acc ) ) { 250 | opposite_acc->setAverage(current_acc->getAverage() - spread ); 251 | } else if ( dynamic_cast ( current_acc ) ) { 252 | opposite_acc->setAverage(current_acc->getAverage() + spread ); 253 | } 254 | } 255 | 256 | inline void TradeInstance::resume() { 257 | is_enable = true; 258 | } 259 | 260 | inline double TradeInstance::sendPrice(uint32_t qto){ 261 | double ret = 0.0; 262 | int64_t os; 263 | if ( trigger_state == TRIGGER_STATE_POSITIVE ) { 264 | os = ask_size - qto*multiplier; 265 | if ( os <= 0 ) ret = ask_price; 266 | else ret = bid_price; 267 | // else if ( instrument_skew > 0 ) ret = bid_price; 268 | // else if ( instrument_skew < 0 && os > 0 ) ret = 0.0; 269 | } else if ( trigger_state == TRIGGER_STATE_NEGATIVE ) { 270 | os = bid_size - qto*multiplier; 271 | if ( os <= 0 ) ret = bid_price; 272 | else ret = ask_price; 273 | // else if ( instrument_skew < 0 ) ret = ask_price; 274 | // else if ( instrument_skew > 0 && os > 0 ) ret = 0.0; 275 | } 276 | 277 | // DEBUG<>; 331 | 332 | #endif /* TRADE_INSTANCE_H_ */ 333 | -------------------------------------------------------------------------------- /src/utils/AsynchronousQueue.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AsynchronousQueue.cpp 3 | * 4 | * Created on: May 10, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #include "AsynchronousQueue.h" 9 | 10 | template 11 | AsynchronousQueue::AsynchronousQueue() { 12 | 13 | 14 | } 15 | 16 | template 17 | AsynchronousQueue::~AsynchronousQueue() { 18 | // TODO Auto-generated destructor stub 19 | } 20 | 21 | template 22 | T& AsynchronousQueue::pop_front(){ 23 | q_mutex.lock(); 24 | T& temp = this->front(); 25 | pop_front(); 26 | q_mutex.unlock(); 27 | return temp; 28 | } 29 | -------------------------------------------------------------------------------- /src/utils/AsynchronousQueue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AsynchronousQueue.h 3 | * 4 | * Created on: May 10, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef ASYNCHRONOUSQUEUE_H_ 9 | #define ASYNCHRONOUSQUEUE_H_ 10 | 11 | #include 12 | #include 13 | 14 | template 15 | class AsynchronousQueue:public std::deque { 16 | std::mutex q_mutex; 17 | public: 18 | AsynchronousQueue(); 19 | virtual ~AsynchronousQueue(); 20 | 21 | void push_back(T &data) { 22 | q_mutex.lock(); 23 | push_back(data); 24 | q_mutex.unlock(); 25 | } 26 | 27 | T& pop_front(); 28 | }; 29 | 30 | #endif /* ASYNCHRONOUSQUEUE_H_ */ 31 | -------------------------------------------------------------------------------- /src/utils/AsynchronousUnorderedMap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AsynchronousUnorderedMap.h 3 | * 4 | * Created on: Jul 29, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef SRC_UTILS_ASYNCHRONOUSUNORDEREDMAP_H_ 9 | #define SRC_UTILS_ASYNCHRONOUSUNORDEREDMAP_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | 17 | template 18 | class AsynchronousUnorderedMap: public std::unordered_map { 19 | std::mutex rw_mutex; 20 | public: 21 | AsynchronousUnorderedMap() { 22 | 23 | } 24 | 25 | ~AsynchronousUnorderedMap() { 26 | 27 | } 28 | 29 | using unordered_map = std::unordered_map; 30 | using iterator = typename unordered_map::iterator; 31 | using value_type = typename unordered_map::value_type; 32 | using key_type = typename unordered_map::key_type; 33 | using size_type = typename unordered_map::size_type; 34 | using const_iterator = typename unordered_map::const_iterator; 35 | using mapped_type = typename unordered_map::mapped_type; 36 | 37 | 38 | 39 | template < typename... _Args > 40 | std::pair 41 | emplace(_Args&&... __args) { 42 | std::lock_guard lock(rw_mutex); 43 | return unordered_map::emplace(std::forward<_Args>(__args)...); 44 | } 45 | 46 | std::pair 47 | insert(const value_type& __x) { 48 | std::lock_guard lock(rw_mutex); 49 | return insert(__x); 50 | } 51 | 52 | template::value>::type> 53 | std::pair 54 | insert(_Pair&& __x) { 55 | std::lock_guard lock(rw_mutex); 56 | return unordered_map::insert(std::forward<_Pair>(__x)); 57 | } 58 | 59 | iterator erase(const_iterator __position) { 60 | std::lock_guard lock(rw_mutex); 61 | return unordered_map::erase(__position); 62 | } 63 | 64 | 65 | iterator erase(iterator __it) { 66 | std::lock_guard lock(rw_mutex); 67 | return unordered_map::erase(__it); 68 | } 69 | 70 | size_type erase(const key_type& __x) { 71 | std::lock_guard lock(rw_mutex); 72 | return unordered_map::erase(__x); 73 | } 74 | 75 | iterator erase(const_iterator __first, const_iterator __last) { 76 | std::lock_guard lock(rw_mutex); 77 | return unordered_map::erase(__first, __last); 78 | } 79 | 80 | 81 | void clear() noexcept { 82 | std::lock_guard lock(rw_mutex); 83 | unordered_map::clear(); 84 | } 85 | 86 | 87 | iterator find(const key_type& __x) { 88 | std::lock_guard lock(rw_mutex); 89 | return unordered_map::find(__x); 90 | } 91 | 92 | const_iterator find(const key_type& __x) const { 93 | std::lock_guard lock(rw_mutex); 94 | return unordered_map::find(__x); 95 | } 96 | 97 | 98 | size_type count(const key_type& __x) const { 99 | std::lock_guard lock(rw_mutex); 100 | return unordered_map::count(__x); 101 | } 102 | 103 | 104 | mapped_type& operator[](const key_type& __k) { 105 | std::lock_guard lock(rw_mutex); 106 | return unordered_map::operator[](__k); 107 | } 108 | 109 | mapped_type& operator[](key_type&& __k) { 110 | std::lock_guard lock(rw_mutex); 111 | return unordered_map::operator[](std::move(__k)); 112 | } 113 | 114 | void lock() { 115 | rw_mutex.lock(); 116 | } 117 | 118 | void unlock() { 119 | rw_mutex.unlock(); 120 | } 121 | 122 | }; 123 | 124 | #endif /* SRC_UTILS_ASYNCHRONOUSUNORDEREDMAP_H_ */ 125 | -------------------------------------------------------------------------------- /src/utils/AsynchronousVector.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AsynchronousVector.h 3 | * 4 | * Created on: Aug 29, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef SRC_UTILS_ASYNCHRONOUSVECTOR_H_ 9 | #define SRC_UTILS_ASYNCHRONOUSVECTOR_H_ 10 | 11 | #include 12 | #include 13 | 14 | template 15 | class AsynchronousVector: public std::vector { 16 | std::mutex rw_mutex; 17 | 18 | public: 19 | 20 | using vector = std::vector; 21 | using iterator = typename vector::iterator; 22 | using value_type = typename vector::value_type; 23 | using size_type = typename vector::size_type; 24 | using const_iterator = typename vector::const_iterator; 25 | using reference = typename vector::reference; 26 | using const_reference = typename vector::const_reference; 27 | 28 | 29 | void push_back(value_type &x) { 30 | std::lock_guard lock(rw_mutex); 31 | vector::push_back(x); 32 | } 33 | 34 | }; 35 | 36 | 37 | 38 | #endif /* SRC_UTILS_ASYNCHRONOUSVECTOR_H_ */ 39 | -------------------------------------------------------------------------------- /src/utils/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | set(UTILS_SOURCES 4 | ${CMAKE_CURRENT_SOURCE_DIR}/AsynchronousQueue.cpp 5 | ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp 6 | PARENT_SCOPE 7 | ) 8 | set(UTILS_HEADERS 9 | ${CMAKE_CURRENT_SOURCE_DIR}/log.h 10 | ${CMAKE_CURRENT_SOURCE_DIR}/AsynchronousQueue.h 11 | ${CMAKE_CURRENT_SOURCE_DIR}/AsynchronousUnorderedMap.h 12 | ${CMAKE_CURRENT_SOURCE_DIR}/AsynchronousVector.h 13 | ${CMAKE_CURRENT_SOURCE_DIR}/ThreadPool.h 14 | PARENT_SCOPE 15 | ) 16 | -------------------------------------------------------------------------------- /src/utils/ThreadPool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ThreadPool.h 3 | * 4 | * Created on: May 10, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef THREADPOOL_H_ 9 | #define THREADPOOL_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | template 22 | class ThreadPool { 23 | //mantaining queue of pending tasks 24 | std::queue tasks_queue; 25 | std::mutex tasks_queue_mutex; 26 | std::condition_variable queue_size_cond; 27 | 28 | 29 | std::mutex pool_mutex; 30 | size_t pool_size; 31 | 32 | std::vector threads; 33 | bool running; 34 | 35 | std::function thread_func; 36 | std::atomic_uint running_tasks; 37 | 38 | bool stop; 39 | 40 | void run() { 41 | // std::cout< lock(tasks_queue_mutex); 53 | queue_size_cond.wait(lock, 54 | [this]() { 55 | return this->tasks_queue.size() > 0 || stop ; 56 | } 57 | ); 58 | 59 | if ( stop ) break; 60 | 61 | running_tasks++; 62 | T task = tasks_queue.front(); 63 | tasks_queue.pop(); 64 | lock.unlock(); 65 | 66 | //run the thread pool function 67 | // std::cout<<"thread id "< func, size_t size): 80 | thread_func(func), 81 | pool_size(size), 82 | threads(size), 83 | stop(false) { 84 | this->run(); 85 | } 86 | 87 | ~ThreadPool() { 88 | stop_execution(); 89 | } 90 | 91 | //push data in the pending tasks queue 92 | void push_task(T data) { 93 | 94 | { 95 | // std::cout<<"pushing data:lock"< lock(tasks_queue_mutex); 97 | tasks_queue.push(data); 98 | // std::cout<<"pushing data:unlock"< lock(tasks_queue_mutex); 114 | ret = tasks_queue.size(); 115 | 116 | } 117 | return ret; 118 | } 119 | 120 | //running tasks 121 | size_t tasks_running() { 122 | return running_tasks.load(); 123 | } 124 | 125 | //pool size 126 | size_t size() { 127 | return pool_size; 128 | } 129 | 130 | //stop task execution 131 | void stop_execution() { 132 | stop = true; 133 | queue_size_cond.notify_all(); 134 | 135 | //join all the threads 136 | for (auto& t: threads) { 137 | t.join(); 138 | } 139 | } 140 | 141 | }; 142 | 143 | #endif /* THREADPOOL_H_ */ 144 | -------------------------------------------------------------------------------- /src/utils/console.h: -------------------------------------------------------------------------------- 1 | /* 2 | * console.h 3 | * 4 | * Created on: Mar 2, 2017 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef SRC_UTILS_CONSOLE_H_ 9 | #define SRC_UTILS_CONSOLE_H_ 10 | 11 | 12 | #define TRACE std::cout<("TimeStamp", "%Y-%m-%d %H:%M:%S")<<" <"<: "< core = boost::log::core::get(); 41 | 42 | 43 | typedef boost::log::sinks::synchronous_sink sink_t; 44 | boost::shared_ptr filestream 45 | = boost::make_shared( 46 | ); 47 | 48 | 49 | filestream->auto_flush(true); 50 | filestream->add_stream( 51 | boost::shared_ptr< std::ostream >(new std::ofstream(SYS_LOGFILE))); 52 | //must create seperate sinks and stream for each sink. 53 | boost::shared_ptr f_sink(new sink_t(filestream)); 54 | 55 | boost::log::add_common_attributes(); 56 | boost::log::register_formatter_factory("TimeStamp", boost::make_shared()); 57 | 58 | f_sink->set_filter(severity >= getSeverity(AdminConfig::settings->getLogSeverity())); 59 | f_sink->set_formatter( 60 | boost::log::expressions::format("[%1%][%2%] %3%") 61 | % boost::log::expressions::attr("TimeStamp") 62 | % boost::log::trivial::severity 63 | % boost::log::expressions::smessage ); 64 | 65 | core->add_sink(f_sink); 66 | 67 | 68 | //logging to console or verbosity options 69 | boost::shared_ptr consolestream 70 | = boost::make_shared (); 71 | consolestream->add_stream(boost::shared_ptr(&std::cout, boost::log::empty_deleter())); 72 | boost::shared_ptr c_sink(new sink_t(consolestream)); 73 | 74 | c_sink->set_filter(severity >= getSeverity(AdminConfig::settings->getVerboseSeverity()) ); 75 | c_sink->set_formatter(fmt); 76 | core->add_sink(c_sink); 77 | 78 | 79 | boost::shared_ptr mf_backend = 80 | boost::make_shared(); 81 | 82 | //setup the file naming pattern 83 | mf_backend->set_file_name_composer( 84 | boost::log::sinks::file::as_file_name_composer(expr::stream<<"../logs/"<("TradeInfo")<<".log") 85 | ); 86 | 87 | // Wrap it into the frontend and register in the core. 88 | // The backend requires synchronization in the frontend. 89 | typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_multifile_backend > sync_mf_sink; 90 | boost::shared_ptr< sync_mf_sink > mf_sink(new sync_mf_sink(mf_backend)); 91 | 92 | // Set the formatter 93 | mf_sink->set_formatter 94 | ( 95 | expr::stream 96 | << "[" << expr::attr< std::string >("TradeInfo") 97 | << "] " << expr::smessage 98 | ); 99 | 100 | core->add_sink(mf_sink); 101 | 102 | return lg; 103 | } 104 | -------------------------------------------------------------------------------- /src/utils/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * log.h 3 | * 4 | * Created on: Apr 23, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef LOG_H_ 9 | #define LOG_H_ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | 28 | #define TRACE BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::trace) 29 | #define DEBUG BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::debug) 30 | #define INFO BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::info) 31 | #define WARN BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::warning) 32 | #define ERROR BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::error) 33 | #define FATAL BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::fatal) 34 | 35 | BOOST_LOG_ATTRIBUTE_KEYWORD(TradeInfo, "TradeInfo", std::string) 36 | 37 | #define SYS_LOGFILE "stem.log" 38 | 39 | //Narrow-char thread-safe logger. 40 | typedef boost::log::sources::severity_logger_mt logger_t; 41 | 42 | //declares a global logger with a custom initialization 43 | BOOST_LOG_GLOBAL_LOGGER(my_logger, logger_t) 44 | 45 | class TimeStampFormatterFactory : 46 | public boost::log::basic_formatter_factory 47 | { 48 | public: 49 | formatter_type create_formatter(const boost::log::attribute_name& name, const args_map& args) { 50 | args_map::const_iterator it = args.find("format"); 51 | if (it != args.end()) { 52 | return boost::log::expressions::stream 53 | << boost::log::expressions::format_date_time( 54 | boost::log::expressions::attr(name), it->second); 55 | } else { 56 | return boost::log::expressions::stream 57 | << boost::log::expressions::attr(name); 58 | } 59 | } 60 | }; 61 | 62 | #endif /* LOG_H_ */ 63 | -------------------------------------------------------------------------------- /src/utils/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * utils.h 3 | * 4 | * Created on: Nov 28, 2016 5 | * Author: jamil 6 | */ 7 | 8 | #ifndef SRC_UTILS_UTILS_H_ 9 | #define SRC_UTILS_UTILS_H_ 10 | 11 | #include 12 | 13 | 14 | /* 15 | * @brief since c++11 doesn't have make_unique utility like make_shared 16 | * for exception safety I have implemented it on my own 17 | * 18 | * @param all the paramters which is require to pass to the constructor of Type T 19 | * 20 | * @return std::unique_ptr of type T 21 | */ 22 | template 23 | std::unique_ptr make_unique( Args&& ...args ) 24 | { 25 | return std::unique_ptr( new T( std::forward(args)... ) ); 26 | } 27 | 28 | /* 29 | * @brief truncate for decimal number up to given decimal places 30 | * 31 | * @param number to apply truncate to 32 | * 33 | * @param digits to which truncation is applied to 34 | * 35 | * @return truncated number 36 | */ 37 | inline double truncate(double number, uint32_t digits) { 38 | return int32_t(number*pow(10, digits))/pow(10, digits); 39 | } 40 | 41 | /* 42 | * @brief ceiling for decimal number up to given decimal places 43 | * 44 | * @param number to apply ceil to 45 | * 46 | * @param digits to which ceiling is applied to 47 | * 48 | * @return ceiled number 49 | */ 50 | inline double dceil(double number, uint32_t digits) { 51 | auto factor = pow(10.0, digits); 52 | auto d = number*factor; 53 | auto n = uint32_t(d); 54 | auto mod = d - n; 55 | if ( mod > 0 ) n++; 56 | return n/factor; 57 | } 58 | 59 | /* 60 | * @brief flooring for decimal number up to given decimal places. this is same as truncate 61 | * 62 | * @param number to apply floor to 63 | * 64 | * @param digits to which flooring is applied to 65 | * 66 | * @return floored number 67 | */ 68 | inline double dfloor(double number, uint32_t digits) { 69 | auto factor = pow(10.0, digits); 70 | auto d = number*factor; 71 | auto n = uint32_t(d); 72 | // auto mod = d - n; 73 | // if ( mod > 0 ) n++; 74 | return n/factor; 75 | } 76 | #endif /* SRC_UTILS_UTILS_H_ */ 77 | --------------------------------------------------------------------------------