├── .gitattributes
├── .gitignore
├── Backlog.md
├── CSharp
├── .gitignore
├── .nuget
│ ├── NuGet.Config
│ ├── NuGet.exe
│ └── NuGet.targets
├── OtherTeam.StandardizedMarketGatewayAPI
│ ├── ApiDealExecutedEventArgs.cs
│ ├── ApiLimitOrder.cs
│ ├── ApiMarketDataUpdateEventArgs.cs
│ ├── ApiMarketGateway.cs
│ ├── ApiMarketOrder.cs
│ ├── ApiMarketWay.cs
│ ├── ApiOrder.cs
│ ├── ApiOrderFailedEventArgs.cs
│ ├── OtherTeam.StandardizedMarketGatewayAPI.csproj
│ └── Properties
│ │ └── AssemblyInfo.cs
├── Settings.StyleCop
├── SimpleOrderRouting.Console
│ ├── App.config
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── SimpleOrderRouting.Console.csproj
├── SimpleOrderRouting.Domain
│ ├── ICanReceiveMarketData.cs
│ ├── ICanRouteOrders.cs
│ ├── IHandleInvestorInstructions.cs
│ ├── IOrder.cs
│ ├── IProvideMarkets.cs
│ ├── ISolveInvestorInstructions.cs
│ ├── InvestorIntructionCallback.cs
│ ├── Investors
│ │ ├── InstructionExecutionContext.cs
│ │ ├── InvestorInstruction.cs
│ │ ├── InvestorInstructionExecutedEventArgs.cs
│ │ └── InvestorInstructionStatus.cs
│ ├── Markets
│ │ ├── Feeds
│ │ │ └── MarketDataUpdatedArgs.cs
│ │ ├── MarketInfo.cs
│ │ ├── MarketSnapshot.cs
│ │ ├── MarketSnapshotProvider.cs
│ │ └── Orders
│ │ │ ├── DealExecutedEventArgs.cs
│ │ │ ├── InstrumentIdentifier.cs
│ │ │ ├── OrderBasket.cs
│ │ │ ├── OrderDescription.cs
│ │ │ ├── OrderExecutedEventArgs.cs
│ │ │ └── OrderFailedEventArgs.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── SimpleOrderRouting.Domain.csproj
│ ├── SmartOrderRoutingEngine.cs
│ ├── SolvingStrategies
│ │ └── MarketSweepSolver.cs
│ └── Way.cs
├── SimpleOrderRouting.Infra
│ ├── CompositionRootHelper.cs
│ ├── Investors
│ │ ├── InstructionExecutedDto.cs
│ │ ├── InstructionFailedDto.cs
│ │ ├── InvestorInstructionDto.cs
│ │ ├── InvestorInstructionDtoCallBacks.cs
│ │ ├── InvestorInstructionIdentifierDto.cs
│ │ ├── InvestorInstructionUpdatedDto.cs
│ │ ├── InvestorInstructionsAdapter.cs
│ │ └── Way.cs
│ ├── Markets
│ │ ├── LimitOrderAdapter.cs
│ │ ├── MarketDataAdapter.cs
│ │ ├── MarketOrderAdapter.cs
│ │ ├── MarketsAdapter.cs
│ │ ├── OrderAdapter.cs
│ │ └── OrderRoutingAdapter.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Settings.StyleCop
│ ├── SimpleOrderRouting.Infra.csproj
│ └── SimpleOrderRouting.Infra.csproj.DotSettings
├── SimpleOrderRouting.Tests
│ ├── Infra
│ │ ├── ApiMarketGatewayTests.cs
│ │ ├── HarnessTests.cs
│ │ ├── InvestorInstructionDtoTests.cs
│ │ └── SorTestHarness.cs
│ ├── InvestorInstructionTests.cs
│ ├── MarketSweepSolverTests.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Settings.StyleCop
│ ├── SimpleOrderRouting.Tests.csproj
│ ├── SorAcceptanceTests.cs
│ └── packages.config
├── SimpleOrderRouting.sln
└── SimpleOrderRouting.sln.DotSettings
├── DoD.md
├── FSharp
├── SimpleOrderRouting.Journey1
│ ├── Adapters.fs
│ ├── Adapters.fsi
│ ├── Domain.fs
│ ├── Domain.fsi
│ ├── External.fs
│ ├── External.fsi
│ ├── MarketDataAdapter.fs
│ ├── Ports.fs
│ ├── SORoutingEngine.fs
│ ├── Script.fsx
│ ├── SimpleOrderRouting.Journey1.fsproj
│ └── Utilities.fs
├── SimpleOrderRouting.Tests
│ ├── MarketTests.fs
│ ├── SimpleOrderRouting.Tests.fsproj
│ ├── SorAcceptanceTests.fs
│ ├── UtilitiesTests.fs
│ ├── app.config
│ └── packages.config
└── SimpleOrderRouting.sln
├── LICENSE.txt
├── Readme.md
└── images
├── 10kfeet.jpg
├── 25kfeet.jpg
├── 5feet.jpg
├── Hegagonal-firstDraft.jpg
├── HexaMendel.jpg
├── HexaThomas.jpg
├── HexaTomasz.jpg
├── MarketsRaceConditions.jpg
├── PortAndAdapters.jpg
├── SOR-bigPicture.jpg
├── XPDesign.jpg
├── You-Are-Here.jpg
├── duty_calls.png
└── goodmanpistoff.jpg
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
19 | !packages/*/build/
20 |
21 | # MSTest test Results
22 | [Tt]est[Rr]esult*/
23 | [Bb]uild[Ll]og.*
24 |
25 | *_i.c
26 | *_p.c
27 | *.ilk
28 | *.meta
29 | *.obj
30 | *.pch
31 | *.pdb
32 | *.pgc
33 | *.pgd
34 | *.rsp
35 | *.sbr
36 | *.tlb
37 | *.tli
38 | *.tlh
39 | *.tmp
40 | *.tmp_proj
41 | *.log
42 | *.vspscc
43 | *.vssscc
44 | .builds
45 | *.pidb
46 | *.log
47 | *.scc
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 | *.cachefile
56 |
57 | # Visual Studio profiler
58 | *.psess
59 | *.vsp
60 | *.vspx
61 |
62 | # Guidance Automation Toolkit
63 | *.gpState
64 |
65 | # ReSharper is a .NET coding add-in
66 | _ReSharper*/
67 | *.[Rr]e[Ss]harper
68 |
69 | # TeamCity is a build add-in
70 | _TeamCity*
71 |
72 | # DotCover is a Code Coverage Tool
73 | *.dotCover
74 |
75 | # NCrunch
76 | *.ncrunch*
77 | .*crunch*.local.xml
78 |
79 | # Installshield output folder
80 | [Ee]xpress/
81 |
82 | # DocProject is a documentation generator add-in
83 | DocProject/buildhelp/
84 | DocProject/Help/*.HxT
85 | DocProject/Help/*.HxC
86 | DocProject/Help/*.hhc
87 | DocProject/Help/*.hhk
88 | DocProject/Help/*.hhp
89 | DocProject/Help/Html2
90 | DocProject/Help/html
91 |
92 | # Click-Once directory
93 | publish/
94 |
95 | # Publish Web Output
96 | *.Publish.xml
97 |
98 | # NuGet Packages Directory
99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
100 | packages/
101 |
102 | # Windows Azure Build Output
103 | csx
104 | *.build.csdef
105 |
106 | # Windows Store app package directory
107 | AppPackages/
108 |
109 | # Others
110 | sql/
111 | *.Cache
112 | ClientBin/
113 | [Ss]tyle[Cc]op.*
114 | ~$*
115 | *~
116 | *.dbmdl
117 | *.[Pp]ublish.xml
118 | *.pfx
119 | *.publishsettings
120 |
121 | # RIA/Silverlight projects
122 | Generated_Code/
123 |
124 | # Backup & report files from converting an old project file to a newer
125 | # Visual Studio version. Backup files are not needed, because we have git ;-)
126 | _UpgradeReport_Files/
127 | Backup*/
128 | UpgradeLog*.XML
129 | UpgradeLog*.htm
130 |
131 | # SQL Server files
132 | App_Data/*.mdf
133 | App_Data/*.ldf
134 |
135 |
136 | #LightSwitch generated files
137 | GeneratedArtifacts/
138 | _Pvt_Extensions/
139 | ModelManifest.xml
140 |
141 | # =========================
142 | # Windows detritus
143 | # =========================
144 |
145 | # Windows image file caches
146 | Thumbs.db
147 | ehthumbs.db
148 |
149 | # Folder config file
150 | Desktop.ini
151 |
152 | # Recycle Bin used on file shares
153 | $RECYCLE.BIN/
154 |
155 | # Mac desktop service store files
156 | .DS_Store
157 |
--------------------------------------------------------------------------------
/Backlog.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/Backlog.md
--------------------------------------------------------------------------------
/CSharp/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # MSTest test Results
20 | [Tt]est[Rr]esult*/
21 | [Bb]uild[Ll]og.*
22 |
23 | #NUNIT
24 | *.VisualState.xml
25 | TestResult.xml
26 |
27 | # Build Results of an ATL Project
28 | [Dd]ebugPS/
29 | [Rr]eleasePS/
30 | dlldata.c
31 |
32 | *_i.c
33 | *_p.c
34 | *_i.h
35 | *.ilk
36 | *.meta
37 | *.obj
38 | *.pch
39 | *.pdb
40 | *.pgc
41 | *.pgd
42 | *.rsp
43 | *.sbr
44 | *.tlb
45 | *.tli
46 | *.tlh
47 | *.tmp
48 | *.tmp_proj
49 | *.log
50 | *.vspscc
51 | *.vssscc
52 | .builds
53 | *.pidb
54 | *.svclog
55 | *.scc
56 |
57 | # Chutzpah Test files
58 | _Chutzpah*
59 |
60 | # Visual C++ cache files
61 | ipch/
62 | *.aps
63 | *.ncb
64 | *.opensdf
65 | *.sdf
66 | *.cachefile
67 |
68 | # Visual Studio profiler
69 | *.psess
70 | *.vsp
71 | *.vspx
72 |
73 | # TFS 2012 Local Workspace
74 | $tf/
75 |
76 | # Guidance Automation Toolkit
77 | *.gpState
78 |
79 | # ReSharper is a .NET coding add-in
80 | _ReSharper*/
81 | *.[Rr]e[Ss]harper
82 | *.DotSettings.user
83 |
84 | # JustCode is a .NET coding addin-in
85 | .JustCode
86 |
87 | # TeamCity is a build add-in
88 | _TeamCity*
89 |
90 | # DotCover is a Code Coverage Tool
91 | *.dotCover
92 |
93 | # NCrunch
94 | *.ncrunch*
95 | _NCrunch_*
96 | .*crunch*.local.xml
97 |
98 | # MightyMoose
99 | *.mm.*
100 | AutoTest.Net/
101 |
102 | # Web workbench (sass)
103 | .sass-cache/
104 |
105 | # Installshield output folder
106 | [Ee]xpress/
107 |
108 | # DocProject is a documentation generator add-in
109 | DocProject/buildhelp/
110 | DocProject/Help/*.HxT
111 | DocProject/Help/*.HxC
112 | DocProject/Help/*.hhc
113 | DocProject/Help/*.hhk
114 | DocProject/Help/*.hhp
115 | DocProject/Help/Html2
116 | DocProject/Help/html
117 |
118 | # Click-Once directory
119 | publish/
120 |
121 | # Publish Web Output
122 | *.[Pp]ublish.xml
123 | *.azurePubxml
124 |
125 | # NuGet Packages Directory
126 | packages/
127 | ## TODO: If the tool you use requires repositories.config uncomment the next line
128 | #!packages/repositories.config
129 |
130 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
131 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
132 | !packages/build/
133 |
134 | # Windows Azure Build Output
135 | csx/
136 | *.build.csdef
137 |
138 | # Windows Store app package directory
139 | AppPackages/
140 |
141 | # Others
142 | sql/
143 | *.Cache
144 | ClientBin/
145 | [Ss]tyle[Cc]op.*
146 | ~$*
147 | *~
148 | *.dbmdl
149 | *.dbproj.schemaview
150 | *.pfx
151 | *.publishsettings
152 | node_modules/
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | *.mdf
166 | *.ldf
167 |
168 | # Business Intelligence projects
169 | *.rdl.data
170 | *.bim.layout
171 | *.bim_*.settings
172 |
173 | # Microsoft Fakes
174 | FakesAssemblies/
175 |
--------------------------------------------------------------------------------
/CSharp/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CSharp/.nuget/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/CSharp/.nuget/NuGet.exe
--------------------------------------------------------------------------------
/CSharp/.nuget/NuGet.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildProjectDirectory)\..\
5 |
6 |
7 | false
8 |
9 |
10 | false
11 |
12 |
13 | true
14 |
15 |
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
31 |
32 |
33 |
34 |
35 | $(SolutionDir).nuget
36 |
37 |
38 |
39 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config
40 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config
41 |
42 |
43 |
44 | $(MSBuildProjectDirectory)\packages.config
45 | $(PackagesProjectConfig)
46 |
47 |
48 |
49 |
50 | $(NuGetToolsPath)\NuGet.exe
51 | @(PackageSource)
52 |
53 | "$(NuGetExePath)"
54 | mono --runtime=v4.0.30319 "$(NuGetExePath)"
55 |
56 | $(TargetDir.Trim('\\'))
57 |
58 | -RequireConsent
59 | -NonInteractive
60 |
61 | "$(SolutionDir) "
62 | "$(SolutionDir)"
63 |
64 |
65 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
66 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
67 |
68 |
69 |
70 | RestorePackages;
71 | $(BuildDependsOn);
72 |
73 |
74 |
75 |
76 | $(BuildDependsOn);
77 | BuildPackage;
78 |
79 |
80 |
81 |
82 |
83 |
84 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
99 |
100 |
103 |
104 |
105 |
106 |
108 |
109 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/ApiDealExecutedEventArgs.cs:
--------------------------------------------------------------------------------
1 | namespace OtherTeam.StandardizedMarketGatewayAPI
2 | {
3 | using System;
4 |
5 | ///
6 | /// Event data for DealExecuted event.
7 | ///
8 | public class ApiDealExecutedEventArgs : EventArgs
9 | {
10 | public ApiDealExecutedEventArgs(decimal price, int quantity)
11 | {
12 | this.Price = price;
13 | this.Quantity = quantity;
14 | }
15 |
16 | public decimal Price { get; private set; }
17 |
18 | public int Quantity { get; private set; }
19 | }
20 | }
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/ApiLimitOrder.cs:
--------------------------------------------------------------------------------
1 | namespace OtherTeam.StandardizedMarketGatewayAPI
2 | {
3 | public class ApiLimitOrder : ApiOrder
4 | {
5 | public decimal Price { get; private set; }
6 |
7 | public ApiLimitOrder(ApiMarketWay way, int quantity, decimal price, bool allowPartialExecution)
8 | {
9 | this.Quantity = quantity;
10 | this.Price = price;
11 | this.AllowPartialExecution = allowPartialExecution;
12 | this.Way = way;
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/ApiMarketDataUpdateEventArgs.cs:
--------------------------------------------------------------------------------
1 | namespace OtherTeam.StandardizedMarketGatewayAPI
2 | {
3 | using System;
4 |
5 | public class ApiMarketDataUpdateEventArgs : EventArgs
6 | {
7 | public ApiMarketDataUpdateEventArgs(string originMarketName, decimal marketPrice, int quantityOnTheMarket)
8 | {
9 | this.QuantityOnTheMarket = quantityOnTheMarket;
10 | this.MarketPrice = marketPrice;
11 | this.OriginMarketName = originMarketName;
12 | }
13 |
14 | // TODO : introduce the concept of various instruments
15 |
16 | public string OriginMarketName { get; private set; }
17 | public decimal MarketPrice { get; private set; }
18 | public int QuantityOnTheMarket { get; private set; }
19 | }
20 | }
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/ApiMarketGateway.cs:
--------------------------------------------------------------------------------
1 | namespace OtherTeam.StandardizedMarketGatewayAPI
2 | {
3 | using System;
4 |
5 | ///
6 | /// Gives access and mocks a Market given various initialization informations.
7 | ///
8 | public class ApiMarketGateway
9 | {
10 | public ApiMarketGateway(string marketName, int sellQuantity, decimal sellPrice, Predicate orderPredicate = null)
11 | {
12 | this.MarketName = marketName;
13 | this.SellQuantity = sellQuantity;
14 | this.SellPrice = sellPrice;
15 | this.OrderPredicate = orderPredicate;
16 | }
17 |
18 | public event EventHandler MarketDataUpdated;
19 |
20 | public event EventHandler OrderExecuted;
21 |
22 | // TODO: set a proper event handler instead of this string
23 | public event EventHandler OrderFailed;
24 |
25 | public string MarketName { get; private set; }
26 |
27 | public int SellQuantity { get; private set; }
28 |
29 | public decimal SellPrice { get; private set; }
30 |
31 | public int TimesSent { get; private set; }
32 |
33 | public Predicate OrderPredicate { get; set; }
34 |
35 | public ApiMarketOrder CreateMarketOrder(ApiMarketWay way, int quantity)
36 | {
37 | return new ApiMarketOrder(way, quantity);
38 | }
39 |
40 | public ApiLimitOrder CreateLimitOrder(ApiMarketWay apiMarketWay, int quantity, decimal price, bool allowPartial)
41 | {
42 | return new ApiLimitOrder(apiMarketWay, quantity, price, allowPartial);
43 | }
44 |
45 | public void Send(ApiMarketOrder marketOrder)
46 | {
47 | this.TimesSent++;
48 |
49 | if (this.PredicateFailed(marketOrder))
50 | {
51 | this.RaiseOrderFailed(marketOrder, new ApiOrderFailedEventArgs(this.MarketName, "Predicate failed."));
52 | return;
53 | }
54 |
55 | switch (marketOrder.Way)
56 | {
57 | case ApiMarketWay.Buy:
58 | if (this.AskMoreThanAvailableQuantityAndDontSupportPartialExecution(marketOrder))
59 | {
60 | this.RaiseOrderFailed(marketOrder, new ApiOrderFailedEventArgs(this.MarketName, "Excessive quantity!"));
61 | return;
62 | }
63 |
64 | this.ExecuteProperQuantity(marketOrder);
65 |
66 | break;
67 |
68 | default:
69 | throw new NotImplementedException();
70 | break;
71 | }
72 | }
73 |
74 | private void ExecuteProperQuantity(ApiOrder marketOrder)
75 | {
76 | var executedQuantity = Math.Min(marketOrder.Quantity, this.SellQuantity);
77 | this.SellQuantity -= executedQuantity;
78 |
79 | this.RaiseMarketDataUpdated(this.SellPrice, this.SellQuantity);
80 | this.RaiseOrderExecuted(marketOrder, executedQuantity);
81 | }
82 |
83 | private bool PredicateFailed(ApiOrder marketOrder)
84 | {
85 | return this.OrderPredicate != null && this.OrderPredicate(marketOrder) == false;
86 | }
87 |
88 | public void Send(ApiLimitOrder limitOrder)
89 | {
90 | this.TimesSent++;
91 |
92 | if (this.PredicateFailed(limitOrder))
93 | {
94 | this.RaiseOrderFailed(limitOrder, new ApiOrderFailedEventArgs(this.MarketName, "Predicate failed."));
95 | return;
96 | }
97 |
98 | switch (limitOrder.Way)
99 | {
100 | case ApiMarketWay.Buy:
101 | if (limitOrder.Price > this.SellPrice)
102 | {
103 | this.RaiseOrderFailed(limitOrder, new ApiOrderFailedEventArgs(this.MarketName, "Invalid price"));
104 | return;
105 | }
106 |
107 | if (this.AskMoreThanAvailableQuantityAndDontSupportPartialExecution(limitOrder))
108 | {
109 | this.RaiseOrderFailed(limitOrder, new ApiOrderFailedEventArgs(this.MarketName, "Excessive quantity!"));
110 | return;
111 | }
112 |
113 | this.ExecuteProperQuantity(limitOrder);
114 |
115 | break;
116 |
117 | default:
118 | throw new NotImplementedException();
119 | break;
120 | }
121 | }
122 |
123 | private bool AskMoreThanAvailableQuantityAndDontSupportPartialExecution(ApiOrder limitOrder)
124 | {
125 | return (limitOrder.Quantity > this.SellQuantity) && (!limitOrder.AllowPartialExecution);
126 | }
127 |
128 | private void RaiseMarketDataUpdated(decimal newSellPrice, int newQuantityOnTheMarket)
129 | {
130 | var marketDataUpdated = this.MarketDataUpdated;
131 | if (marketDataUpdated != null)
132 | {
133 | marketDataUpdated(this, new ApiMarketDataUpdateEventArgs(this.MarketName, newSellPrice, newQuantityOnTheMarket));
134 | }
135 | }
136 |
137 | private void RaiseOrderExecuted(ApiOrder order, int executedQuantity)
138 | {
139 | var onOrderExecuted = this.OrderExecuted;
140 | if (onOrderExecuted != null)
141 | {
142 | onOrderExecuted(order, new ApiDealExecutedEventArgs(this.SellPrice, executedQuantity));
143 | }
144 | }
145 |
146 | private void RaiseOrderFailed(ApiOrder order, ApiOrderFailedEventArgs args)
147 | {
148 | var onOrderFailed = this.OrderFailed;
149 | if (onOrderFailed != null)
150 | {
151 | onOrderFailed(order, args);
152 | }
153 | }
154 |
155 |
156 | }
157 | }
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/ApiMarketOrder.cs:
--------------------------------------------------------------------------------
1 | namespace OtherTeam.StandardizedMarketGatewayAPI
2 | {
3 | public class ApiMarketOrder : ApiOrder
4 | {
5 | public new bool AllowPartialExecution
6 | {
7 | get
8 | {
9 | return false;
10 | }
11 | }
12 |
13 | public ApiMarketOrder(ApiMarketWay way, int quantity)
14 | {
15 | this.Quantity = quantity;
16 | this.Way = way;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/ApiMarketWay.cs:
--------------------------------------------------------------------------------
1 | namespace OtherTeam.StandardizedMarketGatewayAPI
2 | {
3 | ///
4 | /// Sell or Buy way for Orders.
5 | ///
6 | public enum ApiMarketWay
7 | {
8 | ///
9 | /// The Buy way.
10 | ///
11 | Buy,
12 |
13 | ///
14 | /// The Sell way.
15 | ///
16 | Sell
17 | }
18 | }
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/ApiOrder.cs:
--------------------------------------------------------------------------------
1 | namespace OtherTeam.StandardizedMarketGatewayAPI
2 | {
3 | using System;
4 |
5 | public class ApiOrder
6 | {
7 | public int Quantity { get; protected set; }
8 |
9 | public ApiMarketWay Way { get; protected set; }
10 |
11 | public bool AllowPartialExecution { get; protected set; }
12 |
13 | private void Send()
14 | {
15 | throw new NotImplementedException();
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/ApiOrderFailedEventArgs.cs:
--------------------------------------------------------------------------------
1 | namespace OtherTeam.StandardizedMarketGatewayAPI
2 | {
3 | using System;
4 |
5 | ///
6 | /// Event data for DealExecuted event.
7 | ///
8 | public class ApiOrderFailedEventArgs : EventArgs
9 | {
10 | public string MarketName { get; private set; }
11 |
12 | public string FailureCause { get; private set; }
13 |
14 | public ApiOrderFailedEventArgs(string marketName, string failureCause)
15 | {
16 | this.MarketName = marketName;
17 | this.FailureCause = failureCause;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/OtherTeam.StandardizedMarketGatewayAPI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {FE2D8118-AFD3-4005-A6D5-C1D240DAD3E4}
8 | Library
9 | Properties
10 | OtherTeam.StandardizedMarketGatewayAPI
11 | OtherTeam.StandardizedMarketGatewayAPI
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
60 |
--------------------------------------------------------------------------------
/CSharp/OtherTeam.StandardizedMarketGatewayAPI/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("OtherTeam.StandardizedMarketGatewayAPI")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("OtherTeam.StandardizedMarketGatewayAPI")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("c777c093-158c-4a25-b245-84b2f5ab65d2")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/CSharp/Settings.StyleCop:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hashtable
5 | enum
6 | gzip
7 | nullable
8 | struct
9 | sut
10 | uint
11 | ulong
12 | ushort
13 | vs
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | False
22 |
23 |
24 |
25 |
26 | False
27 |
28 |
29 |
30 |
31 | False
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | False
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Console/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Console/Program.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Console
2 | {
3 | using System;
4 |
5 | using OtherTeam.StandardizedMarketGatewayAPI;
6 | using SimpleOrderRouting.Infra;
7 |
8 | class Program
9 | {
10 | static void Main(string[] args)
11 | {
12 | var marketA = new ApiMarketGateway("NYSE (New York)", sellQuantity: 150, sellPrice: 100M);
13 | var marketB = new ApiMarketGateway("CME (Chicago)", sellQuantity: 55, sellPrice: 101M);
14 |
15 | var investorAdapter = CompositionRootHelper.ComposeTheHexagon(marketA, marketB);
16 |
17 | System.Console.WriteLine("SOR connected to markets: {0} and {1}", marketA.MarketName, marketB.MarketName);
18 |
19 | var investorInstructionDto = new InvestorInstructionDto(Way.Buy, quantity: 125, price: 100M);
20 |
21 | System.Console.WriteLine();
22 | System.Console.WriteLine("Type 'Enter' to submit the following investor instruction: [{0}]\n\n", investorInstructionDto);
23 | System.Console.ReadLine();
24 |
25 | investorAdapter.Route(investorInstructionDto, arg => { System.Console.WriteLine("Instruction executed: [{0}]", arg); }, eventArgs => {});
26 |
27 | System.Console.WriteLine();
28 | System.Console.WriteLine("Type 'Enter' to exit");
29 | System.Console.ReadLine();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Console/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SimpleOrderRouting.Console")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SimpleOrderRouting.Console")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("fd7fc9da-f31f-48d1-877a-ed85d4cddbd8")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Console/SimpleOrderRouting.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F20EBD6E-C774-4856-91D5-1BA43005513D}
8 | Exe
9 | Properties
10 | SimpleOrderRouting.Console
11 | SimpleOrderRouting.Console
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | {fe2d8118-afd3-4005-a6d5-c1d240dad3e4}
53 | OtherTeam.StandardizedMarketGatewayAPI
54 |
55 |
56 | {4f66c7d2-8cbd-4280-9a2d-6555e276c6a7}
57 | SimpleOrderRouting.Domain
58 |
59 |
60 | {00dd3731-e815-4770-be17-4f17bfec4171}
61 | SimpleOrderRouting.Infra
62 |
63 |
64 |
65 |
72 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/ICanReceiveMarketData.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting
2 | {
3 | using System;
4 |
5 | using SimpleOrderRouting.Markets.Feeds;
6 | using SimpleOrderRouting.Markets.Orders;
7 |
8 | ///
9 | /// Allows to receive MarketData events.
10 | ///
11 | public interface ICanReceiveMarketData
12 | {
13 |
14 | ///
15 | /// Occurs when market data is updated for an Instrument.
16 | ///
17 | event EventHandler InstrumentMarketDataUpdated;
18 |
19 | ///
20 | /// Occurs when one order failed on a Market.
21 | ///
22 | event EventHandler OrderFailedOnAMarket;
23 |
24 | void Subscribe(string marketName);
25 | }
26 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/ICanRouteOrders.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting
2 | {
3 | using System;
4 |
5 | using SimpleOrderRouting.Markets.Orders;
6 |
7 | ///
8 | /// Allows to create and route Orders on Market venues.
9 | ///
10 | public interface ICanRouteOrders
11 | {
12 | IOrder CreateMarketOrder(OrderDescription orderDescription);
13 |
14 | IOrder CreateLimitOrder(OrderDescription orderDescription);
15 |
16 | void Route(OrderBasket basketOrder);
17 |
18 | ///
19 | /// Occurs when one order is executed.
20 | ///
21 | event EventHandler OrderExecuted;
22 |
23 | ///
24 | /// Occurs when one order failed.
25 | ///
26 | event EventHandler OrderFailed;
27 | }
28 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/IHandleInvestorInstructions.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting
2 | {
3 | using System;
4 |
5 | using SimpleOrderRouting.Investors;
6 |
7 | ///
8 | /// Provides an integration point for all investor side use cases.
9 | ///
10 | public interface IHandleInvestorInstructions
11 | {
12 | void Route(InvestorInstruction investorInstruction, Action executedCallback, Action failureCallback);
13 | }
14 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/IOrder.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 | namespace SimpleOrderRouting
17 | {
18 | using System;
19 |
20 | using SimpleOrderRouting.Markets.Orders;
21 |
22 | ///
23 | /// Orders to buy or sell a given quantity of a product.
24 | ///
25 | public interface IOrder
26 | {
27 | event EventHandler OrderExecuted;
28 |
29 | // TODO: Maybe not necessary if we change the Send() signature to inlcude the notification.
30 | event EventHandler OrderFailed;
31 |
32 | Way Way { get; }
33 |
34 | int Quantity { get; }
35 |
36 | bool AllowPartialExecution { get; }
37 |
38 | void Send();
39 | }
40 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/IProvideMarkets.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting
2 | {
3 | using System.Collections.Generic;
4 |
5 | ///
6 | /// Lists the names of available markets.
7 | ///
8 | public interface IProvideMarkets
9 | {
10 | IEnumerable GetAvailableMarketNames();
11 | }
12 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/ISolveInvestorInstructions.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 | namespace SimpleOrderRouting
17 | {
18 | using SimpleOrderRouting.Investors;
19 | using SimpleOrderRouting.Markets.Orders;
20 |
21 | ///
22 | /// Transforms an into an .
23 | ///
24 | public interface ISolveInvestorInstructions
25 | {
26 | // TODO: remove the reference to ICanRouteOrder (currently requested for the OrderBasket creation;-(
27 | ///
28 | /// Build the description of the orders needed to fulfill an which
29 | /// is aggregated within an instance.
30 | ///
31 | /// The instance that aggregates the .
32 | /// The can route orders (temp hack that should be removed afterwards).
33 | ///
34 | /// An containing all the orders to be routed in order to fulfill the initial .
35 | ///
36 | OrderBasket Solve(InstructionExecutionContext instructionExecutionContext, ICanRouteOrders canRouteOrders);
37 | }
38 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/InvestorIntructionCallback.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting
23 | {
24 | using System;
25 |
26 | using SimpleOrderRouting.Markets.Orders;
27 |
28 | ///
29 | /// Allows to raise Callbacks on a given investor instruction.
30 | ///
31 | public class InvestorIntructionCallback
32 | {
33 | private readonly Action executedCallback;
34 |
35 | private readonly Action failureCallback;
36 |
37 | public InvestorIntructionCallback(Action executedCallback, Action failureCallback)
38 | {
39 | this.executedCallback = executedCallback;
40 | this.failureCallback = failureCallback;
41 | }
42 |
43 | public void OnExecuted(object sender, OrderExecutedEventArgs e)
44 | {
45 | this.executedCallback(e);
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Investors/InstructionExecutionContext.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Investors
22 | {
23 | using System;
24 |
25 | using SimpleOrderRouting.Markets.Orders;
26 |
27 | ///
28 | /// 1 to 1 relationship with an . Keeps the current state of the instruction execution.
29 | /// Entity
30 | ///
31 | public class InstructionExecutionContext
32 | {
33 | public InvestorInstruction Instruction { get; private set; }
34 |
35 | private readonly Action instructionExecutedCallBack;
36 |
37 | private readonly Action instructionFailedCallback;
38 |
39 | private readonly int initialQuantity;
40 |
41 | public InstructionExecutionContext(InvestorInstruction investorInstruction, Action instructionExecutedCallBack, Action instructionFailedCallback)
42 | {
43 | this.Instruction = investorInstruction;
44 | this.instructionExecutedCallBack = instructionExecutedCallBack;
45 | this.instructionFailedCallback = instructionFailedCallback;
46 | this.initialQuantity = investorInstruction.Quantity;
47 | this.RemainingQuantityToBeExecuted = investorInstruction.Quantity;
48 | this.Price = investorInstruction.Price;
49 | this.Way = investorInstruction.Way;
50 | this.AllowPartialExecution = investorInstruction.AllowPartialExecution;
51 | }
52 |
53 | public int RemainingQuantityToBeExecuted { get; private set; }
54 |
55 | public decimal Price { get; private set; }
56 |
57 | public Way Way { get; private set; }
58 |
59 | public bool AllowPartialExecution { get; private set; }
60 |
61 | ///
62 | /// Records that an order has been executed and calls the instructionExecutedCallBack if the Instruction is fully executed.
63 | ///
64 | /// The executed quantity.
65 | public void RecordOrderExecution(int quantity)
66 | {
67 | var previousRemainingQuantityToBeExecuted = this.RemainingQuantityToBeExecuted;
68 |
69 | this.RemainingQuantityToBeExecuted -= quantity;
70 |
71 | if (this.RemainingQuantityToBeExecuted == 0)
72 | {
73 | this.instructionExecutedCallBack(new InvestorInstructionExecutedEventArgs(this.Way, this.initialQuantity, this.Price));
74 | }
75 | else if (this.RemainingQuantityToBeExecuted < 0)
76 | {
77 | throw new ApplicationException(string.Format("Executed more than the investor instruction has requested. Previous remaining quantity to be executed: {0}, latest executed quantity: {1}. New remaining quantity to be executed: {2}.", previousRemainingQuantityToBeExecuted, quantity, this.RemainingQuantityToBeExecuted));
78 | }
79 | }
80 |
81 | public bool ShouldTheInstructionBeContinued()
82 | {
83 | return this.Instruction.GoodTill != null && this.Instruction.GoodTill > DateTime.Now && this.RemainingQuantityToBeExecuted > 0;
84 | }
85 |
86 | public void DeclareFailure(OrderFailedEventArgs orderFailedEventArgs)
87 | {
88 | this.instructionFailedCallback(orderFailedEventArgs.Reason);
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Investors/InvestorInstruction.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Investors
22 | {
23 | using System;
24 |
25 | ///
26 | /// Trading instruction given to the SOR on the investor-side.
27 | ///
28 | public class InvestorInstruction
29 | {
30 | public InvestorInstruction(long investorInstructionIdentifier, Way way, int quantity, decimal price, bool allowPartialExecution = false, DateTime? goodTill = null)
31 | {
32 | this.Way = way;
33 | this.Quantity = quantity;
34 | this.Price = price;
35 | this.AllowPartialExecution = allowPartialExecution;
36 | this.GoodTill = goodTill;
37 |
38 | this.InvestorInstructionIdentifier = investorInstructionIdentifier;
39 | }
40 |
41 | public long InvestorInstructionIdentifier { get; private set; }
42 |
43 | public DateTime? GoodTill { get; private set; }
44 |
45 | public bool AllowPartialExecution { get; private set; }
46 |
47 | public decimal Price { get; private set; }
48 |
49 | public int Quantity { get; private set; }
50 |
51 | public Way Way { get; private set; }
52 |
53 | public static bool operator ==(InvestorInstruction left, InvestorInstruction right)
54 | {
55 | return Equals(left, right);
56 | }
57 |
58 | public static bool operator !=(InvestorInstruction left, InvestorInstruction right)
59 | {
60 | return !Equals(left, right);
61 | }
62 |
63 | protected bool Equals(InvestorInstruction other)
64 | {
65 | return this.InvestorInstructionIdentifier == other.InvestorInstructionIdentifier && this.GoodTill.Equals(other.GoodTill) && this.AllowPartialExecution == other.AllowPartialExecution && this.Price == other.Price && this.Quantity == other.Quantity && this.Way == other.Way;
66 | }
67 |
68 | public override bool Equals(object obj)
69 | {
70 | if (ReferenceEquals(null, obj))
71 | {
72 | return false;
73 | }
74 | if (ReferenceEquals(this, obj))
75 | {
76 | return true;
77 | }
78 | if (obj.GetType() != this.GetType())
79 | {
80 | return false;
81 | }
82 | return this.Equals((InvestorInstruction)obj);
83 | }
84 |
85 | public override int GetHashCode()
86 | {
87 | unchecked
88 | {
89 | var hashCode = this.InvestorInstructionIdentifier.GetHashCode();
90 | hashCode = (hashCode * 397) ^ this.GoodTill.GetHashCode();
91 | hashCode = (hashCode * 397) ^ this.AllowPartialExecution.GetHashCode();
92 | hashCode = (hashCode * 397) ^ this.Price.GetHashCode();
93 | hashCode = (hashCode * 397) ^ this.Quantity;
94 | hashCode = (hashCode * 397) ^ (int)this.Way;
95 | return hashCode;
96 | }
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Investors/InvestorInstructionExecutedEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SimpleOrderRouting.Investors
4 | {
5 | ///
6 | /// Event data for InvestorInstructionExecuted event.
7 | ///
8 | public class InvestorInstructionExecutedEventArgs : EventArgs
9 | {
10 | public InvestorInstructionExecutedEventArgs(Way way, int quantity, decimal price)
11 | {
12 | this.Quantity = quantity;
13 | this.Price = price;
14 | this.Way = way;
15 | }
16 |
17 | public int Quantity { get; private set; }
18 |
19 | public decimal Price { get; private set; }
20 |
21 | public Way Way { get; private set; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Investors/InvestorInstructionStatus.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Investors
23 | {
24 | public enum InvestorInstructionStatus
25 | {
26 | Executed,
27 |
28 | PartiallyExecuted,
29 |
30 | Failed
31 | }
32 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/Feeds/MarketDataUpdatedArgs.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Markets.Feeds
2 | {
3 | using System;
4 | using SimpleOrderRouting.Markets.Orders;
5 |
6 | public class MarketDataUpdatedArgs : EventArgs
7 | {
8 | public MarketDataUpdatedArgs(string marketName, decimal price, int quantity)
9 | {
10 | this.Quantity = quantity;
11 | this.Price = price;
12 | this.MarketName = marketName;
13 | }
14 |
15 | public string MarketName { get; private set; }
16 |
17 | // TODO : introduce the concept of various instruments
18 | public InstrumentIdentifier InstrumentIdentifier { get; private set; }
19 |
20 | public decimal Price { get; private set; }
21 | public int Quantity { get; private set; }
22 | }
23 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/MarketInfo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Markets
22 | {
23 | ///
24 | /// Aggregates information about a given Market (e.g. # of failures, etc.).
25 | ///
26 | public class MarketInfo
27 | {
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | /// Name of the market.
32 | /// The sell quantity.
33 | /// The sell price.
34 | public MarketInfo(string marketName, int sellQuantity, decimal sellPrice)
35 | {
36 | this.MarketName = marketName;
37 | this.SellQuantity = sellQuantity;
38 | this.SellPrice = sellPrice;
39 | }
40 |
41 | public string MarketName { get; private set; }
42 |
43 | public int SellQuantity { get; private set; }
44 |
45 | public decimal SellPrice { get; private set; }
46 |
47 | ///
48 | /// Gets or sets the number of failures for orders we received from this market.
49 | ///
50 | ///
51 | /// The number of failures for orders we received from this market.
52 | ///
53 | public int OrdersFailureCount { get; set; }
54 | }
55 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/MarketSnapshot.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Markets
22 | {
23 | using System.Collections.Generic;
24 |
25 | ///
26 | /// Snapshot of multiple Markets venues.
27 | ///
28 | public class MarketSnapshot
29 | {
30 | public MarketSnapshot(IList marketInfos)
31 | {
32 | this.MarketInfos = marketInfos;
33 | }
34 |
35 | public IList MarketInfos { get; private set; }
36 |
37 | }
38 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/MarketSnapshotProvider.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Markets
22 | {
23 | using System.Collections.Generic;
24 | using System.Linq;
25 |
26 | using SimpleOrderRouting.Markets.Feeds;
27 |
28 | ///
29 | /// Provide instances.
30 | ///
31 | public class MarketSnapshotProvider
32 | {
33 | private readonly Dictionary lastMarketUpdates = new Dictionary();
34 |
35 | public MarketSnapshotProvider(IEnumerable marketNames, ICanReceiveMarketData canReceiveMarketData)
36 | {
37 | canReceiveMarketData.InstrumentMarketDataUpdated += this.InstrumentMarketDataUpdated;
38 | canReceiveMarketData.OrderFailedOnAMarket += this.canReceiveMarketData_OrderFailedOnAMarket;
39 |
40 | foreach (var marketName in marketNames)
41 | {
42 | // TODO : Get rid of the hack (casting to concrete class)
43 | canReceiveMarketData.Subscribe(marketName);
44 | }
45 | }
46 |
47 | void canReceiveMarketData_OrderFailedOnAMarket(object sender, Orders.OrderFailedEventArgs e)
48 | {
49 | this.DeclareFailure(e.MarketName);
50 | }
51 |
52 | private void InstrumentMarketDataUpdated(object sender, MarketDataUpdatedArgs marketDataUpdatedArgs)
53 | {
54 | this.lastMarketUpdates[marketDataUpdatedArgs.MarketName] = new MarketInfo(marketDataUpdatedArgs.MarketName, marketDataUpdatedArgs.Quantity, marketDataUpdatedArgs.Price);
55 | }
56 |
57 | public MarketSnapshot GetSnapshot()
58 | {
59 | return new MarketSnapshot(this.lastMarketUpdates.Values.ToList());
60 | }
61 |
62 | private void DeclareFailure(string marketName)
63 | {
64 | this.lastMarketUpdates.First(m => m.Key == marketName).Value.OrdersFailureCount++;
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/Orders/DealExecutedEventArgs.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 | namespace SimpleOrderRouting.Markets.Orders
17 | {
18 | using System;
19 |
20 | ///
21 | /// Event data for DealExecuted event.
22 | ///
23 | public class DealExecutedEventArgs : EventArgs
24 | {
25 | public DealExecutedEventArgs(decimal price, int quantity)
26 | {
27 | this.Price = price;
28 | this.Quantity = quantity;
29 | }
30 |
31 | public decimal Price { get; private set; }
32 |
33 | public int Quantity { get; private set; }
34 | }
35 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/Orders/InstrumentIdentifier.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Markets.Orders
2 | {
3 | public class InstrumentIdentifier
4 | {
5 | private readonly string instrumentIdentifier;
6 |
7 | public InstrumentIdentifier(string instrumentIdentifier)
8 | {
9 | this.instrumentIdentifier = instrumentIdentifier;
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/Orders/OrderBasket.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Markets.Orders
22 | {
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 |
27 | ///
28 | /// Aggregates multiple instances.
29 | /// OrderBasket is a composite (pattern).
30 | ///
31 | public class OrderBasket : IOrder
32 | {
33 | public List OrdersDescriptions { get; private set; }
34 |
35 | private readonly ICanRouteOrders canRouteOrders;
36 |
37 | ///
38 | /// Initializes a new instance of the class.
39 | ///
40 | /// The orders descriptions.
41 | /// The can route orders.
42 | public OrderBasket(List ordersDescriptions, ICanRouteOrders canRouteOrders)
43 | {
44 | this.OrdersDescriptions = ordersDescriptions;
45 | this.canRouteOrders = canRouteOrders;
46 |
47 | if (ordersDescriptions.Count > 0)
48 | {
49 | this.Way = ordersDescriptions[0].OrderWay;
50 |
51 | foreach (var orderDescription in ordersDescriptions)
52 | {
53 | if (orderDescription.AllowPartialExecution)
54 | {
55 | this.AllowPartialExecution = true;
56 | }
57 |
58 | this.Quantity += orderDescription.Quantity;
59 | }
60 | }
61 | }
62 |
63 | public event EventHandler OrderExecuted;
64 |
65 | public event EventHandler OrderFailed;
66 |
67 | public bool AllowPartialExecution { get; private set; }
68 |
69 | public int Quantity { get; private set; }
70 |
71 | public Way Way { get; private set; }
72 |
73 | // TODO: Change the IOrder interface to always include the notification.
74 | public void Send()
75 | {
76 | var failures = new List(this.OrdersDescriptions.Count);
77 |
78 | foreach (var orderDescription in this.OrdersDescriptions)
79 | {
80 | // TODO: refactor this to prevent this domain object to rely too much on ICanRouterOrders things...
81 | var limitOrder = this.canRouteOrders.CreateLimitOrder(orderDescription);
82 |
83 | EventHandler orderExecuted = (sender, executedEventArgs) => this.OnOrderExecuted(executedEventArgs);
84 | EventHandler orderFailed = (sender, reason) => failures.Add(reason);
85 |
86 | limitOrder.OrderExecuted += orderExecuted;
87 | limitOrder.OrderFailed += orderFailed;
88 |
89 | limitOrder.Send();
90 |
91 | limitOrder.OrderExecuted -= orderExecuted;
92 | limitOrder.OrderFailed -= orderFailed;
93 | }
94 |
95 | if (failures.Count > 0)
96 | {
97 | this.RaiseOrderFailed(failures);
98 | }
99 | }
100 |
101 | private void OnOrderExecuted(DealExecutedEventArgs e)
102 | {
103 | this.RaiseOrderExecuted(e);
104 | }
105 |
106 | private void RaiseOrderFailed(List failures)
107 | {
108 | var onOrderFailed = this.OrderFailed;
109 | if (onOrderFailed != null)
110 | {
111 | onOrderFailed(this, failures.First());
112 | }
113 | }
114 |
115 | private void RaiseOrderExecuted(DealExecutedEventArgs e)
116 | {
117 | var onOrderExecuted = this.OrderExecuted;
118 | if (onOrderExecuted != null)
119 | {
120 | onOrderExecuted(this, e);
121 | }
122 | }
123 | }
124 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/Orders/OrderDescription.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 | namespace SimpleOrderRouting.Markets.Orders
17 | {
18 | ///
19 | /// Caracteristics of an Order to be passed on a market.
20 | ///
21 | public struct OrderDescription
22 | {
23 | // TODO: does OrderDescription need to expose its corresponding order type somehow (i.e. marketorder, limitorder)?
24 |
25 | public string TargetMarketName;
26 |
27 | public Way OrderWay;
28 |
29 | public int Quantity { get; private set; }
30 |
31 | public decimal OrderPrice;
32 |
33 | public bool AllowPartialExecution;
34 |
35 | public OrderDescription(string targetMarketName, Way orderWay, int quantity, decimal orderPrice, bool allowPartialExecution)
36 | : this()
37 | {
38 | this.TargetMarketName = targetMarketName;
39 | this.OrderWay = orderWay;
40 | this.Quantity = quantity;
41 | this.OrderPrice = orderPrice;
42 | this.AllowPartialExecution = allowPartialExecution;
43 | }
44 |
45 | public override string ToString()
46 | {
47 | return string.Format("Order description: TargetMarketName={0} - quantity={1} - Way={2} - Price={3} - AllowPartialExecution={4}.", this.TargetMarketName, this.Quantity, this.OrderWay, this.OrderPrice, this.AllowPartialExecution);
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/Orders/OrderExecutedEventArgs.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 | namespace SimpleOrderRouting.Markets.Orders
17 | {
18 | ///
19 | /// Event data for OrderExecuted event.
20 | ///
21 | public class OrderExecutedEventArgs
22 | {
23 | public OrderExecutedEventArgs(Way way, int quantity, decimal price)
24 | {
25 | this.Quantity = quantity;
26 | this.Price = price;
27 | this.Way = way;
28 | }
29 |
30 | public int Quantity { get; private set; }
31 |
32 | public decimal Price { get; private set; }
33 |
34 | public Way Way { get; private set; }
35 | }
36 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Markets/Orders/OrderFailedEventArgs.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Markets.Orders
22 | {
23 | ///
24 | /// Event data for OrderFailed event.
25 | ///
26 | public class OrderFailedEventArgs
27 | {
28 | public OrderFailedEventArgs(string marketName, string reason)
29 | {
30 | this.Reason = reason;
31 | this.MarketName = marketName;
32 | }
33 |
34 | public string MarketName { get; private set; }
35 |
36 | public string Reason { get; private set; }
37 | }
38 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SimpleOrderRouting.Interfaces")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SimpleOrderRouting.Interfaces")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("2e31b1b3-60a8-422c-ba1d-f404a5e851d3")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/SimpleOrderRouting.Domain.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {4F66C7D2-8CBD-4280-9A2D-6555E276C6A7}
8 | Library
9 | Properties
10 | SimpleOrderRouting
11 | SimpleOrderRouting.Domain
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
77 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/SmartOrderRoutingEngine.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting
22 | {
23 | using System;
24 | using System.Collections.Generic;
25 |
26 | using SimpleOrderRouting.Investors;
27 | using SimpleOrderRouting.Markets;
28 | using SimpleOrderRouting.Markets.Orders;
29 | using SimpleOrderRouting.SolvingStrategies;
30 |
31 | ///
32 | /// Provides access to the various services offered by the external market venues.
33 | /// Manages incoming InvestorInstructions and monitor their lifecycle.
34 | /// Is responsible for the consistency of the open positions (i.e. alive orders) that are present on every markets.
35 | ///
36 | public class SmartOrderRoutingEngine : IHandleInvestorInstructions
37 | {
38 | private readonly ICanRouteOrders routeOrders;
39 | private readonly MarketSnapshotProvider marketSnapshotProvider;
40 |
41 | ///
42 | /// Initializes a new instance of the class.
43 | ///
44 | /// The markets provider.
45 | /// The order routing.
46 | /// The market data provider.
47 | public SmartOrderRoutingEngine(IProvideMarkets marketsProvider, ICanRouteOrders routeOrders, ICanReceiveMarketData marketDataProvider)
48 | {
49 | this.routeOrders = routeOrders;
50 | var availableMarkets = marketsProvider.GetAvailableMarketNames();
51 | this.marketSnapshotProvider = new MarketSnapshotProvider(availableMarkets, marketDataProvider);
52 | }
53 |
54 | public void Route(InvestorInstruction investorInstruction, Action instructionExecutedCallback, Action failureCallback)
55 | {
56 | // Prepares to feedback the investor
57 | var instructionExecutionContext = new InstructionExecutionContext(investorInstruction, instructionExecutedCallback, failureCallback);
58 |
59 | this.routeOrders.OrderExecuted += this.WhenOneOrderIsExecuted(instructionExecutionContext);
60 | this.routeOrders.OrderFailed += this.WhenOneOrderFailed(instructionExecutionContext);
61 |
62 | this.RouteImpl(instructionExecutionContext);
63 |
64 | this.routeOrders.OrderExecuted -= this.WhenOneOrderIsExecuted(instructionExecutionContext);
65 | this.routeOrders.OrderFailed -= this.WhenOneOrderFailed(instructionExecutionContext);
66 | }
67 |
68 | private void RouteImpl(InstructionExecutionContext instructionExecutionContext)
69 | {
70 | // 1. Prepare the corresponding OrderBasket (via solver)
71 | var solver = new MarketSweepSolver(this.marketSnapshotProvider);
72 | var orderBasket = solver.Solve(instructionExecutionContext, this.routeOrders);
73 |
74 | // 2. Route the OrderBasket
75 | this.routeOrders.Route(orderBasket);
76 | }
77 |
78 | private EventHandler WhenOneOrderIsExecuted(InstructionExecutionContext instructionExecutionContext)
79 | {
80 | // TODO: must process the message only if it's related to the proper instruction
81 | return (sender, dealExecuted) => instructionExecutionContext.RecordOrderExecution(dealExecuted.Quantity);
82 | }
83 |
84 | private EventHandler WhenOneOrderFailed(InstructionExecutionContext instructionExecutionContext)
85 | {
86 | // TODO: must process the message only if it's related to the proper instruction
87 | return (sender, orderFailed) => this.OnOrderFailed(orderFailed, instructionExecutionContext);
88 | }
89 |
90 | private void OnOrderFailed(OrderFailedEventArgs reason, InstructionExecutionContext instructionExecutionContext)
91 | {
92 | if (instructionExecutionContext.ShouldTheInstructionBeContinued())
93 | {
94 | this.RetryInvestorInstruction(instructionExecutionContext);
95 | }
96 | else
97 | {
98 | instructionExecutionContext.DeclareFailure(reason);
99 | }
100 | }
101 |
102 | private void RetryInvestorInstruction(InstructionExecutionContext instructionExecutionContext)
103 | {
104 | this.RouteImpl(instructionExecutionContext);
105 | }
106 | }
107 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/SolvingStrategies/MarketSweepSolver.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 | namespace SimpleOrderRouting.SolvingStrategies
17 | {
18 | using System;
19 | using System.Collections.Generic;
20 | using System.Linq;
21 |
22 | using SimpleOrderRouting.Investors;
23 | using SimpleOrderRouting.Markets;
24 | using SimpleOrderRouting.Markets.Orders;
25 |
26 | ///
27 | /// Transforms an into an that
28 | /// will allow us to route following a weight average strategy on
29 | /// the relevant markets.
30 | ///
31 | public class MarketSweepSolver : ISolveInvestorInstructions
32 | {
33 | private const int MaxSupportedFailuresPerMarket = 3;
34 |
35 | private readonly MarketSnapshotProvider marketSnapshotProvider;
36 |
37 | ///
38 | /// Initializes a new instance of the class.
39 | ///
40 | /// The market information.
41 | public MarketSweepSolver(MarketSnapshotProvider marketSnapshotProvider)
42 | {
43 | this.marketSnapshotProvider = marketSnapshotProvider;
44 | }
45 |
46 | ///
47 | /// Build the description of the orders needed to fulfill an which
48 | /// is aggregated within an instance.
49 | ///
50 | /// The instance that aggregates the .
51 | ///
52 | ///
53 | /// An containing all the orders to be routed in order to fulfill the initial .
54 | ///
55 | public OrderBasket Solve(InstructionExecutionContext instructionExecutionContext, ICanRouteOrders canRouteOrders)
56 | {
57 | // Checks liquidities available to weighted average for execution
58 | int remainingQuantityToBeExecuted = instructionExecutionContext.RemainingQuantityToBeExecuted;
59 | decimal requestedPrice = instructionExecutionContext.Price;
60 |
61 | var validMarkets = this.GetValidMarkets(requestedPrice);
62 | int availableQuantityOnMarkets = this.ComputeAvailableQuantityForThisPrice(validMarkets);
63 |
64 | if (availableQuantityOnMarkets == 0)
65 | {
66 | return new OrderBasket(new List(), canRouteOrders);
67 | }
68 |
69 | var ordersDescription = GenerateOrdersDescription(instructionExecutionContext, remainingQuantityToBeExecuted, validMarkets, requestedPrice, availableQuantityOnMarkets);
70 |
71 | return new OrderBasket(ordersDescription, canRouteOrders);
72 | }
73 |
74 | private static List GenerateOrdersDescription(InstructionExecutionContext instructionExecutionContext, int remainingQuantityToBeExecuted, IEnumerable validMarkets, decimal requestedPrice, int availableQuantityOnMarkets)
75 | {
76 | var ordersDescription = new List();
77 |
78 | if (remainingQuantityToBeExecuted == 1)
79 | {
80 | ordersDescription.Add(new OrderDescription(validMarkets.First(m => m.SellQuantity >= 1).MarketName, instructionExecutionContext.Way, remainingQuantityToBeExecuted, requestedPrice, instructionExecutionContext.AllowPartialExecution));
81 | }
82 | else
83 | {
84 | var ratio = remainingQuantityToBeExecuted / (decimal)availableQuantityOnMarkets;
85 |
86 | // ReSharper disable once LoopCanBeConvertedToQuery
87 | foreach (var marketInfo in validMarkets)
88 | {
89 | var convertedMarketQuantity = Math.Round(marketInfo.SellQuantity * ratio, 2, MidpointRounding.AwayFromZero);
90 | var quantityToExecute = Convert.ToInt32(convertedMarketQuantity);
91 |
92 | if (quantityToExecute > 0)
93 | {
94 | ordersDescription.Add(new OrderDescription(marketInfo.MarketName, instructionExecutionContext.Way, quantityToExecute, requestedPrice, instructionExecutionContext.AllowPartialExecution));
95 | }
96 | }
97 | }
98 |
99 | if (ordersDescription.Count <= 0)
100 | {
101 | throw new InvalidOperationException(string.Format("No order description has been created while there is still {0} quantity to be executed (available quantity on the market is {1}).", remainingQuantityToBeExecuted, availableQuantityOnMarkets));
102 | }
103 |
104 | return ordersDescription;
105 | }
106 |
107 | private IEnumerable GetValidMarkets(decimal requestedPrice)
108 | {
109 | var allMarkets = this.marketSnapshotProvider.GetSnapshot();
110 | return allMarkets.MarketInfos.Where(m => m.OrdersFailureCount < MaxSupportedFailuresPerMarket && requestedPrice >= m.SellPrice);
111 | }
112 |
113 | private int ComputeAvailableQuantityForThisPrice(IEnumerable validMarkets)
114 | {
115 | var availableQuantityOnMarkets = 0;
116 |
117 | foreach (var marketInfo in validMarkets)
118 | {
119 | availableQuantityOnMarkets += marketInfo.SellQuantity;
120 | }
121 |
122 | return availableQuantityOnMarkets;
123 | }
124 | }
125 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Domain/Way.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 | namespace SimpleOrderRouting
17 | {
18 | ///
19 | /// Sell or Buy way for Orders.
20 | ///
21 | public enum Way
22 | {
23 | ///
24 | /// The Buy way.
25 | ///
26 | Buy,
27 |
28 | ///
29 | /// The Sell way.
30 | ///
31 | Sell
32 | }
33 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/CompositionRootHelper.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Thomas PIERRAIN (@tpierrain)
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | //
16 | // --------------------------------------------------------------------------------------------------------------------
17 |
18 | namespace SimpleOrderRouting.Infra
19 | {
20 | using OtherTeam.StandardizedMarketGatewayAPI;
21 |
22 | public static class CompositionRootHelper
23 | {
24 | ///
25 | /// Acts like a composition root for the SOR Hexagonal Architecture.
26 | ///
27 | /// The list of ApiMarketGateway the SOR must interact with.
28 | /// The adapter we must use as Investors in order to give investment instructions.
29 | public static InvestorInstructionsAdapter ComposeTheHexagon(params ApiMarketGateway[] marketGateways)
30 | {
31 | // Step1: instantiates the adapter(s) the (SOR) domain will need to work with through the Dependency Inversion principle.
32 | var marketGatewaysAdapter = new MarketsAdapter(marketGateways);
33 |
34 | // Step2: instantiates the SOR domain entry point.
35 | var sor = new SmartOrderRoutingEngine(marketGatewaysAdapter, marketGatewaysAdapter, marketGatewaysAdapter);
36 |
37 | // Step3: instantiates the adapters we will use to interact with our domain.
38 | var investorInstructionAdapter = new InvestorInstructionsAdapter(sor);
39 |
40 | return investorInstructionAdapter;
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Investors/InstructionExecutedDto.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Infra
22 | {
23 | using System;
24 |
25 | ///
26 | /// Event data for InstructionExecuted.
27 | ///
28 | public class InstructionExecutedDto
29 | {
30 | public InstructionExecutedDto(InvestorWay way, decimal price, int quantity)
31 | {
32 | this.Quantity = quantity;
33 | this.Price = price;
34 | this.Way = way;
35 | }
36 |
37 | public int Quantity { get; private set; }
38 |
39 | public decimal Price { get; private set; }
40 |
41 | public InvestorWay Way { get; private set; }
42 |
43 | public override string ToString()
44 | {
45 | return String.Format("Instruction executed: Way: {0} - Quantity: {1} - Price: {2}", this.Way, this.Quantity, this.Price);
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Investors/InstructionFailedDto.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | public class InstructionFailedDto
25 | {
26 | public InstructionFailedDto(string reason)
27 | {
28 | this.Reason = reason;
29 | }
30 |
31 | public string Reason { get; private set; }
32 | }
33 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Investors/InvestorInstructionDto.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | using System;
25 |
26 | ///
27 | /// Data Transfer Object for Investor Instruction.
28 | ///
29 | public class InvestorInstructionDto
30 | {
31 | public InvestorInstructionDto(Way way, int quantity, decimal price, bool allowPartialExecution = false, DateTime? goodTill = null) : this(new InvestorInstructionIdentifierDto(), way, quantity, price, allowPartialExecution, goodTill)
32 | {
33 | }
34 |
35 | public InvestorInstructionDto(InvestorInstructionIdentifierDto uniqueIdentifier, Way way, int quantity, decimal price, bool allowPartialExecution = false, DateTime? goodTill = null)
36 | {
37 | this.UniqueIdentifier = uniqueIdentifier;
38 | this.Way = way;
39 | this.Quantity = quantity;
40 | this.Price = price;
41 | this.AllowPartialExecution = allowPartialExecution;
42 | this.GoodTill = goodTill;
43 | }
44 |
45 | public InvestorInstructionIdentifierDto UniqueIdentifier { get; private set; }
46 |
47 | ///
48 | /// Gets the way to be used for the Instruction (Buy/Sell).
49 | ///
50 | ///
51 | /// The way to be used for the Instruction (Buy/Sell).
52 | ///
53 | public Way Way { get; private set; }
54 |
55 | ///
56 | /// Gets the quantity to be bought or sell.
57 | ///
58 | ///
59 | /// The quantity to be bought or sell.
60 | ///
61 | public int Quantity { get; private set; }
62 |
63 | ///
64 | /// Gets the price we are looking for the execution.
65 | ///
66 | ///
67 | /// The price we are looking for the execution.
68 | ///
69 | public decimal Price { get; private set; }
70 |
71 | public bool AllowPartialExecution { get; private set; }
72 |
73 | public DateTime? GoodTill { get; private set; }
74 |
75 | #region Unicity and Identity
76 |
77 | private bool Equals(InvestorInstructionDto other)
78 | {
79 | return object.Equals(this.UniqueIdentifier, other.UniqueIdentifier) && this.Way == other.Way && this.Quantity == other.Quantity && this.Price == other.Price && this.AllowPartialExecution == other.AllowPartialExecution && this.GoodTill.Equals(other.GoodTill);
80 | }
81 |
82 | public override bool Equals(object obj)
83 | {
84 | if (ReferenceEquals(null, obj))
85 | {
86 | return false;
87 | }
88 |
89 | if (ReferenceEquals(this, obj))
90 | {
91 | return true;
92 | }
93 |
94 | if (obj.GetType() != this.GetType())
95 | {
96 | return false;
97 | }
98 |
99 | return this.Equals((InvestorInstructionDto)obj);
100 | }
101 |
102 | public override int GetHashCode()
103 | {
104 | unchecked
105 | {
106 | var hashCode = (this.UniqueIdentifier != null ? this.UniqueIdentifier.GetHashCode() : 0);
107 | hashCode = (hashCode * 397) ^ (int)this.Way;
108 | hashCode = (hashCode * 397) ^ this.Quantity;
109 | hashCode = (hashCode * 397) ^ this.Price.GetHashCode();
110 | hashCode = (hashCode * 397) ^ this.AllowPartialExecution.GetHashCode();
111 | hashCode = (hashCode * 397) ^ this.GoodTill.GetHashCode();
112 | return hashCode;
113 | }
114 | }
115 |
116 | public static bool operator ==(InvestorInstructionDto left, InvestorInstructionDto right)
117 | {
118 | return object.Equals(left, right);
119 | }
120 |
121 | public static bool operator !=(InvestorInstructionDto left, InvestorInstructionDto right)
122 | {
123 | return !object.Equals(left, right);
124 | }
125 |
126 | #endregion
127 |
128 | public override string ToString()
129 | {
130 | return string.Format("Investor Instruction DTO: Way: {0} - Quantity: {1} - Price: {2} - AllowPartialExecution: {3} - GoodTill: {4}.", this.Way, this.Quantity, this.Price, this.AllowPartialExecution, this.GoodTill);
131 | }
132 | }
133 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Investors/InvestorInstructionDtoCallBacks.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | using System;
25 |
26 | using SimpleOrderRouting.Investors;
27 | using SimpleOrderRouting.Markets.Orders;
28 |
29 | ///
30 | /// Adapts callbacks from the domain model to the InvestorInstruction infra one.
31 | ///
32 | public class InvestorInstructionDtoCallBacks
33 | {
34 | private readonly Action instructionExecutedCallback;
35 |
36 | private readonly Action instructionFailedCallback;
37 |
38 | public InvestorInstructionDtoCallBacks(Action instructionExecutedCallback, Action instructionFailedCallback)
39 | {
40 | this.instructionExecutedCallback = instructionExecutedCallback;
41 | this.instructionFailedCallback = instructionFailedCallback;
42 | }
43 |
44 | public void ExecutedCallback(InvestorInstructionExecutedEventArgs args)
45 | {
46 | // Adapts to the inside (domain) model to the outside one (investor)
47 | var investorWay = (args.Way == Way.Buy) ? InvestorWay.Buy : InvestorWay.Sell;
48 | var instructionExecutedArgs = new InstructionExecutedDto(investorWay, args.Price, args.Quantity);
49 | this.instructionExecutedCallback(instructionExecutedArgs);
50 | }
51 |
52 | public void FailedCallbacks(string reason)
53 | {
54 | // Adapts to the inside (domain) model to the outside one
55 | var instructionFailedArgs = new InstructionFailedDto(reason);
56 | this.instructionFailedCallback(instructionFailedArgs);
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Investors/InvestorInstructionIdentifierDto.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | using System.Threading;
25 |
26 | ///
27 | /// Unique Identifier of an Investor instruction DTO.
28 | ///
29 | public class InvestorInstructionIdentifierDto
30 | {
31 | ///
32 | /// Initializes a new instance of the class.
33 | ///
34 | public InvestorInstructionIdentifierDto()
35 | {
36 | this.Value = Interlocked.Increment(ref nextValue);
37 | }
38 |
39 | private bool Equals(InvestorInstructionIdentifierDto other)
40 | {
41 | return this.Value == other.Value;
42 | }
43 |
44 | public override bool Equals(object obj)
45 | {
46 | if (ReferenceEquals(null, obj))
47 | {
48 | return false;
49 | }
50 |
51 | if (ReferenceEquals(this, obj))
52 | {
53 | return true;
54 | }
55 |
56 | if (obj.GetType() != this.GetType())
57 | {
58 | return false;
59 | }
60 |
61 | return this.Equals((InvestorInstructionIdentifierDto)obj);
62 | }
63 |
64 | public override int GetHashCode()
65 | {
66 | return this.Value.GetHashCode();
67 | }
68 |
69 | public static bool operator ==(InvestorInstructionIdentifierDto left, InvestorInstructionIdentifierDto right)
70 | {
71 | return object.Equals(left, right);
72 | }
73 |
74 | public static bool operator !=(InvestorInstructionIdentifierDto left, InvestorInstructionIdentifierDto right)
75 | {
76 | return !object.Equals(left, right);
77 | }
78 |
79 | private static long nextValue;
80 |
81 | public long Value { get; private set; }
82 | }
83 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Investors/InvestorInstructionUpdatedDto.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | using System;
25 |
26 | using SimpleOrderRouting.Investors;
27 |
28 | ///
29 | /// Data transfer Object to interact with an Investor.
30 | ///
31 | public class InvestorInstructionUpdatedDto : EventArgs
32 | {
33 | public InvestorInstructionUpdatedDto(InvestorInstructionIdentifierDto identifierDto, InvestorInstructionStatus status)
34 | {
35 | this.IdentifierDto = identifierDto;
36 | this.Status = status;
37 | }
38 |
39 | public InvestorInstructionIdentifierDto IdentifierDto { get; set; }
40 |
41 | public InvestorInstructionStatus Status { get; set; }
42 | }
43 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Investors/InvestorInstructionsAdapter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | using System;
25 |
26 | using SimpleOrderRouting.Investors;
27 |
28 | ///
29 | /// External API for the Smart Order Routing service. Aggregates all instruction events.
30 | /// (Hexagonal) Adapter from the infrastructure code to the domain code and vice-versa.
31 | ///
32 | public class InvestorInstructionsAdapter
33 | {
34 | private readonly IHandleInvestorInstructions sor;
35 |
36 | ///
37 | /// Initializes a new instance of the class.
38 | ///
39 | /// The SOR entry point.
40 | public InvestorInstructionsAdapter(IHandleInvestorInstructions sor)
41 | {
42 | this.sor = sor;
43 | }
44 |
45 | // TODO: expose some infra callbacks instead of the domain one
46 | public void Route(InvestorInstructionDto investorInstructionDto, Action instructionExecutedCallback, Action instructionFailedCallback)
47 | {
48 | // Maps the DTO model to the domain one
49 | var investorIntruction = new InvestorInstruction(investorInstructionDto.UniqueIdentifier.Value, investorInstructionDto.Way, investorInstructionDto.Quantity, investorInstructionDto.Price, investorInstructionDto.AllowPartialExecution, investorInstructionDto.GoodTill);
50 | var dtoCallBacks = new InvestorInstructionDtoCallBacks(instructionExecutedCallback, instructionFailedCallback);
51 |
52 | this.sor.Route(investorIntruction, dtoCallBacks.ExecutedCallback, dtoCallBacks.FailedCallbacks);
53 |
54 | // TODO: cleanup the dtoCallback resource
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Investors/Way.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | ///
25 | /// Sell or Buy way for Orders.
26 | ///
27 | public enum InvestorWay
28 | {
29 | ///
30 | /// The Buy way.
31 | ///
32 | Buy,
33 |
34 | ///
35 | /// The Sell way.
36 | ///
37 | Sell
38 | }
39 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Markets/LimitOrderAdapter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | using OtherTeam.StandardizedMarketGatewayAPI;
25 |
26 | ///
27 | /// Adapts LimitOrder between the SOR and the external market gateway models.
28 | ///
29 | public class LimitOrderAdapter : OrderAdapter
30 | {
31 | private readonly ApiLimitOrder apiLimitOrder;
32 |
33 | public LimitOrderAdapter(ApiMarketGateway marketGateway, ApiLimitOrder apiLimitOrder)
34 | : base(marketGateway, apiLimitOrder)
35 | {
36 | this.apiLimitOrder = apiLimitOrder;
37 | }
38 |
39 | public override void Send()
40 | {
41 | this.MarketGateway.Send(this.apiLimitOrder);
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Markets/MarketDataAdapter.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Infra
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | using OtherTeam.StandardizedMarketGatewayAPI;
8 |
9 | using SimpleOrderRouting.Markets.Feeds;
10 |
11 | public sealed class MarketDataAdapter
12 | {
13 | private readonly IReadOnlyDictionary gateways;
14 |
15 | public MarketDataAdapter(IReadOnlyDictionary gateways)
16 | {
17 | this.gateways = gateways;
18 | foreach (var marketGateway in this.gateways.Values)
19 | {
20 | marketGateway.MarketDataUpdated += marketGateway_MarketDataUpdated;
21 | }
22 | }
23 |
24 | void marketGateway_MarketDataUpdated(object sender, ApiMarketDataUpdateEventArgs args)
25 | {
26 | // Adapts the external API feed format to the SOR domain format
27 | var marketDataUpdatedArgs = new MarketDataUpdatedArgs(args.OriginMarketName, args.MarketPrice, args.QuantityOnTheMarket);
28 | this.RaiseMarketDataUpdate(marketDataUpdatedArgs);
29 | }
30 |
31 | public event EventHandler InstrumentMarketDataUpdated;
32 |
33 | public void Subscribe(string marketName)
34 | {
35 | var internalMarket = this.gateways.First(m => m.Key == marketName).Value;
36 |
37 | // Raise the first event
38 | var marketDataUpdatedArgs = new MarketDataUpdatedArgs(internalMarket.MarketName, internalMarket.SellPrice, internalMarket.SellQuantity);
39 |
40 | this.RaiseMarketDataUpdate(marketDataUpdatedArgs);
41 | }
42 |
43 | private void RaiseMarketDataUpdate(MarketDataUpdatedArgs args)
44 | {
45 | var onInstrumentMarketDataUpdated = this.InstrumentMarketDataUpdated;
46 | if (onInstrumentMarketDataUpdated != null)
47 | {
48 | onInstrumentMarketDataUpdated(this, args);
49 | }
50 | }
51 |
52 | }
53 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Markets/MarketOrderAdapter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | using OtherTeam.StandardizedMarketGatewayAPI;
25 |
26 | ///
27 | /// Adapts MarketOrder between the SOR and the external market gateway models.
28 | ///
29 | public class MarketOrderAdapter : OrderAdapter
30 | {
31 | private readonly ApiMarketOrder apiMarketOrder;
32 |
33 | public MarketOrderAdapter(ApiMarketGateway marketGateway, ApiMarketOrder apiMarketOrder)
34 | : base(marketGateway, apiMarketOrder)
35 | {
36 | this.apiMarketOrder = apiMarketOrder;
37 | }
38 |
39 | public override void Send()
40 | {
41 | this.MarketGateway.Send(this.apiMarketOrder);
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Markets/OrderAdapter.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Infra
23 | {
24 | using System;
25 |
26 | using OtherTeam.StandardizedMarketGatewayAPI;
27 |
28 | using SimpleOrderRouting.Markets.Orders;
29 |
30 | ///
31 | /// Base class for the and the .
32 | ///
33 | public abstract class OrderAdapter : IOrder
34 | {
35 | protected readonly ApiMarketGateway MarketGateway;
36 |
37 | private readonly ApiOrder apiOrder;
38 |
39 | protected OrderAdapter(ApiMarketGateway marketGateway, ApiOrder apiOrder)
40 | {
41 | this.apiOrder = apiOrder;
42 | this.MarketGateway = marketGateway;
43 | }
44 |
45 | public event EventHandler OrderExecuted;
46 |
47 | public event EventHandler OrderFailed;
48 |
49 | public Way Way
50 | {
51 | get
52 | {
53 | return (this.apiOrder.Way == ApiMarketWay.Sell) ? Way.Sell : Way.Buy;
54 | }
55 | }
56 |
57 | public int Quantity
58 | {
59 | get
60 | {
61 | return this.apiOrder.Quantity;
62 | }
63 | }
64 |
65 | public bool AllowPartialExecution
66 | {
67 | get
68 | {
69 | return false;
70 | }
71 | }
72 |
73 | public abstract void Send();
74 | }
75 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Markets/OrderRoutingAdapter.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Infra
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | using OtherTeam.StandardizedMarketGatewayAPI;
7 |
8 | using SimpleOrderRouting.Markets.Orders;
9 |
10 | public sealed class OrderRoutingAdapter : ICanRouteOrders
11 | {
12 | private IReadOnlyDictionary gateways;
13 |
14 | public OrderRoutingAdapter(IReadOnlyDictionary gateways)
15 | {
16 | this.gateways = gateways;
17 | }
18 |
19 | public event EventHandler OrderExecuted;
20 |
21 | public event EventHandler OrderFailed;
22 |
23 |
24 | public IOrder CreateMarketOrder(OrderDescription orderDescription)
25 | {
26 | // Adapts from the SOR model to the external market gateway one
27 | var marketGateway = this.gateways[orderDescription.TargetMarketName];
28 |
29 | ApiMarketWay apiMarketWay = (orderDescription.OrderWay == Way.Sell) ? ApiMarketWay.Sell : ApiMarketWay.Buy;
30 | ApiMarketOrder apiMarketOrder = marketGateway.CreateMarketOrder(apiMarketWay, orderDescription.Quantity);
31 |
32 | return new MarketOrderAdapter(marketGateway, apiMarketOrder);
33 | }
34 |
35 | public IOrder CreateLimitOrder(OrderDescription orderDescription)
36 | {
37 | var marketGateway = this.gateways[orderDescription.TargetMarketName];
38 | ApiMarketWay apiMarketWay = (orderDescription.OrderWay == Way.Sell) ? ApiMarketWay.Sell : ApiMarketWay.Buy;
39 | ApiLimitOrder apiLimitOrder = marketGateway.CreateLimitOrder(apiMarketWay, orderDescription.Quantity, orderDescription.OrderPrice, orderDescription.AllowPartialExecution);
40 |
41 | return new LimitOrderAdapter(marketGateway, apiLimitOrder);
42 | }
43 |
44 | public void Route(OrderBasket basketOrder)
45 | {
46 | basketOrder.Send();
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 |
17 | using System.Reflection;
18 | using System.Runtime.InteropServices;
19 |
20 | // General Information about an assembly is controlled through the following
21 | // set of attributes. Change these attribute values to modify the information
22 | // associated with an assembly.
23 | [assembly: AssemblyTitle("SimpleOrderRouter")]
24 | [assembly: AssemblyDescription("")]
25 | [assembly: AssemblyConfiguration("")]
26 | [assembly: AssemblyCompany("")]
27 | [assembly: AssemblyProduct("SimpleOrderRouter")]
28 | [assembly: AssemblyCopyright("Copyright © 2014")]
29 | [assembly: AssemblyTrademark("")]
30 | [assembly: AssemblyCulture("")]
31 |
32 | // Setting ComVisible to false makes the types in this assembly not visible
33 | // to COM components. If you need to access a type in this assembly from
34 | // COM, set the ComVisible attribute to true on that type.
35 | [assembly: ComVisible(false)]
36 |
37 | // The following GUID is for the ID of the typelib if this project is exposed to COM
38 | [assembly: Guid("b040dd8e-8cb3-42c3-a546-5e9501781325")]
39 |
40 | // Version information for an assembly consists of the following four values:
41 | //
42 | // Major Version
43 | // Minor Version
44 | // Build Number
45 | // Revision
46 | //
47 | // You can specify all the values or you can default the Build and Revision Numbers
48 | // by using the '*' as shown below:
49 | // [assembly: AssemblyVersion("1.0.*")]
50 | [assembly: AssemblyVersion("1.0.0.0")]
51 | [assembly: AssemblyFileVersion("1.0.0.0")]
52 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/Settings.StyleCop:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | awaitable
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | True
13 |
14 |
15 |
16 |
17 | True
18 |
19 |
20 |
21 |
22 | True
23 |
24 |
25 |
26 |
27 | True
28 |
29 |
30 |
31 |
32 | True
33 |
34 |
35 |
36 |
37 | True
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/SimpleOrderRouting.Infra.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {00DD3731-E815-4770-BE17-4F17BFEC4171}
8 | Library
9 | Properties
10 | SimpleOrderRouting.Infra
11 | SimpleOrderRouting.Infra
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | {fe2d8118-afd3-4005-a6d5-c1d240dad3e4}
63 | OtherTeam.StandardizedMarketGatewayAPI
64 |
65 |
66 | {4F66C7D2-8CBD-4280-9A2D-6555E276C6A7}
67 | SimpleOrderRouting.Domain
68 |
69 |
70 |
71 |
78 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Infra/SimpleOrderRouting.Infra.csproj.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | True
3 | True
4 | True
5 | True
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/Infra/ApiMarketGatewayTests.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 | namespace SimpleOrderRouting.Tests.Infra
22 | {
23 | using NFluent;
24 |
25 | using NUnit.Framework;
26 |
27 | using OtherTeam.StandardizedMarketGatewayAPI;
28 |
29 | public class ApiMarketGatewayTests
30 | {
31 | [Test]
32 | public void Should_decrease_available_quantity_for_the_market_when_an_order_is_sent()
33 | {
34 | var marketGateway = new ApiMarketGateway(marketName: "euronext", sellQuantity: 50, sellPrice: 100M);
35 |
36 | var order = marketGateway.CreateMarketOrder(ApiMarketWay.Buy, quantity: 10);
37 | marketGateway.Send(order);
38 |
39 | Check.That(marketGateway.SellQuantity).IsEqualTo(40);
40 | }
41 |
42 | [Test]
43 | public void Should_failed_to_execute_order_when_quantity_is_excessive()
44 | {
45 | var marketGateway = new ApiMarketGateway(marketName: "euronext", sellQuantity: 50, sellPrice: 100M);
46 |
47 | var order = marketGateway.CreateMarketOrder(ApiMarketWay.Buy, quantity: 100);
48 |
49 | bool failed = false;
50 | string failureReason = null;
51 |
52 | marketGateway.OrderFailed += (s, failedEventArgs) =>
53 | {
54 | failed = true;
55 | failureReason = failedEventArgs.FailureCause;
56 | };
57 |
58 | marketGateway.Send(order);
59 |
60 | Check.That(failed).IsTrue();
61 | Check.That(failureReason).IsEqualTo("Excessive quantity!");
62 | }
63 |
64 | [Test]
65 | public void Should_Notify_MarketOrder_execution()
66 | {
67 | var marketGateway = new ApiMarketGateway(marketName: "euronext", sellQuantity: 50, sellPrice: 100M);
68 |
69 | var executed = false;
70 | var order = marketGateway.CreateMarketOrder(ApiMarketWay.Buy, quantity: 10);
71 |
72 | marketGateway.OrderExecuted += (s, a) => executed = true;
73 | marketGateway.Send(order);
74 |
75 | Check.That(executed).IsTrue();
76 | Check.That(marketGateway.SellQuantity).IsEqualTo(40);
77 | }
78 |
79 | [Test]
80 | public void Should_Notify_LimitOrder_execution()
81 | {
82 | var marketGateway = new ApiMarketGateway(marketName: "euronext", sellQuantity: 50, sellPrice: 100M);
83 |
84 | var executed = false;
85 | var order = marketGateway.CreateLimitOrder(ApiMarketWay.Buy, price: 100M, quantity: 10, allowPartial: false);
86 |
87 | marketGateway.OrderExecuted += (s, a) => executed = true;
88 | marketGateway.Send(order);
89 |
90 | Check.That(executed).IsTrue();
91 | Check.That(marketGateway.SellQuantity).IsEqualTo(40);
92 | }
93 |
94 | [Test]
95 | public void Should_not_execute_LimitOrder_when_price_is_too_high()
96 | {
97 | var marketGateway = new ApiMarketGateway(marketName: "euronext", sellQuantity: 50, sellPrice: 100M);
98 |
99 | var executed = false;
100 | bool failed = false;
101 | string failureReason = null;
102 | var order = marketGateway.CreateLimitOrder(ApiMarketWay.Buy, price: 101M, quantity: 10, allowPartial: false);
103 |
104 | marketGateway.OrderExecuted += (s, a) => executed = true;
105 | marketGateway.OrderFailed += (s, failedEventArgs) =>
106 | {
107 | failed = true;
108 | failureReason = failedEventArgs.FailureCause;
109 | };
110 | marketGateway.Send(order);
111 |
112 | Check.That(executed).IsFalse();
113 | Check.That(failed).IsTrue();
114 | Check.That(failureReason).IsEqualTo("Invalid price");
115 | Check.That(marketGateway.SellQuantity).IsEqualTo(50);
116 | }
117 |
118 | [Test]
119 | public void Should_support_partial_execution_for_LimitOrder()
120 | {
121 | var marketGateway = new ApiMarketGateway(marketName: "euronext", sellQuantity: 50, sellPrice: 100M);
122 |
123 | var executed = false;
124 | var order = marketGateway.CreateLimitOrder(ApiMarketWay.Buy, price: 100M, quantity: 110, allowPartial: true);
125 |
126 | var execQuantity = 0;
127 | marketGateway.OrderExecuted += (s, a) =>
128 | {
129 | executed = true;
130 | execQuantity = a.Quantity;
131 | };
132 | marketGateway.Send(order);
133 |
134 | Check.That(execQuantity).IsEqualTo(50);
135 | Check.That(executed).IsTrue();
136 | Check.That(marketGateway.SellQuantity).IsEqualTo(0);
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/Infra/HarnessTests.cs:
--------------------------------------------------------------------------------
1 | //// --------------------------------------------------------------------------------------------------------------------
2 | ////
3 | //// Copyright 2014 The Lunch-Box mob:
4 | //// Ozgur DEVELIOGLU (@Zgurrr)
5 | //// Cyrille DUPUYDAUBY (@Cyrdup)
6 | //// Tomasz JASKULA (@tjaskula)
7 | //// Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | //// Thomas PIERRAIN (@tpierrain)
9 | ////
10 | //// Licensed under the Apache License, Version 2.0 (the "License");
11 | //// you may not use this file except in compliance with the License.
12 | //// You may obtain a copy of the License at
13 | //// http://www.apache.org/licenses/LICENSE-2.0
14 | //// Unless required by applicable law or agreed to in writing, software
15 | //// distributed under the License is distributed on an "AS IS" BASIS,
16 | //// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | //// See the License for the specific language governing permissions and
18 | //// limitations under the License.
19 | ////
20 | //// --------------------------------------------------------------------------------------------------------------------
21 | //namespace SimpleOrderRouting.Tests
22 | //{
23 | // using NFluent;
24 | // using Xunit;
25 |
26 | // public class HarnessTests
27 | // {
28 | // [Fact]
29 | // public void Should_return_a_latency()
30 | // {
31 | // var runner = new SorTestHarness();
32 | // runner.Run();
33 |
34 | // Check.That(runner.AverageLatency).Not.IsNegative();
35 | // }
36 |
37 | // }
38 | //}
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/Infra/InvestorInstructionDtoTests.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Tests.Infra
23 | {
24 | using System;
25 | using System.Collections.Generic;
26 |
27 | using NFluent;
28 |
29 | using NUnit.Framework;
30 |
31 | using SimpleOrderRouting.Infra;
32 | using SimpleOrderRouting.Investors;
33 |
34 | public class InvestorInstructionDtoTests
35 | {
36 | [Test]
37 | public void Should_rely_on_values_for_equality()
38 | {
39 | var investorInstructionIdentifier = 42;
40 | const Way Way = Way.Buy;
41 | var quantity = 1;
42 | var price = 23.3M;
43 | var allowPartialExecution = true;
44 | var goodTill = DateTime.Now;
45 |
46 | var dtoIdentifier = new InvestorInstructionIdentifierDto();
47 | var firstInstruction = new InvestorInstructionDto(dtoIdentifier, Way, quantity, price, allowPartialExecution, goodTill);
48 | var secondIdenticalInstruction = new InvestorInstructionDto(dtoIdentifier, Way, quantity, price, allowPartialExecution, goodTill);
49 |
50 | Check.That(firstInstruction).IsEqualTo(secondIdenticalInstruction);
51 |
52 | allowPartialExecution = false;
53 | var slightlyDifferentInstruction = new InvestorInstruction(investorInstructionIdentifier, Way, quantity, price, allowPartialExecution, goodTill);
54 | Check.That(slightlyDifferentInstruction).IsNotEqualTo(firstInstruction);
55 | }
56 |
57 | [Test]
58 | public void Should_rely_on_values_for_unicity()
59 | {
60 | var goodTill = DateTime.Now;
61 | var dtoIdentifier = new InvestorInstructionIdentifierDto();
62 |
63 | var instruction = new InvestorInstructionDto(dtoIdentifier, Way.Buy, 1, 1.1M, true, goodTill);
64 | var identicalInstruction = new InvestorInstructionDto(dtoIdentifier, Way.Buy, 1, 1.1M, true, goodTill);
65 | var dictionary = new Dictionary();
66 | dictionary[instruction] = 2;
67 | dictionary[identicalInstruction] = 3;
68 |
69 | Check.That(dictionary[instruction]).IsEqualTo(3);
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/Infra/SorTestHarness.cs:
--------------------------------------------------------------------------------
1 | //// --------------------------------------------------------------------------------------------------------------------
2 | ////
3 | //// Copyright 2014 The Lunch-Box mob:
4 | //// Ozgur DEVELIOGLU (@Zgurrr)
5 | //// Cyrille DUPUYDAUBY (@Cyrdup)
6 | //// Tomasz JASKULA (@tjaskula)
7 | //// Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | //// Thomas PIERRAIN (@tpierrain)
9 | ////
10 | //// Licensed under the Apache License, Version 2.0 (the "License");
11 | //// you may not use this file except in compliance with the License.
12 | //// You may obtain a copy of the License at
13 | //// http://www.apache.org/licenses/LICENSE-2.0
14 | //// Unless required by applicable law or agreed to in writing, software
15 | //// distributed under the License is distributed on an "AS IS" BASIS,
16 | //// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | //// See the License for the specific language governing permissions and
18 | //// limitations under the License.
19 | ////
20 | //// --------------------------------------------------------------------------------------------------------------------
21 | //namespace SimpleOrderRouting.Tests
22 | //{
23 | // using System.Collections.Generic;
24 | // using System.Diagnostics;
25 | // using System.Threading;
26 |
27 | // using SimpleOrderRouting.Infra;
28 | // using SimpleOrderRouting.Investors;
29 | // using SimpleOrderRouting.Markets;
30 | // using SimpleOrderRouting.Markets.Orders;
31 | // using SimpleOrderRouting.Tests.TestHelpers;
32 |
33 | // public class SorTestHarness
34 | // {
35 | // private InvestorInstructionDto investorInstructionDto;
36 |
37 | // private readonly object synchro = new object();
38 |
39 | // private bool done = false;
40 |
41 | // private InvestorInstructionIdentifierDto instructionIdentifier;
42 |
43 | // public void Run()
44 | // {
45 | // // Build our hexagon (3 steps)
46 |
47 | // // 1. Builds the runtime dependencies needed for our domain to work with (through DIP)
48 | // var markets = BuildMarketVenues();
49 | // var marketDataProvider = new MarketDataProvider(markets);
50 | // var marketProvider = new MarketProvider(markets);
51 |
52 | // // 2. Instantiates our domain entry point with its runtime dependencies
53 | // var sor = new SmartOrderRoutingEngine(marketProvider, null, marketDataProvider);
54 |
55 | // // 3. Instantiates the adapter(s) we will use to interact with our domain
56 | // var instructionsAdapter = new InvestorInstructionsAdapter(sor);
57 |
58 | // // Prepare the adapter to do some work
59 | // instructionsAdapter.InstructionUpdated += this.ServiceOnInstructionUpdated;
60 | // var identifier = InvestorInstructionIdentifierFactory.RequestUniqueIdentifier();
61 | // this.instructionIdentifier = identifier; //adapter.RequestUniqueIdentifier();
62 |
63 | // // build demo order
64 | // this.investorInstructionDto = new InvestorInstructionDto(identifier, Way.Buy, 10, 100M, true, null);
65 |
66 | // var stopWatch = new Stopwatch();
67 |
68 | // // sends the instruction
69 | // stopWatch.Start();
70 | // // Subscribes to the instruction's events
71 | // OrderExecutedEventArgs orderExecutedEventArgs = null;
72 | // string failureReason = null;
73 | // instructionsAdapter.Route(this.investorInstructionDto, (args) => { orderExecutedEventArgs = args; }, (args) => { failureReason = args; });
74 | // instructionsAdapter.Route(this.investorInstructionDto);
75 |
76 | // // wait for the exit condition
77 | // lock (this.synchro)
78 | // {
79 | // if (this.done == false)
80 | // {
81 | // Monitor.Wait(this.synchro, 500);
82 | // }
83 | // }
84 |
85 | // stopWatch.Stop();
86 |
87 | // if (this.done)
88 | // {
89 | // this.AverageLatency = stopWatch.ElapsedMilliseconds;
90 | // }
91 |
92 | // }
93 |
94 | // private void ServiceOnInstructionUpdated(object sender, InvestorInstructionUpdatedDto investorInstructionUpdatedDto)
95 | // {
96 | // if (investorInstructionUpdatedDto.IdentifierDto == this.instructionIdentifier)
97 | // {
98 | // if (investorInstructionUpdatedDto.Status == InvestorInstructionStatus.PartiallyExecuted)
99 | // {
100 | // return;
101 | // }
102 | // lock (this.synchro)
103 | // {
104 | // this.done = true;
105 | // Monitor.PulseAll(this.synchro);
106 | // }
107 | // }
108 | // }
109 |
110 | // private static IEnumerable BuildMarketVenues()
111 | // {
112 | // var marketA = new Market
113 | // {
114 | // SellQuantity = 150,
115 | // SellPrice = 100M,
116 | // };
117 |
118 | // var marketB = new Market
119 | // {
120 | // SellQuantity = 55,
121 | // SellPrice = 101M,
122 | // };
123 |
124 | // var markets = new[] { marketA, marketB };
125 | // return markets;
126 | // }
127 |
128 | // public double AverageLatency { get; set; }
129 | // }
130 | //}
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/InvestorInstructionTests.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Tests
23 | {
24 | using System;
25 | using System.Collections.Generic;
26 |
27 | using NFluent;
28 |
29 | using NUnit.Framework;
30 |
31 | using SimpleOrderRouting.Investors;
32 |
33 | public class InvestorInstructionTests
34 | {
35 | [Test]
36 | public void Should_rely_on_values_for_equality()
37 | {
38 | var investorInstructionIdentifier = 42;
39 | const Way Way = Way.Buy;
40 | const int quantity = 1;
41 | var price = 23.3M;
42 | var allowPartialExecution = true;
43 | var goodTill = DateTime.Now;
44 |
45 | var firstInstruction = new InvestorInstruction(investorInstructionIdentifier, Way, quantity, price, allowPartialExecution, goodTill);
46 | var secondIdenticalInstruction = new InvestorInstruction(investorInstructionIdentifier, Way, quantity, price, allowPartialExecution, goodTill);
47 |
48 | Check.That(firstInstruction).IsEqualTo(secondIdenticalInstruction);
49 |
50 | allowPartialExecution = false;
51 | var slightlyDifferentInstruction = new InvestorInstruction(investorInstructionIdentifier, Way, quantity, price, allowPartialExecution, goodTill);
52 | Check.That(slightlyDifferentInstruction).IsNotEqualTo(firstInstruction);
53 | }
54 |
55 | [Test]
56 | public void Should_rely_on_values_for_unicity()
57 | {
58 | var goodTill = DateTime.Now;
59 | var instruction = new InvestorInstruction(1, Way.Buy, 1, 1.1M, true, goodTill);
60 | var identicalInstruction = new InvestorInstruction(1, Way.Buy, 1, 1.1M, true, goodTill);
61 | var dictionary = new Dictionary();
62 | dictionary[instruction] = 2;
63 | dictionary[identicalInstruction] = 3;
64 |
65 | Check.That(dictionary[instruction]).IsEqualTo(3);
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/MarketSweepSolverTests.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Tests
23 | {
24 | using System;
25 |
26 | using NFluent;
27 |
28 | using NUnit.Framework;
29 |
30 | using OtherTeam.StandardizedMarketGatewayAPI;
31 |
32 | using SimpleOrderRouting.Infra;
33 | using SimpleOrderRouting.Investors;
34 | using SimpleOrderRouting.Markets;
35 | using SimpleOrderRouting.SolvingStrategies;
36 |
37 | public class MarketSweepSolverTests
38 | {
39 | [Test]
40 | public void Should_Solve_with_2_markets_when_asked_quantity_is_odd()
41 | {
42 | var marketA = new ApiMarketGateway("NYSE (New York)", sellQuantity: 50, sellPrice: 100M);
43 | var rejectingMarket = new ApiMarketGateway("CME (Chicago)", sellQuantity: 50, sellPrice: 100M, orderPredicate: _ => false);
44 | var marketsInvolved = new[] { marketA, rejectingMarket };
45 | var marketGatewayAdapter = new MarketsAdapter(marketsInvolved);
46 |
47 | var investorInstruction = new InvestorInstruction(new InvestorInstructionIdentifierDto().Value, Way.Buy, quantity: 50, price: 100M, goodTill: DateTime.Now.AddMinutes(5));
48 | var instructionExecutionContext = new InstructionExecutionContext(investorInstruction, args => {}, failure => {});
49 |
50 | var marketSweepSolver = new MarketSweepSolver(new MarketSnapshotProvider(marketGatewayAdapter.GetAvailableMarketNames(), marketGatewayAdapter));
51 | var orderBasket = marketSweepSolver.Solve(instructionExecutionContext, marketGatewayAdapter);
52 |
53 | Check.That(orderBasket.OrdersDescriptions.Extracting("Quantity")).ContainsExactly(25, 25);
54 | }
55 |
56 | [Test]
57 | public void Should_Solve_with_2_markets_when_asked_quantity_is_1()
58 | {
59 | var marketA = new ApiMarketGateway("NYSE (New York)", sellQuantity: 50, sellPrice: 100M);
60 | var rejectingMarket = new ApiMarketGateway("CME (Chicago)", sellQuantity: 50, sellPrice: 100M, orderPredicate: _ => false);
61 | var marketsInvolved = new[] { marketA, rejectingMarket };
62 | var marketGatewayAdapter = new MarketsAdapter(marketsInvolved);
63 |
64 | var investorInstruction = new InvestorInstruction(new InvestorInstructionIdentifierDto().Value, Way.Buy, quantity: 1, price: 100M, goodTill: DateTime.Now.AddMinutes(5));
65 | var instructionExecutionContext = new InstructionExecutionContext(investorInstruction, args => { }, failure => { });
66 |
67 | var marketSweepSolver = new MarketSweepSolver(new MarketSnapshotProvider(marketGatewayAdapter.GetAvailableMarketNames(), marketGatewayAdapter));
68 | var orderBasket = marketSweepSolver.Solve(instructionExecutionContext, marketGatewayAdapter);
69 |
70 | Check.That(orderBasket.OrdersDescriptions.Extracting("Quantity")).ContainsExactly(1);
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob: Ozgur DEVELIOGLU (@Zgurrr), Cyrille DUPUYDAUBY
4 | // (@Cyrdup), Tomasz JASKULA (@tjaskula), Thomas PIERRAIN (@tpierrain)
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // --------------------------------------------------------------------------------------------------------------------
16 |
17 | using System.Reflection;
18 | using System.Runtime.InteropServices;
19 |
20 | // General Information about an assembly is controlled through the following
21 | // set of attributes. Change these attribute values to modify the information
22 | // associated with an assembly.
23 | [assembly: AssemblyTitle("SimpleOrderRouter.Tests")]
24 | [assembly: AssemblyDescription("")]
25 | [assembly: AssemblyConfiguration("")]
26 | [assembly: AssemblyCompany("")]
27 | [assembly: AssemblyProduct("SimpleOrderRouter.Tests")]
28 | [assembly: AssemblyCopyright("Copyright © 2014")]
29 | [assembly: AssemblyTrademark("")]
30 | [assembly: AssemblyCulture("")]
31 |
32 | // Setting ComVisible to false makes the types in this assembly not visible
33 | // to COM components. If you need to access a type in this assembly from
34 | // COM, set the ComVisible attribute to true on that type.
35 | [assembly: ComVisible(false)]
36 |
37 | // The following GUID is for the ID of the typelib if this project is exposed to COM
38 | [assembly: Guid("f3230376-e78f-4d20-aa05-dfd71f79e272")]
39 |
40 | // Version information for an assembly consists of the following four values:
41 | //
42 | // Major Version
43 | // Minor Version
44 | // Build Number
45 | // Revision
46 | //
47 | // You can specify all the values or you can default the Build and Revision Numbers
48 | // by using the '*' as shown below:
49 | // [assembly: AssemblyVersion("1.0.*")]
50 | [assembly: AssemblyVersion("1.0.0.0")]
51 | [assembly: AssemblyFileVersion("1.0.0.0")]
52 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/Settings.StyleCop:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | False
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | True
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/SimpleOrderRouting.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7F099472-E44E-4252-BBB8-633BF48EECBB}
8 | Library
9 | Properties
10 | SimpleOrderRouting.Tests
11 | SimpleOrderRouting.Tests
12 | v4.5
13 | 512
14 | ..\
15 | true
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\packages\NFluent.1.3.1.0\lib\net40\NFluent.dll
37 |
38 |
39 | ..\packages\NSubstitute.1.7.2.0\lib\NET45\NSubstitute.dll
40 |
41 |
42 | ..\packages\NUnit.3.2.1\lib\net45\nunit.framework.dll
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | {fe2d8118-afd3-4005-a6d5-c1d240dad3e4}
69 | OtherTeam.StandardizedMarketGatewayAPI
70 |
71 |
72 | {4F66C7D2-8CBD-4280-9A2D-6555E276C6A7}
73 | SimpleOrderRouting.Domain
74 |
75 |
76 | {00dd3731-e815-4770-be17-4f17bfec4171}
77 | SimpleOrderRouting.Infra
78 |
79 |
80 |
81 |
82 |
83 |
84 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
85 |
86 |
87 |
88 |
95 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleOrderRouting.Infra", "SimpleOrderRouting.Infra\SimpleOrderRouting.Infra.csproj", "{00DD3731-E815-4770-BE17-4F17BFEC4171}"
5 | EndProject
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AE7BEF9F-3190-4A0C-AF57-F9B3E844FC01}"
7 | ProjectSection(SolutionItems) = preProject
8 | ..\Backlog.md = ..\Backlog.md
9 | DoD.md = DoD.md
10 | LICENSE.txt = LICENSE.txt
11 | ..\Readme.md = ..\Readme.md
12 | Settings.StyleCop = Settings.StyleCop
13 | EndProjectSection
14 | EndProject
15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleOrderRouting.Tests", "SimpleOrderRouting.Tests\SimpleOrderRouting.Tests.csproj", "{7F099472-E44E-4252-BBB8-633BF48EECBB}"
16 | EndProject
17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{F7A88DF0-5710-4A1C-9F9B-3D1C36D60186}"
18 | ProjectSection(SolutionItems) = preProject
19 | .nuget\NuGet.Config = .nuget\NuGet.Config
20 | .nuget\NuGet.exe = .nuget\NuGet.exe
21 | .nuget\NuGet.targets = .nuget\NuGet.targets
22 | EndProjectSection
23 | EndProject
24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleOrderRouting.Domain", "SimpleOrderRouting.Domain\SimpleOrderRouting.Domain.csproj", "{4F66C7D2-8CBD-4280-9A2D-6555E276C6A7}"
25 | EndProject
26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherTeam.StandardizedMarketGatewayAPI", "OtherTeam.StandardizedMarketGatewayAPI\OtherTeam.StandardizedMarketGatewayAPI.csproj", "{FE2D8118-AFD3-4005-A6D5-C1D240DAD3E4}"
27 | EndProject
28 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleOrderRouting.Console", "SimpleOrderRouting.Console\SimpleOrderRouting.Console.csproj", "{F20EBD6E-C774-4856-91D5-1BA43005513D}"
29 | EndProject
30 | Global
31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
32 | Debug|Any CPU = Debug|Any CPU
33 | Release|Any CPU = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
36 | {00DD3731-E815-4770-BE17-4F17BFEC4171}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {00DD3731-E815-4770-BE17-4F17BFEC4171}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {00DD3731-E815-4770-BE17-4F17BFEC4171}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {00DD3731-E815-4770-BE17-4F17BFEC4171}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {7F099472-E44E-4252-BBB8-633BF48EECBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {7F099472-E44E-4252-BBB8-633BF48EECBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {7F099472-E44E-4252-BBB8-633BF48EECBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {7F099472-E44E-4252-BBB8-633BF48EECBB}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {4F66C7D2-8CBD-4280-9A2D-6555E276C6A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {4F66C7D2-8CBD-4280-9A2D-6555E276C6A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {4F66C7D2-8CBD-4280-9A2D-6555E276C6A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {4F66C7D2-8CBD-4280-9A2D-6555E276C6A7}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {FE2D8118-AFD3-4005-A6D5-C1D240DAD3E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {FE2D8118-AFD3-4005-A6D5-C1D240DAD3E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {FE2D8118-AFD3-4005-A6D5-C1D240DAD3E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {FE2D8118-AFD3-4005-A6D5-C1D240DAD3E4}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {F20EBD6E-C774-4856-91D5-1BA43005513D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {F20EBD6E-C774-4856-91D5-1BA43005513D}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {F20EBD6E-C774-4856-91D5-1BA43005513D}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {F20EBD6E-C774-4856-91D5-1BA43005513D}.Release|Any CPU.Build.0 = Release|Any CPU
56 | EndGlobalSection
57 | GlobalSection(SolutionProperties) = preSolution
58 | HideSolutionNode = FALSE
59 | EndGlobalSection
60 | EndGlobal
61 |
--------------------------------------------------------------------------------
/CSharp/SimpleOrderRouting.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | --------------------------------------------------------------------------------------------------------------------
3 | <copyright file="$FILENAME$" company="LunchBox corp">
4 | Copyright 2014 The Lunch-Box mob:
5 | Ozgur DEVELIOGLU (@Zgurrr)
6 | Cyrille DUPUYDAUBY (@Cyrdup)
7 | Tomasz JASKULA (@tjaskula)
8 | Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
9 | Thomas PIERRAIN (@tpierrain)
10 |
11 | Licensed under the Apache License, Version 2.0 (the "License");
12 | you may not use this file except in compliance with the License.
13 | You may obtain a copy of the License at
14 | http://www.apache.org/licenses/LICENSE-2.0
15 | Unless required by applicable law or agreed to in writing, software
16 | distributed under the License is distributed on an "AS IS" BASIS,
17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | See the License for the specific language governing permissions and
19 | limitations under the License.
20 | </copyright>
21 | --------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------
/DoD.md:
--------------------------------------------------------------------------------
1 | Definition of Done for the SOR project
2 | ======================================
3 |
4 | We can push when:
5 |
6 | 1. Test coverage is 100%
7 | 1. No StyleCop issue is detected
8 |
9 |
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/Adapters.fs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1
2 |
3 | module MarketAdapters =
4 |
5 | open System
6 | open Domain
7 | open Dtos
8 |
9 | let send (investorInstructionDto : InvestorInstructionDto) =
10 | let investorInstruction = dtoToInvestorInstruction investorInstructionDto
11 | ()
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/Adapters.fsi:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1
2 |
3 | module MarketAdapters =
4 |
5 | open Dtos
6 |
7 | val send : investorInstructionDto : InvestorInstructionDto -> unit
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/Domain.fs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1
2 |
3 | module Domain =
4 |
5 | open System
6 | open Rop
7 |
8 | type Way =
9 | | Buy
10 | | Sell
11 |
12 | type Market = {SellQuantity : int; SellPrice : decimal; TimeSent : int}
13 |
14 | // ------------------------------
15 | // InvestorInstruction
16 |
17 | type InvestorInstructionId = InvestorInstructionId of int
18 | type InvestorInstruction = {Way : Way; Quantity : int; Price : decimal; AllowPartialExecution : bool; GoodTill : DateTime option}
19 |
20 | // Create a InvestorInstructionId from an int
21 | let createInvestorInstructionId id =
22 | if id < 1 then
23 | fail "InvestorInstructionId must be positive integer"
24 | else
25 | succeed (InvestorInstructionId id)
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/Domain.fsi:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1
2 |
3 | module Domain =
4 |
5 | open Rop
6 |
7 | type InvestorInstructionId
8 |
9 | val createInvestorInstructionId : id:int -> RopResult
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/External.fs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1
2 |
3 | module Markets =
4 |
5 | // TODO : This should be declared in an external assembly (we don't owe this code)
6 | type ExternalMarket = {SellQuantity : int; SellPrice : decimal; TimeSent : int}
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/External.fsi:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1
2 |
3 | module Markets =
4 |
5 | type ExternalMarket
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/MarketDataAdapter.fs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1.Infrastructure.Adapters
2 |
3 | module Market =
4 |
5 | let getAvailableMarkets marketsOfInterest =
6 | ()
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/Ports.fs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1.Infrastructure
2 |
3 | // This is the simulation of the external port that invokes the internal adatpers of the domain.
4 | // This part is not generaly implemented by us but represents an external framework.
5 | module Ports =
6 |
7 | // In memory port that allows to invoke API from the RPC in memory call.
8 | module InMemory =
9 |
10 | // Entry point of the port where a raw data is received (queue, REST, SOAP, etc.)
11 | let send rawData =
12 | ()
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/SORoutingEngine.fs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1
2 |
3 | module Dtos =
4 |
5 | open System
6 | open Domain
7 |
8 | type WayDto =
9 | | Buy
10 | | Sell
11 | | Uninitialized
12 |
13 | /// Represents a DTO that is exposed to the outside world.
14 | /// This is a regular POCO class which can be null.
15 | ///
16 | /// you have to try hard to make an nullable object in F#
17 | []
18 | type InvestorInstructionDto() =
19 | member val Id : int = 0 with get, set
20 | member val Way : WayDto = Uninitialized with get, set
21 | member val Quantity : int = 0 with get, set
22 | member val Price : decimal = 0m with get, set
23 | member val AllowPartialExecution : bool = false with get, set
24 | member val GoodTill : Nullable = Nullable() with get, set
25 |
26 | /// Convert a DTO into a domain contact.
27 | ///
28 | /// We MUST handle the possibility of one or more errors
29 | /// because the InvestorInstruction type has stricter constraints than InvestorInstructionDto
30 | /// and the conversion might fail.
31 | /// This is the adapter entry point for converting the external InvestorInstructionDto to the internal domain
32 | let dtoToInvestorInstruction (dto : InvestorInstructionDto) =
33 | if dto = null then
34 | Rop.fail "Investor instruction is required"
35 | else
36 | let idOrError = createInvestorInstructionId dto.Id
37 | Rop.fail "sdsd"
38 | //{Way = Buy; Quantity = 0; Price = 0m; AllowPartialExecution = false}
39 |
40 | module SmartOrderRoutingEngine =
41 |
42 | let route inverstorInstruction =
43 | ()
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/Script.fsx:
--------------------------------------------------------------------------------
1 | // Learn more about F# at http://fsharp.net. See the 'F# Tutorial' project
2 | // for more guidance on F# programming.
3 |
4 | #load "Utilities.fs"
5 | open SimpleOrderRouting.Journey1.Rop
6 |
7 | // Define your library scripting code here
8 |
9 |
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/SimpleOrderRouting.Journey1.fsproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | 2.0
8 | 63815e01-ad47-4d83-98f5-87160a503d02
9 | Library
10 | SimpleOrderRouting.Journey1
11 | SimpleOrderRouting.Journey1
12 | v4.5.1
13 | 4.3.1.0
14 | SimpleOrderRouting.Journey1
15 |
16 |
17 | true
18 | full
19 | false
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | 3
24 | bin\Debug\SimpleOrderRouting.Journey1.XML
25 |
26 |
27 | pdbonly
28 | true
29 | true
30 | bin\Release\
31 | TRACE
32 | 3
33 | bin\Release\SimpleOrderRouting.Journey1.XML
34 |
35 |
36 |
37 |
38 | True
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | 11
59 |
60 |
61 |
62 |
63 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets
64 |
65 |
66 |
67 |
68 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
69 |
70 |
71 |
72 |
73 |
80 |
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Journey1/Utilities.fs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Journey1
2 |
3 | module Rop =
4 |
5 | // ==============================================
6 | // This is a utility library for managing Success/Failure results
7 | //
8 | // See http://fsharpforfunandprofit.com/rop
9 | // See https://github.com/swlaschin/Railway-Oriented-Programming-Example
10 | // ==============================================
11 |
12 | /// A Result is a success or failure
13 | /// The Success case has a success value
14 | /// The Failure case has a list of messages
15 |
16 | type RopResult<'TSuccess> =
17 | | Success of 'TSuccess
18 | | Failure of string list
19 |
20 | /// create a Success with no messages
21 | let succeed x =
22 | Success x
23 |
24 | /// create a Failure with a message
25 | let fail msg =
26 | Failure [msg]
27 |
28 | /// given a function wrapped in a result
29 | /// and a value wrapped in a result
30 | /// apply the function to the value only if both are Success
31 | let applyR f result =
32 | match f,result with
33 | | Success f, Success x ->
34 | f x |> Success
35 | | Failure errs, Success _
36 | | Success _, Failure errs ->
37 | errs |> Failure
38 | | Failure errs1, Failure errs2 ->
39 | errs1 @ errs2 |> Failure
40 |
41 | /// given a function that transforms a value
42 | /// apply it only if the result is on the Success branch
43 | let liftR f result =
44 | let f' = f |> succeed
45 | applyR f' result
46 |
47 | /// given two values wrapped in results apply a function to both
48 | let lift2R f result1 result2 =
49 | let f' = liftR f result1
50 | applyR f' result2
51 |
52 | /// given three values wrapped in results apply a function to all
53 | let lift3R f result1 result2 result3 =
54 | let f' = lift2R f result1 result2
55 | applyR f' result3
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Tests/MarketTests.fs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Tests
23 |
24 | open Xunit
25 | open FsUnit.Xunit
26 |
27 | module ``Market tests`` =
28 |
29 | []
30 | let ``Market order should decrease available quantity`` =
31 | ()
32 |
33 |
34 |
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Tests/SimpleOrderRouting.Tests.fsproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | 2.0
8 | 54d4d857-f008-4817-bfc5-0f3234ff8781
9 | Library
10 | SimpleOrderRouting.Tests
11 | SimpleOrderRouting.Tests
12 | v4.5.1
13 | 4.3.1.0
14 | SimpleOrderRouting.Tests
15 |
16 |
17 | true
18 | full
19 | false
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | 3
24 | bin\Debug\SimpleOrderRouting.Tests.XML
25 |
26 |
27 | pdbonly
28 | true
29 | true
30 | bin\Release\
31 | TRACE
32 | 3
33 | bin\Release\SimpleOrderRouting.Tests.XML
34 |
35 |
36 | 11
37 |
38 |
39 |
40 |
41 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets
42 |
43 |
44 |
45 |
46 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | ..\packages\FsUnit.xUnit.1.3.0.1\Lib\net40\FsUnit.CustomMatchers.dll
61 | True
62 |
63 |
64 | ..\packages\FsUnit.xUnit.1.3.0.1\Lib\net40\FsUnit.Xunit.dll
65 | True
66 |
67 |
68 |
69 | True
70 |
71 |
72 | ..\packages\FsUnit.xUnit.1.3.0.1\Lib\net40\NHamcrest.dll
73 | True
74 |
75 |
76 |
77 |
78 |
79 | ..\packages\xunit.1.9.2\lib\net20\xunit.dll
80 | True
81 |
82 |
83 |
84 |
85 | SimpleOrderRouting.Journey1
86 | {63815e01-ad47-4d83-98f5-87160a503d02}
87 | True
88 |
89 |
90 |
97 |
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Tests/SorAcceptanceTests.fs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright 2014 The Lunch-Box mob:
4 | // Ozgur DEVELIOGLU (@Zgurrr)
5 | // Cyrille DUPUYDAUBY (@Cyrdup)
6 | // Tomasz JASKULA (@tjaskula)
7 | // Mendel MONTEIRO-BECKERMAN (@MendelMonteiro)
8 | // Thomas PIERRAIN (@tpierrain)
9 | //
10 | // Licensed under the Apache License, Version 2.0 (the "License");
11 | // you may not use this file except in compliance with the License.
12 | // You may obtain a copy of the License at
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 | // --------------------------------------------------------------------------------------------------------------------
21 |
22 | namespace SimpleOrderRouting.Tests
23 |
24 | open Xunit
25 | open FsUnit.Xunit
26 |
27 | module ``Sor acceptance tests`` =
28 |
29 | []
30 | let ``External Api visibility tests``() =
31 | true |> should be True
32 |
33 | []
34 | let ``Should execute "Instruction" When there is enough liquidity on one "Market"``() =
35 | true |> should be True
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Tests/UtilitiesTests.fs:
--------------------------------------------------------------------------------
1 | namespace SimpleOrderRouting.Tests
2 |
3 | open Xunit
4 | open FsUnit.Xunit
5 | open SimpleOrderRouting.Journey1.Rop
6 |
7 | module ``Rop tests`` =
8 |
9 | let failBranch() =
10 | failwith "This branch should not have been called."
11 |
12 | []
13 | let ``Create a Success with no messages``() =
14 | let result = succeed 10
15 | match result with
16 | | Success v -> v |> should equal 10
17 | | Failure _ -> failBranch()
18 |
19 | []
20 | let ``Create a Failure with a message``() =
21 | let result = fail "This is a failure"
22 | match result with
23 | | Success _ -> failBranch()
24 | | Failure errors -> errors.[0] |> should equal "This is a failure"
25 |
26 | []
27 | let ``Apply the function to the value only if both are Success``() =
28 | let success = succeed 10
29 | let intToString i = i.ToString()
30 | let successFunc = succeed intToString
31 | let result = applyR successFunc success
32 | match result with
33 | | Success r -> r |> should equal "10"
34 | | Failure _ -> failBranch()
35 |
36 | []
37 | let ``Apply returns Failure if value is not a Success``() =
38 | let failure = fail "First error"
39 | let intToString i = i.ToString()
40 | let successFunc = succeed intToString
41 | let result = applyR successFunc failure
42 | match result with
43 | | Success _ -> failBranch()
44 | | Failure errors -> errors.[0] |> should equal "First error"
45 |
46 | []
47 | let ``Apply returns Failure if function is not a Success``() =
48 | let success = succeed 10
49 | let intToString i = i.ToString()
50 | let failFunc = fail "Function in error"
51 | let result = applyR failFunc success
52 | match result with
53 | | Success _ -> failBranch()
54 | | Failure errors -> errors.[0] |> should equal "Function in error"
55 |
56 | []
57 | let ``Apply returns Failure if function and value are not a Success``() =
58 | let expectedErrors = ["First error"; "Function in error"]
59 | let failure = fail expectedErrors.[0]
60 | let intToString i = i.ToString()
61 | let failFunc = fail expectedErrors.[1]
62 | let result = applyR failFunc failure
63 | match result with
64 | | Success _ -> failBranch()
65 | | Failure errors -> errors |> List.rev
66 | |> List.iteri (fun i e -> e |> should equal expectedErrors.[i])
67 |
68 | []
69 | let ``Litf a function and applies it if the result is on the Success branch``() =
70 | let intToString i = i.ToString()
71 | let value = succeed 10
72 | let result = liftR intToString value
73 | match result with
74 | | Success r -> r |> should equal "10"
75 | | Failure _ -> failBranch()
76 |
77 | []
78 | let ``Litf a function and not applies it if the result is on the Failure branch``() =
79 | let intToString i = i.ToString()
80 | let value = fail "Failed value"
81 | let result = liftR intToString value
82 | match result with
83 | | Success r -> failBranch()
84 | | Failure errors -> errors.[0] |> should equal "Failed value"
85 |
86 | []
87 | let ``Litf two functions and applies it if the results are on the Success branch``() =
88 | let intToString i i' = (i * i').ToString()
89 | let value = succeed 10
90 | let value' = succeed 5
91 | let result = lift2R intToString value value'
92 | match result with
93 | | Success r -> r |> should equal "50"
94 | | Failure _ -> failBranch()
95 |
96 | []
97 | let ``Litf two functions and not applies it if one of the results are on the Failure branch``() =
98 | let intToString i i' = (i * i').ToString()
99 | let value = fail "First value failed"
100 | let value' = succeed 10
101 | let result = lift2R intToString value value'
102 | match result with
103 | | Success _ -> failBranch()
104 | | Failure errors -> errors.[0] |> should equal "First value failed"
105 |
106 | []
107 | let ``Litf two functions and not applies it if one of the results are on the Failure branch'``() =
108 | let intToString i i' = (i * i').ToString()
109 | let value = succeed 10
110 | let value' = fail "Second value failed"
111 | let result = lift2R intToString value value'
112 | match result with
113 | | Success _ -> failBranch()
114 | | Failure errors -> errors.[0] |> should equal "Second value failed"
115 |
116 | []
117 | let ``Litf three functions and applies it if the results are on the Success branch``() =
118 | let intToString i i' i'' = (i * i' + i'').ToString()
119 | let value = succeed 10
120 | let value' = succeed 5
121 | let value'' = succeed 2
122 | let result = lift3R intToString value value' value''
123 | match result with
124 | | Success r -> r |> should equal "52"
125 | | Failure _ -> failBranch()
126 |
127 | []
128 | let ``Litf three functions and not applies it if one the results are on the Failure branch``() =
129 | let intToString i i' i'' = (i * i' + i'').ToString()
130 | let value = fail "First value failure"
131 | let value' = succeed 5
132 | let value'' = succeed 2
133 | let result = lift3R intToString value value' value''
134 | match result with
135 | | Success _ -> failBranch()
136 | | Failure errors-> errors.[0] |> should equal "First value failure"
137 |
138 | []
139 | let ``Litf three functions and not applies it if one the results are on the Failure branch'``() =
140 | let intToString i i' i'' = (i * i' + i'').ToString()
141 | let value = succeed 10
142 | let value' = fail "Second value failure"
143 | let value'' = succeed 2
144 | let result = lift3R intToString value value' value''
145 | match result with
146 | | Success _ -> failBranch()
147 | | Failure errors-> errors.[0] |> should equal "Second value failure"
148 |
149 | []
150 | let ``Litf three functions and not applies it if one the results are on the Failure branch''``() =
151 | let intToString i i' i'' = (i * i' + i'').ToString()
152 | let value = succeed 10
153 | let value' = succeed 5
154 | let value'' = fail "Third value failure"
155 | let result = lift3R intToString value value' value''
156 | match result with
157 | | Success _ -> failBranch()
158 | | Failure errors-> errors.[0] |> should equal "Third value failure"
159 |
160 | []
161 | let ``Litf three functions and not applies it if one the results are on the Failure branch'''``() =
162 | let expectedErrors = ["First value failure"; "Third value failure"]
163 | let intToString i i' i'' = (i * i' + i'').ToString()
164 | let value = fail expectedErrors.[0]
165 | let value' = succeed 5
166 | let value'' = fail expectedErrors.[1]
167 | let result = lift3R intToString value value' value''
168 | match result with
169 | | Success _ -> failBranch()
170 | | Failure errors-> errors |> List.iteri (fun i e -> e |> should equal expectedErrors.[i])
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Tests/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/FSharp/SimpleOrderRouting.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.30723.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "SimpleOrderRouting.Journey1", "SimpleOrderRouting.Journey1\SimpleOrderRouting.Journey1.fsproj", "{63815E01-AD47-4D83-98F5-87160A503D02}"
7 | EndProject
8 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "SimpleOrderRouting.Tests", "SimpleOrderRouting.Tests\SimpleOrderRouting.Tests.fsproj", "{54D4D857-F008-4817-BFC5-0F3234FF8781}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {63815E01-AD47-4D83-98F5-87160A503D02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {63815E01-AD47-4D83-98F5-87160A503D02}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {63815E01-AD47-4D83-98F5-87160A503D02}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {63815E01-AD47-4D83-98F5-87160A503D02}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {54D4D857-F008-4817-BFC5-0F3234FF8781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {54D4D857-F008-4817-BFC5-0F3234FF8781}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {54D4D857-F008-4817-BFC5-0F3234FF8781}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {54D4D857-F008-4817-BFC5-0F3234FF8781}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # The 'SOR' #LunchBox project
2 |
3 | __[Every information is now available on the project's wiki](https://github.com/Lunch-box/SimpleOrderRouting/wiki)__
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/images/10kfeet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/10kfeet.jpg
--------------------------------------------------------------------------------
/images/25kfeet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/25kfeet.jpg
--------------------------------------------------------------------------------
/images/5feet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/5feet.jpg
--------------------------------------------------------------------------------
/images/Hegagonal-firstDraft.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/Hegagonal-firstDraft.jpg
--------------------------------------------------------------------------------
/images/HexaMendel.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/HexaMendel.jpg
--------------------------------------------------------------------------------
/images/HexaThomas.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/HexaThomas.jpg
--------------------------------------------------------------------------------
/images/HexaTomasz.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/HexaTomasz.jpg
--------------------------------------------------------------------------------
/images/MarketsRaceConditions.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/MarketsRaceConditions.jpg
--------------------------------------------------------------------------------
/images/PortAndAdapters.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/PortAndAdapters.jpg
--------------------------------------------------------------------------------
/images/SOR-bigPicture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/SOR-bigPicture.jpg
--------------------------------------------------------------------------------
/images/XPDesign.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/XPDesign.jpg
--------------------------------------------------------------------------------
/images/You-Are-Here.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/You-Are-Here.jpg
--------------------------------------------------------------------------------
/images/duty_calls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/duty_calls.png
--------------------------------------------------------------------------------
/images/goodmanpistoff.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lunch-box/SimpleOrderRouting/96abee8fb4e9faf0d1e0a35bc39f5e135092290b/images/goodmanpistoff.jpg
--------------------------------------------------------------------------------