///////////////////////////////////////////////////////////////////////// // Zero Intelligence Traders // Author: Dale K. Brearcliffe // Email: dbrearcl@masonlive.gmu.edu // Date: 15 November 2015 // Version: 1.0 // Inspired by: Dr. Robert Axtell's C pThread version // Based on: Gode and Sunder, QJE, 1993 // Usage: ebasic -c n:m zit-1 // where n:m is the range of cores // // Copyright 2015 Dale K. Brearcliffe // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. ///////////////////////////////////////////////////////////////////////// REM Initialize Variables let reportingCore = 0 // The core ID that will provide IO let maxNumOfTrades = 10000000 // The number of trades to attempt let maxBuyerValue = 30 // The upper limit for a random buyer value let maxSellerValue = 30 // The upper limit for a random seller value let numOfBuyers = 100000 // The number of buyers in the market let numOfSellers = numOfBuyers // Always the same as the buyers REM Divide up the agents and trades based on the number of cores //NUMCORES - An internal value indicating the number of cores in use let agentsPerCore = numOfBuyers / NUMCORES let tradesPerCore = maxNumOftrades / NUMCORES REM Display Title // Limited to the single core responsible for IO if COREID = reportingCore then print "ZERO INTELLIGENCE TRADERS (Cores Used: " + NUMCORES + ")" end if REM Initialize Agents // The array must hold all buyer and sellers plus three pieces of data for each // The 'sdim' command ensures the array is stored in shared memory, not in core memory sdim agents[agentsPerCore * 3 * 2] REM Populate agents with initial data // Each agent has three data elements // 0: 1 or 0 indicating they possess/do not possess an item // 1: A random value for which they will buy/sell an item // 2: A transaction price for any successfull trades // Buyer element 0 is set to 0 // Seller element 0 is set to 1 // Buyers are in the first half of the array, sellers in the second let i = 0 do while i < agentsPerCore * 3 agents[i + 0] = 0 agents[i + 1] = (random % maxBuyerValue) + 1 agents[i + 2] = 0 agents[i + (agentsPerCore * 3) + 0] = 1 agents[i + (agentsPerCore * 3) + 1] = (random % maxSellerValue) + 1 agents[i + (agentsPerCore * 3) + 2] = 0 i = i + 3 end do REM Do Trades let i = 0 do while i < tradesPerCore // A random buyer with a random bid price (limited by the agent's maximum bid value) let buyerIndex = (random % agentsPerCore) * 3 let bidPrice = (random % agents[buyerIndex + 1]) + 1 // A random seller with a random ask price (limited by the agent's maximum ask value) let sellerIndex = ((random % agentsPerCore) + agentsPerCore) * 3 let askPrice = agents[sellerIndex + 1] + random % (maxSellerValue - agents[sellerIndex + 1] + 1) // If the buyer has not bought and the seller has not sold then do the trade if agents[buyerIndex] = 0 and agents[sellerIndex] = 1 and bidPrice >= askPrice then // Create a random transaction price between the bid and ask prices let transactionPrice = askPrice + (random % (bidPrice - askPrice + 1)) // Record the transaction price agents[buyerIndex + 2] = transactionPrice agents[sellerIndex + 2] = transactionPrice // Indicate the buyer and seller have participated in a trade thus ensuring they will make no more agents[buyerIndex] = 1 agents[sellerIndex] = 0 end if i = i + 1 end do REM Compute Statistics // Each core computes the statistics for activity on their core let numberBought = 0 let numberSold = 0 let sum1 = 0.0 let sum2 = 0 let n = 0 let avgPrice = 0.0 let sd = 0.0 let i = 0 do while i < agentsPerCore * 3 if agents[i] = 1 then numberBought = numberBought + 1 sum1 = sum1 + agents[i + 2] sum2 = sum2 + (agents[i + 2] ** 2) n = n + 1 end if if agents[i + agentsPerCore * 3] = 0 then numberSold = numberSold + 1 sum1 = sum1 + agents[i + agentsPerCore * 3 + 2] sum2 = sum2 + (agents[i + agentsPerCore * 3 + 2] ** 2) n = n + 1 end if i = i + 3 end do REM Wait for all cores to reach here // This blocks until all cores reach this point and are ready to report results sync REM Calculate across all cores // Reduce directs all cores gather data from all cores and sum them reduce sum numberBought into allNumberBought reduce sum numberSold into allNumberSold reduce sum sum1 into allSum1 reduce sum sum2 into allSum2 reduce sum n into allN // Average price and standard deviation are calculated on each core for all cores allAvgPrice = allSum1 / allN allSD = sqrt((allSum2 - allN * (allAvgPrice ** 2)) / (allN - 1)) REM Display results for all cores // Only the core responsible for IO provides the report if COREID = reportingCore then print allNumberBought + " items bought and " + allNumberSold + " items sold." print "The average price = " + allAvgPrice + " and the s.d. is " + allSD + "." end if