SHOW:
|
|
- or go back to the newest paste.
| 1 | /* | |
| 2 | Code (c) alex rodriguez-mcinteer 2016 | |
| 3 | This code is free to use, modify, and distribute, and is provided as is without warrenty | |
| 4 | youtube video mentioning this is available on the channel: https://www.youtube.com/channel/UCKd5FMMuMkQgtatSc5sSZPw | |
| 5 | if you enjoy my software, please subscribe to my youtube for more c; | |
| 6 | ||
| 7 | FYI, you need to install the controlP5 library on processing for this to work | |
| 8 | ||
| 9 | Please inform me of modifications you make, and I will gladly share them on youtube C: | |
| 10 | */ | |
| 11 | ||
| 12 | import java.util.*; | |
| 13 | import controlP5.*; | |
| 14 | ControlP5 cp5; | |
| 15 | ||
| 16 | final int Range = 200; | |
| 17 | float Liquidity = 1; | |
| 18 | Exchange CommodityExchange; | |
| 19 | Trader Producers[]; | |
| 20 | Trader Consumers[]; | |
| 21 | ||
| 22 | void setup() | |
| 23 | {
| |
| 24 | size( displayWidth, 700 ); | |
| 25 | frameRate( -1 ); | |
| 26 | cp5 = new ControlP5( this ); | |
| 27 | ||
| 28 | CommodityExchange = new Exchange( 4000 ); | |
| 29 | ||
| 30 | Producers = new Trader[2000]; | |
| 31 | Consumers = new Trader[2000]; | |
| 32 | ||
| 33 | for( int i = 0; i < 2000; i++ ) | |
| 34 | {
| |
| 35 | Producers[ i ] = new Trader( i, 10000, 200, true, false, 100, 1 ); | |
| 36 | Consumers[ i ] = new Trader( i+2000, 10000, 200, false, true, 125, 1 ); | |
| 37 | Producers[ i ].Trade( i ); | |
| 38 | Consumers[ i ].Trade( i+2000 ); | |
| 39 | } | |
| 40 | } | |
| 41 | ||
| 42 | void draw() | |
| 43 | {
| |
| 44 | background( 0 ); | |
| 45 | ||
| 46 | CommodityExchange.Draw(); | |
| 47 | CommodityExchange.RunLogic(); | |
| 48 | CommodityExchange.FillTradesLogic(); | |
| 49 | ||
| 50 | for( int i = 0; i < ( CommodityExchange.Traders/2 ); i++ ) | |
| 51 | {
| |
| 52 | Producers[ i ].Trade( i ); | |
| 53 | Consumers[ i ].Trade( i+2000 ); | |
| 54 | } | |
| 55 | } | |
| 56 | ||
| 57 | class Trader | |
| 58 | {
| |
| 59 | boolean Producer; | |
| 60 | boolean Consumer; | |
| 61 | boolean Trading; | |
| 62 | ||
| 63 | int EntryPoint; | |
| 64 | int PurchaseVolume; | |
| 65 | int Time; | |
| 66 | int Id; | |
| 67 | ||
| 68 | public Trader( int Id_, int m, int i, boolean p, boolean c, int pv, int t ) | |
| 69 | {
| |
| 70 | Id = Id_; | |
| 71 | Producer = p; | |
| 72 | Consumer = c; | |
| 73 | PurchaseVolume = pv; | |
| 74 | Time = t; | |
| 75 | Trading = false; | |
| 76 | EntryPoint = 0; | |
| 77 | } | |
| 78 | ||
| 79 | public void Trade( int ID ) | |
| 80 | {
| |
| 81 | if( second() % Time == 0 && Trading == false && random( 0, 1 ) >= .999 ) | |
| 82 | {
| |
| 83 | Trading = true; | |
| 84 | ||
| 85 | int BS = ( ( Integer ) ( ( ArrayList ) CommodityExchange.Bid.get( CommodityExchange.BidPrice ) ).get( ID ) ); | |
| 86 | int AS = ( ( Integer ) ( ( ArrayList ) CommodityExchange.Ask.get( CommodityExchange.AskPrice ) ).get( ID ) ); | |
| 87 | ||
| 88 | if( !Producer ) | |
| 89 | {
| |
| 90 | ||
| 91 | boolean t = ( random( 0, 1 ) < Liquidity ); | |
| 92 | int level = ( int ) random( 0, 5 ); | |
| 93 | ||
| 94 | if( true ) | |
| 95 | {
| |
| 96 | float Size = random( 0, 1 ) * PurchaseVolume; | |
| 97 | ||
| 98 | if( t ) | |
| 99 | {
| |
| 100 | EntryPoint = ( int ) max( 1, ( float ) ( CommodityExchange.AskPrice-level ) ); | |
| 101 | ( ( ArrayList ) CommodityExchange.Bid.get( ( int ) min( ( float )Range - 1, max( 1, ( float ) ( CommodityExchange.AskPrice-level ) ) ) ) ).set( ID, BS + ( ( int ) ( Size ) ) ); | |
| 102 | } | |
| 103 | else | |
| 104 | {
| |
| 105 | EntryPoint = ( int ) max( 1, ( float ) ( CommodityExchange.BidPrice-level ) ); | |
| 106 | ( ( ArrayList ) CommodityExchange.Bid.get( ( int ) min( ( float )Range - 1, max( 1, ( float ) ( CommodityExchange.BidPrice-level ) ) ) ) ).set( ID, BS + ( ( int ) ( Size ) ) ); | |
| 107 | } | |
| 108 | } | |
| 109 | } | |
| 110 | else | |
| 111 | {
| |
| 112 | Trading = true; | |
| 113 | boolean t = ( random( 0, 1 ) < Liquidity ); | |
| 114 | int level = ( int ) random( 0, 5 ); | |
| 115 | ||
| 116 | if( true ) | |
| 117 | {
| |
| 118 | float Size = random( 0, 1 ) * PurchaseVolume; | |
| 119 | ||
| 120 | if( t ) | |
| 121 | {
| |
| 122 | EntryPoint = ( int ) max( 1, ( float ) ( CommodityExchange.BidPrice+level ) ); | |
| 123 | ( ( ArrayList ) CommodityExchange.Ask.get( ( int ) min( ( float )Range - 1, max( 1, ( float ) ( CommodityExchange.BidPrice+level ) ) ) ) ).set( ID, AS + ( ( int ) ( random( 0, 1 ) * PurchaseVolume ) ) ); | |
| 124 | } | |
| 125 | else | |
| 126 | {
| |
| 127 | EntryPoint = ( int ) min( ( float )Range - 1, max( 1, ( float ) ( CommodityExchange.AskPrice+level ) ) ); | |
| 128 | ( ( ArrayList ) CommodityExchange.Ask.get( ( int ) min( ( float )Range - 1, max( 1, ( float ) ( CommodityExchange.AskPrice+level ) ) ) ) ).set( ID, AS + ( ( int ) ( random( 0, 1 ) * PurchaseVolume ) ) ); | |
| 129 | } | |
| 130 | } | |
| 131 | } | |
| 132 | } | |
| 133 | else | |
| 134 | {
| |
| 135 | if( Consumer ) | |
| 136 | {
| |
| 137 | if( CommodityExchange.BidPrice - EntryPoint > 5 ) | |
| 138 | {
| |
| 139 | Trading = false; | |
| 140 | ( ( ArrayList ) CommodityExchange.Bid.get( ( int ) min( 199, EntryPoint ) ) ).set( Id, ( ( int ) ( 0 ) ) ); | |
| 141 | } | |
| 142 | } | |
| 143 | else | |
| 144 | {
| |
| 145 | if( EntryPoint-CommodityExchange.AskPrice > 5 ) | |
| 146 | {
| |
| 147 | Trading = false; | |
| 148 | ( ( ArrayList ) CommodityExchange.Ask.get( ( int ) min( 199, EntryPoint ) ) ).set( Id, ( ( int ) ( 0 ) ) ); | |
| 149 | } | |
| 150 | } | |
| 151 | } | |
| 152 | } | |
| 153 | } | |
| 154 | ||
| 155 | class Exchange | |
| 156 | {
| |
| 157 | ArrayList Bid; | |
| 158 | ArrayList Ask; | |
| 159 | int Traders; | |
| 160 | ||
| 161 | int BidPrice; | |
| 162 | int AskPrice; | |
| 163 | ||
| 164 | Chart myChart; | |
| 165 | ||
| 166 | public Exchange( int T ) | |
| 167 | {
| |
| 168 | Bid = new ArrayList(); | |
| 169 | Ask = new ArrayList(); | |
| 170 | Traders = T; | |
| 171 | BidPrice = 49; | |
| 172 | AskPrice = 50; | |
| 173 | ||
| 174 | cp5.addSlider( "slider_demand" ) | |
| 175 | .setPosition( 275, 525 ) | |
| 176 | .setSize( width - 350, 20 ) | |
| 177 | .setRange( 0, 200 ) | |
| 178 | .setValue( 100 ) | |
| 179 | ; | |
| 180 | ||
| 181 | cp5.addSlider( "slider_supply" ) | |
| 182 | .setPosition( 275, 550 ) | |
| 183 | .setSize( width - 350, 20 ) | |
| 184 | .setRange( 0, 200 ) | |
| 185 | .setValue( 100 ) | |
| 186 | ; | |
| 187 | ||
| 188 | cp5.addSlider( "slider_liquidity" ) | |
| 189 | .setPosition( 275, 575 ) | |
| 190 | .setSize( width - 350, 20 ) | |
| 191 | .setRange( 0, 1 ) | |
| 192 | .setValue( 100 ) | |
| 193 | ; | |
| 194 | ||
| 195 | myChart = cp5.addChart( "dataflow" ) | |
| 196 | .setPosition( 275, 100 ) | |
| 197 | .setSize( width - 300, 400 ) | |
| 198 | .setRange( 0, Range ) | |
| 199 | .setView( Chart.LINE ) // use Chart.LINE, Chart.PIE, Chart.AREA, Chart.BAR_CENTERED | |
| 200 | .setStrokeWeight( 1 ) | |
| 201 | .setColorCaptionLabel( color( 40 ) ) | |
| 202 | ; | |
| 203 | ||
| 204 | myChart.addDataSet( "tickflow_B" ); | |
| 205 | myChart.setData( "tickflow_B", new float[480] ); | |
| 206 | myChart.addDataSet( "tickflow_A" ); | |
| 207 | myChart.setData( "tickflow_A", new float[480] ); | |
| 208 | ||
| 209 | for( int i = 0; i < Range; i ++ ) | |
| 210 | {
| |
| 211 | Bid.add( new ArrayList() ); | |
| 212 | Ask.add( new ArrayList() ); | |
| 213 | ||
| 214 | for( int j = 0; j < Traders; j ++ ) | |
| 215 | {
| |
| 216 | ( ( ArrayList ) Bid.get( i ) ).add( ( int ) 0 ); | |
| 217 | ( ( ArrayList ) Ask.get( i ) ).add( ( int ) 0 ); | |
| 218 | } | |
| 219 | } | |
| 220 | } | |
| 221 | ||
| 222 | public void RunLogic() | |
| 223 | {
| |
| 224 | int BP = 1; | |
| 225 | int AP = Range -3; | |
| 226 | ||
| 227 | for( int i = 1; i < Range -2; i ++ ) | |
| 228 | {
| |
| 229 | int BI1 = 0; | |
| 230 | int AI1 = 0; | |
| 231 | int BI2 = 0; | |
| 232 | int AI2 = 0; | |
| 233 | ||
| 234 | for( int j = 0; j < Traders; j ++ ) | |
| 235 | {
| |
| 236 | BI1 += ( ( Integer ) ( ( ArrayList ) Bid.get( i ) ).get( j ) ); | |
| 237 | AI1 += ( ( Integer ) ( ( ArrayList ) Ask.get( i ) ).get( j ) ); | |
| 238 | BI2 += ( ( Integer ) ( ( ArrayList ) Bid.get( i+1 ) ).get( j ) ); | |
| 239 | AI2 += ( ( Integer ) ( ( ArrayList ) Ask.get( i-1 ) ).get( j ) ); | |
| 240 | } | |
| 241 | ||
| 242 | if( BI2 == 0 && BI1 > 0 ) | |
| 243 | {
| |
| 244 | if( i > BP ) | |
| 245 | {
| |
| 246 | BP = i; | |
| 247 | } | |
| 248 | } | |
| 249 | ||
| 250 | if( AI2 == 0 && AI1 > 0 ) | |
| 251 | {
| |
| 252 | if( i < AP ) | |
| 253 | {
| |
| 254 | AP = i; | |
| 255 | } | |
| 256 | } | |
| 257 | } | |
| 258 | ||
| 259 | if( BP != 1 ) | |
| 260 | {
| |
| 261 | BidPrice = BP; | |
| 262 | } | |
| 263 | ||
| 264 | if( AP < Range-3 ) | |
| 265 | {
| |
| 266 | AskPrice = AP; | |
| 267 | } | |
| 268 | ||
| 269 | myChart.push( "tickflow_A", AskPrice ); | |
| 270 | myChart.push( "tickflow_B", BidPrice ); | |
| 271 | } | |
| 272 | ||
| 273 | public void FillTradesLogic() | |
| 274 | {
| |
| 275 | for( int i = 0; i < Range-1; i++ ) | |
| 276 | {
| |
| 277 | for( int j = 0; j < Traders; j ++ ) | |
| 278 | {
| |
| 279 | int AskSize = ( ( Integer ) ( ( ArrayList ) Ask.get( i ) ).get( j ) ); | |
| 280 | ||
| 281 | if( AskSize > 0 ) | |
| 282 | {
| |
| 283 | for( int x = BidPrice; x >=0; x-- ) | |
| 284 | {
| |
| 285 | for( int y = 0; y < Traders; y ++ ) | |
| 286 | {
| |
| 287 | if( AskSize > 0 && ( ( Integer ) ( ( ArrayList ) Bid.get( x ) ).get( y ) ) > 0 ) | |
| 288 | {
| |
| 289 | int BidSize = ( ( Integer ) ( ( ArrayList ) Bid.get( x ) ).get( y ) ); | |
| 290 | ||
| 291 | if( BidSize < AskSize && BidSize > 0 ) | |
| 292 | {
| |
| 293 | ( ( ArrayList ) Bid.get( x ) ).set( y, 0 ); | |
| 294 | ( ( ArrayList ) Ask.get( i ) ).set( j, AskSize-BidSize ); | |
| 295 | Consumers[ y%( CommodityExchange.Traders/2 ) ].Trading = false; | |
| 296 | ||
| 297 | AskSize -= BidSize; | |
| 298 | } | |
| 299 | else if( BidSize > AskSize && AskSize > 0 ) | |
| 300 | {
| |
| 301 | ( ( ArrayList ) Bid.get( x ) ).set( y, BidSize-AskSize ); | |
| 302 | ( ( ArrayList ) Ask.get( i ) ).set( j, 0 ); | |
| 303 | Producers[ j%( CommodityExchange.Traders/2 ) ].Trading = false; | |
| 304 | AskSize = 0; | |
| 305 | } | |
| 306 | else if( BidSize == AskSize && BidSize > 0 ) | |
| 307 | {
| |
| 308 | Producers[ j%( CommodityExchange.Traders/2 ) ].Trading = false; | |
| 309 | Consumers[ y%( CommodityExchange.Traders/2 ) ].Trading = false; | |
| 310 | ( ( ArrayList ) Bid.get( x ) ).set( y, 0 ); | |
| 311 | ( ( ArrayList ) Ask.get( i ) ).set( j, 0 ); | |
| 312 | AskSize = 0; | |
| 313 | } | |
| 314 | } | |
| 315 | } | |
| 316 | } | |
| 317 | } | |
| 318 | } | |
| 319 | } | |
| 320 | } | |
| 321 | ||
| 322 | public void Draw() | |
| 323 | {
| |
| 324 | fill( 0, 0, 128 ); | |
| 325 | rect( 0, 0, 125, height ); | |
| 326 | fill( 128, 0, 0 ); | |
| 327 | rect( 125, 0, 125, height ); | |
| 328 | ||
| 329 | for( int i = 0; i < Range; i++ ) | |
| 330 | {
| |
| 331 | int B = 0; | |
| 332 | int A = 0; | |
| 333 | ||
| 334 | for( int j = 0; j < Traders; j ++ ) | |
| 335 | {
| |
| 336 | B += ( ( Integer ) ( ( ArrayList ) Bid.get( i ) ).get( j ) ); | |
| 337 | A += ( ( Integer ) ( ( ArrayList ) Ask.get( i ) ).get( j ) ); | |
| 338 | } | |
| 339 | ||
| 340 | fill( 255 ); | |
| 341 | stroke( 255 ); | |
| 342 | text( i, 25, ( height/1.05 )*( ( ( float ) i ) / ( ( float ) Range ) ) + 25 ); | |
| 343 | text( B, 65, ( height/1.05 )*( ( ( float ) i ) / ( ( float ) Range ) ) + 25 ); | |
| 344 | text( i, 145, ( height/1.05 )*( ( ( float ) i ) / ( ( float ) Range ) ) + 25 ); | |
| 345 | text( A, 175, ( height/1.05 )*( ( ( float ) i ) / ( ( float ) Range ) ) + 25 ); | |
| 346 | } | |
| 347 | ||
| 348 | fill( 255 ); | |
| 349 | stroke( 255 ); | |
| 350 | text( "Bid: " + BidPrice, 275, 25 ); | |
| 351 | text( "Ask: " + AskPrice, 275, 50 ); | |
| 352 | } | |
| 353 | } | |
| 354 | ||
| 355 | void slider_supply( float level ) | |
| 356 | {
| |
| 357 | for( int i = 0; i < ( CommodityExchange.Traders/2 )+1; i++ ) | |
| 358 | {
| |
| 359 | Producers[ i ].PurchaseVolume = ( int ) level; | |
| 360 | } | |
| 361 | } | |
| 362 | ||
| 363 | void slider_demand( float level ) | |
| 364 | {
| |
| 365 | for( int i = 0; i < ( CommodityExchange.Traders/2 )+1; i++ ) | |
| 366 | {
| |
| 367 | Consumers[ i ].PurchaseVolume = ( int ) level; | |
| 368 | } | |
| 369 | } | |
| 370 | ||
| 371 | ||
| 372 | void slider_liquidity( float level ) | |
| 373 | {
| |
| 374 | Liquidity = level; | |
| 375 | } |