Skip to content

Commit 212e459

Browse files
authored
Merge pull request #224 from cbusbey/fix_decimal
FIX decimal
2 parents 072f29e + 8e028a7 commit 212e459

File tree

422 files changed

+31600
-31120
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

422 files changed

+31600
-31120
lines changed

cmd/generate-fix/internal/generate.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package internal
22

33
import (
4+
"flag"
45
"fmt"
56
"go/ast"
67
"go/parser"
@@ -11,6 +12,7 @@ import (
1112
)
1213

1314
var (
15+
useFloat = flag.Bool("use-float", false, "By default, FIX float fields are represented as arbitrary-precision fixed-point decimal numbers. Set to 'true' to instead generate FIX float fields as float64 values.")
1416
tabWidth = 8
1517
printerMode = printer.UseSpaces | printer.TabIndent
1618
)

cmd/generate-fix/internal/template_helpers.go

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@ import (
66
"github.com/quickfixgo/quickfix/datadictionary"
77
)
88

9+
func checkFieldDecimalRequired(f *datadictionary.FieldDef) (required bool, err error) {
10+
var globalType *datadictionary.FieldType
11+
if globalType, err = getGlobalFieldType(f); err != nil {
12+
return
13+
}
14+
15+
var t string
16+
if t, err = quickfixType(globalType); err != nil {
17+
return
18+
}
19+
20+
if t == "FIXDecimal" {
21+
required = true
22+
return
23+
}
24+
25+
for _, groupField := range f.Fields {
26+
if required, err = checkFieldDecimalRequired(groupField); required || err != nil {
27+
return
28+
}
29+
}
30+
31+
return
32+
}
33+
934
func checkFieldTimeRequired(f *datadictionary.FieldDef) (required bool, err error) {
1035
var globalType *datadictionary.FieldType
1136
if globalType, err = getGlobalFieldType(f); err != nil {
@@ -37,20 +62,38 @@ func checkFieldTimeRequired(f *datadictionary.FieldDef) (required bool, err erro
3762
}
3863

3964
func collectExtraImports(m *datadictionary.MessageDef) (imports []string, err error) {
40-
//NOTE: the time package is the only extra import considered here
41-
var timeRequired bool
65+
var timeRequired, decimalRequired bool
4266
for _, f := range m.Fields {
43-
if timeRequired, err = checkFieldTimeRequired(f); timeRequired {
44-
imports = []string{"time"}
67+
if !timeRequired {
68+
if timeRequired, err = checkFieldTimeRequired(f); err != nil {
69+
return
70+
}
71+
}
72+
73+
if !decimalRequired {
74+
if decimalRequired, err = checkFieldDecimalRequired(f); err != nil {
75+
return
76+
}
77+
}
78+
79+
if decimalRequired && timeRequired {
4580
break
46-
} else if err != nil {
47-
return
4881
}
4982
}
5083

84+
if timeRequired {
85+
imports = append(imports, "time")
86+
}
87+
88+
if decimalRequired {
89+
imports = append(imports, "github.com/shopspring/decimal")
90+
}
91+
5192
return
5293
}
5394

95+
func useFloatType() bool { return *useFloat }
96+
5497
func quickfixValueType(quickfixType string) (goType string, err error) {
5598
switch quickfixType {
5699
case "FIXString":
@@ -63,6 +106,8 @@ func quickfixValueType(quickfixType string) (goType string, err error) {
63106
goType = "time.Time"
64107
case "FIXFloat":
65108
goType = "float64"
109+
case "FIXDecimal":
110+
goType = "decimal.Decimal"
66111
default:
67112
err = fmt.Errorf("Unknown QuickFIX Type: %v", quickfixType)
68113
}
@@ -141,7 +186,11 @@ func quickfixType(field *datadictionary.FieldType) (quickfixType string, err err
141186
case "PERCENTAGE":
142187
fallthrough
143188
case "FLOAT":
144-
quickfixType = "FIXFloat"
189+
if *useFloat {
190+
quickfixType = "FIXFloat"
191+
} else {
192+
quickfixType = "FIXDecimal"
193+
}
145194

146195
default:
147196
err = fmt.Errorf("Unknown type '%v' for tag '%v'\n", field.Type, field.Tag())

cmd/generate-fix/internal/templates.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func init() {
2525
"quickfixValueType": quickfixValueType,
2626
"getGlobalFieldType": getGlobalFieldType,
2727
"collectExtraImports": collectExtraImports,
28+
"useFloatType": useFloatType,
2829
}
2930

3031
baseTemplate := template.Must(template.New("Base").Funcs(tmplFuncs).Parse(`
@@ -33,10 +34,15 @@ func init() {
3334
{{ define "fieldsetter" -}}
3435
{{- $field_type := getGlobalFieldType . -}}
3536
{{- $qfix_type := quickfixType $field_type -}}
37+
{{- if eq $qfix_type "FIXDecimal" -}}
38+
Set{{ .Name }}(value decimal.Decimal, scale int32) {
39+
{{ template "receiver" }}.Set(field.New{{ .Name }}(value, scale))
40+
}
41+
{{- else -}}
3642
Set{{ .Name }}(v {{ quickfixValueType $qfix_type }}) {
3743
{{ template "receiver" }}.Set(field.New{{ .Name }}(v))
3844
}
39-
{{- end }}
45+
{{- end }}{{ end }}
4046
4147
{{ define "groupsetter" -}}
4248
Set{{ .Name }}(f {{ .Name }}RepeatingGroup){
@@ -191,6 +197,9 @@ package {{ .Package }}
191197
192198
import(
193199
"time"
200+
{{- range collectExtraImports .MessageDef }}
201+
"{{ . }}"
202+
{{- end }}
194203
195204
"github.com/quickfixgo/quickfix"
196205
"{{ importRootPath }}/field"
@@ -275,7 +284,7 @@ package field
275284
import(
276285
"github.com/quickfixgo/quickfix"
277286
"{{ importRootPath }}/tag"
278-
287+
{{ if eq useFloatType false}} "github.com/shopspring/decimal" {{ end }}
279288
"time"
280289
)
281290
@@ -298,6 +307,11 @@ func New{{ .Name }}NoMillis(val time.Time) {{ .Name }}Field {
298307
return {{ .Name }}Field{ quickfix.FIXUTCTimestamp{ Time: val, NoMillis: true } }
299308
}
300309
310+
{{ else if eq $base_type "FIXDecimal" }}
311+
//New{{ .Name }} returns a new {{ .Name }}Field initialized with val and scale
312+
func New{{ .Name }}(val decimal.Decimal, scale int32) {{ .Name }}Field {
313+
return {{ .Name }}Field{ quickfix.FIXDecimal{ Decimal: val, Scale: scale} }
314+
}
301315
{{ else }}
302316
//New{{ .Name }} returns a new {{ .Name }}Field initialized with val
303317
func New{{ .Name }}(val {{ quickfixValueType $base_type }}) {{ .Name }}Field {

doc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ ToApp notifies you of application messages that you are being sent to a counterp
2929
3030
FromAdmin(message Message, sessionID SessionID) MessageRejectError
3131
32-
FromAdmin notifies you when an administrative message is sent from a counterparty to your FIX engine. This can be usefull for doing extra validation on logon messages such as for checking passwords.
32+
FromAdmin notifies you when an administrative message is sent from a counterparty to your FIX engine. This can be useful for doing extra validation on logon messages such as for checking passwords.
3333
3434
FromApp(msg Message, sessionID SessionID) MessageRejectError
3535

0 commit comments

Comments
 (0)